FreeCalypso > hg > themwi-system-sw
comparison utils/sip-out-test.c @ 52:ffb563a17f23
wrote sip-out-test program
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Thu, 08 Sep 2022 00:27:48 -0800 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 51:36a30349b490 | 52:ffb563a17f23 |
|---|---|
| 1 /* | |
| 2 * This program is a contraption for testing manually constructed | |
| 3 * outgoing SIP calls to BulkVS. | |
| 4 */ | |
| 5 | |
| 6 #include <sys/types.h> | |
| 7 #include <sys/socket.h> | |
| 8 #include <sys/time.h> | |
| 9 #include <sys/errno.h> | |
| 10 #include <netinet/in.h> | |
| 11 #include <arpa/inet.h> | |
| 12 #include <stdio.h> | |
| 13 #include <stdlib.h> | |
| 14 #include <string.h> | |
| 15 #include <strings.h> | |
| 16 #include <unistd.h> | |
| 17 | |
| 18 #define MAX_SIP_TX_PACKET 1472 | |
| 19 | |
| 20 static struct in_addr local_ip, remote_ip; | |
| 21 static unsigned local_sip_port, local_rtp_port, remote_port; | |
| 22 static char *invite_filename, *log_filename; | |
| 23 static char invite_packet[MAX_SIP_TX_PACKET]; | |
| 24 static unsigned invite_packet_len; | |
| 25 static FILE *logF; | |
| 26 static struct timeval curtime; | |
| 27 | |
| 28 static void | |
| 29 read_invite_file() | |
| 30 { | |
| 31 FILE *inf; | |
| 32 char linebuf[128], *cp, *dp; | |
| 33 int lineno; | |
| 34 unsigned size_accum, linelen; | |
| 35 | |
| 36 inf = fopen(invite_filename, "r"); | |
| 37 if (!inf) { | |
| 38 perror(invite_filename); | |
| 39 exit(1); | |
| 40 } | |
| 41 size_accum = 0; | |
| 42 dp = invite_packet; | |
| 43 for (lineno = 1; fgets(linebuf, sizeof(linebuf), inf); lineno++) { | |
| 44 cp = index(linebuf, '\n'); | |
| 45 if (!cp) { | |
| 46 fprintf(stderr, | |
| 47 "%s line %d: too long or missing newline\n", | |
| 48 invite_filename, lineno); | |
| 49 exit(1); | |
| 50 } | |
| 51 *cp = '\0'; | |
| 52 linelen = cp - linebuf; | |
| 53 if (size_accum + linelen + 2 > MAX_SIP_TX_PACKET) { | |
| 54 fprintf(stderr, "%s line %d: packet overflow\n", | |
| 55 invite_filename, lineno); | |
| 56 exit(1); | |
| 57 } | |
| 58 bcopy(linebuf, dp, linelen); | |
| 59 dp += linelen; | |
| 60 *dp++ = '\r'; | |
| 61 *dp++ = '\n'; | |
| 62 size_accum += linelen + 2; | |
| 63 } | |
| 64 fclose(inf); | |
| 65 if (!size_accum) { | |
| 66 fprintf(stderr, "error: %s is empty\n", invite_filename); | |
| 67 exit(1); | |
| 68 } | |
| 69 invite_packet_len = size_accum; | |
| 70 } | |
| 71 | |
| 72 static void | |
| 73 log_common(msg, msglen, sin, dir, outf) | |
| 74 char *msg, *dir; | |
| 75 unsigned msglen; | |
| 76 struct sockaddr_in *sin; | |
| 77 FILE *outf; | |
| 78 { | |
| 79 unsigned sec, ms; | |
| 80 | |
| 81 sec = curtime.tv_sec % 86400; | |
| 82 ms = curtime.tv_usec / 1000; | |
| 83 fprintf(outf, "Msg %s %s:%u %u bytes %02u:%02u:%02u.%03u\n", dir, | |
| 84 inet_ntoa(sin->sin_addr), ntohs(sin->sin_port), msglen, | |
| 85 sec / 3600, (sec / 60) % 60, sec % 60, ms); | |
| 86 fwrite(msg, 1, msglen, outf); | |
| 87 putc('\n', outf); | |
| 88 fflush(outf); | |
| 89 } | |
| 90 | |
| 91 static void | |
| 92 log_sip_msg_rx(msg, msglen, sin) | |
| 93 char *msg; | |
| 94 unsigned msglen; | |
| 95 struct sockaddr_in *sin; | |
| 96 { | |
| 97 log_common(msg, msglen, sin, "from", stdout); | |
| 98 if (logF) | |
| 99 log_common(msg, msglen, sin, "from", logF); | |
| 100 } | |
| 101 | |
| 102 static void | |
| 103 log_sip_msg_tx(msg, msglen, sin) | |
| 104 char *msg; | |
| 105 unsigned msglen; | |
| 106 struct sockaddr_in *sin; | |
| 107 { | |
| 108 log_common(msg, msglen, sin, "to", stdout); | |
| 109 if (logF) | |
| 110 log_common(msg, msglen, sin, "to", logF); | |
| 111 } | |
| 112 | |
| 113 main(argc, argv) | |
| 114 char **argv; | |
| 115 { | |
| 116 struct sockaddr_in sin_local, sin_rtp, sin_rtcp, sin_remote, sin_rx; | |
| 117 int sock_sip, sock_rtp, sock_rtcp, max_fd; | |
| 118 socklen_t addrlen; | |
| 119 fd_set fds; | |
| 120 char recv_buf[4096]; | |
| 121 int rc; | |
| 122 | |
| 123 /* grok command line arguments */ | |
| 124 if (argc < 7 || argc > 8) { | |
| 125 fprintf(stderr, | |
| 126 "usage: %s local-ip local-sip local-rtp remote-ip remote-sip inv-file [logfile]\n", | |
| 127 argv[0]); | |
| 128 exit(1); | |
| 129 } | |
| 130 local_ip.s_addr = inet_addr(argv[1]); | |
| 131 if (local_ip.s_addr == INADDR_NONE) { | |
| 132 fprintf(stderr, "error: invalid IP address \"%s\"\n", argv[1]); | |
| 133 exit(1); | |
| 134 } | |
| 135 local_sip_port = atoi(argv[2]); | |
| 136 local_rtp_port = atoi(argv[3]); | |
| 137 remote_ip.s_addr = inet_addr(argv[4]); | |
| 138 if (remote_ip.s_addr == INADDR_NONE) { | |
| 139 fprintf(stderr, "error: invalid IP address \"%s\"\n", argv[4]); | |
| 140 exit(1); | |
| 141 } | |
| 142 remote_port = atoi(argv[5]); | |
| 143 invite_filename = argv[6]; | |
| 144 log_filename = argv[7]; | |
| 145 /* fill sin structures */ | |
| 146 sin_local.sin_family = AF_INET; | |
| 147 sin_local.sin_addr = local_ip; | |
| 148 sin_local.sin_port = htons(local_sip_port); | |
| 149 sin_rtp.sin_family = AF_INET; | |
| 150 sin_rtp.sin_addr = local_ip; | |
| 151 sin_rtp.sin_port = htons(local_rtp_port); | |
| 152 sin_rtcp.sin_family = AF_INET; | |
| 153 sin_rtcp.sin_addr = local_ip; | |
| 154 sin_rtcp.sin_port = htons(local_rtp_port+1); | |
| 155 sin_remote.sin_family = AF_INET; | |
| 156 sin_remote.sin_addr = remote_ip; | |
| 157 sin_remote.sin_port = htons(remote_port); | |
| 158 /* create and bind sockets */ | |
| 159 sock_sip = socket(AF_INET, SOCK_DGRAM, 0); | |
| 160 if (sock_sip < 0) { | |
| 161 perror("socket"); | |
| 162 exit(1); | |
| 163 } | |
| 164 rc = bind(sock_sip, (struct sockaddr *) &sin_local, | |
| 165 sizeof(struct sockaddr_in)); | |
| 166 if (rc < 0) { | |
| 167 perror("bind"); | |
| 168 exit(1); | |
| 169 } | |
| 170 sock_rtp = socket(AF_INET, SOCK_DGRAM, 0); | |
| 171 if (sock_rtp < 0) { | |
| 172 perror("socket"); | |
| 173 exit(1); | |
| 174 } | |
| 175 rc = bind(sock_rtp, (struct sockaddr *) &sin_rtp, | |
| 176 sizeof(struct sockaddr_in)); | |
| 177 if (rc < 0) { | |
| 178 perror("bind"); | |
| 179 exit(1); | |
| 180 } | |
| 181 sock_rtcp = socket(AF_INET, SOCK_DGRAM, 0); | |
| 182 if (sock_rtcp < 0) { | |
| 183 perror("socket"); | |
| 184 exit(1); | |
| 185 } | |
| 186 rc = bind(sock_rtcp, (struct sockaddr *) &sin_rtcp, | |
| 187 sizeof(struct sockaddr_in)); | |
| 188 if (rc < 0) { | |
| 189 perror("bind"); | |
| 190 exit(1); | |
| 191 } | |
| 192 /* read the INVITE packet */ | |
| 193 read_invite_file(); | |
| 194 /* open the log file, if we have one */ | |
| 195 if (log_filename) { | |
| 196 logF = fopen(log_filename, "a"); | |
| 197 if (!logF) { | |
| 198 perror(log_filename); | |
| 199 exit(1); | |
| 200 } | |
| 201 } | |
| 202 /* now get down to business */ | |
| 203 max_fd = sock_sip; | |
| 204 if (sock_rtp > max_fd) | |
| 205 max_fd = sock_rtp; | |
| 206 if (sock_rtcp > max_fd) | |
| 207 max_fd = sock_rtcp; | |
| 208 addrlen = sizeof(struct sockaddr_in); | |
| 209 rc = sendto(sock_sip, invite_packet, invite_packet_len, 0, | |
| 210 (struct sockaddr *) &sin_remote, addrlen); | |
| 211 if (rc < 0) { | |
| 212 perror("sendto"); | |
| 213 exit(1); | |
| 214 } | |
| 215 gettimeofday(&curtime, 0); | |
| 216 log_sip_msg_tx(invite_packet, invite_packet_len, &sin_remote); | |
| 217 /* main select loop */ | |
| 218 for (;;) { | |
| 219 FD_ZERO(&fds); | |
| 220 FD_SET(sock_sip, &fds); | |
| 221 FD_SET(sock_rtp, &fds); | |
| 222 FD_SET(sock_rtcp, &fds); | |
| 223 rc = select(max_fd+1, &fds, 0, 0, 0); | |
| 224 if (rc < 0) { | |
| 225 if (errno == EINTR) | |
| 226 continue; | |
| 227 perror("select"); | |
| 228 exit(1); | |
| 229 } | |
| 230 gettimeofday(&curtime, 0); | |
| 231 if (FD_ISSET(sock_sip, &fds)) { | |
| 232 addrlen = sizeof(struct sockaddr_in); | |
| 233 rc = recvfrom(sock_sip, recv_buf, sizeof recv_buf, 0, | |
| 234 (struct sockaddr *) &sin_rx, &addrlen); | |
| 235 if (rc < 0) { | |
| 236 perror("recvfrom"); | |
| 237 exit(1); | |
| 238 } | |
| 239 log_sip_msg_rx(recv_buf, rc, &sin_rx); | |
| 240 } | |
| 241 if (FD_ISSET(sock_rtp, &fds)) { | |
| 242 addrlen = sizeof(struct sockaddr_in); | |
| 243 rc = recvfrom(sock_rtp, recv_buf, sizeof recv_buf, 0, | |
| 244 (struct sockaddr *) &sin_rx, &addrlen); | |
| 245 if (rc < 0) { | |
| 246 perror("recvfrom"); | |
| 247 exit(1); | |
| 248 } | |
| 249 } | |
| 250 if (FD_ISSET(sock_rtcp, &fds)) { | |
| 251 addrlen = sizeof(struct sockaddr_in); | |
| 252 rc = recvfrom(sock_rtp, recv_buf, sizeof recv_buf, 0, | |
| 253 (struct sockaddr *) &sin_rx, &addrlen); | |
| 254 if (rc < 0) { | |
| 255 perror("recvfrom"); | |
| 256 exit(1); | |
| 257 } | |
| 258 } | |
| 259 } | |
| 260 } |
