This source file includes following definitions.
- __release_request_id_span_chan
- __release_request_id
- __next_request_id
- print_request_ids
- find_ftdmchan
- check_congestion
- FIO_CHANNEL_REQUEST_FUNCTION
- FIO_CHANNEL_OUTGOING_CALL_FUNCTION
- handle_call_progress
- handle_call_start_ack
- handle_call_done
- handle_call_start_nack
- handle_call_released
- handle_call_stop
- handle_call_answer
- handle_call_start
- handle_call_loop_start
- stop_loop
- handle_call_loop_stop
- handle_heartbeat
- handle_restart_ack
- handle_restart
- handle_incoming_digit
- event_process_states
- parse_sangoma_event
- state_advance
- init_outgoing_array
- check_state
- check_events
- ftdm_sangoma_events_run
- ftdm_boost_connection_open
- ftdm_boost_wait_event
- ftdm_boost_read_event
- ftdm_sangoma_boost_run
- sigmod_ss7box_isup_exec_cmd
- ftdm_cli_span_state_cmd
- FIO_API_FUNCTION
- FIO_IO_LOAD_FUNCTION
- FIO_SIG_LOAD_FUNCTION
- FIO_SIG_UNLOAD_FUNCTION
- ftdm_sangoma_boost_start
- ftdm_sangoma_boost_stop
- BOOST_WRITE_MSG_FUNCTION
- BOOST_SIG_STATUS_CB_FUNCTION
- FIO_CHANNEL_SET_SIG_STATUS_FUNCTION
- FIO_CHANNEL_GET_SIG_STATUS_FUNCTION
- FIO_SPAN_SET_SIG_STATUS_FUNCTION
- FIO_SPAN_GET_SIG_STATUS_FUNCTION
- FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION
- ftdm_sangoma_boost_list_sigmods
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
40
41
42
43
44
45
46 #include "private/ftdm_core.h"
47 #include "sangoma_boost_client.h"
48 #include "ftdm_sangoma_boost.h"
49 #ifdef HAVE_SYS_SELECT_H
50 #include <sys/select.h>
51 #endif
52
53
54 ftdm_mutex_t *g_boost_modules_mutex = NULL;
55 ftdm_hash_t *g_boost_modules_hash = NULL;
56
57 #define MAX_TRUNK_GROUPS 64
58
59 static time_t congestion_timeouts[MAX_TRUNK_GROUPS];
60
61 static ftdm_sangoma_boost_trunkgroup_t *g_trunkgroups[MAX_TRUNK_GROUPS];
62
63 static ftdm_io_interface_t ftdm_sangoma_boost_interface;
64 static ftdm_status_t ftdm_sangoma_boost_list_sigmods(ftdm_stream_handle_t *stream);
65
66 #define BOOST_QUEUE_SIZE 500
67
68
69 #define BOOST_SPAN(ftdmchan) ((ftdm_sangoma_boost_data_t*)(ftdmchan)->span->signal_data)->sigmod ? ftdmchan->physical_span_id : ftdmchan->physical_span_id-1
70 #define BOOST_CHAN(ftdmchan) ((ftdm_sangoma_boost_data_t*)(ftdmchan)->span->signal_data)->sigmod ? ftdmchan->physical_chan_id : ftdmchan->physical_chan_id-1
71
72
73
74
75 typedef enum {
76 SFLAG_SENT_FINAL_MSG = (1 << 0),
77 SFLAG_SENT_ACK = (1 << 1),
78 SFLAG_RECVD_ACK = (1 << 2),
79 SFLAG_HANGUP = (1 << 3),
80 SFLAG_TERMINATING = (1 << 4)
81 } sflag_t;
82
83 typedef uint16_t sangoma_boost_request_id_t;
84
85
86
87
88 typedef enum {
89 BST_FREE,
90 BST_WAITING,
91 BST_READY,
92 BST_FAIL
93 } sangoma_boost_request_status_t;
94
95
96
97
98 typedef struct {
99 sangoma_boost_request_status_t status;
100 sangomabc_short_event_t event;
101 ftdm_span_t *span;
102 ftdm_channel_t *ftdmchan;
103 int hangup_cause;
104 int flags;
105 } sangoma_boost_request_t;
106
107 typedef struct {
108 int call_setup_id;
109 int last_event_id;
110 } sangoma_boost_call_t;
111
112 #define CALL_DATA(ftdmchan) ((sangoma_boost_call_t*)((ftdmchan)->call_data))
113
114
115 #define MAX_REQ_ID 6000
116
117 static uint16_t SETUP_GRID[FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN+1][FTDM_MAX_CHANNELS_PHYSICAL_SPAN+1] = {{ 0 }};
118
119 static sangoma_boost_request_t OUTBOUND_REQUESTS[MAX_REQ_ID+1] = {{ 0 }};
120
121 static ftdm_mutex_t *request_mutex = NULL;
122
123 static uint8_t req_map[MAX_REQ_ID+1] = { 0 };
124 static uint8_t nack_map[MAX_REQ_ID+1] = { 0 };
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139 static void __release_request_id_span_chan(int span, int chan, const char *func, int line)
140 {
141 int id;
142
143 ftdm_mutex_lock(request_mutex);
144 if ((id = SETUP_GRID[span][chan])) {
145 ftdm_assert(id <= MAX_REQ_ID, "Invalid request id\n");
146 req_map[id] = 0;
147 SETUP_GRID[span][chan] = 0;
148 }
149 ftdm_mutex_unlock(request_mutex);
150 }
151 #define release_request_id_span_chan(s, c) __release_request_id_span_chan(s, c, __FUNCTION__, __LINE__)
152
153
154
155
156
157
158
159 static void __release_request_id(sangoma_boost_request_id_t r, const char *func, int line)
160 {
161 ftdm_assert(r <= MAX_REQ_ID, "Invalid request id\n");
162 ftdm_mutex_lock(request_mutex);
163 req_map[r] = 0;
164 ftdm_mutex_unlock(request_mutex);
165 }
166 #define release_request_id(r) __release_request_id(r, __FUNCTION__, __LINE__)
167
168 static sangoma_boost_request_id_t last_req = 0;
169
170
171
172
173
174
175
176 static sangoma_boost_request_id_t __next_request_id(const char *func, int line)
177 {
178 sangoma_boost_request_id_t r = 0, i = 0;
179 int found=0;
180
181 ftdm_mutex_lock(request_mutex);
182
183
184
185 for (i=1; i<= MAX_REQ_ID; i++){
186 r = ++last_req;
187
188 if (r >= MAX_REQ_ID) {
189 r = last_req = 1;
190 }
191
192 if (req_map[r]) {
193
194 continue;
195
196 }
197
198 req_map[r] = 1;
199 found=1;
200 break;
201
202 }
203
204 ftdm_mutex_unlock(request_mutex);
205
206 if (!found) {
207 return 0;
208 }
209
210 return r;
211 }
212 #define next_request_id() __next_request_id(__FUNCTION__, __LINE__)
213
214
215 static void print_request_ids(void)
216 {
217 sangoma_boost_request_id_t i = 0;
218 int cnt=0;
219
220 ftdm_mutex_lock(request_mutex);
221
222 for (i=1; i<= MAX_REQ_ID; i++){
223 if (req_map[i]) {
224 ftdm_log(FTDM_LOG_CRIT, "Used Request ID=%i\n",i);
225 cnt++;
226 }
227 }
228
229 ftdm_mutex_unlock(request_mutex);
230 ftdm_log(FTDM_LOG_CRIT, "Total Request IDs=%i\n",cnt);
231
232 return;
233 }
234
235
236
237
238
239
240
241
242
243 static ftdm_channel_t *find_ftdmchan(ftdm_span_t *span, sangomabc_short_event_t *event, int force)
244 {
245 uint32_t i;
246 ftdm_channel_t *ftdmchan = NULL;
247
248 ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
249 uint32_t targetspan = BOOST_EVENT_SPAN(sangoma_boost_data->sigmod, event);
250 uint32_t targetchan = BOOST_EVENT_CHAN(sangoma_boost_data->sigmod, event);
251
252
253
254
255
256
257 if (!span) {
258 ftdm_log(FTDM_LOG_CRIT, "No Span for Event=%s s%dc%d cid=%d\n",
259 BOOST_DECODE_EVENT_ID(event->event_id),
260 targetspan,
261 targetchan,
262 event->call_setup_id);
263 return NULL;
264 }
265
266
267 for(i = 1; i <= span->chan_count; i++) {
268 if (span->channels[i]->physical_span_id == targetspan && span->channels[i]->physical_chan_id == targetchan) {
269 ftdmchan = span->channels[i];
270 if (force || (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN && !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE))) {
271 break;
272 } else {
273 ftdmchan = NULL;
274 ftdm_log(FTDM_LOG_DEBUG, "Channel %d:%d ~ %d:%d is already in use in state %s\n",
275 span->channels[i]->span_id,
276 span->channels[i]->chan_id,
277 span->channels[i]->physical_span_id,
278 span->channels[i]->physical_chan_id,
279 ftdm_channel_state2str(span->channels[i]->state));
280 break;
281 }
282 }
283 }
284
285 return ftdmchan;
286 }
287
288 static int check_congestion(int trunk_group)
289 {
290 if (congestion_timeouts[trunk_group]) {
291 time_t now = time(NULL);
292
293 if (now >= congestion_timeouts[trunk_group]) {
294 congestion_timeouts[trunk_group] = 0;
295 } else {
296 return 1;
297 }
298 }
299
300 return 0;
301 }
302
303
304
305
306
307
308
309
310
311
312
313 static FIO_CHANNEL_REQUEST_FUNCTION(sangoma_boost_channel_request)
314 {
315 ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
316 ftdm_status_t status = FTDM_FAIL;
317 sangoma_boost_request_id_t r;
318 sangomabc_event_t event = {0};
319
320
321
322
323
324
325 int boost_request_timeout = 10000;
326 sangoma_boost_request_status_t st;
327 char dnis[128] = "";
328 char *gr = NULL;
329 uint32_t count = 0;
330 int tg=0;
331
332
333
334
335 if (!sangoma_boost_data->sigmod) {
336 boost_request_timeout = 30000;
337 }
338
339 if (sangoma_boost_data->sigmod) {
340 ftdm_log(FTDM_LOG_CRIT, "This function should not be called when sigmod was configured in boost\n");
341 *ftdmchan = NULL;
342 return FTDM_FAIL;
343 }
344
345 if (ftdm_test_flag(span, FTDM_SPAN_SUSPENDED)) {
346 ftdm_log(FTDM_LOG_CRIT, "SPAN is Suspended.\n");
347 *ftdmchan = NULL;
348 return FTDM_FAIL;
349 }
350
351 if (check_congestion(tg)) {
352 ftdm_log(FTDM_LOG_CRIT, "All circuits are busy. Trunk Group=%i (CONGESTION)\n",tg+1);
353 *ftdmchan = NULL;
354 return FTDM_FAIL;
355 }
356
357 if (count >= span->chan_count) {
358 ftdm_log(FTDM_LOG_CRIT, "All circuits are busy.\n");
359 *ftdmchan = NULL;
360 return FTDM_FAIL;
361 }
362
363 r = next_request_id();
364 if (r == 0) {
365 ftdm_log(FTDM_LOG_CRIT, "All tanks ids are busy.\n");
366 *ftdmchan = NULL;
367 return FTDM_FAIL;
368 }
369
370
371
372
373 ftdm_set_string(dnis, caller_data->dnis.digits);
374
375 if ((gr = strchr(dnis, '@'))) {
376 *gr++ = '\0';
377 }
378
379 if (gr && *(gr+1)) {
380 tg = atoi(gr+1);
381 if (tg > 0) {
382 tg--;
383 }
384 }
385
386 sangomabc_call_init(&event, caller_data->cid_num.digits, dnis, r);
387
388 event.trunk_group = tg;
389
390
391 ftdm_span_channel_use_count(span, &count);
392
393 if (gr && *(gr+1)) {
394 switch(*gr) {
395 case 'g':
396 event.hunt_group = SIGBOOST_HUNTGRP_SEQ_ASC;
397 break;
398 case 'G':
399 event.hunt_group = SIGBOOST_HUNTGRP_SEQ_DESC;
400 break;
401 case 'r':
402 event.hunt_group = SIGBOOST_HUNTGRP_RR_ASC;
403 break;
404 case 'R':
405 event.hunt_group = SIGBOOST_HUNTGRP_RR_DESC;
406 break;
407 default:
408 ftdm_log(FTDM_LOG_WARNING, "Failed to determine huntgroup (%s)\n", gr);
409 event.hunt_group = SIGBOOST_HUNTGRP_SEQ_ASC;
410 }
411 }
412
413 ftdm_set_string(event.calling_name, caller_data->cid_name);
414 ftdm_set_string(event.rdnis.digits, caller_data->rdnis.digits);
415 if (strlen(caller_data->rdnis.digits)) {
416 event.rdnis.digits_count = (uint8_t)strlen(caller_data->rdnis.digits)+1;
417 event.rdnis.ton = caller_data->rdnis.type;
418 event.rdnis.npi = caller_data->rdnis.plan;
419 }
420
421 event.calling.screening_ind = caller_data->screen;
422 event.calling.presentation_ind = caller_data->pres;
423
424 event.calling.ton = caller_data->cid_num.type;
425 event.calling.npi = caller_data->cid_num.plan;
426
427 event.called.ton = caller_data->dnis.type;
428 event.called.npi = caller_data->dnis.plan;
429
430
431 event.bearer.capability = caller_data->bearer_capability;
432 event.bearer.uil1p = caller_data->bearer_layer1;
433
434 if (caller_data->raw_data_len) {
435 ftdm_set_string(event.custom_data, caller_data->raw_data);
436 event.custom_data_size = (uint16_t)caller_data->raw_data_len;
437 }
438
439 OUTBOUND_REQUESTS[r].status = BST_WAITING;
440 OUTBOUND_REQUESTS[r].span = span;
441
442 if (sangomabc_connection_write(&sangoma_boost_data->mcon, &event) <= 0) {
443 ftdm_log(FTDM_LOG_CRIT, "Failed to tx boost event [%s]\n", strerror(errno));
444 status = OUTBOUND_REQUESTS[r].status = FTDM_FAIL;
445 if (!sangoma_boost_data->sigmod) {
446 *ftdmchan = NULL;
447 }
448 goto done;
449 }
450
451 while(ftdm_running() && OUTBOUND_REQUESTS[r].status == BST_WAITING) {
452 ftdm_sleep(1);
453 if (--boost_request_timeout <= 0) {
454 status = FTDM_FAIL;
455 if (!sangoma_boost_data->sigmod) {
456 *ftdmchan = NULL;
457 }
458 ftdm_log(FTDM_LOG_CRIT, "Csid:%d Timed out waiting for boost channel request response, current status: BST_WAITING\n", r);
459 goto done;
460 }
461 }
462
463 if (OUTBOUND_REQUESTS[r].status == BST_READY && OUTBOUND_REQUESTS[r].ftdmchan) {
464 *ftdmchan = OUTBOUND_REQUESTS[r].ftdmchan;
465 status = FTDM_SUCCESS;
466 } else {
467 status = FTDM_FAIL;
468 if (!sangoma_boost_data->sigmod) {
469 *ftdmchan = NULL;
470 }
471 }
472
473 done:
474
475 st = OUTBOUND_REQUESTS[r].status;
476 OUTBOUND_REQUESTS[r].status = BST_FREE;
477
478 if (status == FTDM_FAIL) {
479 if (st == BST_FAIL) {
480 caller_data->hangup_cause = OUTBOUND_REQUESTS[r].hangup_cause;
481 } else {
482 caller_data->hangup_cause = FTDM_CAUSE_RECOVERY_ON_TIMER_EXPIRE;
483 }
484 }
485
486 if (st == BST_FAIL) {
487 release_request_id(r);
488 } else if (st != BST_READY) {
489 ftdm_assert_return(r <= MAX_REQ_ID, FTDM_FAIL, "Invalid index\n");
490 nack_map[r] = 1;
491 if (sangoma_boost_data->sigmod) {
492 sangomabc_exec_command(&sangoma_boost_data->mcon,
493 BOOST_SPAN((*ftdmchan)),
494 BOOST_CHAN((*ftdmchan)),
495 r,
496 SIGBOOST_EVENT_CALL_START_NACK,
497 0, 0);
498 } else {
499 sangomabc_exec_command(&sangoma_boost_data->mcon,
500 0,
501 0,
502 r,
503 SIGBOOST_EVENT_CALL_START_NACK,
504 0, 0);
505 }
506 }
507
508 return status;
509 }
510
511
512
513
514
515
516 static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(sangoma_boost_outgoing_call)
517 {
518 ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data;
519
520 if (!sangoma_boost_data->sigmod) {
521 return FTDM_SUCCESS;
522 }
523
524 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND);
525
526 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DIALING);
527
528 return FTDM_SUCCESS;
529 }
530
531
532
533
534
535
536 static void handle_call_progress(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event)
537 {
538 ftdm_channel_t *ftdmchan;
539
540
541 if ((ftdmchan = find_ftdmchan(span, event, 1))) {
542 ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data;
543 ftdm_mutex_lock(ftdmchan->mutex);
544 if (!sangoma_boost_data->sigmod && ftdmchan->state == FTDM_CHANNEL_STATE_HOLD) {
545 if ((event->flags & SIGBOOST_PROGRESS_MEDIA)) {
546 ftdmchan->init_state = FTDM_CHANNEL_STATE_PROGRESS_MEDIA;
547 ftdm_log(FTDM_LOG_DEBUG, "Channel init state updated to PROGRESS_MEDIA [Csid:%d]\n", event->call_setup_id);
548 } else if ((event->flags & SIGBOOST_PROGRESS_RING)) {
549 ftdmchan->init_state = FTDM_CHANNEL_STATE_PROGRESS;
550 ftdm_log(FTDM_LOG_DEBUG, "Channel init state updated to PROGRESS [Csid:%d]\n", event->call_setup_id);
551 } else {
552 ftdmchan->init_state = FTDM_CHANNEL_STATE_IDLE;
553 ftdm_log(FTDM_LOG_DEBUG, "Channel init state updated to IDLE [Csid:%d]\n", event->call_setup_id);
554 }
555 } else {
556 if ((event->flags & SIGBOOST_PROGRESS_MEDIA)) {
557 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
558 } else if ((event->flags & SIGBOOST_PROGRESS_RING)) {
559 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
560 } else {
561 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
562 }
563 }
564 ftdm_mutex_unlock(ftdmchan->mutex);
565 }
566 }
567
568
569
570
571
572
573 static void handle_call_start_ack(sangomabc_connection_t *mcon, sangomabc_short_event_t *event)
574 {
575
576 ftdm_channel_t *ftdmchan = NULL;
577 uint32_t event_span = BOOST_EVENT_SPAN(mcon->sigmod, event);
578 uint32_t event_chan = BOOST_EVENT_CHAN(mcon->sigmod, event);
579
580
581 if (nack_map[event->call_setup_id]) {
582
583
584
585
586 return;
587 }
588
589 if (mcon->sigmod) {
590 ftdmchan = OUTBOUND_REQUESTS[event->call_setup_id].ftdmchan;
591 } else {
592 ftdmchan = find_ftdmchan(OUTBOUND_REQUESTS[event->call_setup_id].span, event, 0);
593 }
594
595
596 if (ftdmchan) {
597 ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data;
598 if (!mcon->sigmod && ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
599 ftdm_log(FTDM_LOG_ERROR, "Failed to open FTDM channel [%s]\n", ftdmchan->last_error);
600 } else {
601
602
603
604 OUTBOUND_REQUESTS[event->call_setup_id].event = *event;
605 SETUP_GRID[event_span][event_chan] = event->call_setup_id;
606
607 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND);
608 ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_INUSE);
609 ftdmchan->sflags = SFLAG_RECVD_ACK;
610
611 if ((event->flags & SIGBOOST_PROGRESS_MEDIA)) {
612 if (sangoma_boost_data->sigmod) {
613 ftdm_log(FTDM_LOG_DEBUG, "Channel state changing to PROGRESS_MEDIA [Csid:%d]\n", event->call_setup_id);
614 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
615 } else {
616 ftdmchan->init_state = FTDM_CHANNEL_STATE_PROGRESS_MEDIA;
617 ftdm_log(FTDM_LOG_DEBUG, "Channel init state changed to PROGRESS_MEDIA [Csid:%d]\n", event->call_setup_id);
618 }
619 } else if ((event->flags & SIGBOOST_PROGRESS_RING)) {
620 if (sangoma_boost_data->sigmod) {
621 ftdm_log(FTDM_LOG_DEBUG, "Channel state changing to PROGRESS [Csid:%d]\n", event->call_setup_id);
622 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
623 } else {
624 ftdmchan->init_state = FTDM_CHANNEL_STATE_PROGRESS;
625 ftdm_log(FTDM_LOG_DEBUG, "Channel init state changed to PROGRESS [Csid:%d]\n", event->call_setup_id);
626 }
627 } else {
628 if (sangoma_boost_data->sigmod) {
629
630 } else {
631 ftdmchan->init_state = FTDM_CHANNEL_STATE_IDLE;
632 ftdm_log(FTDM_LOG_DEBUG, "Channel init state changed to IDLE [Csid:%d]\n", event->call_setup_id);
633 }
634 }
635 if (!sangoma_boost_data->sigmod) {
636 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HOLD);
637 ftdm_log(FTDM_LOG_DEBUG, "Assigned chan %d:%d (%d:%d) to CSid=%d\n",
638 ftdmchan->span_id, ftdmchan->chan_id, event_span, event_chan, event->call_setup_id);
639 OUTBOUND_REQUESTS[event->call_setup_id].ftdmchan = ftdmchan;
640 }
641 OUTBOUND_REQUESTS[event->call_setup_id].flags = event->flags;
642 OUTBOUND_REQUESTS[event->call_setup_id].status = BST_READY;
643 return;
644 }
645
646 } else {
647
648 ftdm_assert(!mcon->sigmod, "CALL STOP ACK: Invalid Sigmod Path");
649
650 if ((ftdmchan = find_ftdmchan(OUTBOUND_REQUESTS[event->call_setup_id].span, (sangomabc_short_event_t*)event, 1))) {
651 int r;
652
653
654
655
656
657 if (ftdmchan->state == FTDM_CHANNEL_STATE_UP ||
658 ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA ||
659 ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS) {
660 ftdm_log(FTDM_LOG_CRIT, "FTDMCHAN CALL ACK STATE UP -> Changed to TERMINATING %d:%d\n", event_span, event_chan);
661 ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, r);
662 } else if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP || ftdm_test_sflag(ftdmchan, SFLAG_HANGUP)) {
663 ftdm_log(FTDM_LOG_CRIT, "FTDMCHAN CALL ACK STATE HANGUP -> Changed to HANGUP COMPLETE %d:%d\n", event_span, event_chan);
664 ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, r);
665 } else {
666 ftdm_log(FTDM_LOG_CRIT, "FTDMCHAN STATE INVALID State %s on IN CALL ACK %d:%d\n",
667 ftdm_channel_state2str(ftdmchan->state), event_span, event_chan);
668 }
669 ftdm_set_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG);
670 ftdmchan=NULL;
671 }
672 }
673
674
675 if (!ftdmchan) {
676 ftdm_log(FTDM_LOG_CRIT, "START ACK CANT FIND A CHAN %d:%d\n", event_span, event_chan);
677 } else {
678
679 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
680 ftdm_set_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG);
681 }
682
683 sangomabc_exec_command(mcon,
684 event->span,
685 event->chan,
686 event->call_setup_id,
687 SIGBOOST_EVENT_CALL_STOPPED,
688 FTDM_CAUSE_DESTINATION_OUT_OF_ORDER, 0);
689 OUTBOUND_REQUESTS[event->call_setup_id].status = BST_FAIL;
690 OUTBOUND_REQUESTS[event->call_setup_id].hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;
691 }
692
693
694
695
696
697
698
699 static void handle_call_done(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event)
700 {
701 ftdm_channel_t *ftdmchan;
702 int r = 0;
703
704 if ((ftdmchan = find_ftdmchan(span, event, 1))) {
705 ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data;
706 ftdm_mutex_lock(ftdmchan->mutex);
707
708 if (sangoma_boost_data->sigmod) {
709
710
711 sangomabc_exec_command(&sangoma_boost_data->mcon,
712 BOOST_SPAN(ftdmchan),
713 BOOST_CHAN(ftdmchan),
714 0,
715 SIGBOOST_EVENT_CALL_RELEASED,
716 0, 0);
717 }
718
719 if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN || ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP_COMPLETE || ftdm_test_sflag(ftdmchan, SFLAG_TERMINATING)) {
720 goto done;
721 }
722
723 ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, r);
724 if (r) {
725 ftdm_mutex_unlock(ftdmchan->mutex);
726 return;
727 }
728 }
729
730 done:
731
732 if (ftdmchan) {
733 ftdm_mutex_unlock(ftdmchan->mutex);
734 }
735
736 if (event->call_setup_id) {
737 release_request_id(event->call_setup_id);
738 } else {
739 release_request_id_span_chan(BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
740 }
741 }
742
743
744
745
746
747
748
749
750 static void handle_call_start_nack(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event)
751 {
752 ftdm_channel_t *ftdmchan;
753 ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
754
755 if (event->release_cause == SIGBOOST_CALL_SETUP_NACK_ALL_CKTS_BUSY) {
756 uint32_t count = 0;
757 int delay = 0;
758 int tg=event->trunk_group;
759
760 ftdm_span_channel_use_count(span, &count);
761
762 delay = (int) (count / 100) * 2;
763
764 if (delay > 10) {
765 delay = 10;
766 } else if (delay < 1) {
767 delay = 1;
768 }
769
770 if (tg < 0 || tg >= MAX_TRUNK_GROUPS) {
771 ftdm_log(FTDM_LOG_CRIT, "Invalid All Ckt Busy trunk group number %i\n", tg);
772 tg=0;
773 }
774
775 congestion_timeouts[tg] = time(NULL) + delay;
776 event->release_cause = 17;
777
778 } else if (event->release_cause == SIGBOOST_CALL_SETUP_CSUPID_DBL_USE) {
779 event->release_cause = 17;
780 }
781
782 if (event->call_setup_id) {
783 if (sangoma_boost_data->sigmod) {
784 ftdmchan = OUTBOUND_REQUESTS[event->call_setup_id].ftdmchan;
785 CALL_DATA(ftdmchan)->last_event_id = event->event_id;
786 CALL_DATA(ftdmchan)->call_setup_id = event->call_setup_id;
787 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
788 ftdm_clear_sflag_locked(ftdmchan, SFLAG_SENT_FINAL_MSG);
789 } else {
790 sangomabc_exec_command(mcon,
791 0,
792 0,
793 event->call_setup_id,
794 SIGBOOST_EVENT_CALL_START_NACK_ACK,
795 0, 0);
796 OUTBOUND_REQUESTS[event->call_setup_id].event = *event;
797 OUTBOUND_REQUESTS[event->call_setup_id].status = BST_FAIL;
798 OUTBOUND_REQUESTS[event->call_setup_id].hangup_cause = event->release_cause;
799 ftdm_log(FTDM_LOG_DEBUG, "setting outbound request status %d to BST_FAIL\n", event->call_setup_id);
800 }
801 return;
802 } else {
803 if ((ftdmchan = find_ftdmchan(span, event, 1))) {
804 int r = 0;
805
806
807 ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND), "Yay, outbound flag should not be set here!\n");
808
809 CALL_DATA(ftdmchan)->last_event_id = event->event_id;
810 ftdm_mutex_lock(ftdmchan->mutex);
811 ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, r);
812 if (r == FTDM_SUCCESS) {
813 ftdmchan->caller_data.hangup_cause = event->release_cause;
814 }
815 ftdm_mutex_unlock(ftdmchan->mutex);
816 if (r) {
817 return;
818 }
819 }
820 }
821
822 if (ftdmchan) {
823 ftdm_set_sflag_locked(ftdmchan, SFLAG_SENT_FINAL_MSG);
824 }
825
826
827 sangomabc_exec_command(mcon,
828 event->span,
829 event->chan,
830 event->call_setup_id,
831 SIGBOOST_EVENT_CALL_START_NACK_ACK,
832 0, 0);
833 }
834
835 static void handle_call_released(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event)
836 {
837 ftdm_channel_t *ftdmchan;
838
839 if ((ftdmchan = find_ftdmchan(span, event, 1))) {
840 ftdm_log(FTDM_LOG_DEBUG, "Releasing completely chan s%dc%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event),
841 BOOST_EVENT_CHAN(mcon->sigmod, event));
842 ftdm_channel_close(&ftdmchan);
843 } else {
844 ftdm_log(FTDM_LOG_CRIT, "Odd, We could not find chan: s%dc%d to release the call completely!!\n",
845 BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
846 }
847 }
848
849
850
851
852
853
854
855 static void handle_call_stop(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event)
856 {
857 ftdm_channel_t *ftdmchan;
858
859 if ((ftdmchan = find_ftdmchan(span, event, 1))) {
860 int r = 0;
861
862 ftdm_mutex_lock(ftdmchan->mutex);
863
864 if (ftdm_test_sflag(ftdmchan, SFLAG_HANGUP) ||
865 ftdmchan->state == FTDM_CHANNEL_STATE_DOWN ||
866 ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
867
868
869
870
871
872
873
874
875
876
877
878 sangomabc_exec_command(mcon,
879 BOOST_SPAN(ftdmchan),
880 BOOST_CHAN(ftdmchan),
881 0,
882 SIGBOOST_EVENT_CALL_STOPPED_ACK,
883 0, 0);
884 ftdm_mutex_unlock(ftdmchan->mutex);
885 return;
886 } else if (ftdmchan->state == FTDM_CHANNEL_STATE_HOLD) {
887 ftdmchan->init_state = FTDM_CHANNEL_STATE_TERMINATING;
888 ftdm_log(FTDM_LOG_DEBUG, "Channel init state updated to TERMINATING [Csid:%d]\n", event->call_setup_id);
889 OUTBOUND_REQUESTS[event->call_setup_id].hangup_cause = event->release_cause;
890 ftdmchan->caller_data.hangup_cause = event->release_cause;
891 ftdm_mutex_unlock(ftdmchan->mutex);
892 return;
893 } else {
894 ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, r);
895 }
896
897 if (r == FTDM_SUCCESS) {
898 ftdmchan->caller_data.hangup_cause = event->release_cause;
899 }
900
901 ftdm_mutex_unlock(ftdmchan->mutex);
902
903 if (r) {
904 return;
905 }
906 } else {
907 ftdm_log(FTDM_LOG_CRIT, "Odd, We could not find chan: s%dc%d\n",
908 BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
909 release_request_id_span_chan(BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
910 }
911 }
912
913
914
915
916
917
918
919 static void handle_call_answer(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event)
920 {
921 ftdm_channel_t *ftdmchan;
922
923 if ((ftdmchan = find_ftdmchan(span, event, 1))) {
924 ftdm_mutex_lock(ftdmchan->mutex);
925
926 if (ftdm_test_sflag(ftdmchan, SFLAG_HANGUP) ||
927 ftdmchan->state == FTDM_CHANNEL_STATE_DOWN ||
928 ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
929
930
931
932 ftdm_log(FTDM_LOG_DEBUG, "Got answer but call is already hangup %d:%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event),
933 BOOST_EVENT_CHAN(mcon->sigmod, event));
934
935 } else if (ftdmchan->state == FTDM_CHANNEL_STATE_HOLD) {
936 ftdmchan->init_state = FTDM_CHANNEL_STATE_UP;
937
938 } else {
939 int r = 0;
940 ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_UP, r);
941 }
942 ftdm_mutex_unlock(ftdmchan->mutex);
943 } else {
944 ftdm_log(FTDM_LOG_CRIT, "Could not find channel %d:%d on answer message!\n", BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
945 sangomabc_exec_command(mcon,
946 event->span,
947 event->chan,
948 event->call_setup_id,
949 SIGBOOST_EVENT_CALL_STOPPED,
950 FTDM_CAUSE_DESTINATION_OUT_OF_ORDER, 0);
951 }
952 }
953
954 static __inline__ void stop_loop(ftdm_channel_t *ftdmchan);
955
956
957
958
959
960
961
962 static void handle_call_start(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_event_t *event)
963 {
964 ftdm_channel_t *ftdmchan = NULL;
965 int hangup_cause = FTDM_CAUSE_CALL_REJECTED;
966 int retry = 1;
967
968 tryagain:
969
970 if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 0))) {
971 if ((ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) {
972 int r;
973
974
975
976
977
978
979
980 if (ftdmchan->state == FTDM_CHANNEL_STATE_UP ||
981 ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA ||
982 ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS) {
983 ftdm_log(FTDM_LOG_CRIT, "s%dc%d: FTDMCHAN STATE UP -> Changed to TERMINATING\n",
984 BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
985 ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING, r);
986 } else if (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP || ftdm_test_sflag(ftdmchan, SFLAG_HANGUP)) {
987 ftdm_log(FTDM_LOG_CRIT, "s%dc%d: FTDMCHAN STATE HANGUP -> Changed to HANGUP COMPLETE\n",
988 BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
989 ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, r);
990 } else if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) {
991 ftdm_log(FTDM_LOG_WARNING, "s%dc%d: Collision, hanging up incoming call\n",
992 BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
993
994
995
996
997
998
999
1000
1001 } else if (ftdmchan->state == FTDM_CHANNEL_STATE_IN_LOOP && retry) {
1002 retry = 0;
1003 stop_loop(ftdmchan);
1004 ftdm_channel_advance_states(ftdmchan);
1005 goto tryagain;
1006 } else {
1007 ftdm_log(FTDM_LOG_ERROR, "s%dc%d: rejecting incoming call in channel state %s\n",
1008 BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event),
1009 ftdm_channel_state2str(ftdmchan->state));
1010 }
1011 ftdm_set_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG);
1012 ftdmchan = NULL;
1013 } else {
1014 ftdm_log(FTDM_LOG_CRIT, "s%dc%d: incoming call in invalid channel (channel not found)!\n",
1015 BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
1016 }
1017 goto error;
1018 }
1019
1020 if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
1021 ftdm_log(FTDM_LOG_ERROR, "s%dc%d: failed to open channel on incoming call, rejecting!\n",
1022 BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
1023 goto error;
1024 }
1025
1026 ftdm_log(FTDM_LOG_DEBUG, "Got call start from s%dc%d mapped to freetdm logical s%dc%d, physical s%dc%d\n",
1027 event->span, event->chan,
1028 ftdmchan->span_id, ftdmchan->chan_id,
1029 ftdmchan->physical_span_id, ftdmchan->physical_chan_id);
1030
1031 ftdmchan->sflags = 0;
1032 ftdm_set_string(ftdmchan->caller_data.cid_num.digits, (char *)event->calling.digits);
1033 ftdm_set_string(ftdmchan->caller_data.cid_name, (char *)event->calling.digits);
1034 ftdm_set_string(ftdmchan->caller_data.ani.digits, (char *)event->calling.digits);
1035 ftdm_set_string(ftdmchan->caller_data.dnis.digits, (char *)event->called.digits);
1036 ftdm_set_string(ftdmchan->caller_data.rdnis.digits, (char *)event->rdnis.digits);
1037 if (event->custom_data_size) {
1038 ftdm_set_string(ftdmchan->caller_data.raw_data, event->custom_data);
1039 ftdmchan->caller_data.raw_data_len = event->custom_data_size;
1040 }
1041
1042 if (strlen(event->calling_name)) {
1043 ftdm_set_string(ftdmchan->caller_data.cid_name, (char *)event->calling_name);
1044 }
1045
1046 ftdmchan->caller_data.cid_num.plan = event->calling.npi;
1047 ftdmchan->caller_data.cid_num.type = event->calling.ton;
1048
1049 ftdmchan->caller_data.ani.plan = event->calling.npi;
1050 ftdmchan->caller_data.ani.type = event->calling.ton;
1051
1052 ftdmchan->caller_data.dnis.plan = event->called.npi;
1053 ftdmchan->caller_data.dnis.type = event->called.ton;
1054
1055 ftdmchan->caller_data.rdnis.plan = event->rdnis.npi;
1056 ftdmchan->caller_data.rdnis.type = event->rdnis.ton;
1057
1058 ftdmchan->caller_data.screen = event->calling.screening_ind;
1059 ftdmchan->caller_data.pres = event->calling.presentation_ind;
1060
1061 ftdmchan->caller_data.bearer_capability = event->bearer.capability;
1062 ftdmchan->caller_data.bearer_layer1 = event->bearer.uil1p;
1063
1064
1065 if (event->custom_data_size) {
1066 char* p = NULL;
1067
1068 p = strstr((char*)event->custom_data,"PRI001-ANI2-");
1069 if (p!=NULL) {
1070 int ani2 = 0;
1071 sscanf(p, "PRI001-ANI2-%d", &ani2);
1072 snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", ani2);
1073 }
1074 }
1075
1076 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
1077 return;
1078
1079 error:
1080 hangup_cause = ftdmchan ? ftdmchan->caller_data.hangup_cause : FTDM_CAUSE_REQUESTED_CHAN_UNAVAIL;
1081 sangomabc_exec_command(mcon,
1082 event->span,
1083 event->chan,
1084 event->call_setup_id,
1085 SIGBOOST_EVENT_CALL_START_NACK,
1086 hangup_cause, 0);
1087
1088 }
1089
1090 static void handle_call_loop_start(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event)
1091 {
1092 ftdm_status_t res = FTDM_FAIL;
1093 ftdm_channel_t *ftdmchan;
1094
1095 if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 0))) {
1096 ftdm_log(FTDM_LOG_CRIT, "CANNOT START LOOP, CHAN NOT AVAILABLE %d:%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
1097 return;
1098 }
1099
1100 if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
1101 ftdm_log(FTDM_LOG_CRIT, "CANNOT START LOOP, CANT OPEN CHAN %d:%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
1102 return;
1103 }
1104
1105 ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP, res);
1106 if (res != FTDM_SUCCESS) {
1107 ftdm_channel_t *toclose = ftdmchan;
1108 ftdm_log(FTDM_LOG_CRIT, "yay, could not set the state of the channel to IN_LOOP, loop will fail\n");
1109 ftdm_channel_close(&toclose);
1110 return;
1111 }
1112 ftdm_log(FTDM_LOG_DEBUG, "%d:%d starting loop\n", ftdmchan->span_id, ftdmchan->chan_id);
1113 ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_LOOP, NULL);
1114 }
1115
1116 static __inline__ void stop_loop(ftdm_channel_t *ftdmchan)
1117 {
1118 ftdm_status_t res = FTDM_FAIL;
1119 ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL);
1120
1121 ftdm_set_flag(ftdmchan, SFLAG_SENT_FINAL_MSG);
1122 ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_DOWN, res);
1123 if (res != FTDM_SUCCESS) {
1124 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "yay, could not set the state of the channel from IN_LOOP to DOWN\n");
1125 }
1126 }
1127
1128 static void handle_call_loop_stop(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event)
1129 {
1130 ftdm_channel_t *ftdmchan;
1131 if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) {
1132 ftdm_log(FTDM_LOG_CRIT, "CANNOT STOP LOOP, INVALID CHAN REQUESTED %d:%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
1133 return;
1134 }
1135 if (ftdmchan->state != FTDM_CHANNEL_STATE_IN_LOOP) {
1136 ftdm_log(FTDM_LOG_WARNING, "Got stop loop request in a channel that is not in loop, ignoring ...\n");
1137 return;
1138 }
1139 stop_loop(ftdmchan);
1140 }
1141
1142
1143
1144
1145
1146
1147 static void handle_heartbeat(sangomabc_connection_t *mcon, sangomabc_short_event_t *event)
1148 {
1149 int err;
1150
1151 err = sangomabc_connection_writep(mcon, (sangomabc_event_t*)event);
1152
1153 if (err <= 0) {
1154 ftdm_log(FTDM_LOG_CRIT, "Failed to tx on boost connection [%s]: %s\n", strerror(errno));
1155 }
1156 return;
1157 }
1158
1159
1160
1161
1162
1163
1164
1165 static void handle_restart_ack(sangomabc_connection_t *mcon, ftdm_span_t *span, sangomabc_short_event_t *event)
1166 {
1167 ftdm_log(FTDM_LOG_DEBUG, "RECV RESTART ACK\n");
1168 }
1169
1170
1171
1172
1173
1174
1175
1176 static void handle_restart(sangomabc_connection_t *mcon, ftdm_span_t *span, sangomabc_short_event_t *event)
1177 {
1178 ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
1179
1180 mcon->rxseq_reset = 0;
1181 ftdm_set_flag((&sangoma_boost_data->mcon), MSU_FLAG_DOWN);
1182 ftdm_set_flag_locked(span, FTDM_SPAN_SUSPENDED);
1183 ftdm_set_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RESTARTING);
1184
1185 }
1186
1187
1188
1189
1190
1191
1192
1193 static void handle_incoming_digit(sangomabc_connection_t *mcon, ftdm_span_t *span, sangomabc_event_t *event)
1194 {
1195 ftdm_channel_t *ftdmchan = NULL;
1196 char digits[MAX_DIALED_DIGITS + 2] = "";
1197
1198 if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t *)event, 1))) {
1199 ftdm_log(FTDM_LOG_ERROR, "Invalid channel\n");
1200 return;
1201 }
1202
1203 if (event->called_number_digits_count == 0) {
1204 ftdm_log(FTDM_LOG_WARNING, "Error Incoming digit with len %s %d [w%dg%d]\n",
1205 event->called_number_digits,
1206 event->called_number_digits_count,
1207 BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
1208 return;
1209 }
1210
1211 ftdm_log(FTDM_LOG_WARNING, "Incoming digit with len %s %d [w%dg%d]\n",
1212 event->called_number_digits,
1213 event->called_number_digits_count,
1214 BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
1215
1216 memcpy(digits, event->called_number_digits, event->called_number_digits_count);
1217 ftdm_channel_queue_dtmf(ftdmchan, digits);
1218
1219 return;
1220 }
1221
1222
1223
1224
1225
1226
1227
1228
1229 static ftdm_channel_t* event_process_states(ftdm_span_t *span, sangomabc_short_event_t *event)
1230 {
1231 ftdm_channel_t *ftdmchan = NULL;
1232 ftdm_sangoma_boost_data_t *signal_data = span->signal_data;
1233
1234 switch (event->event_id) {
1235 case SIGBOOST_EVENT_CALL_START_NACK:
1236 case SIGBOOST_EVENT_CALL_START_NACK_ACK:
1237 if (event->call_setup_id && !signal_data->sigmod) {
1238 return NULL;
1239 }
1240
1241 case SIGBOOST_EVENT_CALL_START:
1242 case SIGBOOST_EVENT_CALL_START_ACK:
1243 case SIGBOOST_EVENT_CALL_STOPPED:
1244 case SIGBOOST_EVENT_CALL_PROGRESS:
1245 case SIGBOOST_EVENT_CALL_ANSWERED:
1246 case SIGBOOST_EVENT_CALL_STOPPED_ACK:
1247 case SIGBOOST_EVENT_DIGIT_IN:
1248 case SIGBOOST_EVENT_INSERT_CHECK_LOOP:
1249 case SIGBOOST_EVENT_REMOVE_CHECK_LOOP:
1250 case SIGBOOST_EVENT_CALL_RELEASED:
1251 if (!(ftdmchan = find_ftdmchan(span, (sangomabc_short_event_t*)event, 1))) {
1252 ftdm_log(FTDM_LOG_CRIT, "could not find channel %d:%d to process pending state changes!\n",
1253 BOOST_EVENT_SPAN(signal_data->sigmod, event),
1254 BOOST_EVENT_CHAN(signal_data->sigmod, event));
1255 return NULL;
1256 }
1257 break;
1258 case SIGBOOST_EVENT_HEARTBEAT:
1259 case SIGBOOST_EVENT_SYSTEM_RESTART_ACK:
1260 case SIGBOOST_EVENT_SYSTEM_RESTART:
1261 case SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE:
1262 return NULL;
1263 default:
1264 ftdm_log(FTDM_LOG_CRIT, "Unhandled event id: %d\n", event->event_id);
1265 return NULL;
1266 }
1267
1268 ftdm_mutex_lock(ftdmchan->mutex);
1269 ftdm_channel_advance_states(ftdmchan);
1270 return ftdmchan;
1271 }
1272
1273
1274
1275
1276
1277
1278
1279 static int parse_sangoma_event(ftdm_span_t *span, sangomabc_connection_t *mcon, sangomabc_short_event_t *event)
1280 {
1281 ftdm_channel_t* ftdmchan = NULL;
1282
1283 if (!ftdm_running()) {
1284 ftdm_log(FTDM_LOG_WARNING, "System is shutting down.\n");
1285 return -1;
1286 }
1287
1288 ftdm_assert_return(event->call_setup_id <= MAX_REQ_ID, -1, "Unexpected call setup id\n");
1289
1290
1291
1292 ftdmchan = event_process_states(span, event);
1293
1294 switch(event->event_id) {
1295 case SIGBOOST_EVENT_CALL_START:
1296 handle_call_start(span, mcon, (sangomabc_event_t*)event);
1297 break;
1298 case SIGBOOST_EVENT_CALL_STOPPED:
1299 handle_call_stop(span, mcon, event);
1300 break;
1301 case SIGBOOST_EVENT_CALL_RELEASED:
1302 handle_call_released(span, mcon, event);
1303 break;
1304 case SIGBOOST_EVENT_CALL_START_ACK:
1305 handle_call_start_ack(mcon, event);
1306 break;
1307 case SIGBOOST_EVENT_CALL_PROGRESS:
1308 handle_call_progress(span, mcon, event);
1309 break;
1310 case SIGBOOST_EVENT_CALL_START_NACK:
1311 handle_call_start_nack(span, mcon, event);
1312 break;
1313 case SIGBOOST_EVENT_CALL_ANSWERED:
1314 handle_call_answer(span, mcon, event);
1315 break;
1316 case SIGBOOST_EVENT_HEARTBEAT:
1317 handle_heartbeat(mcon, event);
1318 break;
1319 case SIGBOOST_EVENT_CALL_STOPPED_ACK:
1320 handle_call_done(span, mcon, event);
1321 break;
1322 case SIGBOOST_EVENT_CALL_START_NACK_ACK:
1323
1324
1325 if (event->call_setup_id) {
1326 nack_map[event->call_setup_id] = 0;
1327 release_request_id(event->call_setup_id);
1328 } else {
1329 handle_call_done(span, mcon, event);
1330 }
1331 break;
1332 case SIGBOOST_EVENT_INSERT_CHECK_LOOP:
1333 handle_call_loop_start(span, mcon, event);
1334 break;
1335 case SIGBOOST_EVENT_REMOVE_CHECK_LOOP:
1336 handle_call_loop_stop(span, mcon, event);
1337 break;
1338 case SIGBOOST_EVENT_SYSTEM_RESTART_ACK:
1339 handle_restart_ack(mcon, span, event);
1340 break;
1341 case SIGBOOST_EVENT_SYSTEM_RESTART:
1342 handle_restart(mcon, span, event);
1343 break;
1344 case SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE:
1345
1346 break;
1347 case SIGBOOST_EVENT_DIGIT_IN:
1348 handle_incoming_digit(mcon, span, (sangomabc_event_t*)event);
1349 break;
1350 default:
1351 ftdm_log(FTDM_LOG_WARNING, "No handler implemented for [%s]\n", sangomabc_event_id_name(event->event_id));
1352 break;
1353 }
1354
1355 if(ftdmchan != NULL) {
1356 ftdm_channel_advance_states(ftdmchan);
1357 ftdm_mutex_unlock(ftdmchan->mutex);
1358 }
1359
1360 return 0;
1361
1362 }
1363
1364
1365
1366
1367
1368 static ftdm_status_t state_advance(ftdm_channel_t *ftdmchan)
1369 {
1370 ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data;
1371 sangomabc_connection_t *mcon = &sangoma_boost_data->mcon;
1372 ftdm_sigmsg_t sig;
1373 ftdm_status_t status;
1374
1375
1376 ftdm_assert_return(ftdmchan->last_state != ftdmchan->state, FTDM_FAIL, "Channel state already processed\n");
1377
1378 ftdm_log(FTDM_LOG_DEBUG, "%d:%d PROCESSING STATE [%s]\n", ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state));
1379
1380 memset(&sig, 0, sizeof(sig));
1381 sig.chan_id = ftdmchan->chan_id;
1382 sig.span_id = ftdmchan->span_id;
1383 sig.channel = ftdmchan;
1384
1385 ftdm_channel_complete_state(ftdmchan);
1386
1387 switch (ftdmchan->state) {
1388 case FTDM_CHANNEL_STATE_DOWN:
1389 {
1390 int call_stopped_ack_sent = 0;
1391 ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data;
1392
1393 if (ftdmchan->last_state == FTDM_CHANNEL_STATE_IN_LOOP) {
1394 ftdm_log(FTDM_LOG_DEBUG, "%d:%d terminating loop\n", ftdmchan->span_id, ftdmchan->chan_id);
1395 } else {
1396 release_request_id_span_chan(ftdmchan->physical_span_id, ftdmchan->physical_chan_id);
1397
1398 if (!ftdm_test_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG)) {
1399 ftdm_set_sflag_locked(ftdmchan, SFLAG_SENT_FINAL_MSG);
1400
1401 if (ftdmchan->call_data && CALL_DATA(ftdmchan)->last_event_id == SIGBOOST_EVENT_CALL_START_NACK) {
1402 sangomabc_exec_command(mcon,
1403 BOOST_SPAN(ftdmchan),
1404 BOOST_CHAN(ftdmchan),
1405 CALL_DATA(ftdmchan)->call_setup_id,
1406 SIGBOOST_EVENT_CALL_START_NACK_ACK,
1407 0, 0);
1408
1409 } else {
1410
1411 sangomabc_exec_command(mcon,
1412 BOOST_SPAN(ftdmchan),
1413 BOOST_CHAN(ftdmchan),
1414 0,
1415 SIGBOOST_EVENT_CALL_STOPPED_ACK,
1416 0, 0);
1417 call_stopped_ack_sent = 1;
1418 }
1419 }
1420 }
1421
1422 ftdmchan->sflags = 0;
1423 memset(ftdmchan->call_data, 0, sizeof(sangoma_boost_call_t));
1424 if (sangoma_boost_data->sigmod && call_stopped_ack_sent) {
1425
1426 ftdm_log(FTDM_LOG_DEBUG, "Waiting for call release confirmation before declaring chan %d:%d as available \n",
1427 ftdmchan->span_id, ftdmchan->chan_id);
1428 } else {
1429 ftdm_channel_t *toclose = ftdmchan;
1430 ftdm_channel_close(&toclose);
1431 }
1432 }
1433 break;
1434 case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
1435 {
1436 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
1437 sig.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
1438 if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) {
1439 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
1440 }
1441 } else {
1442 if (!ftdm_test_sflag(ftdmchan, SFLAG_SENT_ACK)) {
1443 ftdm_set_sflag(ftdmchan, SFLAG_SENT_ACK);
1444 sangomabc_exec_command(mcon,
1445 BOOST_SPAN(ftdmchan),
1446 BOOST_CHAN(ftdmchan),
1447 0,
1448 SIGBOOST_EVENT_CALL_START_ACK,
1449 0, 0);
1450 }
1451 sangomabc_exec_command(mcon,
1452 BOOST_SPAN(ftdmchan),
1453 BOOST_CHAN(ftdmchan),
1454 0,
1455 SIGBOOST_EVENT_CALL_PROGRESS,
1456 0, SIGBOOST_PROGRESS_MEDIA);
1457 }
1458 }
1459 break;
1460 case FTDM_CHANNEL_STATE_PROGRESS:
1461 {
1462 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
1463 sig.event_id = FTDM_SIGEVENT_PROGRESS;
1464 if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) {
1465 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
1466 }
1467 } else {
1468 if (!ftdm_test_sflag(ftdmchan, SFLAG_SENT_ACK)) {
1469 ftdm_set_sflag(ftdmchan, SFLAG_SENT_ACK);
1470 sangomabc_exec_command(mcon,
1471 BOOST_SPAN(ftdmchan),
1472 BOOST_CHAN(ftdmchan),
1473 0,
1474 SIGBOOST_EVENT_CALL_START_ACK,
1475 0, SIGBOOST_PROGRESS_RING);
1476 }
1477 }
1478 }
1479 break;
1480 case FTDM_CHANNEL_STATE_IDLE:
1481 case FTDM_CHANNEL_STATE_HOLD:
1482 {
1483
1484 }
1485 break;
1486 case FTDM_CHANNEL_STATE_RING:
1487 {
1488 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
1489 sig.event_id = FTDM_SIGEVENT_START;
1490 if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) {
1491 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
1492 }
1493 }
1494 }
1495 break;
1496 case FTDM_CHANNEL_STATE_RESTART:
1497 {
1498 sig.event_id = FTDM_SIGEVENT_RESTART;
1499 status = ftdm_span_send_signal(ftdmchan->span, &sig);
1500 ftdm_set_sflag_locked(ftdmchan, SFLAG_SENT_FINAL_MSG);
1501 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
1502 }
1503 break;
1504 case FTDM_CHANNEL_STATE_UP:
1505 {
1506 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
1507 sig.event_id = FTDM_SIGEVENT_UP;
1508 if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) {
1509 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
1510 }
1511 } else {
1512 if (!(ftdm_test_flag(ftdmchan, FTDM_CHANNEL_PROGRESS) || ftdm_test_flag(ftdmchan, FTDM_CHANNEL_MEDIA))) {
1513 sangomabc_exec_command(mcon,
1514 BOOST_SPAN(ftdmchan),
1515 BOOST_CHAN(ftdmchan),
1516 0,
1517 SIGBOOST_EVENT_CALL_START_ACK,
1518 0, 0);
1519 }
1520
1521 sangomabc_exec_command(mcon,
1522 BOOST_SPAN(ftdmchan),
1523 BOOST_CHAN(ftdmchan),
1524 0,
1525 SIGBOOST_EVENT_CALL_ANSWERED,
1526 0, 0);
1527 }
1528 }
1529 break;
1530 case FTDM_CHANNEL_STATE_DIALING:
1531 {
1532 char dnis[128] = "";
1533 sangoma_boost_request_id_t r;
1534 sangomabc_event_t event = {0};
1535
1536 ftdm_assert(sangoma_boost_data->sigmod != NULL, "We should be in sigmod here!\n");
1537
1538 ftdm_set_string(dnis, ftdmchan->caller_data.dnis.digits);
1539
1540 r = next_request_id();
1541 if (r == 0) {
1542 ftdm_log(FTDM_LOG_CRIT, "All boost request ids are busy.\n");
1543 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
1544 break;
1545 }
1546
1547 sangomabc_call_init(&event, ftdmchan->caller_data.cid_num.digits, dnis, r);
1548
1549 event.span = (uint8_t)ftdmchan->physical_span_id;
1550 event.chan = (uint8_t)ftdmchan->physical_chan_id;
1551
1552 SETUP_GRID[event.span][event.chan] = event.call_setup_id;
1553
1554 ftdm_set_string(event.calling_name, ftdmchan->caller_data.cid_name);
1555 ftdm_set_string(event.rdnis.digits, ftdmchan->caller_data.rdnis.digits);
1556 if (strlen(ftdmchan->caller_data.rdnis.digits)) {
1557 event.rdnis.digits_count = (uint8_t)strlen(ftdmchan->caller_data.rdnis.digits)+1;
1558 event.rdnis.ton = ftdmchan->caller_data.rdnis.type;
1559 event.rdnis.npi = ftdmchan->caller_data.rdnis.plan;
1560 }
1561
1562 event.calling.screening_ind = ftdmchan->caller_data.screen;
1563 event.calling.presentation_ind = ftdmchan->caller_data.pres;
1564
1565 event.calling.ton = ftdmchan->caller_data.cid_num.type;
1566 event.calling.npi = ftdmchan->caller_data.cid_num.plan;
1567
1568 event.called.ton = ftdmchan->caller_data.dnis.type;
1569 event.called.npi = ftdmchan->caller_data.dnis.plan;
1570
1571 if (ftdmchan->caller_data.raw_data_len) {
1572 ftdm_set_string(event.custom_data, ftdmchan->caller_data.raw_data);
1573 event.custom_data_size = (uint16_t)ftdmchan->caller_data.raw_data_len;
1574 }
1575
1576 OUTBOUND_REQUESTS[r].status = BST_WAITING;
1577 OUTBOUND_REQUESTS[r].span = ftdmchan->span;
1578 OUTBOUND_REQUESTS[r].ftdmchan = ftdmchan;
1579
1580 ftdm_log(FTDM_LOG_DEBUG, "Dialing number %s over boost channel with request id %d\n", event.called_number_digits, r);
1581 if (sangomabc_connection_write(&sangoma_boost_data->mcon, &event) <= 0) {
1582 release_request_id(r);
1583 ftdm_log(FTDM_LOG_CRIT, "Failed to tx boost event [%s]\n", strerror(errno));
1584 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
1585 }
1586
1587 }
1588 break;
1589 case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
1590 {
1591 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
1592 }
1593 break;
1594 case FTDM_CHANNEL_STATE_HANGUP:
1595 {
1596 ftdm_set_sflag_locked(ftdmchan, SFLAG_HANGUP);
1597
1598 if (ftdm_test_sflag(ftdmchan, SFLAG_SENT_FINAL_MSG) || ftdm_test_sflag(ftdmchan, SFLAG_TERMINATING)) {
1599 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
1600 } else {
1601 ftdm_set_sflag_locked(ftdmchan, SFLAG_SENT_FINAL_MSG);
1602 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_ANSWERED) ||
1603 ftdm_test_flag(ftdmchan, FTDM_CHANNEL_PROGRESS) ||
1604 ftdm_test_flag(ftdmchan, FTDM_CHANNEL_MEDIA) ||
1605 ftdm_test_sflag(ftdmchan, SFLAG_RECVD_ACK)) {
1606 sangomabc_exec_command(mcon,
1607 BOOST_SPAN(ftdmchan),
1608 BOOST_CHAN(ftdmchan),
1609 0,
1610 SIGBOOST_EVENT_CALL_STOPPED,
1611 ftdmchan->caller_data.hangup_cause, 0);
1612 } else {
1613 sangomabc_exec_command(mcon,
1614 BOOST_SPAN(ftdmchan),
1615 BOOST_CHAN(ftdmchan),
1616 0,
1617 SIGBOOST_EVENT_CALL_START_NACK,
1618 ftdmchan->caller_data.hangup_cause, 0);
1619 }
1620 }
1621 }
1622 break;
1623 case FTDM_CHANNEL_STATE_TERMINATING:
1624 {
1625 ftdm_set_sflag_locked(ftdmchan, SFLAG_TERMINATING);
1626 sig.event_id = FTDM_SIGEVENT_STOP;
1627 status = ftdm_span_send_signal(ftdmchan->span, &sig);
1628 }
1629 break;
1630 case FTDM_CHANNEL_STATE_IN_LOOP:
1631 {
1632
1633 }
1634 break;
1635 default:
1636 break;
1637 }
1638 return FTDM_SUCCESS;
1639 }
1640
1641
1642
1643
1644 static __inline__ void init_outgoing_array(void)
1645 {
1646 memset(&OUTBOUND_REQUESTS, 0, sizeof(OUTBOUND_REQUESTS));
1647 }
1648
1649
1650
1651
1652
1653 static __inline__ void check_state(ftdm_span_t *span)
1654 {
1655 ftdm_channel_t *ftdmchan = NULL;
1656 ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
1657 int susp = ftdm_test_flag(span, FTDM_SPAN_SUSPENDED);
1658
1659 if (susp && ftdm_check_state_all(span, FTDM_CHANNEL_STATE_DOWN)) {
1660 susp = 0;
1661 }
1662
1663 if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE) || susp) {
1664 uint32_t j;
1665 ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE);
1666 if (susp) {
1667 for(j = 1; j <= span->chan_count; j++) {
1668 if (ftdm_test_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE) || susp) {
1669 ftdm_mutex_lock(span->channels[j]->mutex);
1670 ftdm_clear_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE);
1671 if (susp && span->channels[j]->state != FTDM_CHANNEL_STATE_DOWN) {
1672 ftdm_set_state(span->channels[j], FTDM_CHANNEL_STATE_RESTART);
1673 }
1674 ftdm_channel_advance_states(span->channels[j]);
1675 ftdm_mutex_unlock(span->channels[j]->mutex);
1676 }
1677 }
1678 } else {
1679 while ((ftdmchan = ftdm_queue_dequeue(span->pendingchans))) {
1680
1681
1682
1683 ftdm_mutex_lock(ftdmchan->mutex);
1684 ftdm_channel_advance_states(ftdmchan);
1685 ftdm_mutex_unlock(ftdmchan->mutex);
1686 }
1687 }
1688 }
1689
1690 if (ftdm_test_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RESTARTING)) {
1691 if (ftdm_check_state_all(span, FTDM_CHANNEL_STATE_DOWN)) {
1692 sangomabc_exec_command(&sangoma_boost_data->mcon,
1693 0,
1694 0,
1695 -1,
1696 SIGBOOST_EVENT_SYSTEM_RESTART_ACK,
1697 0, 0);
1698 ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RESTARTING);
1699 ftdm_clear_flag_locked(span, FTDM_SPAN_SUSPENDED);
1700 ftdm_clear_flag((&sangoma_boost_data->mcon), MSU_FLAG_DOWN);
1701 init_outgoing_array();
1702 }
1703 }
1704 }
1705
1706
1707
1708
1709
1710
1711 static __inline__ ftdm_status_t check_events(ftdm_span_t *span, int ms_timeout)
1712 {
1713 ftdm_status_t status;
1714 ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
1715
1716 status = ftdm_span_poll_event(span, ms_timeout, NULL);
1717
1718 switch(status) {
1719 case FTDM_SUCCESS:
1720 {
1721 ftdm_event_t *event;
1722 while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) {
1723 switch (event->enum_id) {
1724 case FTDM_OOB_ALARM_TRAP:
1725 if (sangoma_boost_data->sigmod) {
1726 sangoma_boost_data->sigmod->on_hw_link_status_change(event->channel, FTDM_HW_LINK_DISCONNECTED);
1727 }
1728 break;
1729 case FTDM_OOB_ALARM_CLEAR:
1730 if (sangoma_boost_data->sigmod) {
1731 sangoma_boost_data->sigmod->on_hw_link_status_change(event->channel, FTDM_HW_LINK_CONNECTED);
1732 }
1733 break;
1734 }
1735 }
1736 }
1737 break;
1738 case FTDM_FAIL:
1739 {
1740 if (!ftdm_running()) {
1741 break;
1742 }
1743 ftdm_log(FTDM_LOG_ERROR, "Boost Check Event Failure Failure: %s\n", span->last_error);
1744 return FTDM_FAIL;
1745 }
1746 break;
1747 default:
1748 break;
1749 }
1750
1751 return FTDM_SUCCESS;
1752 }
1753
1754
1755
1756
1757
1758
1759 static void *ftdm_sangoma_events_run(ftdm_thread_t *me, void *obj)
1760 {
1761 ftdm_span_t *span = (ftdm_span_t *) obj;
1762 ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
1763 unsigned errs = 0;
1764
1765 while (ftdm_test_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_EVENTS_RUNNING) && ftdm_running()) {
1766 if (check_events(span, 100) != FTDM_SUCCESS) {
1767 if (errs++ > 50) {
1768 ftdm_log(FTDM_LOG_ERROR, "Too many event errors, quitting sangoma events thread\n");
1769 return NULL;
1770 }
1771 }
1772 }
1773
1774 ftdm_log(FTDM_LOG_DEBUG, "Sangoma Boost Events thread ended.\n");
1775
1776 ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_EVENTS_RUNNING);
1777
1778 return NULL;
1779 }
1780
1781 static ftdm_status_t ftdm_boost_connection_open(ftdm_span_t *span)
1782 {
1783 ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
1784 if (sangoma_boost_data->sigmod) {
1785 if (sangoma_boost_data->sigmod->start_span(span) != FTDM_SUCCESS) {
1786 return FTDM_FAIL;
1787 }
1788 ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RESTARTING);
1789 ftdm_clear_flag_locked(span, FTDM_SPAN_SUSPENDED);
1790 ftdm_clear_flag((&sangoma_boost_data->mcon), MSU_FLAG_DOWN);
1791 }
1792
1793 sangoma_boost_data->pcon = sangoma_boost_data->mcon;
1794
1795
1796 if (sangomabc_connection_open(&sangoma_boost_data->mcon,
1797 sangoma_boost_data->mcon.cfg.local_ip,
1798 sangoma_boost_data->mcon.cfg.local_port,
1799 sangoma_boost_data->mcon.cfg.remote_ip,
1800 sangoma_boost_data->mcon.cfg.remote_port) < 0) {
1801 ftdm_log(FTDM_LOG_ERROR, "Error: Opening MCON Socket [%d] %s\n", sangoma_boost_data->mcon.socket, strerror(errno));
1802 return FTDM_FAIL;
1803 }
1804
1805 if (sangomabc_connection_open(&sangoma_boost_data->pcon,
1806 sangoma_boost_data->pcon.cfg.local_ip,
1807 ++sangoma_boost_data->pcon.cfg.local_port,
1808 sangoma_boost_data->pcon.cfg.remote_ip,
1809 ++sangoma_boost_data->pcon.cfg.remote_port) < 0) {
1810 ftdm_log(FTDM_LOG_ERROR, "Error: Opening PCON Socket [%d] %s\n", sangoma_boost_data->pcon.socket, strerror(errno));
1811 return FTDM_FAIL;
1812 }
1813
1814
1815 if (ftdm_interrupt_create(&sangoma_boost_data->pcon.sock_interrupt, sangoma_boost_data->pcon.socket) != FTDM_SUCCESS) {
1816 ftdm_log(FTDM_LOG_ERROR, "Span %s could not create its boost msock interrupt!\n", span->name);
1817 return FTDM_FAIL;
1818 }
1819
1820 if (ftdm_interrupt_create(&sangoma_boost_data->mcon.sock_interrupt, sangoma_boost_data->mcon.socket) != FTDM_SUCCESS) {
1821 ftdm_log(FTDM_LOG_ERROR, "Span %s could not create its boost psock interrupt!\n", span->name);
1822 return FTDM_FAIL;
1823 }
1824
1825 return FTDM_SUCCESS;
1826 }
1827
1828
1829
1830
1831
1832 static int ftdm_boost_wait_event(ftdm_span_t *span)
1833 {
1834 ftdm_status_t res;
1835 ftdm_interrupt_t *ints[3];
1836 int numints;
1837 ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
1838
1839 ftdm_queue_get_interrupt(span->pendingchans, &ints[0]);
1840 numints = 1;
1841
1842 if (sangoma_boost_data->sigmod) {
1843 ftdm_queue_get_interrupt(sangoma_boost_data->boost_queue, &ints[1]);
1844 numints = 2;
1845 }
1846 #ifndef __WINDOWS__
1847 else {
1848
1849 ints[1] = sangoma_boost_data->mcon.sock_interrupt;
1850 ints[2] = sangoma_boost_data->pcon.sock_interrupt;
1851 numints = 3;
1852 sangoma_boost_data->iteration = 0;
1853 }
1854 #endif
1855 res = ftdm_interrupt_multiple_wait(ints, numints, 100);
1856 if (FTDM_SUCCESS != res && FTDM_TIMEOUT != res) {
1857 ftdm_log(FTDM_LOG_CRIT, "Unexpected return value from interrupt waiting: %d\n", res);
1858 return -1;
1859 }
1860 return 0;
1861 }
1862
1863
1864 static sangomabc_event_t *ftdm_boost_read_event(ftdm_span_t *span)
1865 {
1866 sangomabc_event_t *event = NULL;
1867 sangomabc_connection_t *mcon, *pcon;
1868 ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
1869
1870 mcon = &sangoma_boost_data->mcon;
1871 pcon = &sangoma_boost_data->pcon;
1872
1873 event = sangomabc_connection_readp(pcon, sangoma_boost_data->iteration);
1874
1875
1876 if (!event && !sangoma_boost_data->sigmod) {
1877 event = sangomabc_connection_read(mcon, sangoma_boost_data->iteration);
1878 }
1879
1880 return event;
1881 }
1882
1883
1884
1885
1886
1887
1888 static void *ftdm_sangoma_boost_run(ftdm_thread_t *me, void *obj)
1889 {
1890 ftdm_span_t *span = (ftdm_span_t *) obj;
1891 sangomabc_connection_t *mcon, *pcon;
1892 ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
1893
1894 mcon = &sangoma_boost_data->mcon;
1895 pcon = &sangoma_boost_data->pcon;
1896
1897
1898 if (sangoma_boost_data->sigmod) {
1899 mcon->span = span;
1900 pcon->span = span;
1901
1902 mcon->sigmod = sangoma_boost_data->sigmod;
1903 pcon->sigmod = sangoma_boost_data->sigmod;
1904 mcon->boost_queue = sangoma_boost_data->boost_queue;
1905 pcon->boost_queue = sangoma_boost_data->boost_queue;
1906 }
1907
1908 if (ftdm_boost_connection_open(span) != FTDM_SUCCESS) {
1909 ftdm_log(FTDM_LOG_CRIT, "ftdm_boost_connection_open failed\n");
1910 goto end;
1911 }
1912
1913 init_outgoing_array();
1914 if (!sangoma_boost_data->sigmod) {
1915 sangomabc_exec_commandp(pcon,
1916 0,
1917 0,
1918 -1,
1919 SIGBOOST_EVENT_SYSTEM_RESTART,
1920 0);
1921 ftdm_set_flag(mcon, MSU_FLAG_DOWN);
1922 }
1923
1924 while (ftdm_test_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RUNNING)) {
1925 sangomabc_event_t *event = NULL;
1926
1927 if (!ftdm_running()) {
1928 if (!sangoma_boost_data->sigmod) {
1929 sangomabc_exec_commandp(pcon,
1930 0,
1931 0,
1932 -1,
1933 SIGBOOST_EVENT_SYSTEM_RESTART,
1934 0);
1935 ftdm_set_flag(mcon, MSU_FLAG_DOWN);
1936 }
1937 ftdm_log(FTDM_LOG_DEBUG, "ftdm is no longer running\n");
1938 break;
1939 }
1940
1941 if (ftdm_boost_wait_event(span) < 0) {
1942 ftdm_log(FTDM_LOG_ERROR, "ftdm_boost_wait_event failed\n");
1943 }
1944
1945 while ((event = ftdm_boost_read_event(span))) {
1946 parse_sangoma_event(span, pcon, (sangomabc_short_event_t*)event);
1947 sangoma_boost_data->iteration++;
1948 }
1949
1950 check_state(span);
1951 }
1952
1953 end:
1954 if (!sangoma_boost_data->sigmod) {
1955 sangomabc_connection_close(&sangoma_boost_data->mcon);
1956 sangomabc_connection_close(&sangoma_boost_data->pcon);
1957 }
1958
1959 ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RUNNING);
1960
1961 ftdm_log(FTDM_LOG_DEBUG, "Sangoma Boost thread ended.\n");
1962 return NULL;
1963 }
1964
1965 #if 0
1966 static int sigmod_ss7box_isup_exec_cmd(ftdm_stream_handle_t *stream, char *cmd)
1967 {
1968 FILE *fp;
1969 int status=0;
1970 char path[1024];
1971
1972 fp = popen(cmd, "r");
1973 if (fp == NULL) {
1974 stream->write_function(stream, "%s: -ERR failed to execute cmd: %s\n",
1975 __FILE__,cmd);
1976 return -1;
1977 }
1978
1979 while (fgets(path, sizeof(path)-1, fp) != NULL) {
1980 path[sizeof(path)-1]='\0';
1981 stream->write_function(stream,"%s", path);
1982 }
1983
1984
1985 status = pclose(fp);
1986 if (status == -1) {
1987
1988 } else {
1989
1990
1991 }
1992
1993 return status;
1994 }
1995 #endif
1996
1997 static void ftdm_cli_span_state_cmd(ftdm_span_t *span, char *state)
1998 {
1999 unsigned int j;
2000 int cnt=0;
2001 ftdm_channel_state_t state_e = ftdm_str2ftdm_channel_state(state);
2002 if (state_e == FTDM_CHANNEL_STATE_INVALID) {
2003 ftdm_log(FTDM_LOG_CRIT, "Checking for channels not in the INVALID state is probably not what you want\n");
2004 }
2005 for(j = 1; j <= span->chan_count; j++) {
2006 if (span->channels[j]->state != state_e) {
2007 ftdm_channel_t *ftdmchan = span->channels[j];
2008 ftdm_log(FTDM_LOG_CRIT, "Channel %i s%dc%d State=%s\n",
2009 j, ftdmchan->physical_span_id-1, ftdmchan->physical_chan_id-1, ftdm_channel_state2str(ftdmchan->state));
2010 cnt++;
2011 }
2012 }
2013 ftdm_log(FTDM_LOG_CRIT, "Total Channel Cnt %i\n",cnt);
2014 }
2015
2016 #define FTDM_BOOST_SYNTAX "list sigmods | <sigmod_name> <command> | tracelevel <span> <level>"
2017
2018
2019
2020
2021
2022
2023 static FIO_API_FUNCTION(ftdm_sangoma_boost_api)
2024 {
2025 char *mycmd = NULL, *argv[10] = { 0 };
2026 int argc = 0;
2027
2028 if (data) {
2029 mycmd = ftdm_strdup(data);
2030 argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
2031 }
2032
2033 if (argc > 1) {
2034 if (!strcasecmp(argv[0], "list")) {
2035 if (!strcasecmp(argv[1], "sigmods")) {
2036 if (ftdm_sangoma_boost_list_sigmods(stream) != FTDM_SUCCESS) {
2037 stream->write_function(stream, "-ERR failed to list sigmods\n");
2038 goto done;
2039 }
2040 goto done;
2041 }
2042
2043 if (!strcasecmp(argv[1], "ids")) {
2044 print_request_ids();
2045 goto done;
2046 }
2047 } else if (!strcasecmp(argv[0], "tracelevel")) {
2048 ftdm_status_t status;
2049 const char *levelname = NULL;
2050 int dbglevel;
2051 ftdm_sangoma_boost_data_t *sangoma_boost_data;
2052 ftdm_span_t *span;
2053
2054 if (argc <= 2) {
2055 stream->write_function(stream, "-ERR usage: tracelevel <span> <level>\n");
2056 goto done;
2057 }
2058
2059 status = ftdm_span_find_by_name(argv[1], &span);
2060 if (FTDM_SUCCESS != status) {
2061 stream->write_function(stream, "-ERR failed to find span by name %s\n", argv[1]);
2062 goto done;
2063 }
2064
2065 if (span->signal_type != FTDM_SIGTYPE_SANGOMABOOST) {
2066 stream->write_function(stream, "-ERR span %s is not of boost type\n", argv[1]);
2067 goto done;
2068 }
2069
2070 for (dbglevel = 0; (levelname = FTDM_LEVEL_NAMES[dbglevel]); dbglevel++) {
2071 if (!strcasecmp(levelname, argv[2])) {
2072 break;
2073 }
2074 }
2075
2076 if (!levelname) {
2077 stream->write_function(stream, "-ERR invalid log level %s\n", argv[2]);
2078 goto done;
2079 }
2080
2081 sangoma_boost_data = span->signal_data;
2082 sangoma_boost_data->pcon.debuglevel = dbglevel;
2083 sangoma_boost_data->mcon.debuglevel = dbglevel;
2084 stream->write_function(stream, "+OK span %s has now trace level %s\n", argv[1], FTDM_LEVEL_NAMES[dbglevel]);
2085 goto done;
2086 #ifndef __WINDOWS__
2087 #if 0
2088
2089 } else if (!strcasecmp(argv[0], "ss7box_isupd_ckt")) {
2090
2091 if (!strcasecmp(argv[1], "used")) {
2092 stream->write_function(stream, "ss7box_isupd: in use\n", FTDM_BOOST_SYNTAX);
2093 sigmod_ss7box_isup_exec_cmd(stream, (char*) "ckt_report.sh inuse");
2094 } else if (!strcasecmp(argv[1], "reset")) {
2095 stream->write_function(stream, "ss7box_isupd: in reset\n", FTDM_BOOST_SYNTAX);
2096 sigmod_ss7box_isup_exec_cmd(stream, (char*) "ckt_report.sh reset");
2097 } else if (!strcasecmp(argv[1], "ready")) {
2098 stream->write_function(stream, "ss7box_isupd: ready \n", FTDM_BOOST_SYNTAX);
2099 sigmod_ss7box_isup_exec_cmd(stream, (char*) "ckt_report.sh free");
2100 } else {
2101 stream->write_function(stream, "ss7box_isupd: list\n", FTDM_BOOST_SYNTAX);
2102 sigmod_ss7box_isup_exec_cmd(stream, (char*) "ckt_report.sh");
2103 }
2104
2105 goto done;
2106 #endif
2107 #endif
2108
2109 } else if (!strcasecmp(argv[0], "span")) {
2110 int err;
2111 sangomabc_connection_t *pcon;
2112 ftdm_sangoma_boost_data_t *sangoma_boost_data;
2113 ftdm_span_t *span;
2114
2115 if (argc <= 2) {
2116 stream->write_function(stream, "-ERR invalid span usage: span <name> <cmd>\n");
2117 goto done;
2118 }
2119
2120 err = ftdm_span_find_by_name(argv[1], &span);
2121 if (FTDM_SUCCESS != err) {
2122 stream->write_function(stream, "-ERR failed to find span by name %s\n",argv[1]);
2123 goto done;
2124 }
2125
2126 if (!strcasecmp(argv[2], "restart")) {
2127 sangoma_boost_data = span->signal_data;
2128 pcon = &sangoma_boost_data->pcon;
2129
2130
2131
2132 sangomabc_exec_commandp(pcon,
2133 0,
2134 0,
2135 -1,
2136 SIGBOOST_EVENT_SYSTEM_RESTART,
2137 0);
2138 } else if (!strcasecmp(argv[2], "state")) {
2139 if (argc <= 3) {
2140 stream->write_function(stream, "-ERR invalid span state: span <name> state <state name>\n");
2141 goto done;
2142 }
2143 ftdm_cli_span_state_cmd(span,argv[3]);
2144 }
2145
2146 goto done;
2147
2148 } else {
2149 boost_sigmod_interface_t *sigmod_iface = NULL;
2150 sigmod_iface = hashtable_search(g_boost_modules_hash, argv[0]);
2151 if (sigmod_iface) {
2152 char *p = strchr(data, ' ');
2153 if (++p) {
2154 char* mydup = strdup(p);
2155 if(sigmod_iface->exec_api == NULL) {
2156 stream->write_function(stream, "%s does not support api functions\n", sigmod_iface->name);
2157 goto done;
2158 }
2159
2160 if (sigmod_iface->exec_api(stream, mydup) != FTDM_SUCCESS) {
2161 stream->write_function(stream, "-ERR:failed to execute command:%s\n", mydup);
2162 }
2163 free(mydup);
2164 }
2165
2166 goto done;
2167 } else {
2168 stream->write_function(stream, "-ERR: Could not find sigmod %s\n", argv[0]);
2169 }
2170 }
2171 }
2172 stream->write_function(stream, "-ERR: Usage: %s\n", FTDM_BOOST_SYNTAX);
2173 done:
2174 ftdm_safe_free(mycmd);
2175 return FTDM_SUCCESS;
2176 }
2177
2178
2179
2180
2181
2182
2183 static FIO_IO_LOAD_FUNCTION(ftdm_sangoma_boost_io_init)
2184 {
2185 ftdm_assert(fio != NULL, "fio is NULL");
2186 memset(&ftdm_sangoma_boost_interface, 0, sizeof(ftdm_sangoma_boost_interface));
2187
2188 ftdm_sangoma_boost_interface.name = "boost";
2189 ftdm_sangoma_boost_interface.api = ftdm_sangoma_boost_api;
2190
2191 *fio = &ftdm_sangoma_boost_interface;
2192
2193 return FTDM_SUCCESS;
2194 }
2195
2196
2197
2198
2199
2200
2201 static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_boost_init)
2202 {
2203 g_boost_modules_hash = create_hashtable(10, ftdm_hash_hashfromstring, ftdm_hash_equalkeys);
2204 if (!g_boost_modules_hash) {
2205 return FTDM_FAIL;
2206 }
2207 ftdm_mutex_create(&request_mutex);
2208 ftdm_mutex_create(&g_boost_modules_mutex);
2209 memset(&g_trunkgroups[0], 0, sizeof(g_trunkgroups));
2210 return FTDM_SUCCESS;
2211 }
2212
2213 static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_boost_destroy)
2214 {
2215 ftdm_hash_iterator_t *i = NULL;
2216 boost_sigmod_interface_t *sigmod = NULL;
2217 const void *key = NULL;
2218 void *val = NULL;
2219 ftdm_dso_lib_t lib;
2220 ftdm_log(FTDM_LOG_DEBUG, "Destroying sangoma boost module\n");
2221 for (i = hashtable_first(g_boost_modules_hash); i; i = hashtable_next(i)) {
2222 hashtable_this(i, &key, NULL, &val);
2223 if (key && val) {
2224 sigmod = val;
2225 lib = sigmod->pvt;
2226 ftdm_log(FTDM_LOG_DEBUG, "destroying sigmod %s\n", sigmod->name);
2227 sigmod->on_unload();
2228 ftdm_dso_destroy(&lib);
2229 }
2230 }
2231
2232 hashtable_destroy(g_boost_modules_hash);
2233 ftdm_mutex_destroy(&request_mutex);
2234 ftdm_mutex_destroy(&g_boost_modules_mutex);
2235 return FTDM_SUCCESS;
2236 }
2237
2238 static ftdm_status_t ftdm_sangoma_boost_start(ftdm_span_t *span)
2239 {
2240 int err;
2241
2242 ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
2243
2244 ftdm_set_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RUNNING);
2245 err = ftdm_thread_create_detached(ftdm_sangoma_boost_run, span);
2246 if (err) {
2247 ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RUNNING);
2248 return err;
2249 }
2250
2251
2252
2253 ftdm_set_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_EVENTS_RUNNING);
2254 err = ftdm_thread_create_detached(ftdm_sangoma_events_run, span);
2255 if (err) {
2256 ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_EVENTS_RUNNING);
2257 ftdm_clear_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RUNNING);
2258 }
2259
2260 return err;
2261 }
2262
2263 static ftdm_status_t ftdm_sangoma_boost_stop(ftdm_span_t *span)
2264 {
2265 int cnt = 50;
2266 ftdm_status_t status = FTDM_SUCCESS;
2267 ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
2268
2269 if (sangoma_boost_data->sigmod) {
2270
2271
2272 status = sangoma_boost_data->sigmod->stop_span(span);
2273 if (status != FTDM_SUCCESS) {
2274 ftdm_log(FTDM_LOG_CRIT, "Failed to stop span %s boost signaling\n", span->name);
2275 return FTDM_FAIL;
2276 }
2277 ftdm_queue_enqueue(sangoma_boost_data->boost_queue, NULL);
2278 }
2279
2280 while (ftdm_test_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_RUNNING) && cnt-- > 0) {
2281 ftdm_log(FTDM_LOG_DEBUG, "Waiting for boost thread\n");
2282 ftdm_sleep(100);
2283 }
2284
2285 if (!cnt) {
2286 ftdm_log(FTDM_LOG_CRIT, "it seems boost thread in span %s may be stuck, we may segfault :-(\n", span->name);
2287 return FTDM_FAIL;
2288 }
2289
2290 cnt = 50;
2291 while (ftdm_test_flag(sangoma_boost_data, FTDM_SANGOMA_BOOST_EVENTS_RUNNING) && cnt-- > 0) {
2292 ftdm_log(FTDM_LOG_DEBUG, "Waiting for boost events thread\n");
2293 ftdm_sleep(100);
2294 }
2295
2296 if (!cnt) {
2297 ftdm_log(FTDM_LOG_CRIT, "it seems boost events thread in span %s may be stuck, we may segfault :-(\n", span->name);
2298 return FTDM_FAIL;
2299 }
2300
2301 if (sangoma_boost_data->sigmod) {
2302 ftdm_queue_destroy(&sangoma_boost_data->boost_queue);
2303 }
2304
2305 return status;
2306 }
2307
2308 static ftdm_state_map_t boost_state_map = {
2309 {
2310 {
2311 ZSD_OUTBOUND,
2312 ZSM_UNACCEPTABLE,
2313 {FTDM_ANY_STATE},
2314 {FTDM_CHANNEL_STATE_RESTART, FTDM_END}
2315 },
2316 {
2317 ZSD_OUTBOUND,
2318 ZSM_UNACCEPTABLE,
2319 {FTDM_CHANNEL_STATE_RESTART, FTDM_END},
2320 {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
2321 },
2322 {
2323 ZSD_OUTBOUND,
2324 ZSM_UNACCEPTABLE,
2325 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
2326 {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_IDLE, FTDM_CHANNEL_STATE_HOLD, FTDM_END}
2327 },
2328 {
2329 ZSD_OUTBOUND,
2330 ZSM_UNACCEPTABLE,
2331 {FTDM_CHANNEL_STATE_HOLD, FTDM_END},
2332 {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS,
2333 FTDM_CHANNEL_STATE_IDLE, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
2334 },
2335 {
2336 ZSD_OUTBOUND,
2337 ZSM_UNACCEPTABLE,
2338 {FTDM_CHANNEL_STATE_IDLE, FTDM_CHANNEL_STATE_DIALING, FTDM_END},
2339 {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}
2340 },
2341 {
2342 ZSD_OUTBOUND,
2343 ZSM_UNACCEPTABLE,
2344 {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_IDLE, FTDM_CHANNEL_STATE_DIALING, FTDM_END},
2345 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_END}
2346 },
2347 {
2348 ZSD_OUTBOUND,
2349 ZSM_UNACCEPTABLE,
2350 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
2351 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
2352 },
2353 {
2354 ZSD_OUTBOUND,
2355 ZSM_UNACCEPTABLE,
2356 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
2357 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
2358 },
2359 {
2360 ZSD_OUTBOUND,
2361 ZSM_UNACCEPTABLE,
2362 {FTDM_CHANNEL_STATE_UP, FTDM_END},
2363 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
2364 },
2365
2366
2367 {
2368 ZSD_INBOUND,
2369 ZSM_UNACCEPTABLE,
2370 {FTDM_ANY_STATE},
2371 {FTDM_CHANNEL_STATE_RESTART, FTDM_END}
2372 },
2373 {
2374 ZSD_INBOUND,
2375 ZSM_UNACCEPTABLE,
2376 {FTDM_CHANNEL_STATE_RESTART, FTDM_END},
2377 {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
2378 },
2379 {
2380 ZSD_INBOUND,
2381 ZSM_UNACCEPTABLE,
2382 {FTDM_CHANNEL_STATE_DOWN},
2383 {FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}
2384 },
2385 {
2386 ZSD_INBOUND,
2387 ZSM_UNACCEPTABLE,
2388 {FTDM_CHANNEL_STATE_IN_LOOP},
2389 {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
2390 },
2391 {
2392 ZSD_INBOUND,
2393 ZSM_UNACCEPTABLE,
2394 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
2395 {FTDM_CHANNEL_STATE_RING, FTDM_END}
2396 },
2397 {
2398 ZSD_INBOUND,
2399 ZSM_UNACCEPTABLE,
2400 {FTDM_CHANNEL_STATE_RING, FTDM_END},
2401 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,FTDM_END}
2402 },
2403 {
2404 ZSD_INBOUND,
2405 ZSM_UNACCEPTABLE,
2406 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
2407 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
2408 },
2409 {
2410 ZSD_INBOUND,
2411 ZSM_UNACCEPTABLE,
2412 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
2413 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
2414 },
2415 {
2416 ZSD_INBOUND,
2417 ZSM_UNACCEPTABLE,
2418 {FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
2419 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
2420 },
2421 {
2422 ZSD_INBOUND,
2423 ZSM_UNACCEPTABLE,
2424 {FTDM_CHANNEL_STATE_UP, FTDM_END},
2425 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
2426 },
2427
2428
2429 }
2430 };
2431
2432 static BOOST_WRITE_MSG_FUNCTION(ftdm_boost_write_msg)
2433 {
2434 sangomabc_short_event_t *shortmsg = NULL;
2435 ftdm_sangoma_boost_data_t *sangoma_boost_data = NULL;
2436 sangomabc_queue_element_t *element = NULL;
2437
2438 ftdm_assert_return(msg != NULL, FTDM_FAIL, "Boost message to write was null");
2439
2440 if (!span) {
2441 shortmsg = msg;
2442 ftdm_log(FTDM_LOG_ERROR, "Unexpected boost message %d\n", shortmsg->event_id);
2443 return FTDM_FAIL;
2444 }
2445
2446 element = ftdm_calloc(1, sizeof(*element));
2447 if (!element) {
2448 return FTDM_FAIL;
2449 }
2450 memcpy(element->boostmsg, msg, msglen);
2451 element->size = msglen;
2452
2453 sangoma_boost_data = span->signal_data;
2454 return ftdm_queue_enqueue(sangoma_boost_data->boost_queue, element);
2455 }
2456
2457 static BOOST_SIG_STATUS_CB_FUNCTION(ftdm_boost_sig_status_change)
2458 {
2459 ftdm_sigmsg_t sig;
2460 ftdm_log(FTDM_LOG_NOTICE, "%d:%d Signaling link status changed to %s\n", ftdmchan->span_id, ftdmchan->chan_id, ftdm_signaling_status2str(status));
2461
2462 memset(&sig, 0, sizeof(sig));
2463 sig.chan_id = ftdmchan->chan_id;
2464 sig.span_id = ftdmchan->span_id;
2465 sig.channel = ftdmchan;
2466 sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
2467 sig.ev_data.sigstatus.status = status;
2468 ftdm_span_send_signal(ftdmchan->span, &sig);
2469 return;
2470 }
2471
2472 static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(sangoma_boost_set_channel_sig_status)
2473 {
2474 ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data;
2475 if (!sangoma_boost_data->sigmod) {
2476 ftdm_log(FTDM_LOG_ERROR, "Cannot set signaling status in boost channel with no signaling module configured\n");
2477 return FTDM_FAIL;
2478 }
2479 if (!sangoma_boost_data->sigmod->set_channel_sig_status) {
2480 ftdm_log(FTDM_LOG_ERROR, "Cannot set signaling status in boost channel: method not implemented\n");
2481 return FTDM_NOTIMPL;
2482 }
2483 return sangoma_boost_data->sigmod->set_channel_sig_status(ftdmchan, status);
2484 }
2485
2486 static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(sangoma_boost_get_channel_sig_status)
2487 {
2488 ftdm_sangoma_boost_data_t *sangoma_boost_data = ftdmchan->span->signal_data;
2489 if (!sangoma_boost_data->sigmod) {
2490 return FTDM_FAIL;
2491 }
2492 if (!sangoma_boost_data->sigmod->get_channel_sig_status) {
2493 return FTDM_NOTIMPL;
2494 }
2495 return sangoma_boost_data->sigmod->get_channel_sig_status(ftdmchan, status);
2496 }
2497
2498 static FIO_SPAN_SET_SIG_STATUS_FUNCTION(sangoma_boost_set_span_sig_status)
2499 {
2500 ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
2501 if (!sangoma_boost_data->sigmod) {
2502 ftdm_log(FTDM_LOG_ERROR, "Cannot set signaling status in boost span with no signaling module configured\n");
2503 return FTDM_FAIL;
2504 }
2505 if (!sangoma_boost_data->sigmod->set_span_sig_status) {
2506 ftdm_log(FTDM_LOG_ERROR, "Cannot set signaling status in boost span: method not implemented\n");
2507 return FTDM_NOTIMPL;
2508 }
2509 return sangoma_boost_data->sigmod->set_span_sig_status(span, status);
2510 }
2511
2512 static FIO_SPAN_GET_SIG_STATUS_FUNCTION(sangoma_boost_get_span_sig_status)
2513 {
2514 ftdm_sangoma_boost_data_t *sangoma_boost_data = span->signal_data;
2515 if (!sangoma_boost_data->sigmod) {
2516 return FTDM_FAIL;
2517 }
2518 if (!sangoma_boost_data->sigmod->get_span_sig_status) {
2519 ftdm_log(FTDM_LOG_ERROR, "Cannot get signaling status in boost span: method not implemented\n");
2520 return FTDM_NOTIMPL;
2521 }
2522 return sangoma_boost_data->sigmod->get_span_sig_status(span, status);
2523 }
2524
2525
2526
2527
2528
2529
2530
2531
2532 static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_boost_configure_span)
2533 {
2534 #define FAIL_CONFIG_RETURN(retstatus) \
2535 if (sangoma_boost_data) \
2536 ftdm_safe_free(sangoma_boost_data); \
2537 if (err) \
2538 ftdm_safe_free(err) \
2539 if (hash_locked) \
2540 ftdm_mutex_unlock(g_boost_modules_mutex); \
2541 if (lib) \
2542 ftdm_dso_destroy(&lib); \
2543 return retstatus;
2544
2545 boost_sigmod_interface_t *sigmod_iface = NULL;
2546 ftdm_sangoma_boost_data_t *sangoma_boost_data = NULL;
2547 const char *local_ip = "127.0.0.65", *remote_ip = "127.0.0.66";
2548 const char *sigmod = NULL;
2549 int local_port = 53000, remote_port = 53000;
2550 const char *var = NULL, *val = NULL;
2551 int hash_locked = 0;
2552 ftdm_dso_lib_t lib = NULL;
2553 char path[255] = "";
2554 char *err = NULL;
2555 unsigned int j = 0;
2556 unsigned paramindex = 0;
2557 ftdm_status_t rc = FTDM_SUCCESS;
2558
2559 for (; ftdm_parameters[paramindex].var; paramindex++) {
2560 var = ftdm_parameters[paramindex].var;
2561 val = ftdm_parameters[paramindex].val;
2562 if (!strcasecmp(var, "sigmod")) {
2563 sigmod = val;
2564 } else if (!strcasecmp(var, "local_ip")) {
2565 local_ip = val;
2566 } else if (!strcasecmp(var, "remote_ip")) {
2567 remote_ip = val;
2568 } else if (!strcasecmp(var, "local_port")) {
2569 local_port = atoi(val);
2570 } else if (!strcasecmp(var, "remote_port")) {
2571 remote_port = atoi(val);
2572 } else if (!strcasecmp(var, "outbound-called-ton")) {
2573 ftdm_set_ton(val, &span->default_caller_data.dnis.type);
2574 } else if (!strcasecmp(var, "outbound-called-npi")) {
2575 ftdm_set_npi(val, &span->default_caller_data.dnis.plan);
2576 } else if (!strcasecmp(var, "outbound-calling-ton")) {
2577 ftdm_set_ton(val, &span->default_caller_data.cid_num.type);
2578 } else if (!strcasecmp(var, "outbound-calling-npi")) {
2579 ftdm_set_npi(val, &span->default_caller_data.cid_num.plan);
2580 } else if (!strcasecmp(var, "outbound-rdnis-ton")) {
2581 ftdm_set_ton(val, &span->default_caller_data.rdnis.type);
2582 } else if (!strcasecmp(var, "outbound-rdnis-npi")) {
2583 ftdm_set_npi(val, &span->default_caller_data.rdnis.plan);
2584 } else if (!sigmod) {
2585 snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var);
2586 FAIL_CONFIG_RETURN(FTDM_FAIL);
2587 }
2588 }
2589
2590 if (!sigmod) {
2591 #ifndef HAVE_NETINET_SCTP_H
2592 ftdm_log(FTDM_LOG_CRIT, "No sigmod attribute in span %s, you must either specify a sigmod or re-compile with SCTP available to use socket mode boost!\n", span->name);
2593 ftdm_set_string(span->last_error, "No sigmod configuration was set and there is no SCTP available!");
2594 FAIL_CONFIG_RETURN(FTDM_FAIL);
2595 #else
2596 if (!local_ip && local_port && remote_ip && remote_port && sig_cb) {
2597 ftdm_set_string(span->last_error, "missing Sangoma boost IP parameters");
2598 FAIL_CONFIG_RETURN(FTDM_FAIL);
2599 }
2600 #endif
2601 }
2602
2603 sangoma_boost_data = ftdm_calloc(1, sizeof(*sangoma_boost_data));
2604 if (!sangoma_boost_data) {
2605 FAIL_CONFIG_RETURN(FTDM_FAIL);
2606 }
2607
2608
2609 ftdm_mutex_lock(g_boost_modules_mutex);
2610 hash_locked = 1;
2611 if (sigmod && !(sigmod_iface = hashtable_search(g_boost_modules_hash, (void *)sigmod))) {
2612 ftdm_build_dso_path(sigmod, path, sizeof(path));
2613 lib = ftdm_dso_open(path, &err);
2614 if (!lib) {
2615 ftdm_log(FTDM_LOG_ERROR, "Error loading Sangoma boost signaling module '%s': %s\n", path, err);
2616 snprintf(span->last_error, sizeof(span->last_error), "Failed to load sangoma boost signaling module %s", path);
2617
2618 FAIL_CONFIG_RETURN(FTDM_FAIL);
2619 }
2620 if (!(sigmod_iface = (boost_sigmod_interface_t *)ftdm_dso_func_sym(lib, BOOST_INTERFACE_NAME_STR, &err))) {
2621 ftdm_log(FTDM_LOG_ERROR, "Failed to read Sangoma boost signaling module interface '%s': %s\n", path, err);
2622 snprintf(span->last_error, sizeof(span->last_error), "Failed to read Sangoma boost signaling module interface '%s': %s", path, err);
2623
2624 FAIL_CONFIG_RETURN(FTDM_FAIL);
2625 }
2626 rc = sigmod_iface->on_load();
2627 if (rc != FTDM_SUCCESS) {
2628 ftdm_log(FTDM_LOG_ERROR, "Failed to load Sangoma boost signaling module interface '%s': on_load method failed (%d)\n", path, rc);
2629 FAIL_CONFIG_RETURN(FTDM_FAIL);
2630 }
2631 sigmod_iface->pvt = lib;
2632 sigmod_iface->set_write_msg_cb(ftdm_boost_write_msg);
2633 sigmod_iface->set_sig_status_cb(ftdm_boost_sig_status_change);
2634 hashtable_insert(g_boost_modules_hash, (void *)sigmod_iface->name, sigmod_iface, HASHTABLE_FLAG_NONE);
2635 lib = NULL;
2636 }
2637 ftdm_mutex_unlock(g_boost_modules_mutex);
2638 hash_locked = 0;
2639
2640 if (sigmod_iface) {
2641
2642 if (ftdm_queue_create(&sangoma_boost_data->boost_queue, BOOST_QUEUE_SIZE) != FTDM_SUCCESS) {
2643 ftdm_log(FTDM_LOG_ERROR, "Span %s could not create its boost queue!\n", span->name);
2644 FAIL_CONFIG_RETURN(FTDM_FAIL);
2645 }
2646 ftdm_log(FTDM_LOG_NOTICE, "Span %s will use Sangoma Boost Signaling Module %s\n", span->name, sigmod_iface->name);
2647 sangoma_boost_data->sigmod = sigmod_iface;
2648 sigmod_iface->configure_span(span, ftdm_parameters);
2649 } else {
2650 ftdm_log(FTDM_LOG_NOTICE, "Span %s will use boost socket mode\n", span->name);
2651 ftdm_set_string(sangoma_boost_data->mcon.cfg.local_ip, local_ip);
2652 sangoma_boost_data->mcon.cfg.local_port = local_port;
2653 ftdm_set_string(sangoma_boost_data->mcon.cfg.remote_ip, remote_ip);
2654 sangoma_boost_data->mcon.cfg.remote_port = remote_port;
2655 }
2656
2657 for (j = 1; j <= span->chan_count; j++) {
2658 span->channels[j]->call_data = ftdm_calloc(1, sizeof(sangoma_boost_call_t));
2659 if (!span->channels[j]->call_data) {
2660 FAIL_CONFIG_RETURN(FTDM_FAIL);
2661 }
2662 }
2663
2664 span->signal_cb = sig_cb;
2665 span->start = ftdm_sangoma_boost_start;
2666 span->stop = ftdm_sangoma_boost_stop;
2667 span->signal_data = sangoma_boost_data;
2668 span->signal_type = FTDM_SIGTYPE_SANGOMABOOST;
2669 span->outgoing_call = sangoma_boost_outgoing_call;
2670 span->channel_request = sangoma_boost_channel_request;
2671 span->get_channel_sig_status = sangoma_boost_get_channel_sig_status;
2672 span->set_channel_sig_status = sangoma_boost_set_channel_sig_status;
2673 span->get_span_sig_status = sangoma_boost_get_span_sig_status;
2674 span->set_span_sig_status = sangoma_boost_set_span_sig_status;
2675 span->state_map = &boost_state_map;
2676 span->state_processor = state_advance;
2677 sangoma_boost_data->mcon.debuglevel = FTDM_LOG_LEVEL_DEBUG;
2678 sangoma_boost_data->pcon.debuglevel = FTDM_LOG_LEVEL_DEBUG;
2679 ftdm_clear_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID);
2680 ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE);
2681 if (sigmod_iface) {
2682
2683 span->channel_request = NULL;
2684 }
2685 ftdm_set_flag_locked(span, FTDM_SPAN_SUSPENDED);
2686 return FTDM_SUCCESS;
2687 }
2688
2689 static ftdm_status_t ftdm_sangoma_boost_list_sigmods(ftdm_stream_handle_t *stream)
2690 {
2691 ftdm_hash_iterator_t *i = NULL;
2692 boost_sigmod_interface_t *sigmod_iface = NULL;
2693 const void *key = NULL;
2694 void *val = NULL;
2695
2696 stream->write_function(stream, "List of loaded sigmod modules:\n");
2697 for (i = hashtable_first(g_boost_modules_hash); i; i = hashtable_next(i)) {
2698 hashtable_this(i, &key, NULL, &val);
2699 if (key && val) {
2700 sigmod_iface = val;
2701 stream->write_function(stream, " %s\n", sigmod_iface->name);
2702 }
2703 }
2704 stream->write_function(stream, "\n");
2705 return FTDM_SUCCESS;
2706 }
2707
2708
2709
2710
2711 EX_DECLARE_DATA ftdm_module_t ftdm_module = {
2712 "sangoma_boost",
2713 ftdm_sangoma_boost_io_init,
2714 NULL,
2715 ftdm_sangoma_boost_init,
2716 NULL,
2717 ftdm_sangoma_boost_destroy,
2718 ftdm_sangoma_boost_configure_span
2719 };
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730