This source file includes following definitions.
- sangomabc_print_event_call
- sangomabc_print_event_short
- create_conn_socket
- sangomabc_connection_close
- sangomabc_connection_open
- sangomabc_exec_command
- sangomabc_exec_commandp
- __sangomabc_connection_read
- __sangomabc_connection_readp
- __sangomabc_connection_write
- __sangomabc_connection_writep
- sangomabc_call_init
- sangomabc_event_init
- sangomabc_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 #if HAVE_NETDB_H
35 #include <netdb.h>
36 #endif
37
38 #include "freetdm.h"
39 #include "sangoma_boost_client.h"
40
41 #ifndef HAVE_GETHOSTBYNAME_R
42 extern int gethostbyname_r (const char *__name,
43 struct hostent *__result_buf,
44 char *__buf, size_t __buflen,
45 struct hostent **__result,
46 int *__h_errnop);
47 #endif
48
49 struct sangomabc_map {
50 uint32_t event_id;
51 const char *name;
52 };
53
54 static struct sangomabc_map sangomabc_table[] = {
55 {SIGBOOST_EVENT_CALL_START, "CALL_START"},
56 {SIGBOOST_EVENT_CALL_START_ACK, "CALL_START_ACK"},
57 {SIGBOOST_EVENT_CALL_START_NACK, "CALL_START_NACK"},
58 {SIGBOOST_EVENT_CALL_PROGRESS, "CALL PROGRESS"},
59 {SIGBOOST_EVENT_CALL_START_NACK_ACK, "CALL_START_NACK_ACK"},
60 {SIGBOOST_EVENT_CALL_ANSWERED, "CALL_ANSWERED"},
61 {SIGBOOST_EVENT_CALL_STOPPED, "CALL_STOPPED"},
62 {SIGBOOST_EVENT_CALL_STOPPED_ACK, "CALL_STOPPED_ACK"},
63 {SIGBOOST_EVENT_CALL_RELEASED, "CALL_RELEASED"},
64 {SIGBOOST_EVENT_SYSTEM_RESTART, "SYSTEM_RESTART"},
65 {SIGBOOST_EVENT_SYSTEM_RESTART_ACK, "SYSTEM_RESTART_ACK"},
66 {SIGBOOST_EVENT_HEARTBEAT, "HEARTBEAT"},
67 {SIGBOOST_EVENT_INSERT_CHECK_LOOP, "LOOP START"},
68 {SIGBOOST_EVENT_REMOVE_CHECK_LOOP, "LOOP STOP"},
69 {SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE, "AUTO_CALL_GAP_ABATE"},
70 {SIGBOOST_EVENT_DIGIT_IN, "DIGIT_IN"}
71 };
72
73
74
75 static void sangomabc_print_event_call(sangomabc_connection_t *mcon, sangomabc_event_t *event, int priority, int dir, const char *file, const char *func, int line)
76 {
77 if (event->event_id == SIGBOOST_EVENT_HEARTBEAT)
78 return;
79
80 ftdm_log(file, func, line, mcon->debuglevel, "%s EVENT (%s): %s:(%X) [w%dg%d] CSid=%i Seq=%i Cn=[%s] Cd=[%s] Ci=[%s] Rdnis=[%s]\n",
81 dir ? "TX":"RX",
82 priority ? "P":"N",
83 sangomabc_event_id_name(event->event_id),
84 event->event_id,
85 BOOST_EVENT_SPAN(mcon->sigmod, event),
86 BOOST_EVENT_CHAN(mcon->sigmod, event),
87 event->call_setup_id,
88 event->fseqno,
89 strlen(event->calling_name)?event->calling_name:"N/A",
90 (event->called_number_digits_count ? (char *) event->called_number_digits : "N/A"),
91 (event->calling_number_digits_count ? (char *) event->calling_number_digits : "N/A"),
92 event->isup_in_rdnis);
93
94 }
95 static void sangomabc_print_event_short(sangomabc_connection_t *mcon, sangomabc_short_event_t *event, int priority, int dir, const char *file, const char *func, int line)
96 {
97 if (event->event_id == SIGBOOST_EVENT_HEARTBEAT)
98 return;
99 ftdm_log(file, func, line, mcon->debuglevel, "%s EVENT (%s): %s:(%X) [s%dc%d] Rc=%i CSid=%i Seq=%i \n",
100 dir ? "TX":"RX",
101 priority ? "P":"N",
102 sangomabc_event_id_name(event->event_id),
103 event->event_id,
104 BOOST_EVENT_SPAN(mcon->sigmod, event),
105 BOOST_EVENT_CHAN(mcon->sigmod, event),
106 event->release_cause,
107 event->call_setup_id,
108 event->fseqno);
109 }
110
111
112 static int create_conn_socket(sangomabc_connection_t *mcon, char *local_ip, int local_port, char *ip, int port)
113 {
114 #ifndef WIN32
115 int rc;
116 struct hostent *result, *local_result;
117 char buf[512], local_buf[512];
118 int err = 0, local_err = 0;
119
120 if (mcon->sigmod) {
121 ftdm_log(FTDM_LOG_WARNING, "I should not be called on a sigmod-managed connection!\n");
122 return 0;
123 }
124
125 memset(&mcon->remote_hp, 0, sizeof(mcon->remote_hp));
126 memset(&mcon->local_hp, 0, sizeof(mcon->local_hp));
127 #ifdef HAVE_NETINET_SCTP_H
128 ftdm_log(FTDM_LOG_DEBUG, "Creating SCTP socket L=%s:%d R=%s:%d\n",
129 local_ip, local_port, ip, port);
130 mcon->socket = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
131 #else
132 ftdm_log(FTDM_LOG_DEBUG, "Creating UDP socket L=%s:%d R=%s:%d\n",
133 local_ip, local_port, ip, port);
134 mcon->socket = socket(AF_INET, SOCK_DGRAM, 0);
135 #endif
136
137 if (mcon->socket >= 0) {
138 int flag;
139
140 flag = 1;
141 #ifdef HAVE_GETHOSTBYNAME_R_FIVE
142 gethostbyname_r(ip, &mcon->remote_hp, buf, sizeof(buf), &err);
143 gethostbyname_r(local_ip, &mcon->local_hp, local_buf, sizeof(local_buf), &local_err);
144 if (!err && !local_err) {
145 #else
146 gethostbyname_r(ip, &mcon->remote_hp, buf, sizeof(buf), &result, &err);
147 gethostbyname_r(local_ip, &mcon->local_hp, local_buf, sizeof(local_buf), &local_result, &local_err);
148 if (result && local_result) {
149 #endif
150 mcon->remote_addr.sin_family = mcon->remote_hp.h_addrtype;
151 memcpy((char *) &mcon->remote_addr.sin_addr.s_addr, mcon->remote_hp.h_addr_list[0], mcon->remote_hp.h_length);
152 mcon->remote_addr.sin_port = htons(port);
153
154 mcon->local_addr.sin_family = mcon->local_hp.h_addrtype;
155 memcpy((char *) &mcon->local_addr.sin_addr.s_addr, mcon->local_hp.h_addr_list[0], mcon->local_hp.h_length);
156 mcon->local_addr.sin_port = htons(local_port);
157
158 #ifdef HAVE_NETINET_SCTP_H
159 setsockopt(mcon->socket, IPPROTO_SCTP, SCTP_NODELAY,
160 (char *)&flag, sizeof(int));
161 #endif
162
163 if ((rc = bind(mcon->socket,
164 (struct sockaddr *) &mcon->local_addr,
165 sizeof(mcon->local_addr))) < 0) {
166 close(mcon->socket);
167 mcon->socket = -1;
168 } else {
169 #ifdef HAVE_NETINET_SCTP_H
170 rc=listen(mcon->socket, 100);
171 if (rc) {
172 close(mcon->socket);
173 mcon->socket = -1;
174 }
175 #endif
176 }
177 }
178 }
179
180 return mcon->socket;
181 #else
182 return 0;
183 #endif
184 }
185
186 int sangomabc_connection_close(sangomabc_connection_t *mcon)
187 {
188 #ifndef WIN32
189 if (mcon->sigmod) {
190 ftdm_log(FTDM_LOG_WARNING, "I should not be called on a sigmod-managed connection!\n");
191 return 0;
192 }
193 if (mcon->socket > -1) {
194 close(mcon->socket);
195 }
196
197 if (mcon->mutex) {
198 ftdm_mutex_lock(mcon->mutex);
199 ftdm_mutex_unlock(mcon->mutex);
200 ftdm_mutex_destroy(&mcon->mutex);
201 }
202 memset(mcon, 0, sizeof(*mcon));
203 mcon->socket = -1;
204 #endif
205 return 0;
206 }
207
208 int sangomabc_connection_open(sangomabc_connection_t *mcon, char *local_ip, int local_port, char *ip, int port)
209 {
210 ftdm_mutex_create(&mcon->mutex);
211 if (mcon->sigmod) {
212
213 return 0;
214 }
215 #ifndef WIN32
216 create_conn_socket(mcon, local_ip, local_port, ip, port);
217 return mcon->socket;
218 #else
219 return 0;
220 #endif
221 }
222
223
224 int sangomabc_exec_command(sangomabc_connection_t *mcon, int span, int chan, int id, int cmd, int cause, int flags)
225 {
226 sangomabc_event_t *oevent;
227 sangomabc_short_event_t sevent;
228 sangomabc_event_t fevent;
229 int retry = 5;
230
231 if (boost_full_event(cmd)) {
232 sangomabc_event_init((void *)&fevent, cmd, chan, span);
233 oevent = &fevent;
234 } else {
235 sangomabc_event_init(&sevent, cmd, chan, span);
236 sevent.release_cause = (uint8_t)cause;
237 oevent = (sangomabc_event_t *)&sevent;
238 }
239 oevent->flags = flags;
240
241 if (cmd == SIGBOOST_EVENT_SYSTEM_RESTART || cmd == SIGBOOST_EVENT_SYSTEM_RESTART_ACK) {
242 mcon->rxseq_reset = 1;
243 mcon->txseq = 0;
244 mcon->rxseq = 0;
245 mcon->txwindow = 0;
246 }
247
248 if (id >= 0) {
249 oevent->call_setup_id = (uint16_t)id;
250 }
251
252 while (sangomabc_connection_write(mcon, (sangomabc_event_t*)oevent) <= 0) {
253 if (--retry <= 0) {
254 ftdm_log(FTDM_LOG_CRIT, "Failed to tx on boost socket: %s\n", strerror(errno));
255 return -1;
256 } else {
257 ftdm_log(FTDM_LOG_WARNING, "Failed to tx on boost socket: %s :retry %i\n", strerror(errno), retry);
258 ftdm_sleep(1);
259 }
260 }
261
262 return 0;
263 }
264
265
266 int sangomabc_exec_commandp(sangomabc_connection_t *pcon, int span, int chan, int id, int cmd, int cause)
267 {
268 sangomabc_short_event_t oevent;
269 int retry = 5;
270
271 sangomabc_event_init(&oevent, cmd, chan, span);
272 oevent.release_cause = (uint8_t)cause;
273
274 if (id >= 0) {
275 oevent.call_setup_id = (uint16_t)id;
276 }
277
278 while (sangomabc_connection_writep(pcon, (sangomabc_event_t*)&oevent) <= 0) {
279 if (--retry <= 0) {
280 ftdm_log(FTDM_LOG_CRIT, "Failed to tx on boost socket: %s\n", strerror(errno));
281 return -1;
282 } else {
283 ftdm_log(FTDM_LOG_WARNING, "Failed to tx on boost socket: %s :retry %i\n", strerror(errno), retry);
284 ftdm_sleep(1);
285 }
286 }
287
288 return 0;
289 }
290
291 sangomabc_event_t *__sangomabc_connection_read(sangomabc_connection_t *mcon, int iteration, const char *file, const char *func, int line)
292 {
293 #ifndef WIN32
294 unsigned int fromlen = sizeof(struct sockaddr_in);
295 #endif
296 int bytes = 0;
297 int msg_ok = 0;
298 sangomabc_queue_element_t *e = NULL;
299
300 if (mcon->sigmod) {
301 e = ftdm_queue_dequeue(mcon->boost_queue);
302 if (e) {
303 bytes = (int)e->size;
304 memcpy(&mcon->event, e->boostmsg, bytes);
305 ftdm_safe_free(e);
306 }
307 }
308 #ifndef WIN32
309 else {
310 bytes = recvfrom(mcon->socket, &mcon->event, sizeof(mcon->event), MSG_DONTWAIT,
311 (struct sockaddr *) &mcon->local_addr, &fromlen);
312 }
313 #endif
314 if (bytes <= 0) {
315 return NULL;
316 }
317
318 if (mcon->event.version != SIGBOOST_VERSION) {
319 ftdm_log(FTDM_LOG_CRIT, "Invalid Boost Version %i Expecting %i\n",mcon->event.version, SIGBOOST_VERSION);
320 }
321
322 if ((bytes >= MIN_SIZE_CALLSTART_MSG) && boost_full_event(mcon->event.event_id)) {
323 msg_ok=1;
324
325 } else if (bytes == sizeof(sangomabc_short_event_t)) {
326 msg_ok=1;
327
328 } else {
329 msg_ok=0;
330 }
331
332 if (msg_ok) {
333 if (sangomabc_test_flag(mcon, MSU_FLAG_DOWN)) {
334 if (mcon->event.event_id != SIGBOOST_EVENT_SYSTEM_RESTART &&
335 mcon->event.event_id != SIGBOOST_EVENT_SYSTEM_RESTART_ACK &&
336 mcon->event.event_id != SIGBOOST_EVENT_HEARTBEAT) {
337 ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "Not reading packets when connection is down. [%s]\n",
338 sangomabc_event_id_name(mcon->event.event_id));
339 return NULL;
340 }
341 }
342
343 if (boost_full_event(mcon->event.event_id)) {
344 sangomabc_print_event_call(mcon, &mcon->event, 0, 0, file, func, line);
345 } else {
346 sangomabc_print_event_short(mcon, (sangomabc_short_event_t*)&mcon->event, 0, 0, file, func, line);
347 }
348
349 #if 0
350
351 if (mcon->rxseq_reset) {
352
353 ftdm_log(FTDM_LOG_DEBUG, "Rx sync ok\n");
354 mcon->rxseq = mcon->event.fseqno;
355 return &mcon->event;
356
357 errno=EAGAIN;
358 ftdm_log(FTDM_LOG_DEBUG, "Waiting for rx sync...\n");
359 return NULL;
360 }
361 #endif
362
363 mcon->txwindow = mcon->txseq - mcon->event.bseqno;
364 mcon->rxseq++;
365
366 #if 0
367 if (mcon->rxseq != mcon->event.fseqno) {
368 ftdm_log(FTDM_LOG_CRIT, "Invalid Sequence Number Expect=%i Rx=%i\n", mcon->rxseq, mcon->event.fseqno);
369 return NULL;
370 }
371 #endif
372
373 return &mcon->event;
374 } else {
375 if (iteration == 0) {
376 ftdm_log(FTDM_LOG_CRIT, "NC - Invalid Event length from boost rxlen=%i evsz=%i\n", bytes, sizeof(mcon->event));
377 return NULL;
378 }
379 }
380
381 return NULL;
382 }
383
384 sangomabc_event_t *__sangomabc_connection_readp(sangomabc_connection_t *mcon, int iteration, const char *file, const char *func, int line)
385 {
386 #ifndef WIN32
387 unsigned int fromlen = sizeof(struct sockaddr_in);
388 #endif
389 int bytes = 0;
390
391 if (mcon->sigmod) {
392
393 return sangomabc_connection_read(mcon, iteration);
394 }
395 #ifndef WIN32
396 else {
397 bytes = recvfrom(mcon->socket, &mcon->event, sizeof(mcon->event), MSG_DONTWAIT, (struct sockaddr *) &mcon->local_addr, &fromlen);
398 }
399 #endif
400 if (bytes <= 0) {
401 return NULL;
402 }
403
404 if (mcon->event.version != SIGBOOST_VERSION) {
405 ftdm_log(FTDM_LOG_CRIT, "Invalid Boost Version %i Expecting %i\n",mcon->event.version, SIGBOOST_VERSION);
406 }
407
408 if (bytes == sizeof(sangomabc_short_event_t)) {
409
410 if (boost_full_event(mcon->event.event_id)) {
411 sangomabc_print_event_call(mcon, &mcon->event, 1, 0, file, func, line);
412 } else {
413 sangomabc_print_event_short(mcon, (sangomabc_short_event_t*)&mcon->event, 1, 0, file, func, line);
414 }
415
416 return &mcon->event;
417 } else {
418 if (iteration == 0) {
419 ftdm_log(FTDM_LOG_CRIT, "Critical Error: PQ Invalid Event lenght from boost rxlen=%i evsz=%i\n", bytes, sizeof(mcon->event));
420 return NULL;
421 }
422 }
423
424 return NULL;
425 }
426
427
428 int __sangomabc_connection_write(sangomabc_connection_t *mcon, sangomabc_event_t *event, const char *file, const char *func, int line)
429 {
430 int err = 0;
431 int event_size=MIN_SIZE_CALLSTART_MSG+event->isup_in_rdnis_size;
432
433 ftdm_assert_return(event != NULL, -1, "No event!");
434 ftdm_assert_return(mcon->socket >= 0, -1, "No mcon->socket!");
435 ftdm_assert_return(mcon->mutex != NULL, -1, "No mcon->mutex!");
436
437 ftdm_assert_return(event->span <= FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN, -1, "Invalid span when writing boost event\n");
438 ftdm_assert_return(event->chan <= FTDM_MAX_CHANNELS_PHYSICAL_SPAN, -1, "Invalid chan when writing boost event\n");
439
440 if (!boost_full_event(event->event_id)) {
441 event_size=sizeof(sangomabc_short_event_t);
442 }
443
444 if (sangomabc_test_flag(mcon, MSU_FLAG_DOWN)) {
445 if (event->event_id != SIGBOOST_EVENT_SYSTEM_RESTART &&
446 event->event_id != SIGBOOST_EVENT_SYSTEM_RESTART_ACK &&
447 event->event_id != SIGBOOST_EVENT_HEARTBEAT) {
448 ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "Not writing packets when connection is down. [%s]\n",
449 sangomabc_event_id_name(event->event_id));
450 return 0;
451 }
452 }
453
454 ftdm_mutex_lock(mcon->mutex);
455 if (event->event_id == SIGBOOST_EVENT_SYSTEM_RESTART_ACK) {
456 mcon->txseq=0;
457 mcon->rxseq=0;
458 event->fseqno=0;
459 } else {
460 event->fseqno = mcon->txseq++;
461 }
462 event->bseqno = mcon->rxseq;
463 event->version = SIGBOOST_VERSION;
464
465 if (boost_full_event(event->event_id)) {
466 sangomabc_print_event_call(mcon, event, 0, 1, file, func, line);
467 } else {
468 sangomabc_print_event_short(mcon, (sangomabc_short_event_t*)event, 0, 1, file, func, line);
469 }
470
471 if (mcon->sigmod) {
472 mcon->sigmod->write_msg(mcon->span, event, event_size);
473 err = event_size;
474 }
475 #ifndef WIN32
476 else {
477 err = sendto(mcon->socket, event, event_size, 0, (struct sockaddr *) &mcon->remote_addr, sizeof(mcon->remote_addr));
478 }
479 #endif
480
481 ftdm_mutex_unlock(mcon->mutex);
482
483 ftdm_assert_return(err == event_size, -1, "Failed to send the boost message completely!");
484
485 return err;
486 }
487
488
489 int __sangomabc_connection_writep(sangomabc_connection_t *mcon, sangomabc_event_t *event, const char *file, const char *func, int line)
490 {
491 int err = 0;
492 int event_size=sizeof(sangomabc_event_t);
493
494 if (!mcon->sigmod) {
495 ftdm_assert_return(event != NULL, -1, "No event!");
496 ftdm_assert_return(mcon->socket >= 0, -1, "No mcon->socket!");
497 ftdm_assert_return(mcon->mutex != NULL, -1, "No mcon->mutex!");
498 }
499
500 if (!boost_full_event(event->event_id)) {
501 event_size=sizeof(sangomabc_short_event_t);
502 }
503
504 ftdm_mutex_lock(mcon->mutex);
505 event->version = SIGBOOST_VERSION;
506 if (mcon->sigmod) {
507 mcon->sigmod->write_msg(mcon->span, event, event_size);
508 err = event_size;
509
510 }
511 #ifndef WIN32
512 else {
513 err = sendto(mcon->socket, event, event_size, 0, (struct sockaddr *) &mcon->remote_addr, sizeof(mcon->remote_addr));
514 }
515 #endif
516 ftdm_mutex_unlock(mcon->mutex);
517
518 ftdm_assert_return(err == event_size, -1, "Failed to send boost message completely!");
519
520 if (boost_full_event(event->event_id)) {
521 sangomabc_print_event_call(mcon, event, 1, 1, file, func, line);
522 } else {
523 sangomabc_print_event_short(mcon, (sangomabc_short_event_t*)event, 1, 1, file, func, line);
524 }
525
526 return err;
527 }
528
529
530 void sangomabc_call_init(sangomabc_event_t *event, const char *calling, const char *called, int setup_id)
531 {
532 memset(event, 0, sizeof(sangomabc_event_t));
533 event->event_id = SIGBOOST_EVENT_CALL_START;
534
535 if (calling) {
536 strncpy((char*)event->calling_number_digits, calling, sizeof(event->calling_number_digits)-1);
537 event->calling_number_digits_count = (uint8_t)strlen(calling);
538 }
539
540 if (called) {
541 strncpy((char*)event->called_number_digits, called, sizeof(event->called_number_digits)-1);
542 event->called_number_digits_count = (uint8_t)strlen(called);
543 }
544
545 event->call_setup_id = (uint16_t)setup_id;
546
547 }
548
549 void sangomabc_event_init(sangomabc_short_event_t *event, sangomabc_event_id_t event_id, int chan, int span)
550 {
551 if (boost_full_event(event_id)) {
552 memset(event, 0, sizeof(sangomabc_event_t));
553 } else {
554 memset(event, 0, sizeof(sangomabc_short_event_t));
555 }
556 event->event_id = event_id;
557 event->chan = (uint8_t)chan;
558 event->span = (uint8_t)span;
559 }
560
561 const char *sangomabc_event_id_name(uint32_t event_id)
562 {
563 unsigned int x;
564 const char *ret = NULL;
565
566 for (x = 0 ; x < sizeof(sangomabc_table)/sizeof(struct sangomabc_map); x++) {
567 if (sangomabc_table[x].event_id == event_id) {
568 ret = sangomabc_table[x].name;
569 break;
570 }
571 }
572
573 return ret;
574 }
575
576
577
578
579
580
581
582
583
584
585
586
587