This source file includes following definitions.
- _ftdm_channel_set_state_force
- FIO_IO_UNLOAD_FUNCTION
- FIO_CHANNEL_GET_SIG_STATUS_FUNCTION
- FIO_SPAN_GET_SIG_STATUS_FUNCTION
- FIO_CHANNEL_OUTGOING_CALL_FUNCTION
- FIO_CHANNEL_REQUEST_FUNCTION
- s_pri_error
- s_pri_message
- parse_debug
- print_debug
- FIO_API_FUNCTION
- FIO_IO_LOAD_FUNCTION
- FIO_SIG_LOAD_FUNCTION
- state_advance
- check_state
- on_info
- on_hangup
- on_answer
- on_proceeding
- on_progress
- on_ringing
- on_ring
- process_event
- check_events
- check_flags
- on_restart
- aoc_billing_id
- aoc_money_amount
- handle_facility_aoc_s
- handle_facility_aoc_d
- handle_facility_aoc_e
- on_facility
- on_dchan_up
- on_dchan_down
- on_anything
- on_io_fail
- ftdm_libpri_run
- ftdm_libpri_stop
- ftdm_libpri_start
- parse_mode
- parse_dialect
- parse_layer1
- parse_ton
- parse_opts
- FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION
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 #include "private/ftdm_core.h"
35 #include "ftmod_libpri.h"
36
37 static void _ftdm_channel_set_state_force(ftdm_channel_t *chan, const ftdm_channel_state_t state)
38 {
39 assert(chan);
40 chan->state = state;
41 }
42
43
44
45
46
47 static FIO_IO_UNLOAD_FUNCTION(ftdm_libpri_unload)
48 {
49 return FTDM_SUCCESS;
50 }
51
52
53
54
55
56
57
58
59 static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(isdn_get_channel_sig_status)
60 {
61 *status = FTDM_SIG_STATE_DOWN;
62
63 ftdm_libpri_data_t *isdn_data = ftdmchan->span->signal_data;
64 if (ftdm_test_flag(&(isdn_data->spri), LPWRAP_PRI_READY)) {
65 *status = FTDM_SIG_STATE_UP;
66 }
67 return FTDM_SUCCESS;
68 }
69
70
71
72
73
74
75
76
77 static FIO_SPAN_GET_SIG_STATUS_FUNCTION(isdn_get_span_sig_status)
78 {
79 *status = FTDM_SIG_STATE_DOWN;
80
81 ftdm_libpri_data_t *isdn_data = span->signal_data;
82 if (ftdm_test_flag(&(isdn_data->spri), LPWRAP_PRI_READY)) {
83 *status = FTDM_SIG_STATE_UP;
84 }
85 return FTDM_SUCCESS;
86 }
87
88
89
90
91
92
93
94 static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(isdn_outgoing_call)
95 {
96 ftdm_status_t status = FTDM_SUCCESS;
97 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND);
98 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DIALING);
99 return status;
100 }
101
102
103
104
105
106
107
108
109
110
111 static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request)
112 {
113 return FTDM_FAIL;
114 }
115
116 #ifdef WIN32
117
118
119
120
121 static void s_pri_error(char *s)
122 #else
123
124
125
126
127
128 static void s_pri_error(struct pri *pri, char *s)
129 #endif
130 {
131 ftdm_log(FTDM_LOG_ERROR, "%s", s);
132 }
133
134 #ifdef WIN32
135
136
137
138
139 static void s_pri_message(char *s)
140 #else
141
142
143
144
145
146 static void s_pri_message(struct pri *pri, char *s)
147 #endif
148 {
149 ftdm_log(FTDM_LOG_DEBUG, "%s", s);
150 }
151
152 #define PRI_DEBUG_Q921_ALL (PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE)
153 #define PRI_DEBUG_Q931_ALL (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | PRI_DEBUG_Q931_ANOMALY)
154
155 static const struct ftdm_libpri_debug {
156 const char *name;
157 const int flags;
158 } ftdm_libpri_debug[] = {
159
160 { "q921_all", PRI_DEBUG_Q921_ALL },
161 { "q921_raw", PRI_DEBUG_Q921_RAW },
162 { "q921_dump", PRI_DEBUG_Q921_DUMP },
163 { "q921_state", PRI_DEBUG_Q921_STATE },
164
165 { "q931_all", PRI_DEBUG_Q931_ALL },
166 { "q931_dump", PRI_DEBUG_Q931_DUMP },
167 { "q931_state", PRI_DEBUG_Q931_STATE },
168 { "q931_anomaly", PRI_DEBUG_Q931_ANOMALY },
169
170 { "config", PRI_DEBUG_CONFIG },
171 { "apdu", PRI_DEBUG_APDU },
172 { "aoc", PRI_DEBUG_AOC }
173 };
174
175
176
177
178
179
180 static int parse_debug(const char *in, uint32_t *flags)
181 {
182 int res = -1;
183 int i;
184
185 if (!in || !flags)
186 return -1;
187
188 if (!strcmp(in, "all")) {
189 *flags = PRI_DEBUG_ALL;
190 return 0;
191 }
192 if (strstr(in, "none")) {
193 *flags = 0;
194 return 0;
195 }
196
197 for (i = 0; i < ftdm_array_len(ftdm_libpri_debug); i++) {
198 if (strstr(in, ftdm_libpri_debug[i].name)) {
199 *flags |= ftdm_libpri_debug[i].flags;
200 res = 0;
201 }
202 }
203 return res;
204 }
205
206 static int print_debug(uint32_t flags, char *tmp, const int size)
207 {
208 int offset = 0;
209 int res = 0;
210 int i;
211
212 if ((flags & PRI_DEBUG_ALL) == PRI_DEBUG_ALL) {
213 strcat(tmp, "all");
214 return 0;
215 }
216 else if (!flags) {
217 strcat(tmp, "none");
218 return 0;
219 }
220
221 for (i = 0; i < ftdm_array_len(ftdm_libpri_debug); i++) {
222 if ((flags & ftdm_libpri_debug[i].flags) == ftdm_libpri_debug[i].flags) {
223 res = snprintf(&tmp[offset], size - offset, "%s,", ftdm_libpri_debug[i].name);
224 if (res <= 0 || res == (size - offset))
225 goto out;
226 offset += res;
227 flags &= ~ftdm_libpri_debug[i].flags;
228 }
229 }
230
231 out:
232 tmp[offset - 1] = '\0';
233 return 0;
234 }
235
236 static ftdm_status_t ftdm_libpri_start(ftdm_span_t *span);
237 static ftdm_io_interface_t ftdm_libpri_interface;
238
239 static const char *ftdm_libpri_usage =
240 "Usage:\n"
241 "libpri kill <span>\n"
242 "libpri debug <span> [all|none|flag,...flagN]\n"
243 "\n"
244 "Possible debug flags:\n"
245 "\tq921_raw - Q.921 Raw messages\n"
246 "\tq921_dump - Q.921 Decoded messages\n"
247 "\tq921_state - Q.921 State machine changes\n"
248 "\tq921_all - Enable all Q.921 debug options\n"
249 "\n"
250 "\tq931_dump - Q.931 Messages\n"
251 "\tq931_state - Q.931 State machine changes\n"
252 "\tq931_anomaly - Q.931 Anomalies\n"
253 "\tq931_all - Enable all Q.931 debug options\n"
254 "\n"
255 "\tapdu - Application protocol data unit\n"
256 "\taoc - Advice of Charge messages\n"
257 "\tconfig - Configuration\n"
258 "\n"
259 "\tnone - Disable debugging\n"
260 "\tall - Enable all debug options\n";
261
262
263
264
265
266
267
268 static FIO_API_FUNCTION(ftdm_libpri_api)
269 {
270 char *mycmd = NULL, *argv[10] = { 0 };
271 int argc = 0;
272
273 if (data) {
274 mycmd = ftdm_strdup(data);
275 argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
276 }
277
278 if (argc == 1) {
279 if (!strcasecmp(argv[0], "help") || !strcasecmp(argv[0], "usage")) {
280 stream->write_function(stream, ftdm_libpri_usage);
281 goto done;
282 }
283 }
284
285 if (argc == 2) {
286 if (!strcasecmp(argv[0], "kill")) {
287 int span_id = atoi(argv[1]);
288 ftdm_span_t *span = NULL;
289
290 if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) {
291 ftdm_libpri_data_t *isdn_data = span->signal_data;
292
293 if (span->start != ftdm_libpri_start) {
294 stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
295 goto done;
296 }
297
298 ftdm_clear_flag(&(isdn_data->spri), LPWRAP_PRI_READY);
299 stream->write_function(stream, "%s: +OK killed.\n", __FILE__);
300 goto done;
301 } else {
302 stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
303 goto done;
304 }
305 }
306 }
307
308 if (argc >= 2) {
309 if (!strcasecmp(argv[0], "debug")) {
310 ftdm_span_t *span = NULL;
311
312 if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) {
313 ftdm_libpri_data_t *isdn_data = span->signal_data;
314 uint32_t flags = 0;
315
316 if (span->start != ftdm_libpri_start) {
317 stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
318 goto done;
319 }
320
321 if (argc == 2) {
322 char tmp[100] = { 0 };
323 print_debug(pri_get_debug(isdn_data->spri.pri), tmp, sizeof(tmp));
324 stream->write_function(stream, "%s: +OK current debug flags: '%s'\n", __FILE__, tmp);
325 goto done;
326 }
327
328 if (parse_debug(argv[2], &flags) == -1) {
329 stream->write_function(stream, "%s: -ERR invalid debug flags given\n", __FILE__);
330 goto done;
331 }
332
333 pri_set_debug(isdn_data->spri.pri, flags);
334 stream->write_function(stream, "%s: +OK debug %s.\n", __FILE__, (flags) ? "enabled" : "disabled");
335 goto done;
336 } else {
337 stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
338 goto done;
339 }
340 }
341
342 }
343 stream->write_function(stream, "%s: -ERR invalid command.\n", __FILE__);
344
345 done:
346 ftdm_safe_free(mycmd);
347
348 return FTDM_SUCCESS;
349 }
350
351
352
353
354
355
356
357 static FIO_IO_LOAD_FUNCTION(ftdm_libpri_io_init)
358 {
359 assert(fio != NULL);
360
361 memset(&ftdm_libpri_interface, 0, sizeof(ftdm_libpri_interface));
362 ftdm_libpri_interface.name = "libpri";
363 ftdm_libpri_interface.api = &ftdm_libpri_api;
364
365 *fio = &ftdm_libpri_interface;
366
367 return FTDM_SUCCESS;
368 }
369
370
371
372
373
374
375 static FIO_SIG_LOAD_FUNCTION(ftdm_libpri_init)
376 {
377 pri_set_error(s_pri_error);
378 pri_set_message(s_pri_message);
379 return FTDM_SUCCESS;
380 }
381
382
383
384
385 static ftdm_state_map_t isdn_state_map = {
386 {
387 {
388 ZSD_OUTBOUND,
389 ZSM_UNACCEPTABLE,
390 {FTDM_ANY_STATE},
391 {FTDM_CHANNEL_STATE_RESTART, FTDM_END}
392 },
393 {
394 ZSD_OUTBOUND,
395 ZSM_UNACCEPTABLE,
396 {FTDM_CHANNEL_STATE_RESTART, FTDM_END},
397 {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
398 },
399 {
400 ZSD_OUTBOUND,
401 ZSM_UNACCEPTABLE,
402 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
403 {FTDM_CHANNEL_STATE_DIALING, FTDM_END}
404 },
405 {
406 ZSD_OUTBOUND,
407 ZSM_UNACCEPTABLE,
408 {FTDM_CHANNEL_STATE_DIALING, FTDM_END},
409 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
410 FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS,
411 FTDM_CHANNEL_STATE_UP, FTDM_END}
412 },
413 {
414 ZSD_OUTBOUND,
415 ZSM_UNACCEPTABLE,
416 {FTDM_CHANNEL_STATE_PROCEED, FTDM_END},
417 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
418 FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
419 },
420 {
421 ZSD_OUTBOUND,
422 ZSM_UNACCEPTABLE,
423 {FTDM_CHANNEL_STATE_RINGING, FTDM_END},
424 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
425 FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
426 },
427 {
428 ZSD_OUTBOUND,
429 ZSM_UNACCEPTABLE,
430 {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
431 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
432 FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_END}
433 },
434 {
435 ZSD_OUTBOUND,
436 ZSM_UNACCEPTABLE,
437 {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
438 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_END}
439 },
440 {
441 ZSD_OUTBOUND,
442 ZSM_UNACCEPTABLE,
443 {FTDM_CHANNEL_STATE_UP, FTDM_END},
444 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
445 },
446 {
447 ZSD_OUTBOUND,
448 ZSM_UNACCEPTABLE,
449 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
450 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
451 },
452 {
453 ZSD_OUTBOUND,
454 ZSM_UNACCEPTABLE,
455 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
456 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
457 },
458 {
459 ZSD_OUTBOUND,
460 ZSM_UNACCEPTABLE,
461 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
462 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
463 },
464
465
466 {
467 ZSD_INBOUND,
468 ZSM_UNACCEPTABLE,
469 {FTDM_ANY_STATE},
470 {FTDM_CHANNEL_STATE_RESTART, FTDM_END}
471 },
472 {
473 ZSD_INBOUND,
474 ZSM_UNACCEPTABLE,
475 {FTDM_CHANNEL_STATE_RESTART, FTDM_END},
476 {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
477 },
478 {
479 ZSD_INBOUND,
480 ZSM_UNACCEPTABLE,
481 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
482 {FTDM_CHANNEL_STATE_DIALTONE, FTDM_CHANNEL_STATE_RING, FTDM_END}
483 },
484 {
485 ZSD_INBOUND,
486 ZSM_UNACCEPTABLE,
487 {FTDM_CHANNEL_STATE_DIALTONE, FTDM_END},
488 {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
489 },
490 {
491 ZSD_INBOUND,
492 ZSM_UNACCEPTABLE,
493 {FTDM_CHANNEL_STATE_RING, FTDM_END},
494 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_END}
495 },
496 {
497 ZSD_INBOUND,
498 ZSM_UNACCEPTABLE,
499 {FTDM_CHANNEL_STATE_PROCEED, FTDM_END},
500 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS,
501 FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}
502 },
503 {
504 ZSD_INBOUND,
505 ZSM_UNACCEPTABLE,
506 {FTDM_CHANNEL_STATE_RINGING, FTDM_END},
507 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
508 FTDM_CHANNEL_STATE_UP, FTDM_END}
509 },
510 {
511 ZSD_INBOUND,
512 ZSM_UNACCEPTABLE,
513 {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
514 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}
515 },
516 {
517 ZSD_INBOUND,
518 ZSM_UNACCEPTABLE,
519 {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
520 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_UP, FTDM_END}
521 },
522 {
523 ZSD_INBOUND,
524 ZSM_UNACCEPTABLE,
525 {FTDM_CHANNEL_STATE_UP, FTDM_END},
526 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
527 },
528 {
529 ZSD_INBOUND,
530 ZSM_UNACCEPTABLE,
531 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
532 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
533 },
534 {
535 ZSD_INBOUND,
536 ZSM_UNACCEPTABLE,
537 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
538 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
539 },
540 {
541 ZSD_INBOUND,
542 ZSM_UNACCEPTABLE,
543 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
544 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
545 },
546 }
547 };
548
549
550
551
552
553
554 static ftdm_status_t state_advance(ftdm_channel_t *chan)
555 {
556 ftdm_libpri_data_t *isdn_data = chan->span->signal_data;
557 q931_call *call = (q931_call *)chan->call_data;
558 ftdm_status_t status;
559 ftdm_sigmsg_t sig;
560
561 ftdm_log(FTDM_LOG_DEBUG, "-- %d:%d STATE [%s]\n",
562 ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan), ftdm_channel_get_state_str(chan));
563
564 memset(&sig, 0, sizeof(sig));
565 sig.chan_id = ftdm_channel_get_id(chan);
566 sig.span_id = ftdm_channel_get_span_id(chan);
567 sig.channel = chan;
568
569 ftdm_channel_complete_state(chan);
570
571 switch (ftdm_channel_get_state(chan)) {
572 case FTDM_CHANNEL_STATE_DOWN:
573 {
574 ftdm_channel_t *chtmp = chan;
575 chan->call_data = NULL;
576
577 if (ftdm_channel_close(&chtmp) != FTDM_SUCCESS) {
578 ftdm_log(FTDM_LOG_WARNING, "-- Failed to close channel %d:%d\n",
579 ftdm_channel_get_span_id(chan),
580 ftdm_channel_get_id(chan));
581 } else {
582 ftdm_log(FTDM_LOG_DEBUG, "-- Closed channel %d:%d\n",
583 ftdm_channel_get_span_id(chan),
584 ftdm_channel_get_id(chan));
585 }
586 }
587 break;
588
589 case FTDM_CHANNEL_STATE_PROGRESS:
590 {
591 if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) {
592 sig.event_id = FTDM_SIGEVENT_PROGRESS;
593 if ((status = ftdm_span_send_signal(ftdm_channel_get_span(chan), &sig) != FTDM_SUCCESS)) {
594 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP);
595 }
596 } else if (call) {
597 pri_progress(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0);
598 } else {
599 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART);
600 }
601 }
602 break;
603
604 case FTDM_CHANNEL_STATE_RINGING:
605 {
606 if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) {
607 sig.event_id = FTDM_SIGEVENT_RINGING;
608 if ((status = ftdm_span_send_signal(ftdm_channel_get_span(chan), &sig) != FTDM_SUCCESS)) {
609 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP);
610 }
611 } else if (call) {
612
613 pri_acknowledge(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 1);
614 } else {
615 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART);
616 }
617 }
618 break;
619
620 case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
621 {
622 if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) {
623 sig.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
624 if ((status = ftdm_span_send_signal(ftdm_channel_get_span(chan), &sig) != FTDM_SUCCESS)) {
625 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP);
626 }
627 } else if (call) {
628
629 if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
630 ftdm_channel_open_chan(chan);
631 }
632 pri_progress(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 1);
633 } else {
634 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART);
635 }
636 }
637 break;
638
639 case FTDM_CHANNEL_STATE_PROCEED:
640 {
641 if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) {
642
643 sig.event_id = FTDM_SIGEVENT_PROCEED;
644 if ((status = ftdm_span_send_signal(ftdm_channel_get_span(chan), &sig) != FTDM_SUCCESS)) {
645 ftdm_log(FTDM_LOG_ERROR, "Failed to send PROCEED sigevent on Channel %d:%d\n",
646 ftdm_channel_get_span_id(chan),
647 ftdm_channel_get_id(chan));
648 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP);
649 }
650 } else if (call) {
651 pri_proceeding(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0);
652 } else {
653 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART);
654 }
655 }
656 break;
657
658 case FTDM_CHANNEL_STATE_RING:
659 {
660
661
662
663
664 if (!ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) {
665 if (call) {
666 pri_proceeding(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0);
667
668 sig.event_id = FTDM_SIGEVENT_START;
669 if ((status = ftdm_span_send_signal(ftdm_channel_get_span(chan), &sig) != FTDM_SUCCESS)) {
670 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP);
671 }
672 } else {
673 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART);
674 }
675 }
676 }
677 break;
678
679 case FTDM_CHANNEL_STATE_RESTART:
680 {
681 chan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_UNSPECIFIED;
682 sig.event_id = FTDM_SIGEVENT_RESTART;
683 status = ftdm_span_send_signal(ftdm_channel_get_span(chan), &sig);
684 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_DOWN);
685 }
686 break;
687
688 case FTDM_CHANNEL_STATE_UP:
689 {
690 if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) {
691 sig.event_id = FTDM_SIGEVENT_UP;
692 if ((status = ftdm_span_send_signal(ftdm_channel_get_span(chan), &sig) != FTDM_SUCCESS)) {
693 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP);
694 }
695 } else if (call) {
696
697 if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
698 ftdm_channel_open_chan(chan);
699 }
700 pri_answer(isdn_data->spri.pri, call, 0, 1);
701 } else {
702 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART);
703 }
704 }
705 break;
706
707 case FTDM_CHANNEL_STATE_DIALING:
708 if (isdn_data) {
709 ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
710 struct pri_sr *sr;
711 int ton;
712
713 if (!(call = pri_new_call(isdn_data->spri.pri))) {
714 ftdm_log(FTDM_LOG_ERROR, "Failed to create new call on channel %d:%d\n",
715 ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan));
716
717 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART);
718 return FTDM_SUCCESS;
719 }
720
721 ton = caller_data->dnis.type;
722 switch (ton) {
723 case FTDM_TON_NATIONAL:
724 ton = PRI_NATIONAL_ISDN;
725 break;
726 case FTDM_TON_INTERNATIONAL:
727 ton = PRI_INTERNATIONAL_ISDN;
728 break;
729 case FTDM_TON_SUBSCRIBER_NUMBER:
730 ton = PRI_LOCAL_ISDN;
731 break;
732 default:
733 ton = isdn_data->ton;
734 }
735
736 chan->call_data = call;
737
738 sr = pri_sr_new();
739 if (!sr) {
740 ftdm_log(FTDM_LOG_ERROR, "Failed to create new setup request on channel %d:%d\n",
741 ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan));
742
743 }
744 assert(sr);
745
746 pri_sr_set_channel(sr, ftdm_channel_get_id(chan), 0, 0);
747 pri_sr_set_bearer(sr, PRI_TRANS_CAP_SPEECH, isdn_data->layer1);
748
749 pri_sr_set_called(sr, caller_data->dnis.digits, ton, 1);
750 pri_sr_set_caller(sr, caller_data->cid_num.digits,
751 ((isdn_data->opts & FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE) ? NULL : caller_data->cid_name),
752 ton,
753 ((caller_data->pres != 1) ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_PROHIB_USER_NUMBER_NOT_SCREENED));
754
755 if (!(isdn_data->opts & FTMOD_LIBPRI_OPT_OMIT_REDIRECTING_NUMBER_IE)) {
756 pri_sr_set_redirecting(sr, caller_data->cid_num.digits, ton,
757 PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, PRI_REDIR_UNCONDITIONAL);
758 }
759 #ifdef HAVE_LIBPRI_AOC
760 if (isdn_data->opts & FTMOD_LIBPRI_OPT_FACILITY_AOC) {
761
762 pri_sr_set_aoc_charging_request(sr, (PRI_AOC_REQUEST_S | PRI_AOC_REQUEST_E | PRI_AOC_REQUEST_D));
763 ftdm_log(FTDM_LOG_DEBUG, "Requesting AOC-S/D/E on call\n");
764 }
765 #endif
766 if (pri_setup(isdn_data->spri.pri, call, sr)) {
767 caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;
768 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP);
769 }
770
771 pri_sr_free(sr);
772 }
773 break;
774
775 case FTDM_CHANNEL_STATE_HANGUP:
776 {
777 if (call) {
778 ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
779
780 pri_hangup(isdn_data->spri.pri, call, caller_data->hangup_cause);
781
782
783 chan->call_data = NULL;
784 }
785 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
786 }
787 break;
788
789 case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
790 {
791 if (call) {
792 pri_destroycall(isdn_data->spri.pri, call);
793 chan->call_data = NULL;
794 }
795 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_DOWN);
796 }
797 break;
798
799 case FTDM_CHANNEL_STATE_TERMINATING:
800 {
801 sig.event_id = FTDM_SIGEVENT_STOP;
802 status = ftdm_span_send_signal(ftdm_channel_get_span(chan), &sig);
803
804 }
805 default:
806 break;
807 }
808 return FTDM_SUCCESS;
809 }
810
811
812
813
814
815 static __inline__ void check_state(ftdm_span_t *span)
816 {
817 if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE)) {
818 uint32_t j;
819
820 ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE);
821
822 for (j = 1; j <= ftdm_span_get_chan_count(span); j++) {
823 ftdm_channel_t *chan = ftdm_span_get_channel(span, j);
824 ftdm_channel_lock(chan);
825 ftdm_channel_advance_states(chan);
826 ftdm_channel_unlock(chan);
827 }
828 }
829 }
830
831
832
833
834
835
836
837
838 static int on_info(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
839 {
840 ftdm_log(FTDM_LOG_DEBUG, "number is: %s\n", pevent->ring.callednum);
841
842 if (strlen(pevent->ring.callednum) > 3) {
843 ftdm_log(FTDM_LOG_DEBUG, "final number is: %s\n", pevent->ring.callednum);
844 pri_answer(spri->pri, pevent->ring.call, 0, 1);
845 }
846 return 0;
847 }
848
849
850
851
852
853
854
855
856 static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
857 {
858 ftdm_span_t *span = spri->span;
859 ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->hangup.channel);
860 q931_call *call = NULL;
861
862 if (!chan) {
863 ftdm_log(FTDM_LOG_CRIT, "-- Hangup on channel %d:%d %s but it's not in use?\n", ftdm_span_get_id(spri->span), pevent->hangup.channel);
864 return 0;
865 }
866
867 ftdm_channel_lock(chan);
868
869 if (ftdm_channel_get_state(chan) >= FTDM_CHANNEL_STATE_TERMINATING) {
870 ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Ignoring remote hangup in state %s\n", ftdm_channel_get_state_str(chan));
871 goto done;
872 }
873
874 if (!chan->call_data) {
875 ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Ignoring remote hangup in state %s with no call data\n", ftdm_channel_get_state_str(chan));
876 goto done;
877 }
878
879 call = (q931_call *)chan->call_data;
880
881 ftdm_log(FTDM_LOG_DEBUG, "-- Hangup on channel %d:%d\n", ftdm_span_get_id(spri->span), pevent->hangup.channel);
882
883 pri_release(spri->pri, call, 0);
884 pri_destroycall(spri->pri, call);
885
886 chan->caller_data.hangup_cause = pevent->hangup.cause;
887 chan->call_data = NULL;
888 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING);
889
890 done:
891 ftdm_channel_unlock(chan);
892 return 0;
893 }
894
895
896
897
898
899
900
901
902 static int on_answer(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
903 {
904 ftdm_span_t *span = spri->span;
905 ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->answer.channel);
906
907 if (chan) {
908 if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
909 ftdm_log(FTDM_LOG_DEBUG, "-- Call answered, opening B-Channel %d:%d\n",
910 ftdm_channel_get_span_id(chan),
911 ftdm_channel_get_id(chan));
912
913 if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) {
914 ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
915
916 ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n",
917 ftdm_channel_get_span_id(chan),
918 ftdm_channel_get_id(chan));
919
920 caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;
921 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING);
922 goto out;
923 }
924 }
925 ftdm_log(FTDM_LOG_DEBUG, "-- Answer on channel %d:%d\n", ftdm_span_get_id(span), pevent->answer.channel);
926 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_UP);
927 } else {
928 ftdm_log(FTDM_LOG_DEBUG, "-- Answer on channel %d:%d but it's not in the span?\n",
929 ftdm_span_get_id(span), pevent->answer.channel);
930 }
931 out:
932 return 0;
933 }
934
935
936
937
938
939
940
941
942 static int on_proceeding(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
943 {
944 ftdm_span_t *span = spri->span;
945 ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->proceeding.channel);
946
947 if (chan) {
948
949 if ((pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) && !ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
950 ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n",
951 ftdm_channel_get_span_id(chan),
952 ftdm_channel_get_id(chan));
953
954 if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) {
955 ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
956
957 ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n",
958 ftdm_channel_get_span_id(chan),
959 ftdm_channel_get_id(chan));
960
961 caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;
962 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING);
963 goto out;
964 }
965 }
966 ftdm_log(FTDM_LOG_DEBUG, "-- Proceeding on channel %d:%d\n", ftdm_span_get_id(span), pevent->proceeding.channel);
967 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROCEED);
968 } else {
969 ftdm_log(FTDM_LOG_DEBUG, "-- Proceeding on channel %d:%d but it's not in the span?\n",
970 ftdm_span_get_id(span), pevent->proceeding.channel);
971 }
972 out:
973 return 0;
974 }
975
976
977
978
979
980
981
982
983
984 static int on_progress(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
985 {
986 ftdm_span_t *span = spri->span;
987 ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->proceeding.channel);
988
989 if (chan) {
990
991 if ((pevent->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) && !ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
992 ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n",
993 ftdm_channel_get_span_id(chan),
994 ftdm_channel_get_id(chan));
995
996 if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) {
997 ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
998
999 ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n",
1000 ftdm_channel_get_span_id(chan),
1001 ftdm_channel_get_id(chan));
1002
1003 caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;
1004 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING);
1005 goto out;
1006 }
1007 ftdm_log(FTDM_LOG_DEBUG, "-- Progress on channel %d:%d with media\n", ftdm_span_get_id(span), pevent->proceeding.channel);
1008 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
1009 } else {
1010 ftdm_log(FTDM_LOG_DEBUG, "-- Progress on channel %d:%d\n", ftdm_span_get_id(span), pevent->proceeding.channel);
1011 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS);
1012 }
1013 } else {
1014 ftdm_log(FTDM_LOG_DEBUG, "-- Progress on channel %d:%d but it's not in the span?\n",
1015 ftdm_span_get_id(span), pevent->proceeding.channel);
1016 }
1017 out:
1018 return 0;
1019 }
1020
1021
1022
1023
1024
1025
1026
1027
1028 static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
1029 {
1030 ftdm_span_t *span = spri->span;
1031 ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->ringing.channel);
1032
1033 if (chan) {
1034 ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d\n", ftdm_span_get_id(span), pevent->ringing.channel);
1035
1036
1037
1038
1039
1040
1041
1042
1043 if ((pevent->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) && !ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
1044 ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n",
1045 ftdm_channel_get_span_id(chan),
1046 ftdm_channel_get_id(chan));
1047
1048 if (ftdm_channel_open_chan(chan) != FTDM_SUCCESS) {
1049 ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
1050
1051 ftdm_log(FTDM_LOG_ERROR, "-- Error opening channel %d:%d\n",
1052 ftdm_channel_get_span_id(chan),
1053 ftdm_channel_get_id(chan));
1054
1055 caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;
1056 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING);
1057 goto out;
1058 }
1059 }
1060
1061 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RINGING);
1062 } else {
1063 ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d but it's not in the span?\n",
1064 ftdm_span_get_id(span), pevent->ringing.channel);
1065 }
1066 out:
1067 return 0;
1068 }
1069
1070
1071
1072
1073
1074
1075
1076
1077 static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
1078 {
1079 ftdm_span_t *span = spri->span;
1080 ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->ring.channel);
1081 ftdm_caller_data_t *caller_data = NULL;
1082 int ret = 0;
1083
1084 if (!chan) {
1085 ftdm_log(FTDM_LOG_ERROR, "-- Unable to get channel %d:%d\n", ftdm_span_get_id(span), pevent->ring.channel);
1086 return ret;
1087 }
1088
1089 ftdm_channel_lock(chan);
1090
1091 if (chan->call_data) {
1092
1093
1094 ftdm_log_chan(chan, FTDM_LOG_ERROR, "channel already has call %p!\n", chan->call_data);
1095 chan->call_data = NULL;
1096 }
1097
1098 if (ftdm_channel_get_state(chan) != FTDM_CHANNEL_STATE_DOWN || ftdm_test_flag(chan, FTDM_CHANNEL_INUSE)) {
1099 ftdm_log(FTDM_LOG_WARNING, "-- Duplicate Ring on channel %d:%d (ignored)\n", ftdm_span_get_id(span), pevent->ring.channel);
1100 goto done;
1101 }
1102
1103 if ((pevent->ring.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
1104
1105 ftdm_log(FTDM_LOG_DEBUG, "-- In-band information available, opening B-Channel %d:%d\n",
1106 ftdm_channel_get_span_id(chan),
1107 ftdm_channel_get_id(chan));
1108
1109 if (!ftdm_test_flag(chan, FTDM_CHANNEL_OPEN) && ftdm_channel_open_chan(chan) != FTDM_SUCCESS) {
1110
1111
1112 ftdm_log(FTDM_LOG_WARNING, "-- Error opening channel %d:%d (ignored)\n",
1113 ftdm_channel_get_span_id(chan),
1114 ftdm_channel_get_id(chan));
1115
1116
1117
1118
1119 }
1120 } else {
1121
1122 if (ftdm_channel_use(chan) != FTDM_SUCCESS) {
1123 ftdm_log(FTDM_LOG_WARNING, "-- Error reserving channel %d:%d (ignored)\n",
1124 ftdm_span_get_id(span), pevent->ring.channel);
1125 goto done;
1126 }
1127 }
1128
1129 ftdm_log(FTDM_LOG_NOTICE, "-- Ring on channel %d:%d (from %s to %s)\n", ftdm_span_get_id(span), pevent->ring.channel,
1130 pevent->ring.callingnum, pevent->ring.callednum);
1131
1132 caller_data = ftdm_channel_get_caller_data(chan);
1133
1134 memset(caller_data, 0, sizeof(*caller_data));
1135
1136 ftdm_set_string(caller_data->cid_num.digits, (char *)pevent->ring.callingnum);
1137 ftdm_set_string(caller_data->ani.digits, (char *)pevent->ring.callingani);
1138 ftdm_set_string(caller_data->dnis.digits, (char *)pevent->ring.callednum);
1139 ftdm_set_string(caller_data->rdnis.digits, (char *)pevent->ring.redirectingnum);
1140
1141 if (!ftdm_strlen_zero((char *)pevent->ring.callingname)) {
1142 ftdm_set_string(caller_data->cid_name, (char *)pevent->ring.callingname);
1143 } else {
1144 ftdm_set_string(caller_data->cid_name, (char *)pevent->ring.callingnum);
1145 }
1146
1147 if (pevent->ring.ani2 >= 0) {
1148 snprintf(caller_data->aniII, 5, "%.2d", pevent->ring.ani2);
1149 }
1150
1151
1152
1153 chan->call_data = pevent->ring.call;
1154
1155 ftdm_set_state(chan, FTDM_CHANNEL_STATE_RING);
1156
1157 done:
1158 ftdm_channel_unlock(chan);
1159 return ret;
1160 }
1161
1162
1163
1164
1165
1166
1167
1168 static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *event)
1169 {
1170 ftdm_alarm_flag_t alarmbits;
1171
1172 ftdm_log(FTDM_LOG_DEBUG, "EVENT [%s][%d][%d:%d] STATE [%s]\n",
1173 ftdm_oob_event2str(event->enum_id),
1174 event->enum_id,
1175 ftdm_channel_get_span_id(event->channel),
1176 ftdm_channel_get_id(event->channel),
1177 ftdm_channel_get_state_str(event->channel));
1178
1179 switch (event->enum_id) {
1180 case FTDM_OOB_ALARM_TRAP:
1181 {
1182 if (ftdm_channel_get_state(event->channel) != FTDM_CHANNEL_STATE_DOWN) {
1183 if (ftdm_channel_get_type(event->channel) == FTDM_CHAN_TYPE_B) {
1184 ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RESTART);
1185 }
1186 }
1187
1188 ftdm_set_flag(event->channel, FTDM_CHANNEL_SUSPENDED);
1189
1190 ftdm_channel_get_alarms(event->channel, &alarmbits);
1191 ftdm_log(FTDM_LOG_WARNING, "channel %d:%d (%d:%d) has alarms! [%s]\n",
1192 ftdm_channel_get_span_id(event->channel), ftdm_channel_get_id(event->channel),
1193 ftdm_channel_get_ph_span_id(event->channel), ftdm_channel_get_ph_id(event->channel),
1194 ftdm_channel_get_last_error(event->channel));
1195 }
1196 break;
1197 case FTDM_OOB_ALARM_CLEAR:
1198 {
1199 ftdm_log(FTDM_LOG_WARNING, "channel %d:%d (%d:%d) alarms Cleared!\n",
1200 ftdm_channel_get_span_id(event->channel), ftdm_channel_get_id(event->channel),
1201 ftdm_channel_get_ph_span_id(event->channel), ftdm_channel_get_ph_id(event->channel));
1202
1203 ftdm_clear_flag(event->channel, FTDM_CHANNEL_SUSPENDED);
1204 ftdm_channel_get_alarms(event->channel, &alarmbits);
1205 }
1206 break;
1207 }
1208 return FTDM_SUCCESS;
1209 }
1210
1211
1212
1213
1214
1215 static __inline__ void check_events(ftdm_span_t *span)
1216 {
1217 ftdm_status_t status;
1218
1219 status = ftdm_span_poll_event(span, 5, NULL);
1220
1221 switch (status) {
1222 case FTDM_SUCCESS:
1223 {
1224 ftdm_event_t *event;
1225
1226 while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) {
1227 if (event->enum_id == FTDM_OOB_NOOP) {
1228 continue;
1229 }
1230 if (process_event(span, event) != FTDM_SUCCESS) {
1231 break;
1232 }
1233 }
1234 }
1235 break;
1236
1237 case FTDM_FAIL:
1238 ftdm_log(FTDM_LOG_DEBUG, "Event Failure! %d\n", ftdm_running());
1239 ftdm_sleep(2000);
1240 break;
1241
1242 default:
1243 break;
1244 }
1245 }
1246
1247
1248
1249
1250
1251
1252 static int check_flags(lpwrap_pri_t *spri)
1253 {
1254 ftdm_span_t *span = spri->span;
1255
1256 if (!ftdm_running() || ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) {
1257 return -1;
1258 }
1259
1260 check_state(span);
1261 check_events(span);
1262 return 0;
1263 }
1264
1265
1266
1267
1268
1269
1270
1271
1272 static int on_restart(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
1273 {
1274 ftdm_span_t *span = spri->span;
1275 ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->restart.channel);
1276
1277 ftdm_log(FTDM_LOG_NOTICE, "-- Restarting %d:%d\n", ftdm_span_get_id(span), pevent->restart.channel);
1278 _ftdm_channel_set_state_force(spri->dchan, FTDM_CHANNEL_STATE_UP);
1279
1280 if (!chan) {
1281 return 0;
1282 }
1283
1284 if (pevent->restart.channel < 1) {
1285 ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART);
1286 } else {
1287 ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_RESTART);
1288 }
1289 return 0;
1290 }
1291
1292
1293
1294
1295 #ifdef HAVE_LIBPRI_AOC
1296 static const char *aoc_billing_id(const int id)
1297 {
1298 switch (id) {
1299 case PRI_AOC_E_BILLING_ID_NOT_AVAILABLE:
1300 return "not available";
1301 case PRI_AOC_E_BILLING_ID_NORMAL:
1302 return "normal";
1303 case PRI_AOC_E_BILLING_ID_REVERSE:
1304 return "reverse";
1305 case PRI_AOC_E_BILLING_ID_CREDIT_CARD:
1306 return "credit card";
1307 case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_UNCONDITIONAL:
1308 return "call forwarding unconditional";
1309 case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_BUSY:
1310 return "call forwarding busy";
1311 case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_NO_REPLY:
1312 return "call forwarding no reply";
1313 case PRI_AOC_E_BILLING_ID_CALL_DEFLECTION:
1314 return "call deflection";
1315 case PRI_AOC_E_BILLING_ID_CALL_TRANSFER:
1316 return "call transfer";
1317 default:
1318 return "unknown\n";
1319 }
1320 }
1321
1322 static float aoc_money_amount(const struct pri_aoc_amount *amount)
1323 {
1324 switch (amount->multiplier) {
1325 case PRI_AOC_MULTIPLIER_THOUSANDTH:
1326 return amount->cost * 0.001f;
1327 case PRI_AOC_MULTIPLIER_HUNDREDTH:
1328 return amount->cost * 0.01f;
1329 case PRI_AOC_MULTIPLIER_TENTH:
1330 return amount->cost * 0.1f;
1331 case PRI_AOC_MULTIPLIER_TEN:
1332 return amount->cost * 10.0f;
1333 case PRI_AOC_MULTIPLIER_HUNDRED:
1334 return amount->cost * 100.0f;
1335 case PRI_AOC_MULTIPLIER_THOUSAND:
1336 return amount->cost * 1000.0f;
1337 default:
1338 return amount->cost;
1339 }
1340 }
1341
1342 static int handle_facility_aoc_s(const struct pri_subcmd_aoc_s *aoc_s)
1343 {
1344
1345 return 0;
1346 }
1347
1348 static int handle_facility_aoc_d(const struct pri_subcmd_aoc_d *aoc_d)
1349 {
1350
1351 return 0;
1352 }
1353
1354 static int handle_facility_aoc_e(const struct pri_subcmd_aoc_e *aoc_e)
1355 {
1356 char tmp[1024] = { 0 };
1357 int x = 0, offset = 0;
1358
1359 switch (aoc_e->charge) {
1360 case PRI_AOC_DE_CHARGE_FREE:
1361 strcat(tmp, "\tcharge-type: none\n");
1362 offset = strlen(tmp);
1363 break;
1364
1365 case PRI_AOC_DE_CHARGE_CURRENCY:
1366 sprintf(tmp, "\tcharge-type: money\n\tcharge-amount: %.2f\n\tcharge-currency: %s\n",
1367 aoc_money_amount(&aoc_e->recorded.money.amount),
1368 aoc_e->recorded.money.currency);
1369 offset = strlen(tmp);
1370 break;
1371
1372 case PRI_AOC_DE_CHARGE_UNITS:
1373 strcat(tmp, "\tcharge-type: units\n");
1374 offset = strlen(tmp);
1375
1376 for (x = 0; x < aoc_e->recorded.unit.num_items; x++) {
1377 sprintf(&tmp[offset], "\tcharge-amount: %ld (type: %d)\n",
1378 aoc_e->recorded.unit.item[x].number,
1379 aoc_e->recorded.unit.item[x].type);
1380 offset += strlen(&tmp[offset]);
1381 }
1382 break;
1383
1384 default:
1385 strcat(tmp, "\tcharge-type: not available\n");
1386 offset = strlen(tmp);
1387 }
1388
1389 sprintf(&tmp[offset], "\tbilling-id: %s\n", aoc_billing_id(aoc_e->billing_id));
1390 offset += strlen(&tmp[offset]);
1391
1392 strcat(&tmp[offset], "\tassociation-type: ");
1393 offset += strlen(&tmp[offset]);
1394
1395 switch (aoc_e->associated.charging_type) {
1396 case PRI_AOC_E_CHARGING_ASSOCIATION_NOT_AVAILABLE:
1397 strcat(&tmp[offset], "not available\n");
1398 break;
1399 case PRI_AOC_E_CHARGING_ASSOCIATION_NUMBER:
1400 sprintf(&tmp[offset], "number\n\tassociation-number: %s\n", aoc_e->associated.charge.number.str);
1401 break;
1402 case PRI_AOC_E_CHARGING_ASSOCIATION_ID:
1403 sprintf(&tmp[offset], "id\n\tassociation-id: %d\n", aoc_e->associated.charge.id);
1404 break;
1405 default:
1406 strcat(&tmp[offset], "unknown\n");
1407 }
1408
1409 ftdm_log(FTDM_LOG_INFO, "AOC-E:\n%s", tmp);
1410 return 0;
1411 }
1412
1413
1414
1415
1416
1417
1418
1419
1420 static int on_facility(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
1421 {
1422 struct pri_event_facility *pfac = &pevent->facility;
1423 int i = 0;
1424
1425 if (!pevent)
1426 return 0;
1427
1428 ftdm_log(FTDM_LOG_DEBUG, "Got a FACILITY event on span %d:%d\n", ftdm_span_get_id(spri->span), pfac->channel);
1429
1430 if (!pfac->subcmds || pfac->subcmds->counter_subcmd <= 0)
1431 return 0;
1432
1433 for (i = 0; i < pfac->subcmds->counter_subcmd; i++) {
1434 struct pri_subcommand *sub = &pfac->subcmds->subcmd[i];
1435 int res = -1;
1436
1437 switch (sub->cmd) {
1438 case PRI_SUBCMD_AOC_S:
1439 res = handle_facility_aoc_s(&sub->u.aoc_s);
1440 break;
1441 case PRI_SUBCMD_AOC_D:
1442 res = handle_facility_aoc_d(&sub->u.aoc_d);
1443 break;
1444 case PRI_SUBCMD_AOC_E:
1445 res = handle_facility_aoc_e(&sub->u.aoc_e);
1446 break;
1447 case PRI_SUBCMD_AOC_CHARGING_REQ:
1448 ftdm_log(FTDM_LOG_NOTICE, "AOC Charging Request received\n");
1449 break;
1450 case PRI_SUBCMD_AOC_CHARGING_REQ_RSP:
1451 ftdm_log(FTDM_LOG_NOTICE, "AOC Charging Request Response received [aoc_s data: %s, req: %x, resp: %x]\n",
1452 sub->u.aoc_request_response.valid_aoc_s ? "yes" : "no",
1453 sub->u.aoc_request_response.charging_request,
1454 sub->u.aoc_request_response.charging_response);
1455 break;
1456 default:
1457 ftdm_log(FTDM_LOG_DEBUG, "FACILITY subcommand %d is not implemented, ignoring\n", sub->cmd);
1458 }
1459
1460 ftdm_log(FTDM_LOG_DEBUG, "FACILITY subcommand %d handler returned %d\n", sub->cmd, res);
1461 }
1462
1463 ftdm_log(FTDM_LOG_DEBUG, "Caught Event on span %d %u (%s)\n", ftdm_span_get_id(spri->span), event_type, lpwrap_pri_event_str(event_type));
1464 return 0;
1465 }
1466 #endif
1467
1468
1469
1470
1471
1472
1473
1474
1475 static int on_dchan_up(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
1476 {
1477 if (!ftdm_test_flag(spri, LPWRAP_PRI_READY)) {
1478 ftdm_signaling_status_t status = FTDM_SIG_STATE_UP;
1479 ftdm_span_t *span = spri->span;
1480 ftdm_sigmsg_t sig;
1481 int i;
1482
1483 ftdm_log(FTDM_LOG_INFO, "Span %d D-Channel UP!\n", ftdm_span_get_id(span));
1484 ftdm_set_flag(spri, LPWRAP_PRI_READY);
1485 ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART);
1486
1487 ftdm_log(FTDM_LOG_NOTICE, "%d:Signaling link status changed to %s\n", ftdm_span_get_id(span), ftdm_signaling_status2str(status));
1488
1489 for (i = 1; i <= ftdm_span_get_chan_count(span); i++) {
1490 ftdm_channel_t *chan = ftdm_span_get_channel(span, i);
1491
1492 memset(&sig, 0, sizeof(sig));
1493 sig.span_id = ftdm_channel_get_span_id(chan);
1494 sig.chan_id = ftdm_channel_get_id(chan);
1495 sig.channel = chan;
1496 sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
1497 sig.ev_data.sigstatus.status = status;
1498 ftdm_span_send_signal(span, &sig);
1499 }
1500 }
1501 return 0;
1502 }
1503
1504
1505
1506
1507
1508
1509
1510
1511 static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
1512 {
1513 if (ftdm_test_flag(spri, LPWRAP_PRI_READY)) {
1514 ftdm_signaling_status_t status = FTDM_SIG_STATE_DOWN;
1515 ftdm_span_t *span = spri->span;
1516 ftdm_sigmsg_t sig;
1517 int i;
1518
1519 ftdm_log(FTDM_LOG_INFO, "Span %d D-Channel DOWN!\n", ftdm_span_get_id(span));
1520 ftdm_clear_flag(spri, LPWRAP_PRI_READY);
1521 ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART);
1522
1523 ftdm_log(FTDM_LOG_NOTICE, "%d:Signaling link status changed to %s\n", ftdm_span_get_id(span), ftdm_signaling_status2str(status));
1524
1525 for (i = 1; i <= ftdm_span_get_chan_count(span); i++) {
1526 ftdm_channel_t *chan = ftdm_span_get_channel(span, i);
1527
1528 memset(&sig, 0, sizeof(sig));
1529 sig.span_id = ftdm_channel_get_span_id(chan);
1530 sig.chan_id = ftdm_channel_get_id(chan);
1531 sig.channel = chan;
1532 sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
1533 sig.ev_data.sigstatus.status = status;
1534
1535 ftdm_span_send_signal(span, &sig);
1536 }
1537 }
1538
1539 return 0;
1540 }
1541
1542
1543
1544
1545
1546
1547
1548
1549 static int on_anything(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
1550 {
1551 ftdm_log(FTDM_LOG_DEBUG, "-- Caught Event span %d %u (%s)\n", ftdm_span_get_id(spri->span), event_type, lpwrap_pri_event_str(event_type));
1552 return 0;
1553 }
1554
1555
1556
1557
1558
1559
1560
1561
1562 static int on_io_fail(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
1563 {
1564 ftdm_log(FTDM_LOG_DEBUG, "-- Caught Event span %d %u (%s)\n", ftdm_span_get_id(spri->span), event_type, lpwrap_pri_event_str(event_type));
1565 return 0;
1566 }
1567
1568
1569
1570
1571
1572
1573
1574
1575 static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
1576 {
1577 ftdm_span_t *span = (ftdm_span_t *) obj;
1578 ftdm_libpri_data_t *isdn_data = span->signal_data;
1579 int down = 0;
1580 int got_d = 0;
1581 int res = 0;
1582
1583 ftdm_set_flag(span, FTDM_SPAN_IN_THREAD);
1584
1585 while (ftdm_running() && !ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) {
1586 if (!got_d) {
1587 int i, x;
1588
1589 for (i = 1, x = 0; i <= ftdm_span_get_chan_count(span); i++) {
1590 ftdm_channel_t *chan = ftdm_span_get_channel(span, i);
1591
1592 if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_DQ921) {
1593 if (ftdm_channel_open(ftdm_span_get_id(span), i, &isdn_data->dchan) == FTDM_SUCCESS) {
1594 ftdm_log(FTDM_LOG_DEBUG, "opening D-Channel #%d %d:%d\n", x,
1595 ftdm_channel_get_span_id(isdn_data->dchan), ftdm_channel_get_id(isdn_data->dchan));
1596 got_d = 1;
1597 x++;
1598 break;
1599 } else {
1600 ftdm_log(FTDM_LOG_ERROR, "failed to open D-Channel #%d %d:%d\n", x,
1601 ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan));
1602 }
1603 }
1604 }
1605 }
1606 if (!got_d || !isdn_data->dchan) {
1607 ftdm_log(FTDM_LOG_ERROR, "Failed to get a D-Channel in span %d\n", ftdm_span_get_id(span));
1608 break;
1609 }
1610
1611
1612 switch (ftdm_span_get_trunk_type(span)) {
1613 case FTDM_TRUNK_E1:
1614 case FTDM_TRUNK_T1:
1615 case FTDM_TRUNK_J1:
1616 res = lpwrap_init_pri(&isdn_data->spri, span, isdn_data->dchan,
1617 isdn_data->dialect, isdn_data->mode, isdn_data->debug_mask);
1618 break;
1619 case FTDM_TRUNK_BRI:
1620 res = lpwrap_init_bri(&isdn_data->spri, span, isdn_data->dchan,
1621 isdn_data->dialect, isdn_data->mode, 1, isdn_data->debug_mask);
1622 #ifndef HAVE_LIBPRI_BRI
1623 goto out;
1624 #endif
1625 break;
1626 case FTDM_TRUNK_BRI_PTMP:
1627 res = lpwrap_init_bri(&isdn_data->spri, span, isdn_data->dchan,
1628 isdn_data->dialect, isdn_data->mode, 0, isdn_data->debug_mask);
1629 #ifndef HAVE_LIBPRI_BRI
1630 goto out;
1631 #endif
1632 break;
1633 default:
1634 snprintf(span->last_error, sizeof(span->last_error), "Invalid trunk type");
1635 goto out;
1636 }
1637
1638 #ifdef HAVE_LIBPRI_AOC
1639
1640
1641
1642
1643 if (isdn_data->opts & FTMOD_LIBPRI_OPT_FACILITY_AOC) {
1644 pri_facility_enable(isdn_data->spri.pri);
1645 }
1646 #endif
1647
1648 if (res == 0) {
1649 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANY, on_anything);
1650 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RING, on_ring);
1651 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RINGING, on_ringing);
1652 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_PROCEEDING, on_proceeding);
1653 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_PROGRESS, on_progress);
1654 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANSWER, on_answer);
1655 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_UP, on_dchan_up);
1656 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_DOWN, on_dchan_down);
1657 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP_REQ, on_hangup);
1658 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP, on_hangup);
1659 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_INFO_RECEIVED, on_info);
1660 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RESTART, on_restart);
1661 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_IO_FAIL, on_io_fail);
1662 #ifdef HAVE_LIBPRI_AOC
1663 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_FACILITY, on_facility);
1664 #endif
1665 if (down) {
1666 ftdm_log(FTDM_LOG_INFO, "PRI back up on span %d\n", ftdm_span_get_id(span));
1667 ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART);
1668 down = 0;
1669 }
1670
1671 isdn_data->spri.on_loop = check_flags;
1672
1673 lpwrap_run_pri(&isdn_data->spri);
1674 } else {
1675 ftdm_log(FTDM_LOG_CRIT, "PRI init failed!\n");
1676 snprintf(span->last_error, sizeof(span->last_error), "PRI init failed!");
1677 break;
1678 }
1679
1680 if (!ftdm_running() || ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) {
1681 break;
1682 }
1683
1684 ftdm_log(FTDM_LOG_CRIT, "PRI down on span %d\n", ftdm_span_get_id(span));
1685 if (isdn_data->spri.dchan) {
1686 _ftdm_channel_set_state_force(isdn_data->spri.dchan, FTDM_CHANNEL_STATE_DOWN);
1687 }
1688
1689 if (!down) {
1690 ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART);
1691 check_state(span);
1692 }
1693
1694 check_state(span);
1695 check_events(span);
1696
1697 down = 1;
1698 ftdm_sleep(5000);
1699 }
1700 out:
1701 ftdm_log(FTDM_LOG_DEBUG, "PRI thread ended on span %d\n", ftdm_span_get_id(span));
1702
1703 ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
1704 ftdm_clear_flag(isdn_data, FTMOD_LIBPRI_RUNNING);
1705
1706 return NULL;
1707 }
1708
1709
1710
1711
1712
1713
1714
1715
1716 static ftdm_status_t ftdm_libpri_stop(ftdm_span_t *span)
1717 {
1718 ftdm_libpri_data_t *isdn_data = span->signal_data;
1719
1720 if (!ftdm_test_flag(isdn_data, FTMOD_LIBPRI_RUNNING)) {
1721 return FTDM_FAIL;
1722 }
1723
1724 ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART);
1725
1726 check_state(span);
1727
1728 ftdm_set_flag(span, FTDM_SPAN_STOP_THREAD);
1729
1730 while (ftdm_test_flag(span, FTDM_SPAN_IN_THREAD)) {
1731 ftdm_sleep(100);
1732 }
1733
1734 check_state(span);
1735
1736 return FTDM_SUCCESS;
1737 }
1738
1739
1740
1741
1742
1743
1744
1745
1746 static ftdm_status_t ftdm_libpri_start(ftdm_span_t *span)
1747 {
1748 ftdm_libpri_data_t *isdn_data = span->signal_data;
1749
1750 if (ftdm_test_flag(isdn_data, FTMOD_LIBPRI_RUNNING)) {
1751 return FTDM_FAIL;
1752 }
1753
1754 ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD);
1755 ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
1756
1757 ftdm_set_flag(isdn_data, FTMOD_LIBPRI_RUNNING);
1758
1759 return ftdm_thread_create_detached(ftdm_libpri_run, span);
1760 }
1761
1762
1763
1764
1765
1766
1767 static int parse_mode(const char *mode)
1768 {
1769 if (!strcasecmp(mode, "cpe") || !strcasecmp(mode, "user"))
1770 return PRI_CPE;
1771 if (!strcasecmp(mode, "network") || !strcasecmp(mode, "net"))
1772 return PRI_NETWORK;
1773
1774 return -1;
1775 }
1776
1777
1778
1779
1780
1781
1782 static int parse_dialect(const char *dialect)
1783 {
1784 if (!strcasecmp(dialect, "ni1"))
1785 return PRI_SWITCH_NI1;
1786 if (!strcasecmp(dialect, "ni2"))
1787 return PRI_SWITCH_NI2;
1788 if (!strcasecmp(dialect, "dms100"))
1789 return PRI_SWITCH_DMS100;
1790 if (!strcasecmp(dialect, "lucent5e") || !strcasecmp(dialect, "5ess"))
1791 return PRI_SWITCH_LUCENT5E;
1792 if (!strcasecmp(dialect, "att4ess") || !strcasecmp(dialect, "4ess"))
1793 return PRI_SWITCH_ATT4ESS;
1794 if (!strcasecmp(dialect, "euroisdn") || !strcasecmp(dialect, "q931"))
1795 return PRI_SWITCH_EUROISDN_E1;
1796 if (!strcasecmp(dialect, "gr303eoc"))
1797 return PRI_SWITCH_GR303_EOC;
1798 if (!strcasecmp(dialect, "gr303tmc"))
1799 return PRI_SWITCH_GR303_TMC;
1800
1801 return PRI_SWITCH_DMS100;
1802 }
1803
1804
1805
1806
1807
1808
1809 static int parse_layer1(const char *val)
1810 {
1811 if (!strcasecmp(val, "alaw"))
1812 return PRI_LAYER_1_ALAW;
1813
1814 return PRI_LAYER_1_ULAW;
1815 }
1816
1817
1818
1819
1820
1821
1822 static int parse_ton(const char *ton)
1823 {
1824 if (!strcasecmp(ton, "international"))
1825 return PRI_INTERNATIONAL_ISDN;
1826 if (!strcasecmp(ton, "national"))
1827 return PRI_NATIONAL_ISDN;
1828 if (!strcasecmp(ton, "local"))
1829 return PRI_LOCAL_ISDN;
1830 if (!strcasecmp(ton, "private"))
1831 return PRI_PRIVATE;
1832 if (!strcasecmp(ton, "unknown"))
1833 return PRI_UNKNOWN;
1834
1835 return PRI_UNKNOWN;
1836 }
1837
1838
1839
1840
1841
1842
1843 static uint32_t parse_opts(const char *in)
1844 {
1845 uint32_t flags = 0;
1846
1847 if (!in) {
1848 return 0;
1849 }
1850
1851 if (strstr(in, "suggest_channel")) {
1852 flags |= FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL;
1853 }
1854 if (strstr(in, "omit_display")) {
1855 flags |= FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE;
1856 }
1857 if (strstr(in, "omit_redirecting_number")) {
1858 flags |= FTMOD_LIBPRI_OPT_OMIT_REDIRECTING_NUMBER_IE;
1859 }
1860 if (strstr(in, "aoc")) {
1861 flags |= FTMOD_LIBPRI_OPT_FACILITY_AOC;
1862 }
1863 return flags;
1864 }
1865
1866
1867
1868
1869
1870
1871
1872
1873 static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
1874 {
1875 ftdm_libpri_data_t *isdn_data = NULL;
1876
1877 uint32_t bchan_count = 0;
1878 uint32_t dchan_count = 0;
1879 uint32_t i;
1880
1881 if (ftdm_span_get_trunk_type(span) >= FTDM_TRUNK_NONE) {
1882 ftdm_log(FTDM_LOG_WARNING, "Invalid trunk type '%s' defaulting to T1.\n", ftdm_span_get_trunk_type_str(span));
1883 ftdm_span_set_trunk_type(span, FTDM_TRUNK_T1);
1884 }
1885
1886 for (i = 1; i <= ftdm_span_get_chan_count(span); i++) {
1887 ftdm_channel_t *chan = ftdm_span_get_channel(span, i);
1888
1889 switch (ftdm_channel_get_type(chan)) {
1890 case FTDM_CHAN_TYPE_DQ921:
1891 if (dchan_count > 1) {
1892 ftdm_log(FTDM_LOG_ERROR, "Span has more than 2 D-Channels!\n");
1893 snprintf(span->last_error, sizeof(span->last_error), "Span has more than 2 D-Channels!");
1894 return FTDM_FAIL;
1895 } else {
1896 #if 0
1897 if (ftdm_channel_open(ftdm_span_get_id(span), i, &dchan) == FTDM_SUCCESS) {
1898 ftdm_log(FTDM_LOG_DEBUG, "opening D-Channel %d:%d\n", ftdm_channel_get_span_id(dchan), ftdm_channel_get_id(dchan));
1899 _ftdm_channel_set_state_force(dchan, FTDM_CHANNEL_STATE_UP);
1900 } else {
1901 ftdm_log(FTDM_LOG_ERROR, "Failed to open D-Channel %d:%d\n", ftdm_channel_get_span_id(chan), ftdm_channel_getid(chan));
1902 snprintf(span->last_error, sizeof(span->last_error), "Failed to open D-Channel %d:%d\n", ftdm_channel_get_span_id(chan), ftdm_channel_getid(chan));
1903 return FTDM_FAIL;
1904 }
1905 #endif
1906 dchan_count++;
1907 }
1908 break;
1909
1910 case FTDM_CHAN_TYPE_B:
1911 bchan_count++;
1912 break;
1913 default:
1914 break;
1915 }
1916 }
1917 if (!dchan_count) {
1918 ftdm_log(FTDM_LOG_ERROR, "Span has no D-Channel!\n");
1919 snprintf(span->last_error, sizeof(span->last_error), "Span has no D-Channel!");
1920 return FTDM_FAIL;
1921 }
1922 if (!bchan_count) {
1923 ftdm_log(FTDM_LOG_ERROR, "Span has no B-Channels!\n");
1924 snprintf(span->last_error, sizeof(span->last_error), "Span has no B-Channels!");
1925 return FTDM_FAIL;
1926 }
1927
1928 isdn_data = ftdm_malloc(sizeof(*isdn_data));
1929 assert(isdn_data != NULL);
1930 memset(isdn_data, 0, sizeof(*isdn_data));
1931
1932 switch (ftdm_span_get_trunk_type(span)) {
1933 case FTDM_TRUNK_BRI:
1934 case FTDM_TRUNK_BRI_PTMP:
1935 #ifndef HAVE_LIBPRI_BRI
1936 ftdm_log(FTDM_LOG_ERROR, "Unsupported trunk type: '%s', libpri too old\n", ftdm_span_get_trunk_type_str(span));
1937 snprintf(span->last_error, sizeof(span->last_error), "Unsupported trunk type [%s], libpri too old", ftdm_span_get_trunk_type_str(span));
1938 return FTDM_FAIL;
1939 #endif
1940 case FTDM_TRUNK_E1:
1941 ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ALAW since this is an E1/BRI/BRI PTMP trunk\n");
1942 isdn_data->layer1 = PRI_LAYER_1_ALAW;
1943 break;
1944 case FTDM_TRUNK_T1:
1945 case FTDM_TRUNK_J1:
1946 ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ULAW since this is a T1/J1 trunk\n");
1947 isdn_data->layer1 = PRI_LAYER_1_ULAW;
1948 break;
1949 default:
1950 ftdm_log(FTDM_LOG_ERROR, "Invalid trunk type: '%s'\n", ftdm_span_get_trunk_type_str(span));
1951 snprintf(span->last_error, sizeof(span->last_error), "Invalid trunk type [%s]", ftdm_span_get_trunk_type_str(span));
1952 return FTDM_FAIL;
1953 }
1954
1955 for (i = 0; ftdm_parameters[i].var; i++) {
1956 const char *var = ftdm_parameters[i].var;
1957 const char *val = ftdm_parameters[i].val;
1958
1959 if (ftdm_strlen_zero(var)) {
1960 ftdm_log(FTDM_LOG_WARNING, "Skipping parameter with no name\n");
1961 continue;
1962 }
1963
1964 if (ftdm_strlen_zero(val)) {
1965 ftdm_log(FTDM_LOG_ERROR, "Parameter '%s' has no value\n", var);
1966 snprintf(span->last_error, sizeof(span->last_error), "Parameter [%s] has no value", var);
1967 return FTDM_FAIL;
1968 }
1969
1970 if (!strcasecmp(var, "node") || !strcasecmp(var, "mode")) {
1971 if ((isdn_data->mode = parse_mode(val)) == -1) {
1972 ftdm_log(FTDM_LOG_ERROR, "Unknown node type '%s', defaulting to CPE mode\n", val);
1973 isdn_data->mode = PRI_CPE;
1974 }
1975 }
1976 else if (!strcasecmp(var, "switch") || !strcasecmp(var, "dialect")) {
1977 isdn_data->dialect = parse_dialect(val);
1978 }
1979 else if (!strcasecmp(var, "opts")) {
1980 isdn_data->opts = parse_opts(val);
1981 }
1982 else if (!strcasecmp(var, "dp") || !strcasecmp(var, "ton")) {
1983 isdn_data->ton = parse_ton(val);
1984 }
1985 else if (!strcasecmp(var, "l1") || !strcasecmp(var, "layer1")) {
1986 isdn_data->layer1 = parse_layer1(val);
1987 }
1988 else if (!strcasecmp(var, "debug")) {
1989 if (parse_debug(val, &isdn_data->debug_mask) == -1) {
1990 ftdm_log(FTDM_LOG_ERROR, "Invalid debug flag, ignoring parameter\n");
1991 isdn_data->debug_mask = 0;
1992 }
1993 }
1994 else {
1995 ftdm_log(FTDM_LOG_ERROR, "Unknown parameter '%s', aborting configuration\n", var);
1996 snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var);
1997 return FTDM_FAIL;
1998 }
1999 }
2000
2001 span->start = ftdm_libpri_start;
2002 span->stop = ftdm_libpri_stop;
2003 span->signal_cb = sig_cb;
2004
2005 span->signal_data = isdn_data;
2006 span->signal_type = FTDM_SIGTYPE_ISDN;
2007 span->outgoing_call = isdn_outgoing_call;
2008
2009 span->state_map = &isdn_state_map;
2010 span->state_processor = state_advance;
2011
2012 span->get_channel_sig_status = isdn_get_channel_sig_status;
2013 span->get_span_sig_status = isdn_get_span_sig_status;
2014
2015
2016 ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE);
2017
2018 if ((isdn_data->opts & FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL)) {
2019 span->channel_request = isdn_channel_request;
2020 ftdm_set_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID);
2021 }
2022
2023 return FTDM_SUCCESS;
2024 }
2025
2026
2027
2028
2029 ftdm_module_t ftdm_module = {
2030 "libpri",
2031 ftdm_libpri_io_init,
2032 ftdm_libpri_unload,
2033 ftdm_libpri_init,
2034 NULL,
2035 NULL,
2036 ftdm_libpri_configure_span
2037 };
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048