FreeCalypso > hg > themwi-system-sw
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 } |