comparison sip-out/mncc_sig_in.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/mncc_handle.c@99fd4ae573ae
children
comparison
equal deleted inserted replaced
153:99fd4ae573ae 154:e54b0a9e322f
1 /*
2 * In this module we implement our handling of call control messages
3 * from OsmoMSC relayed to us via themwi-mncc.
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/mncc.h"
17 #include "../include/gsm48_const.h"
18 #include "../include/out_routes.h"
19 #include "call.h"
20
21 extern struct call *find_call_by_mncc_callref();
22
23 static void
24 handle_disconnect_ind(call, msg)
25 struct call *call;
26 struct gsm_mncc *msg;
27 {
28 /* release back to MNCC */
29 msg->msg_type = MNCC_REL_REQ;
30 send_mncc_to_sock(call->mncc, msg, sizeof(struct gsm_mncc));
31 call->mncc_state = MNCC_STATE_RELEASE;
32 /* signal disconnect to SIP */
33 call->overall_state = OVERALL_STATE_TEARDOWN;
34 disconnect_sip(call);
35 disconnect_tmgw(call);
36 }
37
38 static void
39 handle_final_release(call, msg)
40 struct call *call;
41 struct gsm_mncc *msg;
42 {
43 /* MNCC call leg is gone */
44 call->mncc = 0;
45 /* signal disconnect to SIP */
46 call->overall_state = OVERALL_STATE_TEARDOWN;
47 disconnect_sip(call);
48 disconnect_tmgw(call);
49 check_dead_call(call);
50 }
51
52 static void
53 handle_dtmf_start(call, msg)
54 struct call *call;
55 struct gsm_mncc *msg;
56 {
57 if (!(msg->fields & MNCC_F_KEYPAD) ||
58 !is_valid_dtmf_digit(msg->keypad)) {
59 msg->msg_type = MNCC_START_DTMF_REJ;
60 mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU,
61 GSM48_CC_CAUSE_INVAL_MAND_INF);
62 send_mncc_to_sock(call->mncc, msg, sizeof(struct gsm_mncc));
63 return;
64 }
65 if (call->mncc_state != MNCC_STATE_CONNECTED ||
66 call->mgw_state != MGW_STATE_COMPLETE) {
67 msg->msg_type = MNCC_START_DTMF_REJ;
68 mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU,
69 GSM48_CC_CAUSE_MSGTYPE_INCOMPAT);
70 send_mncc_to_sock(call->mncc, msg, sizeof(struct gsm_mncc));
71 return;
72 }
73 call->dtmf_digit = msg->keypad;
74 tmgw_send_dtmf_start(call);
75 }
76
77 static void
78 handle_dtmf_stop(call, msg)
79 struct call *call;
80 struct gsm_mncc *msg;
81 {
82 if (call->mncc_state != MNCC_STATE_CONNECTED)
83 return;
84 if (call->mgw_state == MGW_STATE_COMPLETE)
85 tmgw_send_dtmf_stop(call);
86 else if (call->mgw_state == MGW_STATE_DTMF_OP)
87 call->dtmf_pending_stop = 1;
88 else {
89 /* dummy OK response */
90 msg->msg_type = MNCC_STOP_DTMF_RSP;
91 send_mncc_to_sock(call->mncc, msg, sizeof(struct gsm_mncc));
92 }
93 }
94
95 static void
96 handle_call_hold(call, msg)
97 struct call *call;
98 struct gsm_mncc *msg;
99 {
100 if (call->mncc_state != MNCC_STATE_CONNECTED ||
101 call->mgw_state != MGW_STATE_COMPLETE) {
102 msg->msg_type = MNCC_HOLD_REJ;
103 mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU,
104 GSM48_CC_CAUSE_MSGTYPE_INCOMPAT);
105 send_mncc_to_sock(call->mncc, msg, sizeof(struct gsm_mncc));
106 return;
107 }
108 tmgw_send_mdcx_hold(call);
109 }
110
111 static void
112 handle_call_retrieve(call, msg)
113 struct call *call;
114 struct gsm_mncc *msg;
115 {
116 if (call->mncc_state != MNCC_STATE_CONNECTED ||
117 call->mgw_state != MGW_STATE_HELD) {
118 msg->msg_type = MNCC_RETRIEVE_REJ;
119 mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU,
120 GSM48_CC_CAUSE_MSGTYPE_INCOMPAT);
121 send_mncc_to_sock(call->mncc, msg, sizeof(struct gsm_mncc));
122 return;
123 }
124 send_rtp_connect(call);
125 tmgw_send_mdcx_retrieve(call);
126 }
127
128 void
129 handle_mncc_signal(mncc, msg, msglen)
130 struct mncc_conn *mncc;
131 struct gsm_mncc *msg;
132 unsigned msglen;
133 {
134 struct call *call;
135
136 if (msglen != sizeof(struct gsm_mncc)) {
137 syslog(LOG_CRIT,
138 "FATAL: Rx MNCC message type 0x%x has wrong length",
139 msg->msg_type);
140 exit(1);
141 }
142 call = find_call_by_mncc_callref(mncc, msg->callref);
143 if (!call) {
144 syslog(LOG_CRIT,
145 "error: Rx MNCC message type 0x%x has invalid callref 0x%x",
146 msg->msg_type, msg->callref);
147 exit(1);
148 }
149 switch (msg->msg_type) {
150 case MNCC_DISC_IND:
151 handle_disconnect_ind(call, msg);
152 return;
153 case MNCC_REL_IND:
154 case MNCC_REL_CNF:
155 handle_final_release(call, msg);
156 return;
157 case MNCC_START_DTMF_IND:
158 handle_dtmf_start(call, msg);
159 return;
160 case MNCC_STOP_DTMF_IND:
161 handle_dtmf_stop(call, msg);
162 return;
163 case MNCC_MODIFY_IND:
164 msg->msg_type = MNCC_MODIFY_REJ;
165 mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU,
166 GSM48_CC_CAUSE_SERV_OPT_UNIMPL);
167 send_mncc_to_sock(mncc, msg, sizeof(struct gsm_mncc));
168 return;
169 case MNCC_HOLD_IND:
170 handle_call_hold(call, msg);
171 return;
172 case MNCC_RETRIEVE_IND:
173 handle_call_retrieve(call, msg);
174 return;
175 }
176 }
177
178 void
179 handle_rtp_create(mncc, msg, msglen)
180 struct mncc_conn *mncc;
181 struct gsm_mncc_rtp *msg;
182 unsigned msglen;
183 {
184 struct call *call;
185
186 if (msglen != sizeof(struct gsm_mncc_rtp)) {
187 syslog(LOG_CRIT,
188 "FATAL: Rx MNCC message type 0x%x has wrong length",
189 msg->msg_type);
190 exit(1);
191 }
192 call = find_call_by_mncc_callref(mncc, msg->callref);
193 if (!call) {
194 syslog(LOG_CRIT,
195 "error: Rx MNCC message type 0x%x has invalid callref 0x%x",
196 msg->msg_type, msg->callref);
197 exit(1);
198 }
199 /* we need to be in the right state */
200 if (call->mncc_state != MNCC_STATE_MO_PROC) {
201 syslog(LOG_ERR,
202 "duplicate MNCC_RTP_CREATE for MO callref 0x%x, ignoring",
203 msg->callref);
204 return;
205 }
206 /* save Osmocom network RTP information */
207 bcopy(&msg->addr, &call->gsm_rtp_osmo, sizeof(struct sockaddr_storage));
208 call->gsm_payload_type = msg->payload_type;
209 call->gsm_payload_msg_type = msg->payload_msg_type;
210 /* move forward */
211 call->mncc_state = MNCC_STATE_GOT_RTP;
212 call->overall_state = OVERALL_STATE_CRCX;
213 tmgw_send_crcx(call);
214 }