comparison mncc/intswitch.c @ 15:ccc5ab6d8388

first version of themwi-mncc for ThemWi2
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 26 Jun 2022 16:31:47 -0800
parents
children 52e801b5ebb1
comparison
equal deleted inserted replaced
14:aea422af79dd 15:ccc5ab6d8388
1 /*
2 * In this module we implement internally switched calls,
3 * going from one GSM subscriber to another.
4 */
5
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <stdio.h>
9 #include <stdint.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <strings.h>
13 #include <syslog.h>
14 #include "../include/mncc.h"
15 #include "../include/gsm48_const.h"
16 #include "struct.h"
17 #include "gsm_call.h"
18
19 void
20 internal_switch_mo_setup(call, msg)
21 struct gsm_call *call;
22 struct gsm_mncc *msg;
23 {
24 struct gsm_call *mt;
25 struct gsm_mncc callproc;
26
27 if (!(msg->fields & MNCC_F_BEARER_CAP)) {
28 reject_mo_call(msg->callref, GSM48_CAUSE_LOC_PRN_S_LU,
29 GSM48_CC_CAUSE_INVAL_MAND_INF);
30 call->gc_flag = 1;
31 return;
32 }
33 /* same speech-only restriction as in OsmoMSC's mncc_builtin */
34 if (msg->bearer_cap.transfer != GSM48_BCAP_ITCAP_SPEECH ||
35 msg->bearer_cap.mode != GSM48_BCAP_TMOD_CIRCUIT) {
36 reject_mo_call(msg->callref, GSM48_CAUSE_LOC_PRN_S_LU,
37 GSM48_CC_CAUSE_BEARER_CA_UNAVAIL);
38 call->gc_flag = 1;
39 return;
40 }
41 mt = create_new_mt_call();
42 if (!mt) {
43 reject_mo_call(msg->callref, GSM48_CAUSE_LOC_PRN_S_LU,
44 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
45 call->gc_flag = 1;
46 return;
47 }
48 call->other_leg = mt;
49 mt->other_leg = call;
50 /* send call proceeding */
51 bzero(&callproc, sizeof(struct gsm_mncc));
52 callproc.msg_type = MNCC_CALL_PROC_REQ;
53 callproc.callref = call->callref;
54 send_mncc_to_gsm(&callproc, sizeof(struct gsm_mncc));
55 /* turn MNCC_SETUP_IND into MNCC_SETUP_REQ for MT */
56 msg->msg_type = MNCC_SETUP_REQ;
57 msg->callref = mt->callref;
58 msg->imsi[0] = '\0';
59 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
60 }
61
62 static void
63 handle_setup_cnf(call, msg)
64 struct gsm_call *call;
65 struct gsm_mncc *msg;
66 {
67 struct gsm_mncc ack;
68 struct gsm_mncc_bridge bridge;
69
70 /* acknowledge connect */
71 bzero(&ack, sizeof(struct gsm_mncc));
72 ack.msg_type = MNCC_SETUP_COMPL_REQ;
73 ack.callref = call->callref;
74 send_mncc_to_gsm(&ack, sizeof(struct gsm_mncc));
75 /* do we have the far end? */
76 if (!call->other_leg)
77 return;
78 msg->msg_type = MNCC_SETUP_RSP;
79 msg->callref = call->other_leg->callref;
80 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
81 /* bridge TCH */
82 bzero(&bridge, sizeof(struct gsm_mncc_bridge));
83 bridge.msg_type = MNCC_BRIDGE;
84 bridge.callref[0] = call->callref;
85 bridge.callref[1] = call->other_leg->callref;
86 send_mncc_to_gsm(&bridge, sizeof(struct gsm_mncc_bridge));
87 }
88
89 static void
90 forward_to_remote(call, msg, new_msg_type)
91 struct gsm_call *call;
92 struct gsm_mncc *msg;
93 uint32_t new_msg_type;
94 {
95 if (!call->other_leg) {
96 /* drop it like OsmoMSC's mncc_builtin does */
97 return;
98 }
99 msg->msg_type = new_msg_type;
100 msg->callref = call->other_leg->callref;
101 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
102 }
103
104 static void
105 handle_disconnect(call, msg)
106 struct gsm_call *call;
107 struct gsm_mncc *msg;
108 {
109 struct gsm_call *remote;
110
111 /* release on near end */
112 msg->msg_type = MNCC_REL_REQ;
113 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
114 /* disconnect on far end */
115 remote = call->other_leg;
116 if (!remote)
117 return;
118 msg->msg_type = MNCC_DISC_REQ;
119 msg->callref = remote->callref;
120 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
121 /* sever the end-to-end association */
122 call->other_leg = 0;
123 remote->other_leg = 0;
124 }
125
126 static void
127 handle_release(call, msg)
128 struct gsm_call *call;
129 struct gsm_mncc *msg;
130 {
131 struct gsm_call *remote;
132
133 /* do we have a far end? */
134 remote = call->other_leg;
135 /* free the near end */
136 call->gc_flag = 1;
137 /* if no remote, nothing more to do */
138 if (!remote)
139 return;
140 /* send them a release request */
141 msg->msg_type = MNCC_REL_REQ;
142 msg->callref = remote->callref;
143 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
144 /* sever the end-to-end association */
145 remote->other_leg = 0;
146 }
147
148 void
149 internal_switch_mncc(call, msg)
150 struct gsm_call *call;
151 struct gsm_mncc *msg;
152 {
153 switch (msg->msg_type) {
154 case MNCC_SETUP_CNF:
155 handle_setup_cnf(call, msg);
156 return;
157 case MNCC_ALERT_IND:
158 forward_to_remote(call, msg, MNCC_ALERT_REQ);
159 return;
160 case MNCC_NOTIFY_IND:
161 forward_to_remote(call, msg, MNCC_NOTIFY_REQ);
162 return;
163 case MNCC_USERINFO_IND:
164 forward_to_remote(call, msg, MNCC_USERINFO_REQ);
165 return;
166 case MNCC_DISC_IND:
167 handle_disconnect(call, msg);
168 return;
169 case MNCC_START_DTMF_IND:
170 msg->msg_type = MNCC_START_DTMF_REJ;
171 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
172 return;
173 case MNCC_STOP_DTMF_IND:
174 msg->msg_type = MNCC_STOP_DTMF_RSP;
175 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
176 return;
177 case MNCC_MODIFY_IND:
178 msg->msg_type = MNCC_MODIFY_REJ;
179 mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU,
180 GSM48_CC_CAUSE_SERV_OPT_UNIMPL);
181 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
182 return;
183 case MNCC_HOLD_IND:
184 msg->msg_type = MNCC_HOLD_REJ;
185 mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU,
186 GSM48_CC_CAUSE_SERV_OPT_UNIMPL);
187 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
188 return;
189 case MNCC_RETRIEVE_IND:
190 msg->msg_type = MNCC_RETRIEVE_REJ;
191 mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU,
192 GSM48_CC_CAUSE_SERV_OPT_UNIMPL);
193 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
194 return;
195 case MNCC_SETUP_COMPL_IND:
196 case MNCC_CALL_CONF_IND:
197 /* no handling needed */
198 return;
199 case MNCC_REL_IND:
200 case MNCC_REJ_IND:
201 handle_release(call, msg);
202 return;
203 case MNCC_REL_CNF:
204 call->gc_flag = 1;
205 return;
206 default:
207 syslog(LOG_ERR,
208 "MNCC message type 0x%x unhandled for internal switch",
209 msg->msg_type);
210 }
211 }