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 } |