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