FreeCalypso > hg > themwi-interim
comparison mncc/extsock.c @ 2:053f04687106
mncc: initial import from old ThemWi
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 08 Jun 2024 23:12:12 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1:b161dbfffdaa | 2:053f04687106 |
---|---|
1 /* | |
2 * In this module we gather functions that deal with external | |
3 * socket connections, both externally-originating MT calls | |
4 * and outbound MO calls. | |
5 */ | |
6 | |
7 #include <sys/types.h> | |
8 #include <sys/socket.h> | |
9 #include <stdio.h> | |
10 #include <stdint.h> | |
11 #include <stdlib.h> | |
12 #include <string.h> | |
13 #include <strings.h> | |
14 #include <syslog.h> | |
15 #include "../include/mncc.h" | |
16 #include "../include/gsm48_const.h" | |
17 #include "struct.h" | |
18 #include "gsm_call.h" | |
19 | |
20 extern char *mncc_msg_name(); | |
21 | |
22 void | |
23 extsock_dec_refcount(conn) | |
24 struct socket_conn *conn; | |
25 { | |
26 if (!conn->ncalls) { | |
27 syslog(LOG_CRIT, "FATAL BUG: ncalls=0 on socket call clearing"); | |
28 exit(1); | |
29 } | |
30 conn->ncalls--; | |
31 } | |
32 | |
33 static void | |
34 send_rel_on_broken_socket(call) | |
35 struct gsm_call *call; | |
36 { | |
37 struct gsm_mncc msg; | |
38 | |
39 bzero(&msg, sizeof(struct gsm_mncc)); | |
40 msg.msg_type = MNCC_REL_REQ; | |
41 msg.callref = call->callref; | |
42 mncc_set_cause(&msg, GSM48_CAUSE_LOC_PRN_S_LU, GSM48_CC_CAUSE_DEST_OOO); | |
43 send_mncc_to_gsm(&msg, sizeof(struct gsm_mncc)); | |
44 } | |
45 | |
46 static void | |
47 broken_socket_clear_calls(conn) | |
48 struct socket_conn *conn; | |
49 { | |
50 extern struct gsm_call *call_list_head; | |
51 struct gsm_call *call; | |
52 | |
53 for (call = call_list_head; call; call = call->next) { | |
54 if (call->gc_flag) | |
55 continue; | |
56 if (call->socket == conn) { | |
57 syslog(LOG_WARNING, | |
58 "clearing broken socket call: GSM callref 0x%x, socket ref 0x%x", | |
59 call->callref, call->socket_ref); | |
60 send_rel_on_broken_socket(call); | |
61 extsock_dec_refcount(conn); | |
62 call->gc_flag = 1; | |
63 } | |
64 } | |
65 if (conn->ncalls) { | |
66 syslog(LOG_CRIT, | |
67 "FATAL BUG: ncalls!=0 after broken socket call clearing"); | |
68 exit(1); | |
69 } | |
70 } | |
71 | |
72 static void | |
73 report_runt(msg) | |
74 union mncc_msg *msg; | |
75 { | |
76 syslog(LOG_CRIT, | |
77 "MNCC message type 0x%x from ThemWi call socket is too short!", | |
78 msg->msg_type); | |
79 } | |
80 | |
81 static void | |
82 handle_setup_req(conn, msg, msglen) | |
83 struct socket_conn *conn; | |
84 struct gsm_mncc *msg; | |
85 unsigned msglen; | |
86 { | |
87 struct gsm_call *call; | |
88 | |
89 if (msglen < sizeof(struct gsm_mncc)) { | |
90 report_runt(msg); | |
91 return; | |
92 } | |
93 syslog(LOG_DEBUG, "Rx MNCC_SETUP_REQ from socket, callref=0x%x", | |
94 msg->callref); | |
95 call = find_socket_call(conn, msg->callref); | |
96 if (call) { | |
97 syslog(LOG_ERR, | |
98 "duplicate MNCC_SETUP_REQ from socket for callref 0x%x", | |
99 msg->callref); | |
100 /* drop it like OsmoMSC's mncc_builtin does */ | |
101 return; | |
102 } | |
103 /* further processing */ | |
104 process_ext_mtcall_setup(conn, msg); | |
105 } | |
106 | |
107 static void | |
108 handle_signaling_msg(conn, msg, msglen) | |
109 struct socket_conn *conn; | |
110 struct gsm_mncc *msg; | |
111 unsigned msglen; | |
112 { | |
113 struct gsm_call *call; | |
114 | |
115 if (msglen < sizeof(struct gsm_mncc)) { | |
116 report_runt(msg); | |
117 return; | |
118 } | |
119 syslog(LOG_DEBUG, "Rx %s from socket, callref=0x%x", | |
120 mncc_msg_name(msg->msg_type), msg->callref); | |
121 call = find_socket_call(conn, msg->callref); | |
122 if (!call) { | |
123 syslog(LOG_ERR, | |
124 "MNCC message from ThemWi call socket: callref 0x%x not found", | |
125 msg->callref); | |
126 /* drop it like OsmoMSC's mncc_builtin does */ | |
127 return; | |
128 } | |
129 /* forward to GSM MNCC interface */ | |
130 msg->callref = call->callref; | |
131 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc)); | |
132 if (msg->msg_type == MNCC_REJ_REQ) { | |
133 extsock_dec_refcount(conn); | |
134 call->gc_flag = 1; | |
135 } | |
136 } | |
137 | |
138 static void | |
139 handle_rtp_msg(conn, msg, msglen) | |
140 struct socket_conn *conn; | |
141 struct gsm_mncc_rtp *msg; | |
142 unsigned msglen; | |
143 { | |
144 struct gsm_call *call; | |
145 | |
146 if (msglen < sizeof(struct gsm_mncc_rtp)) { | |
147 report_runt(msg); | |
148 return; | |
149 } | |
150 syslog(LOG_DEBUG, "Rx %s from socket, callref=0x%x", | |
151 mncc_msg_name(msg->msg_type), msg->callref); | |
152 call = find_socket_call(conn, msg->callref); | |
153 if (!call) { | |
154 syslog(LOG_ERR, | |
155 "MNCC message from ThemWi call socket: callref 0x%x not found", | |
156 msg->callref); | |
157 /* drop it like OsmoMSC's mncc_builtin does */ | |
158 return; | |
159 } | |
160 /* forward to GSM MNCC interface */ | |
161 msg->callref = call->callref; | |
162 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc_rtp)); | |
163 } | |
164 | |
165 void | |
166 extsock_read_select(conn) | |
167 struct socket_conn *conn; | |
168 { | |
169 union mncc_msg msg; | |
170 int rc; | |
171 | |
172 rc = recv(conn->fd, &msg, sizeof msg, 0); | |
173 if (rc < 4) { | |
174 if (conn->ncalls) { | |
175 syslog(LOG_ERR, "ext socket broken with calls present"); | |
176 broken_socket_clear_calls(conn); | |
177 } else | |
178 syslog(LOG_INFO, "normal closing of ext socket"); | |
179 close(conn->fd); | |
180 conn->fd = -1; | |
181 return; | |
182 } | |
183 switch (msg.msg_type) { | |
184 case MNCC_SETUP_REQ: | |
185 handle_setup_req(conn, &msg, rc); | |
186 return; | |
187 case MNCC_SETUP_RSP: | |
188 case MNCC_SETUP_COMPL_REQ: | |
189 case MNCC_CALL_PROC_REQ: | |
190 case MNCC_PROGRESS_REQ: | |
191 case MNCC_ALERT_REQ: | |
192 case MNCC_NOTIFY_REQ: | |
193 case MNCC_DISC_REQ: | |
194 case MNCC_REL_REQ: | |
195 case MNCC_FACILITY_REQ: | |
196 case MNCC_START_DTMF_RSP: | |
197 case MNCC_START_DTMF_REJ: | |
198 case MNCC_STOP_DTMF_RSP: | |
199 case MNCC_MODIFY_REQ: | |
200 case MNCC_MODIFY_RSP: | |
201 case MNCC_MODIFY_REJ: | |
202 case MNCC_HOLD_CNF: | |
203 case MNCC_HOLD_REJ: | |
204 case MNCC_RETRIEVE_CNF: | |
205 case MNCC_RETRIEVE_REJ: | |
206 case MNCC_USERINFO_REQ: | |
207 case MNCC_REJ_REQ: | |
208 handle_signaling_msg(conn, &msg, rc); | |
209 return; | |
210 case MNCC_RTP_CREATE: | |
211 case MNCC_RTP_CONNECT: | |
212 case MNCC_RTP_FREE: | |
213 handle_rtp_msg(conn, &msg, rc); | |
214 return; | |
215 default: | |
216 syslog(LOG_CRIT, | |
217 "unknown MNCC message type 0x%x from ThemWi call socket", | |
218 msg.msg_type); | |
219 } | |
220 } | |
221 | |
222 mncc_signal_to_socket(call, msg) | |
223 struct gsm_call *call; | |
224 struct gsm_mncc *msg; | |
225 { | |
226 msg->callref = call->socket_ref; | |
227 return send(call->socket->fd, msg, sizeof(struct gsm_mncc), 0); | |
228 } | |
229 | |
230 mncc_signal_to_socket_nocall(conn, msg) | |
231 struct socket_conn *conn; | |
232 struct gsm_mncc *msg; | |
233 { | |
234 return send(conn->fd, msg, sizeof(struct gsm_mncc), 0); | |
235 } | |
236 | |
237 mncc_rtp_to_socket(call, msg) | |
238 struct gsm_call *call; | |
239 struct gsm_mncc_rtp *msg; | |
240 { | |
241 msg->callref = call->socket_ref; | |
242 return send(call->socket->fd, msg, sizeof(struct gsm_mncc_rtp), 0); | |
243 } |