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_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_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 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
609 } else {
610 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
611 }
612 }
613 break;
614 case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
615 break;
616 case FTDM_CHANNEL_STATE_TERMINATING:
617 {
618 sig.event_id = FTDM_SIGEVENT_STOP;
619 status = ftdm_span_send_signal(ftdmchan->span, &sig);
620 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
621
622 }
623 default:
624 break;
625 }
626
627
628
629 return;
630 }
631
632
633
634
635
636 static __inline__ void check_state(ftdm_span_t *span)
637 {
638 if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE)) {
639 uint32_t j;
640 ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE);
641 for(j = 1; j <= span->chan_count; j++) {
642 if (ftdm_test_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE)) {
643 ftdm_mutex_lock(span->channels[j]->mutex);
644 ftdm_clear_flag((span->channels[j]), FTDM_CHANNEL_STATE_CHANGE);
645 state_advance(span->channels[j]);
646 ftdm_channel_complete_state(span->channels[j]);
647 ftdm_mutex_unlock(span->channels[j]->mutex);
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 call = (q931_call *) ftdmchan->call_data;
687 ftdm_log(FTDM_LOG_DEBUG, "-- Hangup on channel %d:%d\n", spri->span->span_id, pevent->hangup.channel);
688 ftdmchan->caller_data.hangup_cause = pevent->hangup.cause;
689 pri_release(spri->pri, call, 0);
690 pri_destroycall(spri->pri, call);
691 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
692 } else {
693 ftdm_log(FTDM_LOG_DEBUG, "-- Hangup on channel %d:%d %s but it's not in use?\n", spri->span->span_id,
694 pevent->hangup.channel, ftdmchan->chan_id);
695 }
696
697 return 0;
698 }
699
700
701
702
703
704
705
706
707 static int on_answer(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
708 {
709 ftdm_span_t *span = spri->private_info;
710 ftdm_channel_t *ftdmchan = NULL;
711
712 ftdmchan = span->channels[pevent->answer.channel];
713
714 if (ftdmchan) {
715 ftdm_log(FTDM_LOG_DEBUG, "-- Answer on channel %d:%d\n", spri->span->span_id, pevent->answer.channel);
716 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
717 } else {
718 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);
719
720 }
721
722 return 0;
723 }
724
725
726
727
728
729
730
731
732 static int on_proceed(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
733 {
734 ftdm_span_t *span = spri->private_info;
735 ftdm_channel_t *ftdmchan = NULL;
736
737 ftdmchan = span->channels[pevent->proceeding.channel];
738
739 if (ftdmchan) {
740 ftdm_log(FTDM_LOG_DEBUG, "-- Proceeding on channel %d:%d\n", spri->span->span_id, pevent->proceeding.channel);
741 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
742 } else {
743 ftdm_log(FTDM_LOG_DEBUG, "-- Proceeding on channel %d:%d %s but it's not in use?\n", spri->span->span_id,
744 pevent->proceeding.channel, ftdmchan->chan_id);
745 }
746
747 return 0;
748 }
749
750
751
752
753
754
755
756
757 static int on_ringing(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
758 {
759 ftdm_span_t *span = spri->private_info;
760 ftdm_channel_t *ftdmchan = NULL;
761
762 ftdmchan = span->channels[pevent->ringing.channel];
763
764 if (ftdmchan) {
765 ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d\n", spri->span->span_id, pevent->ringing.channel);
766
767 if (ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA) {
768
769 return 0;
770 }
771 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
772 } else {
773 ftdm_log(FTDM_LOG_DEBUG, "-- Ringing on channel %d:%d %s but it's not in use?\n", spri->span->span_id,
774 pevent->ringing.channel, ftdmchan->chan_id);
775 }
776
777 return 0;
778 }
779
780
781
782
783
784
785
786
787 static int on_ring(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
788 {
789 ftdm_span_t *span = spri->private_info;
790 ftdm_channel_t *ftdmchan = NULL;
791 int ret = 0;
792
793
794
795 ftdmchan = span->channels[pevent->ring.channel];
796 if (!ftdmchan || ftdmchan->state != FTDM_CHANNEL_STATE_DOWN || ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) {
797 ftdm_log(FTDM_LOG_WARNING, "--Duplicate Ring on channel %d:%d (ignored)\n", spri->span->span_id, pevent->ring.channel);
798 ret = 0;
799 goto done;
800 }
801
802 if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
803 ftdm_log(FTDM_LOG_WARNING, "--Failure opening channel %d:%d (ignored)\n", spri->span->span_id, pevent->ring.channel);
804 ret = 0;
805 goto done;
806 }
807
808
809 ftdm_log(FTDM_LOG_NOTICE, "-- Ring on channel %d:%d (from %s to %s)\n", spri->span->span_id, pevent->ring.channel,
810 pevent->ring.callingnum, pevent->ring.callednum);
811
812 memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data));
813
814 ftdm_set_string(ftdmchan->caller_data.cid_num.digits, (char *)pevent->ring.callingnum);
815 if (!ftdm_strlen_zero((char *)pevent->ring.callingname)) {
816 ftdm_set_string(ftdmchan->caller_data.cid_name, (char *)pevent->ring.callingname);
817 } else {
818 ftdm_set_string(ftdmchan->caller_data.cid_name, (char *)pevent->ring.callingnum);
819 }
820 ftdm_set_string(ftdmchan->caller_data.ani.digits, (char *)pevent->ring.callingani);
821 ftdm_set_string(ftdmchan->caller_data.dnis.digits, (char *)pevent->ring.callednum);
822
823 if (pevent->ring.ani2 >= 0) {
824 snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", pevent->ring.ani2);
825 }
826
827
828 ftdmchan->call_data = pevent->ring.call;
829
830 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
831
832 done:
833
834
835 return ret;
836 }
837
838
839
840
841
842
843
844 static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *event)
845 {
846 ftdm_alarm_flag_t alarmbits;
847 ftdm_log(FTDM_LOG_DEBUG, "EVENT [%s][%d][%d:%d] STATE [%s]\n",
848 ftdm_oob_event2str(event->enum_id), event->enum_id, event->channel->span_id, event->channel->chan_id, ftdm_channel_state2str(event->channel->state));
849
850 switch(event->enum_id) {
851 case FTDM_OOB_ALARM_TRAP:
852 {
853 if (event->channel->state != FTDM_CHANNEL_STATE_DOWN) {
854 if (event->channel->type == FTDM_CHAN_TYPE_B) {
855 ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RESTART);
856 }
857 }
858
859
860 ftdm_set_flag(event->channel, FTDM_CHANNEL_SUSPENDED);
861
862
863 ftdm_channel_get_alarms(event->channel, &alarmbits);
864 ftdm_log(FTDM_LOG_WARNING, "channel %d:%d (%d:%d) has alarms! [%s]\n",
865 event->channel->span_id, event->channel->chan_id,
866 event->channel->physical_span_id, event->channel->physical_chan_id,
867 event->channel->last_error);
868 }
869 break;
870 case FTDM_OOB_ALARM_CLEAR:
871 {
872
873 ftdm_log(FTDM_LOG_WARNING, "channel %d:%d (%d:%d) alarms Cleared!\n", event->channel->span_id, event->channel->chan_id,
874 event->channel->physical_span_id, event->channel->physical_chan_id);
875
876 ftdm_clear_flag(event->channel, FTDM_CHANNEL_SUSPENDED);
877 ftdm_channel_get_alarms(event->channel, &alarmbits);
878 }
879 break;
880 }
881
882 return FTDM_SUCCESS;
883 }
884
885
886
887
888
889 static __inline__ void check_events(ftdm_span_t *span)
890 {
891 ftdm_status_t status;
892
893 status = ftdm_span_poll_event(span, 5);
894
895 switch(status) {
896 case FTDM_SUCCESS:
897 {
898 ftdm_event_t *event;
899 while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) {
900 if (event->enum_id == FTDM_OOB_NOOP) {
901 continue;
902 }
903 if (process_event(span, event) != FTDM_SUCCESS) {
904 break;
905 }
906 }
907 }
908 break;
909 case FTDM_FAIL:
910 {
911 ftdm_log(FTDM_LOG_DEBUG, "Event Failure! %d\n", ftdm_running());
912 ftdm_sleep(2000);
913 }
914 break;
915 default:
916 break;
917 }
918 }
919
920
921
922
923
924
925 static int check_flags(lpwrap_pri_t *spri)
926 {
927 ftdm_span_t *span = spri->private_info;
928
929 if (!ftdm_running() || ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) {
930 return -1;
931 }
932
933 check_state(span);
934 check_events(span);
935
936
937 return 0;
938 }
939
940
941
942
943
944
945
946
947 static int on_restart(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
948 {
949 ftdm_span_t *span = spri->private_info;
950 ftdm_channel_t *ftdmchan;
951
952 ftdm_log(FTDM_LOG_NOTICE, "-- Restarting %d:%d\n", spri->span->span_id, pevent->restart.channel);
953
954 spri->dchan->state = FTDM_CHANNEL_STATE_UP;
955 ftdmchan = span->channels[pevent->restart.channel];
956
957 if (!ftdmchan) {
958 return 0;
959 }
960
961 if (pevent->restart.channel < 1) {
962 ftdm_set_state_all(ftdmchan->span, FTDM_CHANNEL_STATE_RESTART);
963 } else {
964 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
965 }
966
967 return 0;
968 }
969
970
971
972
973
974
975
976
977 static int on_dchan_up(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
978 {
979 if (!ftdm_test_flag(spri, LPWRAP_PRI_READY)) {
980 ftdm_signaling_status_t status = FTDM_SIG_STATE_UP;
981 ftdm_channel_t *ftdmchan = NULL;
982 ftdm_sigmsg_t sig;
983 int i;
984 ftdm_log(FTDM_LOG_INFO, "Span %d D-Chan UP!\n", spri->span->span_id);
985 ftdm_set_flag(spri, LPWRAP_PRI_READY);
986 ftdm_set_state_all(spri->span, FTDM_CHANNEL_STATE_RESTART);
987
988 ftdm_log(FTDM_LOG_NOTICE, "%d:Signaling link status changed to %s\n", spri->span->span_id, ftdm_signaling_status2str(status));
989 for(i=1; i <= spri->span->chan_count; i++) {
990 ftdmchan = spri->span->channels[i];
991 memset(&sig, 0, sizeof(sig));
992 sig.chan_id = ftdmchan->chan_id;
993 sig.span_id = ftdmchan->span_id;
994 sig.channel = ftdmchan;
995 sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
996 sig.raw_data = &status;
997 ftdm_span_send_signal(spri->span, &sig);
998 }
999 }
1000 return 0;
1001 }
1002
1003
1004
1005
1006
1007
1008
1009
1010 static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
1011 {
1012 if (ftdm_test_flag(spri, LPWRAP_PRI_READY)) {
1013 ftdm_signaling_status_t status = FTDM_SIG_STATE_DOWN;
1014 ftdm_channel_t *ftdmchan = NULL;
1015 ftdm_sigmsg_t sig;
1016 int i;
1017 ftdm_log(FTDM_LOG_INFO, "Span %d D-Chan DOWN!\n", spri->span->span_id);
1018 ftdm_clear_flag(spri, LPWRAP_PRI_READY);
1019 ftdm_set_state_all(spri->span, FTDM_CHANNEL_STATE_RESTART);
1020
1021
1022 ftdm_log(FTDM_LOG_NOTICE, "%d:Signaling link status changed to %s\n", spri->span->span_id, ftdm_signaling_status2str(status));
1023 for(i=1; i <= spri->span->chan_count; i++) {
1024 ftdmchan = spri->span->channels[i];
1025 memset(&sig, 0, sizeof(sig));
1026 sig.chan_id = ftdmchan->chan_id;
1027 sig.span_id = ftdmchan->span_id;
1028 sig.channel = ftdmchan;
1029 sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
1030 sig.raw_data = &status;
1031 ftdm_span_send_signal(spri->span, &sig);
1032 }
1033 }
1034
1035 return 0;
1036 }
1037
1038
1039
1040
1041
1042
1043
1044
1045 static int on_anything(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
1046 {
1047
1048 ftdm_log(FTDM_LOG_DEBUG, "Caught Event span %d %u (%s)\n", spri->span->span_id, event_type, lpwrap_pri_event_str(event_type));
1049 return 0;
1050 }
1051
1052
1053
1054
1055
1056
1057
1058
1059 static int on_io_fail(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
1060 {
1061
1062 ftdm_log(FTDM_LOG_DEBUG, "Caught Event span %d %u (%s)\n", spri->span->span_id, event_type, lpwrap_pri_event_str(event_type));
1063 return 0;
1064 }
1065
1066
1067
1068
1069
1070
1071 static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
1072 {
1073 ftdm_span_t *span = (ftdm_span_t *) obj;
1074 ftdm_libpri_data_t *isdn_data = span->signal_data;
1075 int i, x = 0;
1076 int down = 0;
1077 int got_d = 0;
1078
1079 ftdm_set_flag(span, FTDM_SPAN_IN_THREAD);
1080
1081 while(ftdm_running() && !ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) {
1082 if (!got_d) {
1083 for(i = 1; i <= span->chan_count; i++) {
1084 if (span->channels[i]->type == FTDM_CHAN_TYPE_DQ921) {
1085 if (ftdm_channel_open(span->span_id, i, &isdn_data->dchan) == FTDM_SUCCESS) {
1086 ftdm_log(FTDM_LOG_DEBUG, "opening d-channel #%d %d:%d\n", x, isdn_data->dchan->span_id, isdn_data->dchan->chan_id);
1087 got_d = 1;
1088 x++;
1089 break;
1090 } else {
1091 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);
1092 }
1093 }
1094 }
1095 }
1096
1097 if (!got_d) {
1098 ftdm_log(FTDM_LOG_ERROR, "Failed to get a D-channel in span %d\n", span->span_id);
1099 break;
1100 }
1101
1102
1103 if (lpwrap_init_pri(&isdn_data->spri,
1104 span,
1105 isdn_data->dchan,
1106 isdn_data->pswitch,
1107 isdn_data->node,
1108 isdn_data->debug) < 0) {
1109 snprintf(span->last_error, sizeof(span->last_error), "PRI init FAIL!");
1110 } else {
1111
1112 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANY, on_anything);
1113 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RING, on_ring);
1114 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RINGING, on_ringing);
1115
1116 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_PROCEEDING, on_proceed);
1117 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANSWER, on_answer);
1118 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_UP, on_dchan_up);
1119 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_DOWN, on_dchan_down);
1120 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP_REQ, on_hangup);
1121 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP, on_hangup);
1122 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_INFO_RECEIVED, on_info);
1123 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RESTART, on_restart);
1124 LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_IO_FAIL, on_io_fail);
1125
1126 if (down) {
1127 ftdm_log(FTDM_LOG_INFO, "PRI back up on span %d\n", isdn_data->spri.span->span_id);
1128 ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART);
1129 down = 0;
1130 }
1131
1132 isdn_data->spri.on_loop = check_flags;
1133 isdn_data->spri.private_info = span;
1134 lpwrap_run_pri(&isdn_data->spri);
1135
1136 }
1137
1138 if (!ftdm_running() || ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) {
1139 break;
1140 }
1141
1142 ftdm_log(FTDM_LOG_CRIT, "PRI down on span %d\n", isdn_data->spri.span->span_id);
1143 if (isdn_data->spri.dchan) {
1144 isdn_data->spri.dchan->state = FTDM_CHANNEL_STATE_DOWN;
1145 }
1146
1147 if (!down) {
1148 ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART);
1149 check_state(span);
1150 }
1151
1152 check_state(span);
1153 check_events(span);
1154
1155 down++;
1156 ftdm_sleep(5000);
1157 }
1158
1159 ftdm_log(FTDM_LOG_DEBUG, "PRI thread ended on span %d\n", span->span_id);
1160
1161 ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
1162 ftdm_clear_flag(isdn_data, FTMOD_LIBPRI_RUNNING);
1163
1164 return NULL;
1165 }
1166
1167
1168
1169
1170
1171
1172
1173
1174 static ftdm_status_t ftdm_libpri_stop(ftdm_span_t *span)
1175 {
1176 ftdm_libpri_data_t *isdn_data = span->signal_data;
1177
1178 if (!ftdm_test_flag(isdn_data, FTMOD_LIBPRI_RUNNING)) {
1179 return FTDM_FAIL;
1180 }
1181
1182 ftdm_set_state_all(span, FTDM_CHANNEL_STATE_RESTART);
1183 check_state(span);
1184 ftdm_set_flag(span, FTDM_SPAN_STOP_THREAD);
1185 while(ftdm_test_flag(span, FTDM_SPAN_IN_THREAD)) {
1186 ftdm_sleep(100);
1187 }
1188 check_state(span);
1189
1190 return FTDM_SUCCESS;
1191 }
1192
1193
1194
1195
1196
1197
1198
1199
1200 static ftdm_status_t ftdm_libpri_start(ftdm_span_t *span)
1201 {
1202 ftdm_status_t ret;
1203 ftdm_libpri_data_t *isdn_data = span->signal_data;
1204
1205 if (ftdm_test_flag(isdn_data, FTMOD_LIBPRI_RUNNING)) {
1206 return FTDM_FAIL;
1207 }
1208
1209 ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD);
1210 ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
1211
1212 ftdm_set_flag(isdn_data, FTMOD_LIBPRI_RUNNING);
1213 ret = ftdm_thread_create_detached(ftdm_libpri_run, span);
1214
1215 if (ret != FTDM_SUCCESS) {
1216 return ret;
1217 }
1218
1219 return ret;
1220 }
1221
1222
1223
1224
1225
1226
1227 static int str2node(char *node)
1228 {
1229 if (!strcasecmp(node, "cpe") || !strcasecmp(node, "user"))
1230 return PRI_CPE;
1231 if (!strcasecmp(node, "network") || !strcasecmp(node, "net"))
1232 return PRI_NETWORK;
1233 return -1;
1234 }
1235
1236
1237
1238
1239
1240
1241 static int str2switch(char *swtype)
1242 {
1243 if (!strcasecmp(swtype, "ni1"))
1244 return PRI_SWITCH_NI1;
1245 if (!strcasecmp(swtype, "ni2"))
1246 return PRI_SWITCH_NI2;
1247 if (!strcasecmp(swtype, "dms100"))
1248 return PRI_SWITCH_DMS100;
1249 if (!strcasecmp(swtype, "lucent5e") || !strcasecmp(swtype, "5ess"))
1250 return PRI_SWITCH_LUCENT5E;
1251 if (!strcasecmp(swtype, "att4ess") || !strcasecmp(swtype, "4ess"))
1252 return PRI_SWITCH_ATT4ESS;
1253 if (!strcasecmp(swtype, "euroisdn"))
1254 return PRI_SWITCH_EUROISDN_E1;
1255 if (!strcasecmp(swtype, "gr303eoc"))
1256 return PRI_SWITCH_GR303_EOC;
1257 if (!strcasecmp(swtype, "gr303tmc"))
1258 return PRI_SWITCH_GR303_TMC;
1259 return PRI_SWITCH_DMS100;
1260 }
1261
1262
1263
1264
1265
1266
1267 static int str2l1(char *l1)
1268 {
1269 if (!strcasecmp(l1, "alaw"))
1270 return PRI_LAYER_1_ALAW;
1271
1272 return PRI_LAYER_1_ULAW;
1273 }
1274
1275
1276
1277
1278
1279
1280 static int str2dp(char *dp)
1281 {
1282 if (!strcasecmp(dp, "international"))
1283 return PRI_INTERNATIONAL_ISDN;
1284 if (!strcasecmp(dp, "national"))
1285 return PRI_NATIONAL_ISDN;
1286 if (!strcasecmp(dp, "local"))
1287 return PRI_LOCAL_ISDN;
1288 if (!strcasecmp(dp, "private"))
1289 return PRI_PRIVATE;
1290 if (!strcasecmp(dp, "unknown"))
1291 return PRI_UNKNOWN;
1292
1293 return PRI_UNKNOWN;
1294 }
1295
1296
1297
1298
1299
1300
1301
1302
1303 static FIO_SIG_CONFIGURE_FUNCTION(ftdm_libpri_configure_span)
1304 {
1305 uint32_t i, x = 0;
1306
1307 ftdm_libpri_data_t *isdn_data;
1308 char *var, *val;
1309 char *debug = NULL;
1310
1311 if (span->trunk_type >= FTDM_TRUNK_NONE) {
1312 ftdm_log(FTDM_LOG_WARNING, "Invalid trunk type '%s' defaulting to T1.\n", ftdm_trunk_type2str(span->trunk_type));
1313 span->trunk_type = FTDM_TRUNK_T1;
1314 }
1315
1316 for(i = 1; i <= span->chan_count; i++) {
1317 if (span->channels[i]->type == FTDM_CHAN_TYPE_DQ921) {
1318 if (x > 1) {
1319 snprintf(span->last_error, sizeof(span->last_error), "Span has more than 2 D-Channels!");
1320 return FTDM_FAIL;
1321 } else {
1322 #if 0
1323 if (ftdm_channel_open(span->span_id, i, &dchans[x]) == FTDM_SUCCESS) {
1324 ftdm_log(FTDM_LOG_DEBUG, "opening d-channel #%d %d:%d\n", x, dchans[x]->span_id, dchans[x]->chan_id);
1325 dchans[x]->state = FTDM_CHANNEL_STATE_UP;
1326 x++;
1327 }
1328 #endif
1329 }
1330 }
1331 }
1332
1333 #if 0
1334 if (!x) {
1335 snprintf(span->last_error, sizeof(span->last_error), "Span has no D-Channels!");
1336 return FTDM_FAIL;
1337 }
1338 #endif
1339
1340 isdn_data = ftdm_malloc(sizeof(*isdn_data));
1341 assert(isdn_data != NULL);
1342 memset(isdn_data, 0, sizeof(*isdn_data));
1343
1344 if (span->trunk_type == FTDM_TRUNK_E1) {
1345 ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ALAW since this is an E1 trunk\n");
1346 isdn_data->l1 = PRI_LAYER_1_ALAW;
1347 } else if (span->trunk_type == FTDM_TRUNK_T1) {
1348 ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ULAW since this is a T1 trunk\n");
1349 isdn_data->l1 = PRI_LAYER_1_ULAW;
1350 }
1351
1352 while((var = va_arg(ap, char *))) {
1353 if (!strcasecmp(var, "node")) {
1354 int node;
1355 if (!(val = va_arg(ap, char *))) {
1356 break;
1357 }
1358 node = str2node(val);
1359 if (-1 == node) {
1360 ftdm_log(FTDM_LOG_ERROR, "Unknown node type %s, defaulting to CPE mode\n", val);
1361 node = PRI_CPE;
1362 }
1363 isdn_data->node = node;
1364 } else if (!strcasecmp(var, "switch")) {
1365 if (!(val = va_arg(ap, char *))) {
1366 break;
1367 }
1368 isdn_data->pswitch = str2switch(val);
1369 } else if (!strcasecmp(var, "opts")) {
1370 if (!(val = va_arg(ap, char *))) {
1371 break;
1372 }
1373 isdn_data->opts = parse_opts(val);
1374 } else if (!strcasecmp(var, "dp")) {
1375 if (!(val = va_arg(ap, char *))) {
1376 break;
1377 }
1378 isdn_data->dp = str2dp(val);
1379 } else if (!strcasecmp(var, "l1")) {
1380 if (!(val = va_arg(ap, char *))) {
1381 break;
1382 }
1383 isdn_data->l1 = str2l1(val);
1384 } else if (!strcasecmp(var, "debug")) {
1385 if (!(val = va_arg(ap, char *))) {
1386 break;
1387 }
1388 debug = val;
1389 } else {
1390 snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var);
1391 return FTDM_FAIL;
1392 }
1393 }
1394
1395 span->start = ftdm_libpri_start;
1396 span->stop = ftdm_libpri_stop;
1397 span->signal_cb = sig_cb;
1398
1399
1400
1401
1402 isdn_data->debug = parse_debug(debug);
1403
1404
1405 span->signal_data = isdn_data;
1406 span->signal_type = FTDM_SIGTYPE_ISDN;
1407 span->outgoing_call = isdn_outgoing_call;
1408
1409 span->get_channel_sig_status = isdn_get_channel_sig_status;
1410 span->get_span_sig_status = isdn_get_span_sig_status;
1411
1412 if ((isdn_data->opts & FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL)) {
1413 span->channel_request = isdn_channel_request;
1414 ftdm_set_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID);
1415 }
1416
1417 span->state_map = &isdn_state_map;
1418
1419 return FTDM_SUCCESS;
1420 }
1421
1422
1423
1424
1425 ftdm_module_t ftdm_module = {
1426 "libpri",
1427 ftdm_libpri_io_init,
1428 ftdm_libpri_unload,
1429 ftdm_libpri_init,
1430 ftdm_libpri_configure_span,
1431 NULL
1432 };
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444