FreeCalypso > hg > themwi-system-sw
comparison sip-in/prack.c @ 108:0d6435808bcd
sip-in: implement 100rel for 180 Ringing response
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 28 Sep 2022 14:29:10 -0800 |
parents | |
children | 9b87894704eb |
comparison
equal
deleted
inserted
replaced
107:372209628038 | 108:0d6435808bcd |
---|---|
1 /* | |
2 * Here we implement our handling of SIP PRACK, expected from callers | |
3 * when we send them a reliable 180 Ringing response. | |
4 */ | |
5 | |
6 #include <sys/types.h> | |
7 #include <sys/socket.h> | |
8 #include <netinet/in.h> | |
9 #include <ctype.h> | |
10 #include <stdio.h> | |
11 #include <stdint.h> | |
12 #include <stdlib.h> | |
13 #include <string.h> | |
14 #include <strings.h> | |
15 #include <syslog.h> | |
16 #include "../include/gsm48_const.h" | |
17 #include "../libsip/parse.h" | |
18 #include "../libsip/uas_basic.h" | |
19 #include "../libsip/out_msg.h" | |
20 #include "call.h" | |
21 | |
22 extern char *get_single_header(); | |
23 extern struct call *find_call_by_sip_id(); | |
24 | |
25 void | |
26 handle_sip_prack(req, ess, sin) | |
27 struct sip_pkt_rx *req; | |
28 struct uas_parse_hdrs *ess; | |
29 struct sockaddr_in *sin; | |
30 { | |
31 struct call *call; | |
32 struct sip_msg_out resp; | |
33 char *rack, *orig_method, *cp; | |
34 unsigned rseq, orig_num; | |
35 int rc; | |
36 | |
37 call = find_call_by_sip_id(ess->call_id); | |
38 if (!call) { | |
39 start_response_out_msg(&resp, "481 Call-ID not found"); | |
40 error_resp: rc = add_resp_basic_headers(&resp, ess, req->req_method); | |
41 if (rc < 0) | |
42 return; | |
43 out_msg_finish(&resp); | |
44 sip_tx_packet(&resp, sin); | |
45 return; | |
46 } | |
47 rack = get_single_header(req, "RAck", (char *) 0, (int *) 0); | |
48 if (!rack) { | |
49 start_response_out_msg(&resp, "400 Missing RAck header"); | |
50 goto error_resp; | |
51 } | |
52 if (!isdigit(*rack)) { | |
53 malformed: start_response_out_msg(&resp, "400 Malformed RAck header"); | |
54 goto error_resp; | |
55 } | |
56 rseq = strtoul(rack, &cp, 10); | |
57 if (!isspace(*cp)) | |
58 goto malformed; | |
59 while (isspace(*cp)) | |
60 cp++; | |
61 if (!isdigit(*cp)) | |
62 goto malformed; | |
63 orig_num = strtoul(cp, &cp, 10); | |
64 if (!isspace(*cp)) | |
65 goto malformed; | |
66 while (isspace(*cp)) | |
67 cp++; | |
68 if (!isupper(*cp)) | |
69 goto malformed; | |
70 orig_method = cp; | |
71 while (isalnum(*cp)) | |
72 cp++; | |
73 if (*cp) | |
74 goto malformed; | |
75 if (rseq != 1 || orig_num != call->invite_cseq || | |
76 strcmp(orig_method, "INVITE")) { | |
77 start_response_out_msg(&resp, | |
78 "481 RAck fails to match our 100rel response"); | |
79 goto error_resp; | |
80 } | |
81 switch (call->sip_state) { | |
82 case SIP_STATE_RINGING_REL: | |
83 call->sip_state = SIP_STATE_RINGING; | |
84 start_response_out_msg(&resp, "200 OK"); | |
85 rc = add_resp_basic_headers(&resp, ess, req->req_method); | |
86 if (rc < 0) { | |
87 syslog(LOG_ERR, "PRACK 200 response length exceeded"); | |
88 call->sip_state = SIP_STATE_MSG_SIZE_ERR; | |
89 call->overall_state = OVERALL_STATE_TEARDOWN; | |
90 disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU, | |
91 GSM48_CC_CAUSE_INTERWORKING); | |
92 disconnect_tmgw(call); | |
93 /* TODO: transition from TEARDOWN to DEAD_SIP */ | |
94 return; | |
95 } | |
96 out_msg_finish(&resp); | |
97 sip_tx_packet(&resp, sin); | |
98 return; | |
99 case SIP_STATE_RINGING: | |
100 case SIP_STATE_INVITE_200: | |
101 start_response_out_msg(&resp, "200 OK"); | |
102 rc = add_resp_basic_headers(&resp, ess, req->req_method); | |
103 if (rc < 0) | |
104 return; | |
105 out_msg_finish(&resp); | |
106 sip_tx_packet(&resp, sin); | |
107 return; | |
108 case SIP_STATE_INVITE_PROC: | |
109 case SIP_STATE_CONNECTED: | |
110 case SIP_STATE_BYE_SENT: | |
111 case SIP_STATE_INVITE_ERR: | |
112 case SIP_STATE_ENDED: | |
113 start_response_out_msg(&resp, | |
114 "481 No outstanding 100rel response"); | |
115 goto error_resp; | |
116 } | |
117 } |