This source file includes following definitions.
- 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_opts
- parse_debug
- FIO_API_FUNCTION
- FIO_IO_LOAD_FUNCTION
- FIO_SIG_LOAD_FUNCTION
- state_advance
- check_state
- on_info
- on_hangup
- on_answer
- on_proceed
- on_ringing
- on_ring
- process_event
- check_events
- check_flags
- on_restart
- on_dchan_up
- on_dchan_down
- on_anything
- on_io_fail
- ftdm_libpri_run
- ftdm_libpri_stop
- ftdm_libpri_start
- str2node
- str2switch
- str2l1
- str2dp
- FIO_SIG_CONFIGURE_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
38
39
40
41 static FIO_IO_UNLOAD_FUNCTION(ftdm_libpri_unload)
42 {
43 return FTDM_SUCCESS;
44 }
45
46
47
48
49
50
51
52
53 static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(isdn_get_channel_sig_status)
54 {
55 *status = FTDM_SIG_STATE_DOWN;
56
57 ftdm_libpri_data_t *isdn_data = ftdmchan->span->signal_data;
58 if (ftdm_test_flag(&(isdn_data->spri), LPWRAP_PRI_READY)) {
59 *status = FTDM_SIG_STATE_UP;
60 }
61 return FTDM_SUCCESS;
62 }
63
64
65
66
67
68
69
70
71 static FIO_SPAN_GET_SIG_STATUS_FUNCTION(isdn_get_span_sig_status)
72 {
73 *status = FTDM_SIG_STATE_DOWN;
74
75 ftdm_libpri_data_t *isdn_data = span->signal_data;
76 if (ftdm_test_flag(&(isdn_data->spri), LPWRAP_PRI_READY)) {
77 *status = FTDM_SIG_STATE_UP;
78 }
79 return FTDM_SUCCESS;
80 }
81
82
83
84
85
86
87
88 static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(isdn_outgoing_call)
89 {
90 ftdm_status_t status = FTDM_SUCCESS;
91 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND);
92 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DIALING);
93 return status;
94 }
95
96
97
98
99
100
101
102
103
104
105 static FIO_CHANNEL_REQUEST_FUNCTION(isdn_channel_request)
106 {
107 return FTDM_FAIL;
108 }
109
110 #ifdef WIN32
111
112
113
114
115 static void s_pri_error(char *s)
116 #else
117
118
119
120
121
122 static void s_pri_error(struct pri *pri, char *s)
123 #endif
124 {
125 ftdm_log(FTDM_LOG_ERROR, "%s", s);
126 }
127
128 #ifdef WIN32
129
130
131
132
133 static void s_pri_message(char *s)
134 #else
135
136
137
138
139
140 static void s_pri_message(struct pri *pri, char *s)
141 #endif
142 {
143 ftdm_log(FTDM_LOG_DEBUG, "%s", s);
144 }
145
146
147
148
149
150
151 static uint32_t parse_opts(const char *in)
152 {
153 uint32_t flags = 0;
154
155 if (!in) {
156 return 0;
157 }
158
159 if (strstr(in, "suggest_channel")) {
160 flags |= FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL;
161 }
162
163 if (strstr(in, "omit_display")) {
164 flags |= FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE;
165 }
166
167 if (strstr(in, "omit_redirecting_number")) {
168 flags |= FTMOD_LIBPRI_OPT_OMIT_REDIRECTING_NUMBER_IE;
169 }
170
171 return flags;
172 }
173
174
175
176
177
178
179 static int parse_debug(const char *in)
180 {
181 int flags = 0;
182
183 if (!in) {
184 return 0;
185 }
186
187 if (strstr(in, "q921_raw")) {
188 flags |= PRI_DEBUG_Q921_RAW;
189 }
190
191 if (strstr(in, "q921_dump")) {
192 flags |= PRI_DEBUG_Q921_DUMP;
193 }
194
195 if (strstr(in, "q921_state")) {
196 flags |= PRI_DEBUG_Q921_STATE;
197 }
198
199 if (strstr(in, "config")) {
200 flags |= PRI_DEBUG_CONFIG;
201 }
202
203 if (strstr(in, "q931_dump")) {
204 flags |= PRI_DEBUG_Q931_DUMP;
205 }
206
207 if (strstr(in, "q931_state")) {
208 flags |= PRI_DEBUG_Q931_STATE;
209 }
210
211 if (strstr(in, "q931_anomaly")) {
212 flags |= PRI_DEBUG_Q931_ANOMALY;
213 }
214
215 if (strstr(in, "apdu")) {
216 flags |= PRI_DEBUG_APDU;
217 }
218
219 if (strstr(in, "aoc")) {
220 flags |= PRI_DEBUG_AOC;
221 }
222
223 if (strstr(in, "all")) {
224 flags |= PRI_DEBUG_ALL;
225 }
226
227 if (strstr(in, "none")) {
228 flags = 0;
229 }
230
231 return flags;
232 }
233
234 static ftdm_io_interface_t ftdm_libpri_interface;
235
236 static ftdm_status_t ftdm_libpri_start(ftdm_span_t *span);
237
238
239
240
241
242
243
244 static FIO_API_FUNCTION(ftdm_libpri_api)
245 {
246 char *mycmd = NULL, *argv[10] = { 0 };
247 int argc = 0;
248
249 if (data) {
250 mycmd = ftdm_strdup(data);
251 argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
252 }
253
254 if (argc == 2) {
255 if (!strcasecmp(argv[0], "kill")) {
256 int span_id = atoi(argv[1]);
257 ftdm_span_t *span = NULL;
258
259 if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS || ftdm_span_find(span_id, &span) == FTDM_SUCCESS) {
260 ftdm_libpri_data_t *isdn_data = span->signal_data;
261
262 if (span->start != ftdm_libpri_start) {
263 stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
264 goto done;
265 }
266
267 ftdm_clear_flag((&isdn_data->spri), LPWRAP_PRI_READY);
268 stream->write_function(stream, "%s: +OK killed.\n", __FILE__);
269 goto done;
270 } else {
271 stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
272 goto done;
273 }
274 }
275 }
276
277 if (argc > 2) {
278 if (!strcasecmp(argv[0], "debug")) {
279 ftdm_span_t *span = NULL;
280
281 if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) {
282 ftdm_libpri_data_t *isdn_data = span->signal_data;
283 if (span->start != ftdm_libpri_start) {
284 stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
285 goto done;
286 }
287
288 pri_set_debug(isdn_data->spri.pri, parse_debug(argv[2]));
289 stream->write_function(stream, "%s: +OK debug set.\n", __FILE__);
290 goto done;
291 } else {
292 stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
293 goto done;
294 }
295 }
296
297 }
298
299 stream->write_function(stream, "%s: -ERR invalid command.\n", __FILE__);
300
301 done:
302
303 ftdm_safe_free(mycmd);
304
305 return FTDM_SUCCESS;
306 }
307
308
309
310
311
312
313 static FIO_IO_LOAD_FUNCTION(ftdm_libpri_io_init)
314 {
315 assert(fio != NULL);
316 memset(&ftdm_libpri_interface, 0, sizeof(ftdm_libpri_interface));
317
318 ftdm_libpri_interface.name = "libpri";
319 ftdm_libpri_interface.api = ftdm_libpri_api;
320
321 *fio = &ftdm_libpri_interface;
322
323 return FTDM_SUCCESS;
324 }
325
326
327
328
329
330
331 static FIO_SIG_LOAD_FUNCTION(ftdm_libpri_init)
332 {
333 pri_set_error(s_pri_error);
334 pri_set_message(s_pri_message);
335 return FTDM_SUCCESS;
336 }
337
338
339
340
341 static ftdm_state_map_t isdn_state_map = {
342 {
343 {
344 ZSD_OUTBOUND,
345 ZSM_UNACCEPTABLE,
346 {FTDM_ANY_STATE},
347 {FTDM_CHANNEL_STATE_RESTART, FTDM_END}
348 },
349 {
350 ZSD_OUTBOUND,
351 ZSM_UNACCEPTABLE,
352 {FTDM_CHANNEL_STATE_RESTART, FTDM_END},
353 {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
354 },
355 {
356 ZSD_OUTBOUND,
357 ZSM_UNACCEPTABLE,
358 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
359 {FTDM_CHANNEL_STATE_DIALING, FTDM_END}
360 },
361 {
362 ZSD_OUTBOUND,
363 ZSM_UNACCEPTABLE,
364 {FTDM_CHANNEL_STATE_DIALING, FTDM_END},
365 {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
366 },
367 {
368 ZSD_OUTBOUND,
369 ZSM_UNACCEPTABLE,
370 {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
371 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_END}
372 },
373 {
374 ZSD_OUTBOUND,
375 ZSM_UNACCEPTABLE,
376 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
377 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_DOWN, FTDM_END}
378 },
379 {
380 ZSD_OUTBOUND,
381 ZSM_UNACCEPTABLE,
382 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
383 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
384 },
385 {
386 ZSD_OUTBOUND,
387 ZSM_UNACCEPTABLE,
388 {FTDM_CHANNEL_STATE_UP, FTDM_END},
389 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
390 },
391
392
393 {
394 ZSD_INBOUND,
395 ZSM_UNACCEPTABLE,
396 {FTDM_ANY_STATE},
397 {FTDM_CHANNEL_STATE_RESTART, FTDM_END}
398 },
399 {
400 ZSD_INBOUND,
401 ZSM_UNACCEPTABLE,
402 {FTDM_CHANNEL_STATE_RESTART, FTDM_END},
403 {FTDM_CHANNEL_STATE_DOWN, FTDM_END}
404 },
405 {
406 ZSD_INBOUND,
407 ZSM_UNACCEPTABLE,
408 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
409 {FTDM_CHANNEL_STATE_DIALTONE, FTDM_CHANNEL_STATE_RING, FTDM_END}
410 },
411 {
412 ZSD_INBOUND,
413 ZSM_UNACCEPTABLE,
414 {FTDM_CHANNEL_STATE_DIALTONE, FTDM_END},
415 {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
416 },
417 {
418 ZSD_INBOUND,
419 ZSM_UNACCEPTABLE,
420 {FTDM_CHANNEL_STATE_RING, FTDM_END},
421 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}
422 },
423 {
424 ZSD_INBOUND,
425 ZSM_UNACCEPTABLE,
426 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
427 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_CHANNEL_STATE_DOWN, FTDM_END},
428 },
429 {
430 ZSD_INBOUND,
431 ZSM_UNACCEPTABLE,
432 {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
433 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
434 },
435 {
436 ZSD_INBOUND,
437 ZSM_UNACCEPTABLE,
438 {FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
439 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
440 FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_UP, FTDM_END},
441 },
442 {
443 ZSD_INBOUND,
444 ZSM_UNACCEPTABLE,
445 {FTDM_CHANNEL_STATE_UP, FTDM_END},
446 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
447 },
448
449
450 }
451 };
452
453
454
455
456
457 static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
458 {
459
460 ftdm_libpri_data_t *isdn_data = ftdmchan->span->signal_data;
461 ftdm_status_t status;
462 ftdm_sigmsg_t sig;
463 q931_call *call = (q931_call *) ftdmchan->call_data;
464
465
466 ftdm_log(FTDM_LOG_DEBUG, "%d:%d STATE [%s]\n",
467 ftdmchan->span_id, ftdmchan->chan_id, ftdm_channel_state2str(ftdmchan->state));
468
469
470 #if 0
471 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) && !call) {
472 ftdm_log(FTDM_LOG_WARNING, "NO CALL!!!!\n");
473 }
474 #endif
475
476
477 memset(&sig, 0, sizeof(sig));
478 sig.chan_id = ftdmchan->chan_id;
479 sig.span_id = ftdmchan->span_id;
480 sig.channel = ftdmchan;
481
482
483 switch (ftdmchan->state) {
484 case FTDM_CHANNEL_STATE_DOWN:
485 {
486 ftdmchan->call_data = NULL;
487 ftdm_channel_done(ftdmchan);
488 }
489 break;
490 case FTDM_CHANNEL_STATE_PROGRESS:
491 {
492 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
493 sig.event_id = FTDM_SIGEVENT_PROGRESS;
494 if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) {
495 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
496 }
497 } else if (call) {
498 pri_progress(isdn_data->spri.pri, call, ftdmchan->chan_id, 1);
499 } else {
500 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
501 }
502 }
503 break;
504 case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
505 {
506 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
507 sig.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
508 if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) {
509 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
510 }
511 } else if (call) {
512 pri_proceeding(isdn_data->spri.pri, call, ftdmchan->chan_id, 1);
513 } else {
514 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
515 }
516 }
517 break;
518 case FTDM_CHANNEL_STATE_RING:
519 {
520 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
521 if (call) {
522 pri_acknowledge(isdn_data->spri.pri, call, ftdmchan->chan_id, 0);
523 sig.event_id = FTDM_SIGEVENT_START;
524 if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) {
525 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
526 }
527 } else {
528 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
529 }
530 }
531 }
532 break;
533 case FTDM_CHANNEL_STATE_RESTART:
534 {
535 ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_UNSPECIFIED;
536 sig.event_id = FTDM_SIGEVENT_RESTART;
537 status = ftdm_span_send_signal(ftdmchan->span, &sig);
538 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
539 }
540 break;
541 case FTDM_CHANNEL_STATE_UP:
542 {
543 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
544 sig.event_id = FTDM_SIGEVENT_UP;
545 if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) {
546 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
547 }
548 } else if (call) {
549 pri_answer(isdn_data->spri.pri, call, 0, 1);
550 } else {
551 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
552 }
553 }
554 break;
555 case FTDM_CHANNEL_STATE_DIALING:
556 if (isdn_data) {
557 struct pri_sr *sr;
558 int dp;
559
560 if (!(call = pri_new_call(isdn_data->spri.pri))) {
561 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
562 return;
563 }
564
565
566 dp = ftdmchan->caller_data.dnis.type;
567 switch(dp) {
568 case FTDM_TON_NATIONAL:
569 dp = PRI_NATIONAL_ISDN;
570 break;
571 case FTDM_TON_INTERNATIONAL:
572 dp = PRI_INTERNATIONAL_ISDN;
573 break;
574 case FTDM_TON_SUBSCRIBER_NUMBER:
575 dp = PRI_LOCAL_ISDN;
576 break;
577 default:
578 dp = isdn_data->dp;
579 }
580
581 ftdmchan->call_data = call;
582 sr = pri_sr_new();
583 assert(sr);
584 pri_sr_set_channel(sr, ftdmchan->chan_id, 0, 0);
585 pri_sr_set_bearer(sr, 0, isdn_data->l1);
586 pri_sr_set_called(sr, ftdmchan->caller_data.dnis.digits, dp, 1);
587 pri_sr_set_caller(sr, ftdmchan->caller_data.cid_num.digits, (isdn_data->opts & FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE ? NULL : ftdmchan->caller_data.cid_name),
588 dp, (ftdmchan->caller_data.pres != 1 ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_PROHIB_USER_NUMBER_NOT_SCREENED));
589
590 if (!(isdn_data->opts & FTMOD_LIBPRI_OPT_OMIT_REDIRECTING_NUMBER_IE)) {
591 pri_sr_set_redirecting(sr, ftdmchan->caller_data.cid_num.digits, dp, PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN, PRI_REDIR_UNCONDITIONAL);
592 }
593
594 if (pri_setup(isdn_data->spri.pri, call, sr)) {
595 ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;
596 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
597 }
598
599 pri_sr_free(sr);
600 }
601
602 break;
603 case FTDM_CHANNEL_STATE_HANGUP:
604 {
605 if (call) {
606 pri_hangup(isdn_data->spri.pri, call, ftdmchan->caller_data.hangup_cause);
607 pri_destroycall(isdn_data->spri.pri, call);
608 ftdmchan->call_data = NULL;
609 }
610 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
611 }
612 break;
613 case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
614 break;
615 case FTDM_CHANNEL_STATE_TERMINATING:
616 {
617 sig.event_id = FTDM_SIGEVENT_STOP;
618 status = ftdm_span_send_signal(ftdmchan->span, &sig);
619
620 }
621 default:
622 break;
623 }
624
625
626
627 return;
628 }
629
630
631
632
633
634 static __inline__ void check_state(ftdm_span_t *span)
635 {
636 if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE)) {
637 uint32_t j;
638 ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE);
639 for(j = 1; j <= span->chan_count; j++) {
640 if (ftdm_test_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE)) {
641 ftdm_mutex_lock(span->channels[j]->mutex);
642 ftdm_channel_lock(span->channels[j]);
643 ftdm_clear_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE);
644 state_advance(span->channels[j]);
645 ftdm_channel_complete_state(span->channels[j]);
646 ftdm_mutex_unlock(span->channels[j]->mutex);
647 ftdm_channel_unlock(span->channels[j]);
648 }
649 }
650 }
651 }
652
653
654
655
656
657
658
659
660 static int on_info(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
661 {
662
663 ftdm_log(FTDM_LOG_DEBUG, "number is: %s\n", pevent->ring.callednum);
664 if (strlen(pevent->ring.callednum) > 3) {
665 ftdm_log(FTDM_LOG_DEBUG, "final number is: %s\n", pevent->ring.callednum);
666 pri_answer(spri->pri, pevent->ring.call, 0, 1);
667 }
668 return 0;
669 }
670
671
672
673
674
675
676
677
678 static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
679 {
680 ftdm_span_t *span = spri->private_info;
681 ftdm_channel_t *ftdmchan = NULL;
682 q931_call *call = NULL;
683 ftdmchan = span->channels[pevent->hangup.channel];
684
685 if (!ftdmchan) {
686 ftdm_log(FTDM_LOG_CRIT, "-- Hangup on channel %d:%d %s but it's not in use?\n", spri->span->span_id, pevent->hangup.channel);
687 return 0;
688 }
689
690 ftdm_channel_lock(ftdmchan);
691
692 if (ftdmchan->state >= FTDM_CHANNEL_STATE_TERMINATING) {
693 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Ignoring remote hangup in state %s\n", ftdm_channel_state2str(ftdmchan->state));
694 goto done;
695 }
696
697 if (!ftdmchan->call_data) {
698 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Ignoring remote hangup in state %s with no call data\n", ftdm_channel_state2str(ftdmchan->state));
699 goto done;
700 }
701
702 call = (q931_call *) ftdmchan->call_data;
703 ftdm_log(FTDM_LOG_DEBUG, "-- Hangup on channel %d:%d\n", spri->span->span_id, pevent->hangup.channel);
704 ftdmchan->caller_data.hangup_cause = pevent->hangup.cause;
705 pri_release(spri->pri, call, 0);
706 pri_destroycall(spri->pri, call);
707 ftdmchan->call_data = NULL;
708 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
709
710 done:
711
712 ftdm_channel_unlock(ftdmchan);
713
714 return 0;
715 }
716
717
718
719
720
721
722
723
724 static int on_answer(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
725 {
726 ftdm_span_t *span = spri->private_info;
727 ftdm_channel_t *ftdmchan = NULL;
728
729 ftdmchan = span->channels[pevent->answer.channel];
730
731 if (ftdmchan) {
732 ftdm_log(FTDM_LOG_DEBUG, "-- Answer on channel %d:%d\n", spri->span->span_id, pevent->answer.channel);
733 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
734 } else {
735 ftdm_log(FTDM_LOG_DEBUG, "-- Answer on channel %d:%d %s but it's not in use?\n", spri->span->span_id, pevent->answer.channel, ftdmchan->chan_id);
736
737 }
738
739 return 0;
740 }
741
742
743
744
745
746
747
748
749 static int on_proceed(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
750 {
751 ftdm_span_t *span = spri->private_info;
752 ftdm_channel_t *ftdmchan = NULL;
753
754 ftdmchan = span->channels[pevent->proceeding.channel];
755
756 if (ftdmchan) {
757 ftdm_log(FTDM_LOG_DEBUG, "-- Proceeding on channel %d:%d\n", spri->span->span_id, pevent->proceeding.channel);
758 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
759 } else {
760 ftdm_log(FTDM_LOG_DEBUG, "-- Proceeding on channel %d:%d %s but it's not in use?\n", spri->span->span_id,
761 pevent->proceeding.channel, ftdmchan->chan_id);
762 }
763
764 return 0;
765 }
766
767
768
769
770
771
772
773
774 static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
775 {
776 ftdm_span_t *span = spri->private_info;
777 ftdm_channel_t *ftdmchan = NULL;
778
779 ftdmchan = span->channels[pevent->ringing.channel];
780
781 if (ftdmchan) {
782 ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d\n", spri->span->span_id, pevent->ringing.channel);
783
784 if (ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA) {
785
786 return 0;
787 }
788 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
789 } else {
790 ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d %s but it's not in use?\n", spri->span->span_id,
791 pevent->ringing.channel, ftdmchan->chan_id);
792 }
793
794 return 0;
795 }
796
797
798
799
800
801
802
803
804 static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
805 {
806 ftdm_span_t *span = spri->private_info;
807 ftdm_channel_t *ftdmchan = NULL;
808 int ret = 0;
809
810
811
812 ftdmchan = span->channels[pevent->ring.channel];
813 if (!ftdmchan || ftdmchan->state != FTDM_CHANNEL_STATE_DOWN || ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) {
814 ftdm_log(FTDM_LOG_WARNING, "--Duplicate Ring on channel %d:%d (ignored)\n", spri->span->span_id, pevent->ring.channel);
815 ret = 0;
816 goto done;
817 }
818
819 if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
820 ftdm_log(FTDM_LOG_WARNING, "--Failure opening channel %d:%d (ignored)\n", spri->span->span_id, pevent->ring.channel);
821 ret = 0;
822 goto done;
823 }
824
825
826 ftdm_log(FTDM_LOG_NOTICE, "-- Ring on channel %d:%d (from %s to %s)\n", spri->span->span_id, pevent->ring.channel,
827 pevent->ring.callingnum, pevent->ring.callednum);
828
829 memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data));
830
831 ftdm_set_string(ftdmchan->caller_data.cid_num.digits, (char *)pevent->ring.callingnum);
832 if (!ftdm_strlen_zero((char *)pevent->ring.callingname)) {
833 ftdm_set_string(ftdmchan->caller_data.cid_name, (char *)pevent->ring.callingname);
834 } else {
835 ftdm_set_string(ftdmchan->caller_data.cid_name, (char *)pevent->ring.callingnum);
836 }
837 ftdm_set_string(ftdmchan->caller_data.ani.digits, (char *)pevent->ring.callingani);
838 ftdm_set_string(ftdmchan->caller_data.dnis.digits, (char *)pevent->ring.callednum);
839
840 if (pevent->ring.ani2 >= 0) {
841 snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", pevent->ring.ani2);
842 }
843
844
845 ftdmchan->call_data = pevent->ring.call;
846
847 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
848
849 done:
850
851
852 return ret;
853 }
854
855
856
857
858
859
860
861 static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *event)
862 {
863 ftdm_alarm_flag_t alarmbits;
864 ftdm_log(FTDM_LOG_DEBUG, "EVENT [%s][%d][%d:%d] STATE [%s]\n",
865 ftdm_oob_event2str(event->enum_id), event->enum_id, event->channel->span_id, event->channel->chan_id, ftdm_channel_state2str(event->channel->state));
866
867 switch(event->enum_id) {
868 case FTDM_OOB_ALARM_TRAP:
869 {
870 if (event->channel->state != FTDM_CHANNEL_STATE_DOWN) {
871 if (event->channel->type == FTDM_CHAN_TYPE_B) {
872 ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RESTART);
873 }
874 }
875
876
877 ftdm_set_flag(event->channel, FTDM_CHANNEL_SUSPENDED);
878
879
880 ftdm_channel_get_alarms(event->channel, &alarmbits);
881 ftdm_log(FTDM_LOG_WARNING, "channel %d:%d (%d:%d) has alarms! [%s]\n",
882 event->channel->span_id, event->channel->chan_id,
883 event->channel->physical_span_id, event->channel->physical_chan_id,
884 event->channel->last_error);
885 }
886 break;
887 case FTDM_OOB_ALARM_CLEAR:
888 {
889
890 ftdm_log(FTDM_LOG_WARNING, "channel %d:%d (%d:%d) alarms Cleared!\n", event->channel->span_id, event->channel->chan_id,
891 event->channel->physical_span_id, event->channel->physical_chan_id);
892
893 ftdm_clear_flag(event->channel, FTDM_CHANNEL_SUSPENDED);
894 ftdm_channel_get_alarms(event->channel, &alarmbits);
895 }
896 break;
897 }
898
899 return FTDM_SUCCESS;
900 }
901
902
903
904
905
906 static __inline__ void check_events(ftdm_span_t *span)
907 {
908 ftdm_status_t status;
909
910 status = ftdm_span_poll_event(span, 5);
911
912 switch(status) {
913 case FTDM_SUCCESS:
914 {
915 ftdm_event_t *event;
916 while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) {
917 if (event->enum_id == FTDM_OOB_NOOP) {
918 continue;
919 }
920 if (process_event(span, event) != FTDM_SUCCESS) {
921 break;
922 }
923 }
924 }
925 break;
926 case FTDM_FAIL:
927 {
928 ftdm_log(FTDM_LOG_DEBUG, "Event Failure! %d\n", ftdm_running());
929 ftdm_sleep(2000);
930 }
931 break;
932 default:
933 break;
934 }
935 }
936
937
938
939
940
941
942 static int check_flags(lpwrap_pri_t *spri)
943 {
944 ftdm_span_t *span = spri->private_info;
945
946 if (!ftdm_running() || ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) {
947 return -1;
948 }
949
950 check_state(span);
951 check_events(span);
952
953
954 return 0;
955 }
956
957
958
959
960
961
962
963
964 static int on_restart(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
965 {
966 ftdm_span_t *span = spri->private_info;
967 ftdm_channel_t *ftdmchan;
968
969 ftdm_log(FTDM_LOG_NOTICE, "-- Restarting %d:%d\n", spri->span->span_id, pevent->restart.channel);
970
971 spri->dchan->state = FTDM_CHANNEL_STATE_UP;
972 ftdmchan = span->channels[pevent->restart.channel];
973
974 if (!ftdmchan) {
975 return 0;
976 }
977
978 if (pevent->restart.channel < 1) {
979 ftdm_set_state_all(ftdmchan->span, FTDM_CHANNEL_STATE_RESTART);
980 } else {
981 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
982 }
983
984 return 0;
985 }
986
987
988
989
990
991
992
993
994 static int on_dchan_up(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
995 {
996 if (!ftdm_test_flag(spri, LPWRAP_PRI_READY)) {
997 ftdm_signaling_status_t status = FTDM_SIG_STATE_UP;
998 ftdm_channel_t *ftdmchan = NULL;
999 ftdm_sigmsg_t sig;
1000 int i;
1001 ftdm_log(FTDM_LOG_INFO, "Span %d D-Chan UP!\n", spri->span->span_id);
1002 ftdm_set_flag(spri, LPWRAP_PRI_READY);
1003 ftdm_set_state_all(spri->span, FTDM_CHANNEL_STATE_RESTART);
1004
1005 ftdm_log(FTDM_LOG_NOTICE, "%d:Signaling link status changed to %s\n", spri->span->span_id, ftdm_signaling_status2str(status));
1006 for(i=1; i <= spri->span->chan_count; i++) {
1007 ftdmchan = spri->span->channels[i];
1008 memset(&sig, 0, sizeof(sig));
1009 sig.chan_id = ftdmchan->chan_id;
1010 sig.span_id = ftdmchan->span_id;
1011 sig.channel = ftdmchan;
1012 sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
1013 sig.raw_data = &status;
1014 ftdm_span_send_signal(spri->span, &sig);
1015 }
1016 }
1017 return 0;
1018 }
1019
1020
1021
1022
1023
1024
1025
1026
1027 static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
1028 {
1029 if (ftdm_test_flag(spri, LPWRAP_PRI_READY)) {
1030 ftdm_signaling_status_t status = FTDM_SIG_STATE_DOWN;
1031 ftdm_channel_t *ftdmchan = NULL;
1032 ftdm_sigmsg_t sig;
1033 int i;
1034 ftdm_log(FTDM_LOG_INFO, "Span %d D-Chan DOWN!\n", spri->span->span_id);
1035 ftdm_clear_flag(spri, LPWRAP_PRI_READY);
1036 ftdm_set_state_all(spri->span, FTDM_CHANNEL_STATE_RESTART);
1037
1038
1039 ftdm_log(FTDM_LOG_NOTICE, "%d:Signaling link status changed to %s\n", spri->span->span_id, ftdm_signaling_status2str(status));
1040 for(i=1; i <= spri->span->chan_count; i++) {
1041 ftdmchan = spri->span->channels[i];
1042 memset(&sig, 0, sizeof(sig));
1043 sig.chan_id = ftdmchan->chan_id;
1044 sig.span_id = ftdmchan->span_id;
1045 sig.channel = ftdmchan;
1046 sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
1047 sig.raw_data = &status;
1048 ftdm_span_send_signal(spri->span, &sig);
1049 }
1050 }
1051
1052 return 0;
1053 }
1054
1055
1056
1057
1058
1059
1060
1061
1062 static int on_anything(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
1063 {
1064
1065 ftdm_log(FTDM_LOG_DEBUG, "Caught Event span %d %u (%s)\n", spri->span->span_id, event_type, lpwrap_pri_event_str(event_type));
1066 return 0;
1067 }
1068
1069
1070
1071
1072
1073
1074
1075
1076 static int on_io_fail(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
1077 {
1078
1079 ftdm_log(FTDM_LOG_DEBUG, "Caught Event span %d %u (%s)\n", spri->span->span_id, event_type, lpwrap_pri_event_str(event_type));
1080 return 0;
1081 }
1082
1083
1084
1085
1086
1087
1088 static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
1089 {
1090 ftdm_span_t *span = (ftdm_span_t *) obj;
1091 ftdm_libpri_data_t *isdn_data = span->signal_data;
1092 int i, x = 0;
1093 int down = 0;
1094 int got_d = 0;
1095
1096 ftdm_set_flag(span, FTDM_SPAN_IN_THREAD);
1097
1098 while(ftdm_running() && !ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) {
1099 if (!got_d) {
1100 for(i = 1; i <= span->chan_count; i++) {
1101 if (span->channels[i]->type == FTDM_CHAN_TYPE_DQ921) {
1102 if (ftdm_channel_open(span->span_id, i, &isdn_data->dchan) == FTDM_SUCCESS) {
1103 ftdm_log(FTDM_LOG_DEBUG, "opening d-channel #%d %d:%d\n", x, isdn_data->dchan->span_id, isdn_data->dchan->chan_id);
1104 got_d = 1;
1105 x++;
1106 break;
1107 } else {
1108 ftdm_log(FTDM_LOG_ERROR, "failed to open d-channel #%d %d:%d\n", x, span->channels[i]->span_id, span->channels[i]->chan_id);
1109 }
1110 }
1111 }
1112 }
1113
1114 if (!got_d) {
1115 ftdm_log(FTDM_LOG_ERROR, "Failed to get a D-channel in span %d\n", span->span_id);
1116 break;
1117 }
1118
1119
1120 if (lpwrap_init_pri(&isdn_data->spri,
1121 span,
1122 isdn_data->dchan,
1123 isdn_data->pswitch,
1124 isdn_data->node,
1125 isdn_data->debug) < 0) {
1126 snprintf(span->last_error, sizeof(span->last_error), "PRI init FAIL!");
1127 } else {
1128
1129 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANY, on_anything);
1130 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RING, on_ring);
1131 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RINGING, on_ringing);
1132
1133 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_PROCEEDING, on_proceed);
1134 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANSWER, on_answer);
1135 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_UP, on_dchan_up);
1136 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_DOWN, on_dchan_down);
1137 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP_REQ, on_hangup);
1138 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP, on_hangup);
1139 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_INFO_RECEIVED, on_info);
1140 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RESTART, on_restart);
1141 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_IO_FAIL, on_io_fail);
1142
1143 if (down) {
1144 ftdm_log(FTDM_LOG_INFO, "PRI back up on span %d\n", isdn_data->spri.span->span_id);
1145 ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART);
1146 down = 0;
1147 }
1148
1149 isdn_data->spri.on_loop = check_flags;
1150 isdn_data->spri.private_info = span;
1151 lpwrap_run_pri(&isdn_data->spri);
1152
1153 }
1154
1155 if (!ftdm_running() || ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) {
1156 break;
1157 }
1158
1159 ftdm_log(FTDM_LOG_CRIT, "PRI down on span %d\n", isdn_data->spri.span->span_id);
1160 if (isdn_data->spri.dchan) {
1161 isdn_data->spri.dchan->state = FTDM_CHANNEL_STATE_DOWN;
1162 }
1163
1164 if (!down) {
1165 ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART);
1166 check_state(span);
1167 }
1168
1169 check_state(span);
1170 check_events(span);
1171
1172 down++;
1173 ftdm_sleep(5000);
1174 }
1175
1176 ftdm_log(FTDM_LOG_DEBUG, "PRI thread ended on span %d\n", span->span_id);
1177
1178 ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
1179 ftdm_clear_flag(isdn_data, FTMOD_LIBPRI_RUNNING);
1180
1181 return NULL;
1182 }
1183
1184
1185
1186
1187
1188
1189
1190
1191 static ftdm_status_t ftdm_libpri_stop(ftdm_span_t *span)
1192 {
1193 ftdm_libpri_data_t *isdn_data = span->signal_data;
1194
1195 if (!ftdm_test_flag(isdn_data, FTMOD_LIBPRI_RUNNING)) {
1196 return FTDM_FAIL;
1197 }
1198
1199 ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART);
1200 check_state(span);
1201 ftdm_set_flag(span, FTDM_SPAN_STOP_THREAD);
1202 while(ftdm_test_flag(span, FTDM_SPAN_IN_THREAD)) {
1203 ftdm_sleep(100);
1204 }
1205 check_state(span);
1206
1207 return FTDM_SUCCESS;
1208 }
1209
1210
1211
1212
1213
1214
1215
1216
1217 static ftdm_status_t ftdm_libpri_start(ftdm_span_t *span)
1218 {
1219 ftdm_status_t ret;
1220 ftdm_libpri_data_t *isdn_data = span->signal_data;
1221
1222 if (ftdm_test_flag(isdn_data, FTMOD_LIBPRI_RUNNING)) {
1223 return FTDM_FAIL;
1224 }
1225
1226 ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD);
1227 ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
1228
1229 ftdm_set_flag(isdn_data, FTMOD_LIBPRI_RUNNING);
1230 ret = ftdm_thread_create_detached(ftdm_libpri_run, span);
1231
1232 if (ret != FTDM_SUCCESS) {
1233 return ret;
1234 }
1235
1236 return ret;
1237 }
1238
1239
1240
1241
1242
1243
1244 static int str2node(char *node)
1245 {
1246 if (!strcasecmp(node, "cpe") || !strcasecmp(node, "user"))
1247 return PRI_CPE;
1248 if (!strcasecmp(node, "network") || !strcasecmp(node, "net"))
1249 return PRI_NETWORK;
1250 return -1;
1251 }
1252
1253
1254
1255
1256
1257
1258 static int str2switch(char *swtype)
1259 {
1260 if (!strcasecmp(swtype, "ni1"))
1261 return PRI_SWITCH_NI1;
1262 if (!strcasecmp(swtype, "ni2"))
1263 return PRI_SWITCH_NI2;
1264 if (!strcasecmp(swtype, "dms100"))
1265 return PRI_SWITCH_DMS100;
1266 if (!strcasecmp(swtype, "lucent5e") || !strcasecmp(swtype, "5ess"))
1267 return PRI_SWITCH_LUCENT5E;
1268 if (!strcasecmp(swtype, "att4ess") || !strcasecmp(swtype, "4ess"))
1269 return PRI_SWITCH_ATT4ESS;
1270 if (!strcasecmp(swtype, "euroisdn"))
1271 return PRI_SWITCH_EUROISDN_E1;
1272 if (!strcasecmp(swtype, "gr303eoc"))
1273 return PRI_SWITCH_GR303_EOC;
1274 if (!strcasecmp(swtype, "gr303tmc"))
1275 return PRI_SWITCH_GR303_TMC;
1276 return PRI_SWITCH_DMS100;
1277 }
1278
1279
1280
1281
1282
1283
1284 static int str2l1(char *l1)
1285 {
1286 if (!strcasecmp(l1, "alaw"))
1287 return PRI_LAYER_1_ALAW;
1288
1289 return PRI_LAYER_1_ULAW;
1290 }
1291
1292
1293
1294
1295
1296
1297 static int str2dp(char *dp)
1298 {
1299 if (!strcasecmp(dp, "international"))
1300 return PRI_INTERNATIONAL_ISDN;
1301 if (!strcasecmp(dp, "national"))
1302 return PRI_NATIONAL_ISDN;
1303 if (!strcasecmp(dp, "local"))
1304 return PRI_LOCAL_ISDN;
1305 if (!strcasecmp(dp, "private"))
1306 return PRI_PRIVATE;
1307 if (!strcasecmp(dp, "unknown"))
1308 return PRI_UNKNOWN;
1309
1310 return PRI_UNKNOWN;
1311 }
1312
1313
1314
1315
1316
1317
1318
1319
1320 static FIO_SIG_CONFIGURE_FUNCTION(ftdm_libpri_configure_span)
1321 {
1322 uint32_t i, x = 0;
1323
1324 ftdm_libpri_data_t *isdn_data;
1325 char *var, *val;
1326 char *debug = NULL;
1327
1328 if (span->trunk_type >= FTDM_TRUNK_NONE) {
1329 ftdm_log(FTDM_LOG_WARNING, "Invalid trunk type '%s' defaulting to T1.\n", ftdm_trunk_type2str(span->trunk_type));
1330 span->trunk_type = FTDM_TRUNK_T1;
1331 }
1332
1333 for(i = 1; i <= span->chan_count; i++) {
1334 if (span->channels[i]->type == FTDM_CHAN_TYPE_DQ921) {
1335 if (x > 1) {
1336 snprintf(span->last_error, sizeof(span->last_error), "Span has more than 2 D-Channels!");
1337 return FTDM_FAIL;
1338 } else {
1339 #if 0
1340 if (ftdm_channel_open(span->span_id, i, &dchans[x]) == FTDM_SUCCESS) {
1341 ftdm_log(FTDM_LOG_DEBUG, "opening d-channel #%d %d:%d\n", x, dchans[x]->span_id, dchans[x]->chan_id);
1342 dchans[x]->state = FTDM_CHANNEL_STATE_UP;
1343 x++;
1344 }
1345 #endif
1346 }
1347 }
1348 }
1349
1350 #if 0
1351 if (!x) {
1352 snprintf(span->last_error, sizeof(span->last_error), "Span has no D-Channels!");
1353 return FTDM_FAIL;
1354 }
1355 #endif
1356
1357 isdn_data = ftdm_malloc(sizeof(*isdn_data));
1358 assert(isdn_data != NULL);
1359 memset(isdn_data, 0, sizeof(*isdn_data));
1360
1361 if (span->trunk_type == FTDM_TRUNK_E1) {
1362 ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ALAW since this is an E1 trunk\n");
1363 isdn_data->l1 = PRI_LAYER_1_ALAW;
1364 } else if (span->trunk_type == FTDM_TRUNK_T1) {
1365 ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ULAW since this is a T1 trunk\n");
1366 isdn_data->l1 = PRI_LAYER_1_ULAW;
1367 }
1368
1369 while((var = va_arg(ap, char *))) {
1370 if (!strcasecmp(var, "node")) {
1371 int node;
1372 if (!(val = va_arg(ap, char *))) {
1373 break;
1374 }
1375 node = str2node(val);
1376 if (-1 == node) {
1377 ftdm_log(FTDM_LOG_ERROR, "Unknown node type %s, defaulting to CPE mode\n", val);
1378 node = PRI_CPE;
1379 }
1380 isdn_data->node = node;
1381 } else if (!strcasecmp(var, "switch")) {
1382 if (!(val = va_arg(ap, char *))) {
1383 break;
1384 }
1385 isdn_data->pswitch = str2switch(val);
1386 } else if (!strcasecmp(var, "opts")) {
1387 if (!(val = va_arg(ap, char *))) {
1388 break;
1389 }
1390 isdn_data->opts = parse_opts(val);
1391 } else if (!strcasecmp(var, "dp")) {
1392 if (!(val = va_arg(ap, char *))) {
1393 break;
1394 }
1395 isdn_data->dp = str2dp(val);
1396 } else if (!strcasecmp(var, "l1")) {
1397 if (!(val = va_arg(ap, char *))) {
1398 break;
1399 }
1400 isdn_data->l1 = str2l1(val);
1401 } else if (!strcasecmp(var, "debug")) {
1402 if (!(val = va_arg(ap, char *))) {
1403 break;
1404 }
1405 debug = val;
1406 } else {
1407 snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var);
1408 return FTDM_FAIL;
1409 }
1410 }
1411
1412 span->start = ftdm_libpri_start;
1413 span->stop = ftdm_libpri_stop;
1414 span->signal_cb = sig_cb;
1415
1416
1417
1418
1419 isdn_data->debug = parse_debug(debug);
1420
1421
1422 span->signal_data = isdn_data;
1423 span->signal_type = FTDM_SIGTYPE_ISDN;
1424 span->outgoing_call = isdn_outgoing_call;
1425
1426 span->get_channel_sig_status = isdn_get_channel_sig_status;
1427 span->get_span_sig_status = isdn_get_span_sig_status;
1428
1429 if ((isdn_data->opts & FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL)) {
1430 span->channel_request = isdn_channel_request;
1431 ftdm_set_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID);
1432 }
1433
1434 span->state_map = &isdn_state_map;
1435
1436 return FTDM_SUCCESS;
1437 }
1438
1439
1440
1441
1442 ftdm_module_t ftdm_module = {
1443 "libpri",
1444 ftdm_libpri_io_init,
1445 ftdm_libpri_unload,
1446 ftdm_libpri_init,
1447 ftdm_libpri_configure_span,
1448 NULL
1449 };
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461