comparison mncc/call_setup.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 c6572f4c31d2
comparison
equal deleted inserted replaced
14:aea422af79dd 15:ccc5ab6d8388
1 /*
2 * In this module we implement setup of new calls: either new MO calls
3 * coming from GSM or new MT calls coming from a ThemWi call socket.
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 preen_msc_provided_number(nums)
20 struct gsm_mncc_number *nums;
21 {
22 int len;
23
24 len = grok_number_string(nums->number, 0);
25 switch (len) {
26 case 4:
27 nums->type = GSM48_TON_NET_SPEC;
28 nums->plan = GSM48_NPI_PRIVATE;
29 break;
30 case 11:
31 if (nums->number[0] != '1')
32 return(0);
33 nums->type = GSM48_TON_INTERNATIONAL;
34 nums->plan = GSM48_NPI_ISDN_E164;
35 break;
36 default:
37 return(0);
38 }
39 nums->screen = GSM48_SCRN_NETWORK;
40 return(1);
41 }
42
43 void
44 reject_mo_call(callref, cause_loc, cause_val)
45 uint32_t callref;
46 {
47 struct gsm_mncc msg;
48
49 bzero(&msg, sizeof(struct gsm_mncc));
50 msg.msg_type = MNCC_REJ_REQ;
51 msg.callref = callref;
52 mncc_set_cause(&msg, cause_loc, cause_val);
53 send_mncc_to_gsm(&msg, sizeof(struct gsm_mncc));
54 }
55
56 void
57 process_mo_call_setup(msg)
58 struct gsm_mncc *msg;
59 {
60 struct gsm_call *call;
61 char nanp[11];
62 int res, is_nanp, is_itn, is_local;
63
64 if (preen_msc_provided_number(&msg->calling))
65 msg->fields |= MNCC_F_CALLING;
66 else
67 msg->fields &= ~MNCC_F_CALLING;
68 if (!(msg->fields & MNCC_F_CALLED)) {
69 reject_mo_call(msg->callref, GSM48_CAUSE_LOC_PRN_S_LU,
70 GSM48_CC_CAUSE_INVAL_MAND_INF);
71 return;
72 }
73 call = create_gsm_call(msg->callref);
74 if (!call) {
75 reject_mo_call(msg->callref, GSM48_CAUSE_LOC_PRN_S_LU,
76 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
77 return;
78 }
79 /* route based on destination address */
80 refresh_number_db();
81 is_nanp = is_itn = 0;
82 switch (grok_number_string(msg->called.number, 0)) {
83 case 4:
84 if (msg->called.type != GSM48_TON_UNKNOWN &&
85 msg->called.type != GSM48_TON_NET_SPEC &&
86 msg->called.type != GSM48_TON_SHORT_CODE)
87 break;
88 if (msg->called.plan != GSM48_NPI_UNKNOWN &&
89 msg->called.plan != GSM48_NPI_ISDN_E164 &&
90 msg->called.plan != GSM48_NPI_PRIVATE)
91 break;
92 res = lookup_short_dial_number(msg->called.number, nanp);
93 if (!res) {
94 reject_mo_call(msg->callref, GSM48_CAUSE_LOC_PRN_S_LU,
95 GSM48_CC_CAUSE_UNASSIGNED_NR);
96 call->gc_flag = 1;
97 return;
98 }
99 if (nanp[0]) {
100 is_nanp = 1;
101 msg->called.type = GSM48_TON_INTERNATIONAL;
102 msg->called.plan = GSM48_NPI_ISDN_E164;
103 msg->called.number[0] = '1';
104 strcpy(msg->called.number+1, nanp);
105 } else {
106 is_itn = 1;
107 msg->called.type = GSM48_TON_NET_SPEC;
108 msg->called.plan = GSM48_NPI_PRIVATE;
109 }
110 break;
111 case 10:
112 if (msg->called.type != GSM48_TON_UNKNOWN &&
113 msg->called.type != GSM48_TON_NATIONAL)
114 break;
115 if (msg->called.plan != GSM48_NPI_UNKNOWN &&
116 msg->called.plan != GSM48_NPI_ISDN_E164 &&
117 msg->called.plan != GSM48_NPI_NATIONAL)
118 break;
119 if (!is_nanp_valid_prefix(msg->called.number)) {
120 reject_mo_call(msg->callref, GSM48_CAUSE_LOC_PRN_S_LU,
121 GSM48_CC_CAUSE_INV_NR_FORMAT);
122 call->gc_flag = 1;
123 return;
124 }
125 is_nanp = 1;
126 /* canonicalize to international format */
127 bcopy(msg->called.number, msg->called.number+1, 11);
128 msg->called.number[0] = '1';
129 msg->called.type = GSM48_TON_INTERNATIONAL;
130 msg->called.plan = GSM48_NPI_ISDN_E164;
131 break;
132 case 11:
133 if (msg->called.type != GSM48_TON_UNKNOWN &&
134 msg->called.type != GSM48_TON_INTERNATIONAL)
135 break;
136 if (msg->called.plan != GSM48_NPI_UNKNOWN &&
137 msg->called.plan != GSM48_NPI_ISDN_E164)
138 break;
139 if (msg->called.number[0] != '1')
140 break;
141 if (!is_nanp_valid_prefix(msg->called.number+1)) {
142 reject_mo_call(msg->callref, GSM48_CAUSE_LOC_PRN_S_LU,
143 GSM48_CC_CAUSE_INV_NR_FORMAT);
144 call->gc_flag = 1;
145 return;
146 }
147 is_nanp = 1;
148 /* canonicalize to international format */
149 msg->called.type = GSM48_TON_INTERNATIONAL;
150 msg->called.plan = GSM48_NPI_ISDN_E164;
151 break;
152 }
153 is_local = is_itn;
154 if (is_nanp && is_nanp_locally_owned(msg->called.number+1))
155 is_local = 1;
156 /* weed out attempts to call yourself */
157 if (is_local && !strcmp(msg->calling.number, msg->called.number)) {
158 reject_mo_call(msg->callref, GSM48_CAUSE_LOC_PRN_S_LU,
159 GSM48_CC_CAUSE_INCOMPAT_DEST);
160 call->gc_flag = 1;
161 return;
162 }
163 /* actually route the call */
164 if (is_local) {
165 internal_switch_mo_setup(call, msg);
166 return;
167 }
168 /* outbound calls remain to be implemented */
169 reject_mo_call(msg->callref, GSM48_CAUSE_LOC_PRN_S_LU,
170 GSM48_CC_CAUSE_NO_ROUTE);
171 call->gc_flag = 1;
172 }
173
174 static void
175 reject_mt_call(conn, callref, cause_loc, cause_val)
176 struct socket_conn *conn;
177 uint32_t callref;
178 {
179 struct gsm_mncc msg;
180
181 bzero(&msg, sizeof(struct gsm_mncc));
182 msg.msg_type = MNCC_REJ_REQ;
183 msg.callref = callref;
184 mncc_set_cause(&msg, cause_loc, cause_val);
185 mncc_signal_to_socket_nocall(conn, &msg);
186 }
187
188 void
189 process_ext_mtcall_setup(conn, msg)
190 struct socket_conn *conn;
191 struct gsm_mncc *msg;
192 {
193 struct gsm_call *call;
194
195 if (!(msg->fields & MNCC_F_CALLED) && !msg->imsi[0]) {
196 reject_mt_call(conn, msg->callref, GSM48_CAUSE_LOC_PRN_S_LU,
197 GSM48_CC_CAUSE_INVAL_MAND_INF);
198 return;
199 }
200 call = create_new_mt_call();
201 if (!call) {
202 reject_mt_call(conn, msg->callref, GSM48_CAUSE_LOC_PRN_S_LU,
203 GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
204 return;
205 }
206 call->socket = conn;
207 call->socket_ref = msg->callref;
208 /* forward to GSM MNCC interface */
209 msg->callref = call->callref;
210 send_mncc_to_gsm(&msg, sizeof(struct gsm_mncc));
211 }
212
213 preen_connected_number(msg)
214 struct gsm_mncc *msg;
215 {
216 if (preen_msc_provided_number(&msg->connected))
217 msg->fields |= MNCC_F_CONNECTED;
218 else
219 msg->fields &= ~MNCC_F_CONNECTED;
220 }