comparison sip-out/mgw_resp.c @ 154:e54b0a9e322f

beginning of themwi-sip-out
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 11 Oct 2022 23:04:01 -0800
parents sip-in/mgw_ops.c@0ecbc3dc8f93
children
comparison
equal deleted inserted replaced
153:99fd4ae573ae 154:e54b0a9e322f
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/tmgw_ctrl.h"
18 #include "../include/tmgw_const.h"
19 #include "../include/out_routes.h"
20 #include "call.h"
21
22 extern struct call *find_call_with_mgw_xact();
23
24 static void
25 crcx_response(call, msg)
26 struct call *call;
27 struct tmgw_ctrl_resp *msg;
28 {
29 int cause;
30
31 if (msg->res == TMGW_RESP_OK) {
32 call->mgw_state = MGW_STATE_ALLOCATED;
33 call->mgw_ep_id = msg->ep_id;
34 bcopy(&msg->gsm_addr, &call->gsm_rtp_tmgw,
35 sizeof(struct sockaddr_storage));
36 bcopy(&msg->pstn_addr, &call->pstn_rtp_local,
37 sizeof(struct sockaddr_in));
38 switch (call->overall_state) {
39 case OVERALL_STATE_CRCX:
40 send_rtp_connect(call);
41 start_sip_out(call);
42 return;
43 case OVERALL_STATE_TEARDOWN:
44 tmgw_send_dlcx(call);
45 return;
46 default:
47 bad_state:
48 syslog(LOG_CRIT,
49 "FATAL: invalid overall state 0x%x on CRCX response",
50 call->overall_state);
51 exit(1);
52 }
53 } else {
54 switch (call->overall_state) {
55 case OVERALL_STATE_CRCX:
56 call->overall_state = OVERALL_STATE_TEARDOWN;
57 switch (msg->res) {
58 case TMGW_RESP_ERR_RSRC:
59 cause = GSM48_CC_CAUSE_RESOURCE_UNAVAIL;
60 break;
61 case TMGW_RESP_ERR_NOTSUP:
62 cause = GSM48_CC_CAUSE_BEARER_CA_UNAVAIL;
63 break;
64 default:
65 cause = GSM48_CC_CAUSE_PROTO_ERR;
66 }
67 disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU, cause);
68 return;
69 case OVERALL_STATE_TEARDOWN:
70 check_dead_call(call);
71 return;
72 default:
73 goto bad_state;
74 }
75 }
76 }
77
78 static void
79 mdcx_response(call, msg)
80 struct call *call;
81 struct tmgw_ctrl_resp *msg;
82 {
83 if (call->overall_state == OVERALL_STATE_TEARDOWN) {
84 tmgw_send_dlcx(call);
85 return;
86 }
87 if (msg->res != TMGW_RESP_OK) {
88 call->overall_state = OVERALL_STATE_TEARDOWN;
89 tmgw_send_dlcx(call);
90 if (msg->res == TMGW_RESP_ERR_RSRC &&
91 (call->mgw_state == MGW_STATE_MDCX_IBT ||
92 call->mgw_state == MGW_STATE_MDCX_CONN))
93 disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU,
94 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
95 else
96 disconnect_mncc(call, GSM48_CAUSE_LOC_PRN_S_LU,
97 GSM48_CC_CAUSE_NETWORK_OOO);
98 disconnect_sip(call);
99 return;
100 }
101 switch (call->mgw_state) {
102 case MGW_STATE_MDCX_IBT:
103 call->mgw_state = MGW_STATE_IBT_CONN;
104 mncc_signal_ibt_ring(call);
105 if (call->sip_state == SIP_STATE_CONNECTED)
106 tmgw_send_mdcx_connect(call, 0);
107 return;
108 case MGW_STATE_MDCX_CONN:
109 call->mgw_state = MGW_STATE_COMPLETE;
110 mncc_signal_answer_sup(call);
111 return;
112 case MGW_STATE_MDCX_HOLD:
113 call->mgw_state = MGW_STATE_HELD;
114 mncc_send_hold_ack(call);
115 return;
116 case MGW_STATE_MDCX_RETR:
117 call->mgw_state = MGW_STATE_COMPLETE;
118 mncc_send_retrieve_ack(call);
119 return;
120 default:
121 syslog(LOG_CRIT,
122 "FATAL: invalid MGW state 0x%x on MDCX response",
123 call->mgw_state);
124 exit(1);
125 }
126 }
127
128 static void
129 dlcx_response(call, msg)
130 struct call *call;
131 struct tmgw_ctrl_resp *msg;
132 {
133 if (msg->res != TMGW_RESP_OK) {
134 syslog(LOG_CRIT, "FATAL: TMGW DLCX failed with code 0x%x",
135 msg->res);
136 exit(1);
137 }
138 call->mgw_state = MGW_STATE_NO_EXIST;
139 check_dead_call(call);
140 }
141
142 static void
143 dtmf_start_response(call, msg)
144 struct call *call;
145 struct tmgw_ctrl_resp *msg;
146 {
147 if (call->overall_state == OVERALL_STATE_TEARDOWN) {
148 tmgw_send_dlcx(call);
149 return;
150 }
151 if (msg->res == TMGW_RESP_OK)
152 mncc_dtmf_start_ok(call);
153 else
154 mncc_dtmf_start_err(call);
155 if (call->dtmf_pending_stop)
156 tmgw_send_dtmf_stop(call);
157 else
158 call->mgw_state = MGW_STATE_COMPLETE;
159 }
160
161 static void
162 dtmf_stop_response(call, msg)
163 struct call *call;
164 struct tmgw_ctrl_resp *msg;
165 {
166 if (call->overall_state == OVERALL_STATE_TEARDOWN) {
167 tmgw_send_dlcx(call);
168 return;
169 }
170 mncc_dtmf_stop_ok(call);
171 call->mgw_state = MGW_STATE_COMPLETE;
172 call->dtmf_pending_stop = 0;
173 }
174
175 void
176 process_tmgw_response(msg)
177 struct tmgw_ctrl_resp *msg;
178 {
179 struct call *call;
180 unsigned opc;
181
182 call = find_call_with_mgw_xact(msg->transact_ref);
183 if (!call) {
184 syslog(LOG_CRIT,
185 "FATAL: response from TMGW xact 0x%x does not match any call",
186 msg->transact_ref);
187 exit(1);
188 }
189 opc = call->mgw_xact;
190 call->mgw_xact = 0;
191 switch (opc) {
192 case TMGW_CTRL_OP_CRCX:
193 crcx_response(call, msg);
194 return;
195 case TMGW_CTRL_OP_MDCX:
196 mdcx_response(call, msg);
197 return;
198 case TMGW_CTRL_OP_DLCX:
199 dlcx_response(call, msg);
200 return;
201 case TMGW_CTRL_OP_DTMF_START:
202 dtmf_start_response(call, msg);
203 return;
204 case TMGW_CTRL_OP_DTMF_STOP:
205 dtmf_stop_response(call, msg);
206 return;
207 default:
208 syslog(LOG_CRIT,
209 "FATAL: invalid opcode 0x%x in call->msg_xact", opc);
210 exit(1);
211 }
212 }