This source file includes following definitions.
- create_conn_socket
- m3uac_connection_close
- m3uac_connection_open
- m3uac_exec_command
- m3uac_connection_read
- m3uac_connection_readp
- m3uac_connection_write
- m3uac_call_init
- m3uac_event_init
- m3uac_event_id_name
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 #if HAVE_NETDB_H
40 #include <netdb.h>
41 #endif
42
43 #include "freetdm.h"
44 #include <m3ua_client.h>
45
46
47 #ifndef HAVE_GETHOSTBYNAME_R
48 extern int gethostbyname_r (const char *__name,
49 struct hostent *__result_buf,
50 char *__buf, size_t __buflen,
51 struct hostent **__result,
52 int *__h_errnop);
53 #endif
54
55 struct m3uac_map {
56 uint32_t event_id;
57 const char *name;
58 };
59
60 static struct m3uac_map m3uac_table[] = {
61 {M3UA_EVENT_CALL_START, "CALL_START"},
62 {M3UA_EVENT_CALL_START_ACK, "CALL_START_ACK"},
63 {M3UA_EVENT_CALL_START_NACK, "CALL_START_NACK"},
64 {M3UA_EVENT_CALL_START_NACK_ACK, "CALL_START_NACK_ACK"},
65 {M3UA_EVENT_CALL_ANSWERED, "CALL_ANSWERED"},
66 {M3UA_EVENT_CALL_STOPPED, "CALL_STOPPED"},
67 {M3UA_EVENT_CALL_STOPPED_ACK, "CALL_STOPPED_ACK"},
68 {M3UA_EVENT_SYSTEM_RESTART, "SYSTEM_RESTART"},
69 {M3UA_EVENT_SYSTEM_RESTART_ACK, "SYSTEM_RESTART_ACK"},
70 {M3UA_EVENT_HEARTBEAT, "HEARTBEAT"},
71 {M3UA_EVENT_INSERT_CHECK_LOOP, "LOOP START"},
72 {M3UA_EVENT_REMOVE_CHECK_LOOP, "LOOP STOP"}
73 };
74
75
76
77 static int create_conn_socket(m3uac_connection_t *mcon, char *local_ip, int local_port, char *ip, int port)
78 {
79 int rc;
80 struct hostent *result, *local_result;
81 char buf[512], local_buf[512];
82 int err = 0;
83
84 memset(&mcon->remote_hp, 0, sizeof(mcon->remote_hp));
85 memset(&mcon->local_hp, 0, sizeof(mcon->local_hp));
86 mcon->socket = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
87
88 ftdm_log(FTDM_LOG_DEBUG, "Creating L=%s:%d R=%s:%d\n",
89 local_ip,local_port,ip,port);
90
91 if (mcon->socket >= 0) {
92 int flag;
93
94 flag = 1;
95 gethostbyname_r(ip, &mcon->remote_hp, buf, sizeof(buf), &result, &err);
96 gethostbyname_r(local_ip, &mcon->local_hp, local_buf, sizeof(local_buf), &local_result, &err);
97 if (result && local_result) {
98 mcon->remote_addr.sin_family = mcon->remote_hp.h_addrtype;
99 memcpy((char *) &mcon->remote_addr.sin_addr.s_addr, mcon->remote_hp.h_addr_list[0], mcon->remote_hp.h_length);
100 mcon->remote_addr.sin_port = htons(port);
101
102 mcon->local_addr.sin_family = mcon->local_hp.h_addrtype;
103 memcpy((char *) &mcon->local_addr.sin_addr.s_addr, mcon->local_hp.h_addr_list[0], mcon->local_hp.h_length);
104 mcon->local_addr.sin_port = htons(local_port);
105
106
107 setsockopt(mcon->socket, IPPROTO_SCTP, SCTP_NODELAY, (char *)&flag, sizeof(int));
108
109 rc=listen(mcon->socket,100);
110 if (rc) {
111 close(mcon->socket);
112 mcon->socket = -1;
113
114 }
115 }
116 }
117
118 ftdm_mutex_create(&mcon->mutex);
119
120 return mcon->socket;
121 }
122
123 int m3uac_connection_close(m3uac_connection_t *mcon)
124 {
125 if (mcon->socket > -1) {
126 close(mcon->socket);
127 }
128
129 ftdm_mutex_lock(mcon->mutex);
130 ftdm_mutex_unlock(mcon->mutex);
131 ftdm_mutex_destroy(&mcon->mutex);
132 memset(mcon, 0, sizeof(*mcon));
133 mcon->socket = -1;
134
135 return 0;
136 }
137
138 int m3uac_connection_open(m3uac_connection_t *mcon, char *local_ip, int local_port, char *ip, int port)
139 {
140 create_conn_socket(mcon, local_ip, local_port, ip, port);
141 return mcon->socket;
142 }
143
144
145 int m3uac_exec_command(m3uac_connection_t *mcon, int span, int chan, int id, int cmd, int cause)
146 {
147 m3uac_event_t oevent;
148 int retry = 5;
149
150 m3uac_event_init(&oevent, cmd, chan, span);
151 oevent.release_cause = cause;
152
153 if (cmd == SIGBOOST_EVENT_SYSTEM_RESTART) {
154 mcon->rxseq_reset = 1;
155 mcon->txseq = 0;
156 mcon->rxseq = 0;
157 mcon->txwindow = 0;
158 }
159
160 if (id >= 0) {
161 oevent.call_setup_id = id;
162 }
163
164 while (m3uac_connection_write(mcon, &oevent) <= 0) {
165 if (--retry <= 0) {
166 ftdm_log(FTDM_LOG_CRIT, "Failed to tx on M3UA socket: %s\n", strerror(errno));
167 return -1;
168 } else {
169 ftdm_log(FTDM_LOG_WARNING, "Failed to tx on M3UA socket: %s :retry %i\n", strerror(errno), retry);
170 ftdm_sleep(1);
171 }
172 }
173
174 return 0;
175 }
176
177
178
179 m3uac_event_t *m3uac_connection_read(m3uac_connection_t *mcon, int iteration)
180 {
181 unsigned int fromlen = sizeof(struct sockaddr_in);
182 int bytes = 0;
183
184 bytes = recvfrom(mcon->socket, &mcon->event, sizeof(mcon->event), MSG_DONTWAIT,
185 (struct sockaddr *) &mcon->local_addr, &fromlen);
186
187 if (bytes == sizeof(mcon->event) || bytes == (sizeof(mcon->event)-sizeof(uint32_t))) {
188
189 if (mcon->rxseq_reset) {
190 if (mcon->event.event_id == SIGBOOST_EVENT_SYSTEM_RESTART_ACK) {
191 ftdm_log(FTDM_LOG_DEBUG, "Rx sync ok\n");
192 mcon->rxseq = mcon->event.fseqno;
193 return &mcon->event;
194 }
195 errno=EAGAIN;
196 ftdm_log(FTDM_LOG_DEBUG, "Waiting for rx sync...\n");
197 return NULL;
198 }
199
200 mcon->txwindow = mcon->txseq - mcon->event.bseqno;
201 mcon->rxseq++;
202
203 if (mcon->rxseq != mcon->event.fseqno) {
204 ftdm_log(FTDM_LOG_CRIT, "Invalid Sequence Number Expect=%i Rx=%i\n", mcon->rxseq, mcon->event.fseqno);
205 return NULL;
206 }
207
208 return &mcon->event;
209 } else {
210 if (iteration == 0) {
211 ftdm_log(FTDM_LOG_CRIT, "Invalid Event length from boost rxlen=%i evsz=%i\n", bytes, sizeof(mcon->event));
212 return NULL;
213 }
214 }
215
216 return NULL;
217 }
218
219 m3uac_event_t *m3uac_connection_readp(m3uac_connection_t *mcon, int iteration)
220 {
221 unsigned int fromlen = sizeof(struct sockaddr_in);
222 int bytes = 0;
223
224 bytes = recvfrom(mcon->socket, &mcon->event, sizeof(mcon->event), MSG_DONTWAIT, (struct sockaddr *) &mcon->local_addr, &fromlen);
225
226 if (bytes == sizeof(mcon->event) || bytes == (sizeof(mcon->event)-sizeof(uint32_t))) {
227 return &mcon->event;
228 } else {
229 if (iteration == 0) {
230 ftdm_log(FTDM_LOG_CRIT, "Critical Error: PQ Invalid Event lenght from boost rxlen=%i evsz=%i\n", bytes, sizeof(mcon->event));
231 return NULL;
232 }
233 }
234
235 return NULL;
236 }
237
238
239 int m3uac_connection_write(m3uac_connection_t *mcon, ss7bc_event_t *event)
240 {
241 int err;
242
243 if (!event || mcon->socket < 0 || !mcon->mutex) {
244 ftdm_log(FTDM_LOG_DEBUG, "Critical Error: No Event Device\n");
245 return -EINVAL;
246 }
247
248 if (event->span > 16 || event->chan > 31) {
249 ftdm_log(FTDM_LOG_CRIT, "Critical Error: TX Cmd=%s Invalid Span=%i Chan=%i\n", m3uac_event_id_name(event->event_id), event->span,event->chan);
250 return -1;
251 }
252
253 gettimeofday(&event->tv,NULL);
254
255 ftdm_mutex_lock(mcon->mutex);
256 event->fseqno = mcon->txseq++;
257 event->bseqno = mcon->rxseq;
258 err = sendto(mcon->socket, event, sizeof(m3uac_event_t), 0, (struct sockaddr *) &mcon->remote_addr, sizeof(mcon->remote_addr));
259 ftdm_mutex_unlock(mcon->mutex);
260
261 if (err != sizeof(m3uac_event_t)) {
262 err = -1;
263 }
264
265 ftdm_log(FTDM_LOG_DEBUG, "TX EVENT: %s:(%X) [w%dg%d] Rc=%i CSid=%i Seq=%i Cd=[%s] Ci=[%s]\n",
266 m3uac_event_id_name(event->event_id),
267 event->event_id,
268 event->span+1,
269 event->chan+1,
270 event->release_cause,
271 event->call_setup_id,
272 event->fseqno,
273 (event->called_number_digits_count ? (char *) event->called_number_digits : "N/A"),
274 (event->calling_number_digits_count ? (char *) event->calling_number_digits : "N/A")
275 );
276
277 return err;
278 }
279
280 void m3uac_call_init(m3uac_event_t *event, const char *calling, const char *called, int setup_id)
281 {
282 memset(event, 0, sizeof(m3uac_event_t));
283 event->event_id = M3UA_EVENT_CALL_START;
284
285 if (calling) {
286 strncpy((char*)event->calling_number_digits, calling, sizeof(event->calling_number_digits)-1);
287 event->calling_number_digits_count = strlen(calling);
288 }
289
290 if (called) {
291 strncpy((char*)event->called_number_digits, called, sizeof(event->called_number_digits)-1);
292 event->called_number_digits_count = strlen(called);
293 }
294
295 event->call_setup_id = setup_id;
296
297 }
298
299 void m3uac_event_init(m3uac_event_t *event, m3uac_event_id_t event_id, int chan, int span)
300 {
301 memset(event, 0, sizeof(ss7bc_event_t));
302 event->event_id = event_id;
303 event->chan = chan;
304 event->span = span;
305 }
306
307 const char *m3uac_event_id_name(uint32_t event_id)
308 {
309 unsigned int x;
310 const char *ret = NULL;
311
312 for (x = 0 ; x < sizeof(m3uac_table)/sizeof(struct m3uac_map); x++) {
313 if (m3uac_table[x].event_id == event_id) {
314 ret = m3uac_table[x].name;
315 break;
316 }
317 }
318
319 return ret;
320 }
321
322
323
324
325
326
327
328
329
330
331
332
333