comparison sip-in/mgw_resp.c @ 151:0ecbc3dc8f93

sip-in: split mgw_resp.c from mgw_ops.c
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 11 Oct 2022 15:58:42 -0800
parents sip-in/mgw_ops.c@e499e8db8b82
children 7176dc850d7a
comparison
equal deleted inserted replaced
150:529906fddcfa 151:0ecbc3dc8f93
1 /*
2 * In this module we implement our handling of all responses
3 * from themwi-mgw.
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/mncc.h"
18 #include "../include/tmgw_ctrl.h"
19 #include "../include/tmgw_const.h"
20 #include "call.h"
21
22 extern struct call *find_call_with_mgw_xact();
23
24 static void
25 handle_crcx_fail(call, msg)
26 struct call *call;
27 struct tmgw_ctrl_resp *msg;
28 {
29 call->overall_state = OVERALL_STATE_TEARDOWN;
30 strcpy(call->invite_fail, "503 Gateway resource allocation failure");
31 signal_invite_error(call);
32 }
33
34 static void
35 crcx_response(call, msg)
36 struct call *call;
37 struct tmgw_ctrl_resp *msg;
38 {
39 if (msg->res == TMGW_RESP_OK) {
40 call->mgw_state = MGW_STATE_ALLOCATED;
41 call->mgw_ep_id = msg->ep_id;
42 bcopy(&msg->gsm_addr, &call->gsm_rtp_tmgw,
43 sizeof(struct sockaddr_storage));
44 bcopy(&msg->pstn_addr, &call->pstn_rtp_local,
45 sizeof(struct sockaddr_in));
46 switch (call->overall_state) {
47 case OVERALL_STATE_CRCX:
48 proceed_with_call_setup(call);
49 return;
50 case OVERALL_STATE_TEARDOWN:
51 tmgw_send_dlcx(call);
52 return;
53 default:
54 bad_state:
55 syslog(LOG_CRIT,
56 "FATAL: invalid overall state 0x%x on CRCX response",
57 call->overall_state);
58 exit(1);
59 }
60 } else {
61 switch (call->overall_state) {
62 case OVERALL_STATE_CRCX:
63 handle_crcx_fail(call, msg);
64 return;
65 case OVERALL_STATE_TEARDOWN:
66 transition_dead_sip(call);
67 return;
68 default:
69 goto bad_state;
70 }
71 }
72 }
73
74 static void
75 handle_mdcx_connect_fail(call, msg)
76 struct call *call;
77 struct tmgw_ctrl_resp *msg;
78 {
79 call->overall_state = OVERALL_STATE_TEARDOWN;
80 switch (msg->res) {
81 case TMGW_RESP_ERR_RSRC:
82 disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU,
83 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
84 strcpy(call->invite_fail,
85 "503 Gateway resource allocation failure");
86 break;
87 case TMGW_RESP_ERR_NOTSUP:
88 disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU,
89 GSM48_CC_CAUSE_BEARER_CA_UNAVAIL);
90 strcpy(call->invite_fail, "502 Gateway internal error");
91 break;
92 default:
93 disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU,
94 GSM48_CC_CAUSE_PROTO_ERR);
95 strcpy(call->invite_fail, "502 Gateway internal error");
96 }
97 signal_invite_error(call);
98 }
99
100 static void
101 mdcx_connect_response(call, msg)
102 struct call *call;
103 struct tmgw_ctrl_resp *msg;
104 {
105 if (msg->res == TMGW_RESP_OK) {
106 call->mgw_state = MGW_STATE_COMPLETE;
107 switch (call->overall_state) {
108 case OVERALL_STATE_ANSWERED:
109 signal_invite_200(call);
110 return;
111 case OVERALL_STATE_TEARDOWN:
112 tmgw_send_dlcx(call);
113 return;
114 default:
115 bad_state:
116 syslog(LOG_CRIT,
117 "FATAL: invalid overall state 0x%x on MDCX response",
118 call->overall_state);
119 exit(1);
120 }
121 } else {
122 tmgw_send_dlcx(call);
123 switch (call->overall_state) {
124 case OVERALL_STATE_ANSWERED:
125 handle_mdcx_connect_fail(call, msg);
126 return;
127 case OVERALL_STATE_TEARDOWN:
128 return;
129 default:
130 goto bad_state;
131 }
132 }
133 }
134
135 static struct gsm_mncc_cause mgw_hold_retrieve_error = {
136 .coding = GSM48_CAUSE_CODING_GSM,
137 .location = GSM48_CAUSE_LOC_PRN_S_LU,
138 .value = GSM48_CC_CAUSE_NETWORK_OOO,
139 };
140
141 static void
142 mdcx_hold_response(call, msg)
143 struct call *call;
144 struct tmgw_ctrl_resp *msg;
145 {
146 if (call->overall_state == OVERALL_STATE_TEARDOWN) {
147 tmgw_send_dlcx(call);
148 return;
149 }
150 if (msg->res == TMGW_RESP_OK) {
151 call->mgw_state = MGW_STATE_HELD;
152 mncc_send_hold_ack(call);
153 } else {
154 call->overall_state = OVERALL_STATE_TEARDOWN;
155 tmgw_send_dlcx(call);
156 disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU,
157 GSM48_CC_CAUSE_NETWORK_OOO);
158 disconnect_sip(call, &mgw_hold_retrieve_error);
159 }
160 }
161
162 static void
163 mdcx_retrieve_response(call, msg)
164 struct call *call;
165 struct tmgw_ctrl_resp *msg;
166 {
167 if (call->overall_state == OVERALL_STATE_TEARDOWN) {
168 tmgw_send_dlcx(call);
169 return;
170 }
171 if (msg->res == TMGW_RESP_OK) {
172 call->mgw_state = MGW_STATE_COMPLETE;
173 mncc_send_retrieve_ack(call);
174 } else {
175 call->overall_state = OVERALL_STATE_TEARDOWN;
176 tmgw_send_dlcx(call);
177 disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU,
178 GSM48_CC_CAUSE_NETWORK_OOO);
179 disconnect_sip(call, &mgw_hold_retrieve_error);
180 }
181 }
182
183 static void
184 mdcx_response(call, msg)
185 struct call *call;
186 struct tmgw_ctrl_resp *msg;
187 {
188 switch (call->mgw_state) {
189 case MGW_STATE_CONNECTING:
190 mdcx_connect_response(call, msg);
191 return;
192 case MGW_STATE_HOLD_OP:
193 mdcx_hold_response(call, msg);
194 return;
195 case MGW_STATE_RETRIEVE_OP:
196 mdcx_retrieve_response(call, msg);
197 return;
198 default:
199 syslog(LOG_CRIT,
200 "FATAL: invalid MGW state 0x%x on MDCX response",
201 call->mgw_state);
202 exit(1);
203 }
204 }
205
206 static void
207 dlcx_response(call, msg)
208 struct call *call;
209 struct tmgw_ctrl_resp *msg;
210 {
211 if (msg->res != TMGW_RESP_OK) {
212 syslog(LOG_CRIT, "FATAL: TMGW DLCX failed with code 0x%x",
213 msg->res);
214 exit(1);
215 }
216 call->mgw_state = MGW_STATE_NO_EXIST;
217 transition_dead_sip(call);
218 }
219
220 static void
221 dtmf_start_response(call, msg)
222 struct call *call;
223 struct tmgw_ctrl_resp *msg;
224 {
225 if (call->overall_state == OVERALL_STATE_TEARDOWN) {
226 tmgw_send_dlcx(call);
227 return;
228 }
229 if (msg->res == TMGW_RESP_OK)
230 mncc_dtmf_start_ok(call);
231 else
232 mncc_dtmf_start_err(call);
233 if (call->dtmf_pending_stop)
234 tmgw_send_dtmf_stop(call);
235 else
236 call->mgw_state = MGW_STATE_COMPLETE;
237 }
238
239 static void
240 dtmf_stop_response(call, msg)
241 struct call *call;
242 struct tmgw_ctrl_resp *msg;
243 {
244 if (call->overall_state == OVERALL_STATE_TEARDOWN) {
245 tmgw_send_dlcx(call);
246 return;
247 }
248 mncc_dtmf_stop_ok(call);
249 call->mgw_state = MGW_STATE_COMPLETE;
250 call->dtmf_pending_stop = 0;
251 }
252
253 void
254 process_tmgw_response(msg)
255 struct tmgw_ctrl_resp *msg;
256 {
257 struct call *call;
258 unsigned opc;
259
260 call = find_call_with_mgw_xact(msg->transact_ref);
261 if (!call) {
262 syslog(LOG_CRIT,
263 "FATAL: response from TMGW xact 0x%x does not match any call",
264 msg->transact_ref);
265 exit(1);
266 }
267 opc = call->mgw_xact;
268 call->mgw_xact = 0;
269 switch (opc) {
270 case TMGW_CTRL_OP_CRCX:
271 crcx_response(call, msg);
272 return;
273 case TMGW_CTRL_OP_MDCX:
274 mdcx_response(call, msg);
275 return;
276 case TMGW_CTRL_OP_DLCX:
277 dlcx_response(call, msg);
278 return;
279 case TMGW_CTRL_OP_DTMF_START:
280 dtmf_start_response(call, msg);
281 return;
282 case TMGW_CTRL_OP_DTMF_STOP:
283 dtmf_stop_response(call, msg);
284 return;
285 default:
286 syslog(LOG_CRIT,
287 "FATAL: invalid opcode 0x%x in call->msg_xact", opc);
288 exit(1);
289 }
290 }