comparison sip-in/invite.c @ 60:02761f1ae5e5

sip-in INVITE processing: got as far as CRCX completion
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 11 Sep 2022 15:42:54 -0800
parents d61d0136f6a5
children 7c0309df59f8
comparison
equal deleted inserted replaced
59:bea761629c5b 60:02761f1ae5e5
3 */ 3 */
4 4
5 #include <sys/types.h> 5 #include <sys/types.h>
6 #include <sys/socket.h> 6 #include <sys/socket.h>
7 #include <netinet/in.h> 7 #include <netinet/in.h>
8 #include <arpa/inet.h>
8 #include <stdio.h> 9 #include <stdio.h>
10 #include <stdint.h>
9 #include <stdlib.h> 11 #include <stdlib.h>
10 #include <string.h> 12 #include <string.h>
11 #include <strings.h> 13 #include <strings.h>
12 #include <syslog.h> 14 #include <syslog.h>
13 #include <unistd.h>
14 #include "../libsip/parse.h" 15 #include "../libsip/parse.h"
15 #include "../libsip/uas_basic.h" 16 #include "../libsip/uas_basic.h"
16 #include "../libsip/grok_from.h" 17 #include "../libsip/grok_from.h"
17 #include "../libsip/req_supp.h" 18 #include "../libsip/req_supp.h"
18 #include "../libsip/sdp.h" 19 #include "../libsip/sdp.h"
19 #include "../libsip/out_msg.h" 20 #include "../libsip/out_msg.h"
21 #include "call.h"
20 22
21 extern struct in_addr sip_bind_ip; 23 extern struct in_addr sip_bind_ip;
24 extern unsigned sip_bind_port;
22 extern int cfg_use_100rel; 25 extern int cfg_use_100rel;
23 26 extern struct call *call_list;
27
28 extern struct call *find_call_by_sip_id();
24 extern char *get_single_header(); 29 extern char *get_single_header();
25 30
26 void 31 fill_invite_resp_from_call(msg, call)
27 handle_sip_invite(req, ess, sin) 32 struct sip_msg_out *msg;
33 struct call *call;
34 {
35 char cseq_str[32];
36 int rc;
37
38 rc = out_msg_add_header(msg, "From", call->invite_from);
39 if (rc < 0)
40 return rc;
41 rc = out_msg_add_header(msg, "To", call->invite_to);
42 if (rc < 0)
43 return rc;
44 rc = out_msg_add_header(msg, "Call-ID", call->sip_call_id);
45 if (rc < 0)
46 return rc;
47 sprintf(cseq_str, "%u INVITE", call->invite_cseq);
48 rc = out_msg_add_header(msg, "CSeq", cseq_str);
49 if (rc < 0)
50 return rc;
51 return out_msg_add_header(msg, "Via", call->invite_via);
52 }
53
54 fill_invite_200_resp(msg, call)
55 struct sip_msg_out *msg;
56 struct call *call;
57 {
58 char contact_str[80];
59 struct sdp_gen sdp;
60 int rc;
61
62 start_response_out_msg(msg, "200 CONNECT");
63 rc = fill_invite_resp_from_call(msg, call);
64 if (rc < 0)
65 return rc;
66 sprintf(contact_str, "<sip:%s:%u;transport=udp>",
67 inet_ntoa(sip_bind_ip), sip_bind_port);
68 rc = out_msg_add_header(msg, "Contact", contact_str);
69 if (rc < 0)
70 return rc;
71 rc = out_msg_add_header(msg, "Content-Type", "application/sdp");
72 if (rc < 0)
73 return rc;
74 bzero(&sdp, sizeof sdp);
75 sdp.conn_ip = call->pstn_rtp_local.sin_addr;
76 sdp.conn_port = ntohs(call->pstn_rtp_local.sin_port);
77 sdp.codec_mask = call->use_pcma ? SDP_CODEC_MASK_PCMA
78 : SDP_CODEC_MASK_PCMU;
79 sdp.session_id = (sdp.conn_port << 16) | call->sdp_addend;
80 sdp.owner_ip = sip_bind_ip;
81 return out_msg_finish_sdp(msg, &sdp);
82 }
83
84 static void
85 invite_new_call(req, ess, sin)
28 struct sip_pkt_rx *req; 86 struct sip_pkt_rx *req;
29 struct uas_parse_hdrs *ess; 87 struct uas_parse_hdrs *ess;
30 struct sockaddr_in *sin; 88 struct sockaddr_in *sin;
31 { 89 {
32 char uri_user[13], *called_nanp; 90 char uri_user[13], *called_nanp;
35 struct supported_ext supp_ext; 93 struct supported_ext supp_ext;
36 char *hval, *unsup_ext; 94 char *hval, *unsup_ext;
37 int ext_100rel_req, ext_100rel_sup, use_100rel, use_pcma; 95 int ext_100rel_req, ext_100rel_sup, use_100rel, use_pcma;
38 struct sdp_parse sdp_parse; 96 struct sdp_parse sdp_parse;
39 struct sdp_gen sdp_gen; 97 struct sdp_gen sdp_gen;
40 int rc; 98 struct call *call;
41 99 char *dp;
42 /* check for existing Call-ID will go here */ 100 unsigned copylen;
101 int rc;
102
43 /* extract called number from Request-URI */ 103 /* extract called number from Request-URI */
44 rc = user_from_sip_uri(req->req_uri, uri_user, 12); 104 rc = user_from_sip_uri(req->req_uri, uri_user, 12);
45 if (rc < 0) { 105 if (rc < 0) {
46 not_nanp: start_response_out_msg(&resp, 106 not_nanp: start_response_out_msg(&resp,
47 "416 Request-URI is not a NANP number"); 107 "416 Request-URI is not a NANP number");
48 error_resp: rc = add_resp_basic_headers(&resp, ess, req->req_method); 108 error_resp: rc = add_resp_basic_headers(&resp, ess, req->req_method);
49 if (rc < 0) { 109 if (rc < 0) {
50 error_resp_toolong: syslog(LOG_ERR, 110 error_resp_toolong: syslog(LOG_ERR,
51 "INVITE error response length exceeded"); 111 "INVITE early error response length exceeded");
52 return; 112 return;
53 } 113 }
54 out_msg_finish(&resp); 114 out_msg_finish(&resp);
55 sip_tx_packet(&resp, sin); 115 sip_tx_packet(&resp, sin);
56 return; 116 return;
57 } 117 }
58 if (uri_user[0] == '+') { 118 if (uri_user[0] == '+') {
59 if (grok_number_string(uri_user+1, 0) != 11 || 119 if (grok_number_string(uri_user+1, 0) != 11 ||
60 uri_user[1] != '1') 120 uri_user[1] != '1')
61 goto not_nanp; 121 goto not_nanp;
154 sdp_gen.codec_mask = SDP_CODEC_MASK_BOTH; 214 sdp_gen.codec_mask = SDP_CODEC_MASK_BOTH;
155 rc = out_msg_finish_sdp(&resp, &sdp_gen); 215 rc = out_msg_finish_sdp(&resp, &sdp_gen);
156 if (rc < 0) 216 if (rc < 0)
157 goto error_resp_toolong; 217 goto error_resp_toolong;
158 sip_tx_packet(&resp, sin); 218 sip_tx_packet(&resp, sin);
159 return; 219 return;
160 } 220 }
161 /* SIP INVITE validation done - check if GSM service is up */ 221 /* SIP INVITE validation done - check if GSM service is up */
162 rc = connect_gsm_mtcall(); 222 rc = connect_gsm_mtcall();
163 if (rc < 0) { 223 if (rc < 0) {
164 start_response_out_msg(&resp, "480 GSM service is offline"); 224 start_response_out_msg(&resp, "480 GSM service is offline");
165 goto error_resp; 225 goto error_resp;
166 } 226 }
167 /* stateful processing begins */ 227 /* stateful processing begins */
168 } 228 call = malloc(sizeof(struct call) + strlen(ess->call_id) +
229 strlen(ess->from) + strlen(ess->to) + strlen(ess->via)
230 + 4);
231 if (!call) {
232 syslog(LOG_CRIT, "failed malloc for incoming call!");
233 start_response_out_msg(&resp,
234 "503 Gateway resource allocation failure");
235 goto error_resp;
236 }
237 bzero(call, sizeof(struct call));
238 dp = (char *)(call + 1);
239 copylen = strlen(ess->call_id) + 1;
240 call->sip_call_id = dp;
241 bcopy(ess->call_id, dp, copylen);
242 dp += copylen;
243 copylen = strlen(ess->from) + 1;
244 call->invite_from = dp;
245 bcopy(ess->from, dp, copylen);
246 dp += copylen;
247 copylen = strlen(ess->to) + 1;
248 call->invite_to = dp;
249 bcopy(ess->to, dp, copylen);
250 dp += copylen;
251 copylen = strlen(ess->via) + 1;
252 call->invite_via = dp;
253 bcopy(ess->via, dp, copylen);
254 call->invite_cseq = ess->cseq_num;
255 bcopy(sin, &call->udp_sin, sizeof(struct sockaddr_in));
256 bcopy(called_nanp, call->called_nanp, 11);
257 call->from_uri = call->invite_from + (gfrom.uri - ess->from);
258 call->from_uri_len = gfrom.uri_len;
259 call->from_user = call->invite_from + (gfrom.user - ess->from);
260 call->from_user_len = gfrom.user_len;
261 call->use_100rel = use_100rel;
262 call->pstn_rtp_remote.sin_family = AF_INET;
263 call->pstn_rtp_remote.sin_addr = sdp_parse.ip_addr;
264 call->pstn_rtp_remote.sin_port = htons(sdp_parse.audio_port);
265 call->use_pcma = use_pcma;
266 /* generate 100 response */
267 start_response_out_msg(&resp, "100 Proceeding");
268 rc = fill_invite_resp_from_call(&resp, call);
269 if (rc < 0) {
270 syslog(LOG_ERR, "INVITE 100 response length exceeded");
271 free(call);
272 return;
273 }
274 out_msg_finish(&resp);
275 sip_tx_packet(&resp, sin);
276 /* add to call list */
277 call->next = call_list;
278 call_list = call;
279 /* send CRCX to TMGW */
280 tmgw_send_crcx(call);
281 call->overall_state = OVERALL_STATE_CRCX;
282 call->sip_state = SIP_STATE_INVITE_PROC;
283 }
284
285 static void
286 invite_existing_call(req, ess, sin, call)
287 struct sip_pkt_rx *req;
288 struct uas_parse_hdrs *ess;
289 struct sockaddr_in *sin;
290 struct call *call;
291 {
292 struct sip_msg_out resp;
293 int rc;
294
295 if (ess->cseq_num != call->invite_cseq) {
296 start_response_out_msg(&resp, "501 Re-INVITE not supported");
297 rc = add_resp_basic_headers(&resp, ess, req->req_method);
298 if (rc < 0) {
299 syslog(LOG_ERR,
300 "sending 501 Re-INVITE error: response length exceeded");
301 return;
302 }
303 out_msg_finish(&resp);
304 sip_tx_packet(&resp, sin);
305 return;
306 }
307 /* it's a retransmission, not a re-INVITE */
308 switch (call->sip_state) {
309 case SIP_STATE_INVITE_PROC:
310 start_response_out_msg(&resp, "100 Proceeding");
311 fill_invite_resp_from_call(&resp, call);
312 out_msg_finish(&resp);
313 sip_tx_packet(&resp, sin);
314 return;
315 case SIP_STATE_RINGING:
316 case SIP_STATE_RINGING_PRACK:
317 start_response_out_msg(&resp, "180 Ringing");
318 fill_invite_resp_from_call(&resp, call);
319 out_msg_finish(&resp);
320 sip_tx_packet(&resp, sin);
321 return;
322 case SIP_STATE_INVITE_200:
323 case SIP_STATE_CONNECTED:
324 fill_invite_200_resp(&resp, call);
325 sip_tx_packet(&resp, sin);
326 return;
327 case SIP_STATE_INVITE_ERR:
328 start_response_out_msg(&resp, call->invite_fail);
329 fill_invite_resp_from_call(&resp, call);
330 out_msg_finish(&resp);
331 sip_tx_packet(&resp, sin);
332 return;
333 default:
334 /* silently discard */
335 return;
336 }
337 }
338
339 void
340 handle_sip_invite(req, ess, sin)
341 struct sip_pkt_rx *req;
342 struct uas_parse_hdrs *ess;
343 struct sockaddr_in *sin;
344 {
345 struct call *call;
346
347 call = find_call_by_sip_id(ess->call_id);
348 if (call)
349 invite_existing_call(req, ess, sin, call);
350 else
351 invite_new_call(req, ess, sin);
352 }
353
354 void
355 signal_invite_error(call)
356 struct call *call;
357 {
358 struct sip_msg_out resp;
359 int rc;
360
361 start_response_out_msg(&resp, call->invite_fail);
362 rc = fill_invite_resp_from_call(&resp, call);
363 if (rc < 0) {
364 syslog(LOG_ERR, "INVITE late error response length exceeded");
365 call->sip_state = SIP_STATE_MSG_SIZE_ERR;
366 /* TODO: transition from TEARDOWN to DEAD_SIP */
367 return;
368 }
369 out_msg_finish(&resp);
370 sip_tx_packet(&resp, &call->udp_sin);
371 call->sip_state = SIP_STATE_INVITE_ERR;
372 call->sip_tx_count = 1;
373 }