This source file includes following definitions.
- release_request_id
- state_advance
- check_state
- parse_ss7_event
- FIO_CONFIGURE_FUNCTION
- FIO_CONFIGURE_SPAN_FUNCTION
- FIO_OPEN_FUNCTION
- FIO_CLOSE_FUNCTION
- FIO_WAIT_FUNCTION
- FIO_READ_FUNCTION
- FIO_WRITE_FUNCTION
- FIO_COMMAND_FUNCTION
- FIO_SPAN_POLL_EVENT_FUNCTION
- FIO_SPAN_NEXT_EVENT_FUNCTION
- FIO_SPAN_DESTROY_FUNCTION
- FIO_CHANNEL_DESTROY_FUNCTION
- FIO_GET_ALARMS_FUNCTION
- m3ua_init
- m3ua_destroy
- m3ua_run
- m3ua_start
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 #include "freetdm.h"
42 #include "m3ua_client.h"
43 #include "ftdm_m3ua.h"
44
45 #define MAX_REQ_ID MAX_PENDING_CALLS
46 typedef uint16_t m3ua_request_id_t;
47
48 typedef enum {
49 BST_FREE,
50 BST_WAITING,
51 BST_READY,
52 BST_FAIL
53 } m3ua_request_status_t;
54
55 typedef struct {
56 m3ua_request_status_t status;
57 m3uac_event_t event;
58 ftdm_span_t *span;
59 ftdm_channel_t *ftdmchan;
60 } m3ua_request_t;
61
62
63 struct general_config {
64 uint32_t region;
65 };
66 typedef struct general_config general_config_t;
67
68
69 struct m3ua_channel_profile {
70 char name[80];
71 int cust_span;
72 unsigned char opc[3];
73 unsigned char dpc[3];
74 int local_ip[4];
75 int local_port;
76 int remote_ip[4];
77 int remote_port;
78 int m3ua_mode;
79 };
80 typedef struct m3ua_channel_profile m3ua_channel_profile_t;
81
82 static struct {
83 ftdm_hash_t *profile_hash;
84 general_config_t general_config;
85 } globals;
86
87 struct m3ua_span_data {
88 uint32_t boardno;
89 uint32_t flags;
90 };
91 typedef struct m3ua_span_data m3ua_span_data_t;
92
93 struct m3ua_chan_data {
94 ftdm_buffer_t *digit_buffer;
95 ftdm_mutex_t *digit_mutex;
96 ftdm_size_t dtmf_len;
97 uint32_t flags;
98 uint32_t hdlc_bytes;
99 };
100 typedef struct m3ua_chan_data m3ua_chan_data_t;
101
102 static ftdm_mutex_t *request_mutex = NULL;
103 static ftdm_mutex_t *signal_mutex = NULL;
104
105 static uint8_t req_map[MAX_REQ_ID+1] = { 0 };
106
107 static void release_request_id(m3ua_request_id_t r)
108 {
109 ftdm_mutex_lock(request_mutex);
110 req_map[r] = 0;
111 ftdm_mutex_unlock(request_mutex);
112 }
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137 static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
138 {
139
140 m3ua_data_t *m3ua_data = ftdmchan->span->signal_data;
141 m3uac_connection_t *mcon = &m3ua_data->mcon;
142 ftdm_sigmsg_t sig;
143 ftdm_status_t status;
144
145 ftdm_log(FTDM_LOG_DEBUG, "%d:%d STATE [%s]\n", ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state));
146
147 memset(&sig, 0, sizeof(sig));
148 sig.chan_id = ftdmchan->chan_id;
149 sig.span_id = ftdmchan->span_id;
150 sig.channel = ftdmchan;
151
152 switch (ftdmchan->state) {
153 case FTDM_CHANNEL_STATE_DOWN:
154 {
155 if (ftdmchan->extra_id) {
156 release_request_id((m3ua_request_id_t)ftdmchan->extra_id);
157 ftdmchan->extra_id = 0;
158 }
159 ftdm_channel_done(ftdmchan);
160 }
161 break;
162 case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
163 case FTDM_CHANNEL_STATE_PROGRESS:
164 {
165 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
166 sig.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
167 if ((status = m3ua_data->signal_cb(&sig) != FTDM_SUCCESS)) {
168 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
169 }
170 } else {
171 m3uac_exec_command(mcon,
172 ftdmchan->physical_span_id-1,
173 ftdmchan->physical_chan_id-1,
174 0,
175 SIGBOOST_EVENT_CALL_START_ACK,
176 0);
177 }
178 }
179 break;
180 case FTDM_CHANNEL_STATE_RING:
181 {
182 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
183 sig.event_id = FTDM_SIGEVENT_START;
184 if ((status = m3ua_data->signal_cb(&sig) != FTDM_SUCCESS)) {
185 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
186 }
187 }
188
189 }
190 break;
191 case FTDM_CHANNEL_STATE_RESTART:
192 {
193 if (ftdmchan->last_state != FTDM_CHANNEL_STATE_HANGUP && ftdmchan->last_state != FTDM_CHANNEL_STATE_DOWN) {
194 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
195 } else {
196 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
197 }
198 }
199 break;
200 case FTDM_CHANNEL_STATE_UP:
201 {
202 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
203 sig.event_id = FTDM_SIGEVENT_UP;
204 if ((status = m3ua_data->signal_cb(&sig) != FTDM_SUCCESS)) {
205 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
206 }
207 } else {
208 if (!(ftdm_test_flag(ftdmchan, FTDM_CHANNEL_PROGRESS) || ftdm_test_flag(ftdmchan, FTDM_CHANNEL_MEDIA))) {
209 m3uac_exec_command(mcon,
210 ftdmchan->physical_span_id-1,
211 ftdmchan->physical_chan_id-1,
212 0,
213 SIGBOOST_EVENT_CALL_START_ACK,
214 0);
215 }
216
217 m3uac_exec_command(mcon,
218 ftdmchan->physical_span_id-1,
219 ftdmchan->physical_chan_id-1,
220 0,
221 SIGBOOST_EVENT_CALL_ANSWERED,
222 0);
223 }
224 }
225 break;
226 case FTDM_CHANNEL_STATE_DIALING:
227 {
228 }
229 break;
230 case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
231 {
232 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
233 }
234 break;
235 case FTDM_CHANNEL_STATE_HANGUP:
236 {
237 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_ANSWERED) || ftdm_test_flag(ftdmchan, FTDM_CHANNEL_PROGRESS) || ftdm_test_flag(ftdmchan, FTDM_CHANNEL_MEDIA)) {
238 m3uac_exec_command(mcon,
239 ftdmchan->physical_span_id-1,
240 ftdmchan->physical_chan_id-1,
241 0,
242 SIGBOOST_EVENT_CALL_STOPPED,
243 ftdmchan->caller_data.hangup_cause);
244 } else {
245 m3uac_exec_command(mcon,
246 ftdmchan->physical_span_id-1,
247 ftdmchan->physical_chan_id-1,
248 0,
249 SIGBOOST_EVENT_CALL_START_NACK,
250 ftdmchan->caller_data.hangup_cause);
251 }
252 }
253 break;
254 case FTDM_CHANNEL_STATE_CANCEL:
255 {
256 sig.event_id = FTDM_SIGEVENT_STOP;
257 status = m3ua_data->signal_cb(&sig);
258 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
259 m3uac_exec_command(mcon,
260 ftdmchan->physical_span_id-1,
261 ftdmchan->physical_chan_id-1,
262 0,
263 SIGBOOST_EVENT_CALL_START_NACK_ACK,
264 0);
265 }
266 break;
267 case FTDM_CHANNEL_STATE_TERMINATING:
268 {
269 sig.event_id = FTDM_SIGEVENT_STOP;
270 status = m3ua_data->signal_cb(&sig);
271 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
272 m3uac_exec_command(mcon,
273 ftdmchan->physical_span_id-1,
274 ftdmchan->physical_chan_id-1,
275 0,
276 SIGBOOST_EVENT_CALL_STOPPED_ACK,
277 0);
278 }
279 break;
280 default:
281 break;
282 }
283 }
284
285
286 static __inline__ void check_state(ftdm_span_t *span)
287 {
288 if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE)) {
289 uint32_t j;
290 ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE);
291 for(j = 1; j <= span->chan_count; j++) {
292 if (ftdm_test_flag((&span->channels[j]), FTDM_CHANNEL_STATE_CHANGE)) {
293 ftdm_clear_flag_locked((&span->channels[j]), FTDM_CHANNEL_STATE_CHANGE);
294 state_advance(&span->channels[j]);
295 ftdm_channel_complete_state(&span->channels[j]);
296 }
297 }
298 }
299 }
300
301
302 static int parse_ss7_event(ftdm_span_t *span, m3uac_connection_t *mcon, m3uac_event_t *event)
303 {
304 ftdm_mutex_lock(signal_mutex);
305
306 if (!ftdm_running()) {
307 ftdm_log(FTDM_LOG_WARNING, "System is shutting down.\n");
308 goto end;
309 }
310
311
312 if (ftdm_test_flag(span, FTDM_SPAN_SUSPENDED) &&
313 event->event_id != SIGBOOST_EVENT_SYSTEM_RESTART_ACK && event->event_id != SIGBOOST_EVENT_HEARTBEAT) {
314
315 ftdm_log(FTDM_LOG_WARNING,
316 "INVALID EVENT: %s:(%X) [w%dg%d] Rc=%i CSid=%i Seq=%i Cd=[%s] Ci=[%s]\n",
317 m3uac_event_id_name(event->event_id),
318 event->event_id,
319 event->span+1,
320 event->chan+1,
321 event->release_cause,
322 event->call_setup_id,
323 event->fseqno,
324 (event->called_number_digits_count ? (char *) event->called_number_digits : "N/A"),
325 (event->calling_number_digits_count ? (char *) event->calling_number_digits : "N/A")
326 );
327
328 goto end;
329 }
330
331
332 ftdm_log(FTDM_LOG_DEBUG,
333 "RX EVENT: %s:(%X) [w%dg%d] Rc=%i CSid=%i Seq=%i Cd=[%s] Ci=[%s]\n",
334 m3uac_event_id_name(event->event_id),
335 event->event_id,
336 event->span+1,
337 event->chan+1,
338 event->release_cause,
339 event->call_setup_id,
340 event->fseqno,
341 (event->called_number_digits_count ? (char *) event->called_number_digits : "N/A"),
342 (event->calling_number_digits_count ? (char *) event->calling_number_digits : "N/A")
343 );
344
345
346
347 switch(event->event_id) {
348
349 case SIGBOOST_EVENT_CALL_START:
350
351 break;
352 case SIGBOOST_EVENT_CALL_STOPPED:
353
354 break;
355 case SIGBOOST_EVENT_CALL_START_ACK:
356
357 break;
358 case SIGBOOST_EVENT_CALL_START_NACK:
359
360 break;
361 case SIGBOOST_EVENT_CALL_ANSWERED:
362
363 break;
364 case SIGBOOST_EVENT_HEARTBEAT:
365
366 break;
367 case SIGBOOST_EVENT_CALL_STOPPED_ACK:
368 case SIGBOOST_EVENT_CALL_START_NACK_ACK:
369
370 break;
371 case SIGBOOST_EVENT_INSERT_CHECK_LOOP:
372
373 break;
374 case SIGBOOST_EVENT_REMOVE_CHECK_LOOP:
375
376 break;
377 case SIGBOOST_EVENT_SYSTEM_RESTART_ACK:
378
379 break;
380 case SIGBOOST_EVENT_AUTO_CALL_GAP_ABATE:
381
382 break;
383 default:
384 ftdm_log(FTDM_LOG_WARNING, "No handler implemented for [%s]\n", m3uac_event_id_name(event->event_id));
385 break;
386 }
387
388 end:
389
390 ftdm_mutex_unlock(signal_mutex);
391
392 return 0;
393 }
394
395 static FIO_CONFIGURE_FUNCTION(m3ua_configure)
396 {
397 m3ua_channel_profile_t *profile = NULL;
398
399 int ok = 1;
400
401 if (!(profile = (m3ua_channel_profile_t *) hashtable_search(globals.profile_hash, (char *)category))) {
402 profile = ftdm_malloc(sizeof(*profile));
403 memset(profile, 0, sizeof(*profile));
404 ftdm_set_string(profile->name, category);
405 hashtable_insert(globals.profile_hash, (void *)profile->name, profile);
406 ftdm_log(FTDM_LOG_INFO, "creating profile [%s]\n", category);
407 }
408
409
410 if (!strcasecmp(var, "local_sctp_port")) {
411 profile->local_port = 30000 ;
412 profile->remote_port = 30000;
413 profile->cust_span++;
414 }
415 ok = 1;
416
417
418 if (ok) {
419 ftdm_log(FTDM_LOG_INFO, "setting param [%s]=[%s] for profile [%s]\n", var, val, category);
420 } else {
421 ftdm_log(FTDM_LOG_ERROR, "unknown param [%s]\n", var);
422 }
423
424 return FTDM_SUCCESS;
425 }
426
427 static FIO_CONFIGURE_SPAN_FUNCTION(m3ua_configure_span)
428 {
429
430 return FTDM_FAIL;
431 }
432
433 static FIO_OPEN_FUNCTION(m3ua_open)
434 {
435
436 return FTDM_FAIL;
437 }
438
439 static FIO_CLOSE_FUNCTION(m3ua_close)
440 {
441
442 return FTDM_FAIL;
443 }
444
445
446
447
448
449
450
451 static FIO_WAIT_FUNCTION(m3ua_wait)
452 {
453
454 return FTDM_FAIL;
455 }
456
457 static FIO_READ_FUNCTION(m3ua_read)
458 {
459
460 return FTDM_FAIL;
461 }
462
463 static FIO_WRITE_FUNCTION(m3ua_write)
464 {
465
466 return FTDM_FAIL;
467 }
468
469 static FIO_COMMAND_FUNCTION(m3ua_command)
470 {
471 return FTDM_FAIL;
472 }
473
474 static FIO_SPAN_POLL_EVENT_FUNCTION(m3ua_poll_event)
475 {
476 return FTDM_FAIL;
477 }
478
479 static FIO_SPAN_NEXT_EVENT_FUNCTION(m3ua_next_event)
480 {
481 return FTDM_FAIL;
482 }
483
484
485 static FIO_SPAN_DESTROY_FUNCTION(m3ua_span_destroy)
486 {
487 m3ua_span_data_t *span_data = (m3ua_span_data_t *) span->mod_data;
488
489 if (span_data) {
490 ftdm_safe_free(span_data);
491 }
492
493 return FTDM_SUCCESS;
494 }
495 static FIO_CHANNEL_DESTROY_FUNCTION(m3ua_channel_destroy)
496 {
497 m3ua_chan_data_t *chan_data = (m3ua_chan_data_t *) ftdmchan->mod_data;
498 m3ua_span_data_t *span_data = (m3ua_span_data_t *) ftdmchan->span->mod_data;
499
500 if (!chan_data) {
501 return FTDM_FAIL;
502 }
503
504
505
506
507
508
509 ftdm_mutex_destroy(&chan_data->digit_mutex);
510 ftdm_buffer_destroy(&chan_data->digit_buffer);
511
512
513 ftdm_safe_free(chan_data);
514
515 if (span_data) {
516 ftdm_safe_free(span_data);
517 }
518
519
520 return FTDM_SUCCESS;
521 }
522
523
524
525 static FIO_GET_ALARMS_FUNCTION(m3ua_get_alarms)
526 {
527 return FTDM_FAIL;
528 }
529
530 static ftdm_io_interface_t m3ua_interface;
531
532 ftdm_status_t m3ua_init(ftdm_io_interface_t **zint)
533 {
534 assert(zint != NULL);
535 memset(&m3ua_interface, 0, sizeof(m3ua_interface));
536
537 m3ua_interface.name = "m3ua";
538 m3ua_interface.configure = m3ua_configure;
539 m3ua_interface.configure_span = m3ua_configure_span;
540 m3ua_interface.open = m3ua_open;
541 m3ua_interface.close = m3ua_close;
542 m3ua_interface.wait = m3ua_wait;
543 m3ua_interface.read = m3ua_read;
544 m3ua_interface.write = m3ua_write;
545 m3ua_interface.command = m3ua_command;
546 m3ua_interface.poll_event = m3ua_poll_event;
547 m3ua_interface.next_event = m3ua_next_event;
548 m3ua_interface.channel_destroy = m3ua_channel_destroy;
549 m3ua_interface.span_destroy = m3ua_span_destroy;
550 m3ua_interface.get_alarms = m3ua_get_alarms;
551 *zint = &m3ua_interface;
552
553 return FTDM_FAIL;
554 }
555
556 ftdm_status_t m3ua_destroy(void)
557 {
558 return FTDM_FAIL;
559 }
560
561
562 static void *m3ua_run(ftdm_thread_t *me, void *obj)
563 {
564 ftdm_span_t *span = (ftdm_span_t *) obj;
565 m3ua_data_t *m3ua_data = span->signal_data;
566 m3uac_connection_t *mcon, *pcon;
567 uint32_t ms = 10, too_long = 60000;
568
569
570 m3ua_data->pcon = m3ua_data->mcon;
571
572 if (m3uac_connection_open(&m3ua_data->mcon,
573 m3ua_data->mcon.cfg.local_ip,
574 m3ua_data->mcon.cfg.local_port,
575 m3ua_data->mcon.cfg.remote_ip,
576 m3ua_data->mcon.cfg.remote_port) < 0) {
577 ftdm_log(FTDM_LOG_DEBUG, "Error: Opening MCON Socket [%d] %s\n", m3ua_data->mcon.socket, strerror(errno));
578 goto end;
579 }
580
581 if (m3uac_connection_open(&m3ua_data->pcon,
582 m3ua_data->pcon.cfg.local_ip,
583 ++m3ua_data->pcon.cfg.local_port,
584 m3ua_data->pcon.cfg.remote_ip,
585 m3ua_data->pcon.cfg.remote_port) < 0) {
586 ftdm_log(FTDM_LOG_DEBUG, "Error: Opening PCON Socket [%d] %s\n", m3ua_data->pcon.socket, strerror(errno));
587 goto end;
588 }
589
590 mcon = &m3ua_data->mcon;
591 pcon = &m3ua_data->pcon;
592
593 top:
594
595
596
597 m3uac_exec_command(mcon,
598 0,
599 0,
600 -1,
601 SIGBOOST_EVENT_SYSTEM_RESTART,
602 0);
603
604 while (ftdm_test_flag(m3ua_data, FTDM_M3UA_RUNNING)) {
605 fd_set rfds, efds;
606 struct timeval tv = { 0, ms * 1000 };
607 int max, activity, i = 0;
608 m3uac_event_t *event = NULL;
609
610 if (!ftdm_running()) {
611 m3uac_exec_command(mcon,
612 0,
613 0,
614 -1,
615 SIGBOOST_EVENT_SYSTEM_RESTART,
616 0);
617 break;
618 }
619
620 FD_ZERO(&rfds);
621 FD_ZERO(&efds);
622 FD_SET(mcon->socket, &rfds);
623 FD_SET(mcon->socket, &efds);
624 FD_SET(pcon->socket, &rfds);
625 FD_SET(pcon->socket, &efds);
626
627 max = ((pcon->socket > mcon->socket) ? pcon->socket : mcon->socket) + 1;
628
629 if ((activity = select(max, &rfds, NULL, &efds, &tv)) < 0) {
630 goto error;
631 }
632
633 if (activity) {
634 if (FD_ISSET(pcon->socket, &efds) || FD_ISSET(mcon->socket, &efds)) {
635 goto error;
636 }
637
638 if (FD_ISSET(pcon->socket, &rfds)) {
639 if ((event = m3uac_connection_readp(pcon, i))) {
640 parse_ss7_event(span, mcon, event);
641 } else goto top;
642 }
643
644 if (FD_ISSET(mcon->socket, &rfds)) {
645 if ((event = m3uac_connection_read(mcon, i))) {
646 parse_ss7_event(span, mcon, event);
647 } else goto top;
648 }
649 }
650
651 check_state(span);
652 mcon->hb_elapsed += ms;
653
654 if (mcon->hb_elapsed >= too_long && (mcon->up || !ftdm_test_flag(span, FTDM_SPAN_SUSPENDED))) {
655 ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART);
656 ftdm_set_flag_locked(span, FTDM_SPAN_SUSPENDED);
657 mcon->up = 0;
658 ftdm_log(FTDM_LOG_CRIT, "Lost Heartbeat!\n");
659 }
660
661 }
662
663 goto end;
664
665 error:
666 ftdm_log(FTDM_LOG_CRIT, "Socket Error!\n");
667
668 end:
669
670 m3uac_connection_close(&m3ua_data->mcon);
671 m3uac_connection_close(&m3ua_data->pcon);
672
673 ftdm_clear_flag(m3ua_data, FTDM_M3UA_RUNNING);
674
675 ftdm_log(FTDM_LOG_DEBUG, "M3UA thread ended.\n");
676 return NULL;
677 }
678 ftdm_status_t m3ua_start(ftdm_span_t *span)
679 {
680 m3ua_data_t *m3ua_data = span->signal_data;
681 ftdm_set_flag(m3ua_data, FTDM_M3UA_RUNNING);
682 return ftdm_thread_create_detached(m3ua_run, span);
683 }
684
685
686
687
688
689
690
691
692