FreeCalypso > hg > themwi-system-sw
comparison sip-out/uac_out.c @ 154:e54b0a9e322f
beginning of themwi-sip-out
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 11 Oct 2022 23:04:01 -0800 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
153:99fd4ae573ae | 154:e54b0a9e322f |
---|---|
1 /* | |
2 * In this module we implement generation of outgoing SIP messages | |
3 * in the UAC role. | |
4 */ | |
5 | |
6 #include <sys/types.h> | |
7 #include <sys/socket.h> | |
8 #include <sys/time.h> | |
9 #include <netinet/in.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 "../include/out_routes.h" | |
18 #include "../libsip/out_msg.h" | |
19 #include "../libsip/sdp.h" | |
20 #include "call.h" | |
21 | |
22 extern struct call *find_call_by_sip_id(); | |
23 | |
24 extern struct in_addr sip_bind_ip; | |
25 extern unsigned sip_bind_port; | |
26 extern unsigned max_forwards; | |
27 extern struct timeval cur_event_time; | |
28 | |
29 add_req_boilerplate(msg, call, cseq, to_tag) | |
30 struct sip_msg_out *msg; | |
31 struct call *call; | |
32 char *cseq, *to_tag; | |
33 { | |
34 char strbuf[256]; | |
35 int rc; | |
36 | |
37 sprintf(strbuf, "SIP/2.0/UDP %s:%u", | |
38 inet_ntoa(sip_bind_ip), sip_bind_port); | |
39 rc = out_msg_add_header(msg, "Via", strbuf); | |
40 if (rc < 0) | |
41 return rc; | |
42 rc = out_msg_add_header(msg, "From", call->from_header); | |
43 if (rc < 0) | |
44 return rc; | |
45 if (to_tag && to_tag[0]) { | |
46 sprintf(strbuf, "<%s>;tag=%s", call->to_uri, to_tag); | |
47 rc = out_msg_add_header(msg, "To", strbuf); | |
48 } else | |
49 rc = out_msg_add_header(msg, "To", call->to_uri); | |
50 if (rc < 0) | |
51 return rc; | |
52 rc = out_msg_add_header(msg, "Call-ID", call->sip_call_id); | |
53 if (rc < 0) | |
54 return rc; | |
55 rc = out_msg_add_header(msg, "CSeq", cseq); | |
56 if (rc < 0) | |
57 return rc; | |
58 sprintf(strbuf, "%u", max_forwards); | |
59 return out_msg_add_header(msg, "Max-Forwards", strbuf); | |
60 } | |
61 | |
62 add_contact_header(msg) | |
63 struct sip_msg_out *msg; | |
64 { | |
65 char strbuf[80]; | |
66 | |
67 sprintf(strbuf, "<sip:%s:%u;transport=udp>", | |
68 inet_ntoa(sip_bind_ip), sip_bind_port); | |
69 return out_msg_add_header(msg, "Contact", strbuf); | |
70 } | |
71 | |
72 fill_invite_req_msg(msg, call) | |
73 struct sip_msg_out *msg; | |
74 struct call *call; | |
75 { | |
76 struct sdp_gen sdp; | |
77 int rc; | |
78 | |
79 rc = start_request_out_msg(msg, "INVITE", call->to_uri); | |
80 if (rc < 0) | |
81 return rc; | |
82 rc = add_req_boilerplate(msg, call, "1 INVITE", (char *) 0); | |
83 if (rc < 0) | |
84 return rc; | |
85 rc = add_contact_header(msg); | |
86 if (rc < 0) | |
87 return rc; | |
88 rc = out_msg_add_header(msg, "Content-Type", "application/sdp"); | |
89 if (rc < 0) | |
90 return rc; | |
91 bzero(&sdp, sizeof sdp); | |
92 sdp.conn_ip = call->pstn_rtp_local.sin_addr; | |
93 sdp.conn_port = ntohs(call->pstn_rtp_local.sin_port); | |
94 sdp.codec_mask = SDP_CODEC_MASK_BOTH; | |
95 sdp.session_id = sdp.conn_port << 16; | |
96 sdp.owner_ip = sip_bind_ip; | |
97 return out_msg_finish_sdp(msg, &sdp); | |
98 } | |
99 | |
100 fill_cancel_req_msg(msg, call) | |
101 struct sip_msg_out *msg; | |
102 struct call *call; | |
103 { | |
104 int rc; | |
105 | |
106 rc = start_request_out_msg(msg, "CANCEL", call->to_uri); | |
107 if (rc < 0) | |
108 return rc; | |
109 rc = add_req_boilerplate(msg, call, "1 CANCEL", (char *) 0); | |
110 if (rc < 0) | |
111 return rc; | |
112 out_msg_finish(msg); | |
113 return 0; | |
114 } | |
115 | |
116 fill_bye_req_msg(msg, call) | |
117 struct sip_msg_out *msg; | |
118 struct call *call; | |
119 { | |
120 int rc; | |
121 | |
122 rc = start_request_out_msg(msg, "BYE", call->to_uri); | |
123 if (rc < 0) | |
124 return rc; | |
125 rc = add_req_boilerplate(msg, call, "2 BYE", call->to_tag); | |
126 if (rc < 0) | |
127 return rc; | |
128 out_msg_finish(msg); | |
129 return 0; | |
130 } | |
131 | |
132 void | |
133 start_sip_out(call) | |
134 struct call *call; | |
135 { | |
136 struct sip_msg_out msg; | |
137 int rc; | |
138 | |
139 sprintf(call->sip_call_id, "%08u_%u@%s", | |
140 (unsigned)(cur_event_time.tv_sec % 100000000), | |
141 ntohs(call->pstn_rtp_local.sin_port), inet_ntoa(sip_bind_ip)); | |
142 if (find_call_by_sip_id(call->sip_call_id)) { | |
143 syslog(LOG_ERR, "generated Call-ID collision!"); | |
144 call->overall_state = OVERALL_STATE_TEARDOWN; | |
145 disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU, | |
146 GSM48_CC_CAUSE_SWITCH_CONG); | |
147 disconnect_tmgw(call); | |
148 return; | |
149 } | |
150 sprintf(call->from_header, "<sip:%s@%s>;tag=out%u", call->from_user, | |
151 inet_ntoa(sip_bind_ip), ntohs(call->pstn_rtp_local.sin_port)); | |
152 rc = fill_invite_req_msg(&msg, call); | |
153 if (rc < 0) { | |
154 syslog(LOG_CRIT, "generated SIP INVITE req exceeds msg size!"); | |
155 call->overall_state = OVERALL_STATE_TEARDOWN; | |
156 disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU, | |
157 GSM48_CC_CAUSE_NETWORK_OOO); | |
158 disconnect_tmgw(call); | |
159 return; | |
160 } | |
161 sip_tx_packet(&msg, &call->udp_sin); | |
162 call->overall_state = OVERALL_STATE_SIP_OUT; | |
163 call->sip_call_exists = 1; | |
164 call->sip_state = SIP_STATE_INV_SENT; | |
165 call->sip_tx_count = 1; | |
166 } | |
167 | |
168 void | |
169 initiate_sip_cancel(call) | |
170 struct call *call; | |
171 { | |
172 struct sip_msg_out msg; | |
173 | |
174 fill_cancel_req_msg(&msg, call); | |
175 sip_tx_packet(&msg, &call->udp_sin); | |
176 call->sip_state = SIP_STATE_CANCEL_SENT; | |
177 call->sip_tx_count = 1; | |
178 } | |
179 | |
180 void | |
181 initiate_bye(call) | |
182 struct call *call; | |
183 { | |
184 struct sip_msg_out msg; | |
185 | |
186 fill_bye_req_msg(&msg, call); | |
187 sip_tx_packet(&msg, &call->udp_sin); | |
188 call->sip_state = SIP_STATE_BYE_SENT; | |
189 call->sip_tx_count = 1; | |
190 } |