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
- s_pri_error
- s_pri_message
- parse_debug
- FIO_API_FUNCTION
- FIO_IO_LOAD_FUNCTION
- FIO_SIG_LOAD_FUNCTION
- state_advance
- pritap_check_state
- pri_io_read
- pri_io_write
- tap_pri_get_crv
- tap_pri_get_pcall_bycrv
- tap_pri_get_pcall
- tap_pri_put_pcall
- tap_pri_get_fchan
- handle_pri_passive_event
- ftdm_pritap_run
- ftdm_pritap_stop
- ftdm_pritap_sig_read
- ftdm_pritap_start
- 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 <libpri.h>
35 #include <poll.h>
36 #include "private/ftdm_core.h"
37
38 #define PRI_SPAN(p) (((p) >> 8) & 0xff)
39 #define PRI_CHANNEL(p) ((p) & 0xff)
40
41 typedef enum {
42 PRITAP_RUNNING = (1 << 0),
43 } pritap_flags_t;
44
45 typedef struct {
46 void *callref;
47 ftdm_number_t callingnum;
48 ftdm_number_t callingani;
49 ftdm_number_t callednum;
50 ftdm_channel_t *fchan;
51 char callingname[80];
52 int proceeding:1;
53 int inuse:1;
54 } passive_call_t;
55
56 typedef struct pritap {
57 int32_t flags;
58 struct pri *pri;
59 int debug;
60 ftdm_channel_t *dchan;
61 ftdm_span_t *span;
62 ftdm_span_t *peerspan;
63 ftdm_mutex_t *pcalls_lock;
64 passive_call_t pcalls[FTDM_MAX_CHANNELS_PHYSICAL_SPAN];
65 } pritap_t;
66
67 static FIO_IO_UNLOAD_FUNCTION(ftdm_pritap_unload)
68 {
69 return FTDM_SUCCESS;
70 }
71
72 static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(pritap_get_channel_sig_status)
73 {
74 *status = FTDM_SIG_STATE_UP;
75 return FTDM_SUCCESS;
76 }
77
78 static FIO_SPAN_GET_SIG_STATUS_FUNCTION(pritap_get_span_sig_status)
79 {
80 *status = FTDM_SIG_STATE_UP;
81 return FTDM_SUCCESS;
82 }
83
84
85 static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(pritap_outgoing_call)
86 {
87 ftdm_log(FTDM_LOG_ERROR, "Cannot dial on PRI tapping line!\n");
88 return FTDM_FAIL;
89 }
90
91 static void s_pri_error(struct pri *pri, char *s)
92 {
93 ftdm_log(FTDM_LOG_ERROR, "%s", s);
94 }
95
96 static void s_pri_message(struct pri *pri, char *s)
97 {
98 ftdm_log(FTDM_LOG_DEBUG, "%s", s);
99 }
100
101 static int parse_debug(const char *in)
102 {
103 int flags = 0;
104
105 if (!in) {
106 return 0;
107 }
108
109 if (strstr(in, "q921_raw")) {
110 flags |= PRI_DEBUG_Q921_RAW;
111 }
112
113 if (strstr(in, "q921_dump")) {
114 flags |= PRI_DEBUG_Q921_DUMP;
115 }
116
117 if (strstr(in, "q921_state")) {
118 flags |= PRI_DEBUG_Q921_STATE;
119 }
120
121 if (strstr(in, "config")) {
122 flags |= PRI_DEBUG_CONFIG;
123 }
124
125 if (strstr(in, "q931_dump")) {
126 flags |= PRI_DEBUG_Q931_DUMP;
127 }
128
129 if (strstr(in, "q931_state")) {
130 flags |= PRI_DEBUG_Q931_STATE;
131 }
132
133 if (strstr(in, "q931_anomaly")) {
134 flags |= PRI_DEBUG_Q931_ANOMALY;
135 }
136
137 if (strstr(in, "apdu")) {
138 flags |= PRI_DEBUG_APDU;
139 }
140
141 if (strstr(in, "aoc")) {
142 flags |= PRI_DEBUG_AOC;
143 }
144
145 if (strstr(in, "all")) {
146 flags |= PRI_DEBUG_ALL;
147 }
148
149 if (strstr(in, "none")) {
150 flags = 0;
151 }
152
153 return flags;
154 }
155
156 static ftdm_io_interface_t ftdm_pritap_interface;
157
158 static ftdm_status_t ftdm_pritap_start(ftdm_span_t *span);
159
160 static FIO_API_FUNCTION(ftdm_pritap_api)
161 {
162 char *mycmd = NULL, *argv[10] = { 0 };
163 int argc = 0;
164
165 if (data) {
166 mycmd = ftdm_strdup(data);
167 argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
168 }
169
170 if (argc > 2) {
171 if (!strcasecmp(argv[0], "debug")) {
172 ftdm_span_t *span = NULL;
173
174 if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) {
175 pritap_t *pritap = span->signal_data;
176 if (span->start != ftdm_pritap_start) {
177 stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
178 goto done;
179 }
180
181 pri_set_debug(pritap->pri, parse_debug(argv[2]));
182 stream->write_function(stream, "%s: +OK debug set.\n", __FILE__);
183 goto done;
184 } else {
185 stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
186 goto done;
187 }
188 }
189
190 }
191
192 stream->write_function(stream, "%s: -ERR invalid command.\n", __FILE__);
193
194 done:
195
196 ftdm_safe_free(mycmd);
197
198 return FTDM_SUCCESS;
199 }
200
201 static FIO_IO_LOAD_FUNCTION(ftdm_pritap_io_init)
202 {
203 memset(&ftdm_pritap_interface, 0, sizeof(ftdm_pritap_interface));
204
205 ftdm_pritap_interface.name = "pritap";
206 ftdm_pritap_interface.api = ftdm_pritap_api;
207
208 *fio = &ftdm_pritap_interface;
209
210 return FTDM_SUCCESS;
211 }
212
213 static FIO_SIG_LOAD_FUNCTION(ftdm_pritap_init)
214 {
215 pri_set_error(s_pri_error);
216 pri_set_message(s_pri_message);
217 return FTDM_SUCCESS;
218 }
219
220 static ftdm_state_map_t pritap_state_map = {
221 {
222 {
223 ZSD_INBOUND,
224 ZSM_UNACCEPTABLE,
225 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
226 {FTDM_CHANNEL_STATE_RING, FTDM_END}
227 },
228 {
229 ZSD_INBOUND,
230 ZSM_UNACCEPTABLE,
231 {FTDM_CHANNEL_STATE_RING, FTDM_END},
232 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}
233 },
234 {
235 ZSD_INBOUND,
236 ZSM_UNACCEPTABLE,
237 {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
238 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
239 },
240 {
241 ZSD_INBOUND,
242 ZSM_UNACCEPTABLE,
243 {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
244 {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
245 },
246 {
247 ZSD_INBOUND,
248 ZSM_UNACCEPTABLE,
249 {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
250 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
251 },
252 {
253 ZSD_INBOUND,
254 ZSM_UNACCEPTABLE,
255 {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
256 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_UP, FTDM_END},
257 },
258 {
259 ZSD_INBOUND,
260 ZSM_UNACCEPTABLE,
261 {FTDM_CHANNEL_STATE_UP, FTDM_END},
262 {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
263 },
264
265 }
266 };
267
268 static ftdm_status_t state_advance(ftdm_channel_t *ftdmchan)
269 {
270 ftdm_status_t status;
271 ftdm_sigmsg_t sig;
272 ftdm_channel_t *peerchan = ftdmchan->call_data;
273
274 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "processing state %s\n", ftdm_channel_state2str(ftdmchan->state));
275
276 memset(&sig, 0, sizeof(sig));
277 sig.chan_id = ftdmchan->chan_id;
278 sig.span_id = ftdmchan->span_id;
279 sig.channel = ftdmchan;
280
281 ftdm_channel_complete_state(ftdmchan);
282
283 switch (ftdmchan->state) {
284 case FTDM_CHANNEL_STATE_DOWN:
285 {
286 ftdmchan->call_data = NULL;
287 ftdm_channel_close(&ftdmchan);
288
289 peerchan->call_data = NULL;
290 ftdm_channel_close(&peerchan);
291 }
292 break;
293
294 case FTDM_CHANNEL_STATE_PROGRESS:
295 case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
296 case FTDM_CHANNEL_STATE_UP:
297 case FTDM_CHANNEL_STATE_HANGUP:
298 break;
299
300 case FTDM_CHANNEL_STATE_RING:
301 {
302 sig.event_id = FTDM_SIGEVENT_START;
303 if ((status = ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS)) {
304 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
305 }
306 }
307 break;
308
309 case FTDM_CHANNEL_STATE_TERMINATING:
310 {
311 if (ftdmchan->last_state != FTDM_CHANNEL_STATE_HANGUP) {
312 sig.event_id = FTDM_SIGEVENT_STOP;
313 status = ftdm_span_send_signal(ftdmchan->span, &sig);
314 }
315 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
316 }
317 break;
318
319 default:
320 {
321 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "ignoring state change from %s to %s\n", ftdm_channel_state2str(ftdmchan->last_state), ftdm_channel_state2str(ftdmchan->state));
322 }
323 break;
324 }
325
326 return FTDM_SUCCESS;
327 }
328
329 static __inline__ void pritap_check_state(ftdm_span_t *span)
330 {
331 if (ftdm_test_flag(span, FTDM_SPAN_STATE_CHANGE)) {
332 uint32_t j;
333 ftdm_clear_flag_locked(span, FTDM_SPAN_STATE_CHANGE);
334 for(j = 1; j <= span->chan_count; j++) {
335 ftdm_mutex_lock(span->channels[j]->mutex);
336 ftdm_channel_advance_states(span->channels[j]);
337 ftdm_mutex_unlock(span->channels[j]->mutex);
338 }
339 }
340 }
341
342 static int pri_io_read(struct pri *pri, void *buf, int buflen)
343 {
344 int res;
345 ftdm_status_t zst;
346 pritap_t *pritap = pri_get_userdata(pri);
347 ftdm_size_t len = buflen;
348
349 if ((zst = ftdm_channel_read(pritap->dchan, buf, &len)) != FTDM_SUCCESS) {
350 if (zst == FTDM_FAIL) {
351 ftdm_log(FTDM_LOG_CRIT, "span %d D channel read fail! [%s]\n", pritap->span->span_id, pritap->dchan->last_error);
352 } else {
353 ftdm_log(FTDM_LOG_CRIT, "span %d D channel read timeout!\n", pritap->span->span_id);
354 }
355 return -1;
356 }
357
358 res = (int)len;
359
360 memset(&((unsigned char*)buf)[res],0,2);
361
362 res += 2;
363
364 return res;
365 }
366
367 static int pri_io_write(struct pri *pri, void *buf, int buflen)
368 {
369 pritap_t *pritap = pri_get_userdata(pri);
370 ftdm_size_t len = buflen - 2;
371
372 if (ftdm_channel_write(pritap->dchan, buf, buflen, &len) != FTDM_SUCCESS) {
373 ftdm_log(FTDM_LOG_CRIT, "span %d D channel write failed! [%s]\n", pritap->span->span_id, pritap->dchan->last_error);
374 return -1;
375 }
376
377 return (int)buflen;
378 }
379
380 static int tap_pri_get_crv(struct pri *ctrl, q931_call *call)
381 {
382 int callmode = 0;
383 int crv = pri_get_crv(ctrl, call, &callmode);
384 crv <<= 3;
385 crv |= (callmode & 0x7);
386 return crv;
387 }
388
389 static passive_call_t *tap_pri_get_pcall_bycrv(pritap_t *pritap, int crv)
390 {
391 int i;
392 int tstcrv;
393
394 ftdm_mutex_lock(pritap->pcalls_lock);
395
396 for (i = 0; i < ftdm_array_len(pritap->pcalls); i++) {
397 tstcrv = pritap->pcalls[i].callref ? tap_pri_get_crv(pritap->pri, pritap->pcalls[i].callref) : 0;
398 if (pritap->pcalls[i].callref && tstcrv == crv) {
399 if (!pritap->pcalls[i].inuse) {
400 ftdm_log(FTDM_LOG_ERROR, "Found crv %d in slot %d of span %s with call %p but is no longer in use!\n",
401 crv, i, pritap->span->name, pritap->pcalls[i].callref);
402 continue;
403 }
404
405 ftdm_mutex_unlock(pritap->pcalls_lock);
406
407 return &pritap->pcalls[i];
408 }
409 }
410
411 ftdm_mutex_unlock(pritap->pcalls_lock);
412
413 return NULL;
414 }
415
416 static passive_call_t *tap_pri_get_pcall(pritap_t *pritap, void *callref)
417 {
418 int i;
419 int crv;
420
421 ftdm_mutex_lock(pritap->pcalls_lock);
422
423 for (i = 0; i < ftdm_array_len(pritap->pcalls); i++) {
424 if (pritap->pcalls[i].callref && !pritap->pcalls[i].inuse) {
425 crv = tap_pri_get_crv(pritap->pri, pritap->pcalls[i].callref);
426
427 ftdm_log(FTDM_LOG_DEBUG, "Garbage collecting callref %d/%p from span %s in slot %d\n",
428 crv, pritap->pcalls[i].callref, pritap->span->name, i);
429 pri_passive_destroycall(pritap->pri, pritap->pcalls[i].callref);
430 memset(&pritap->pcalls[i], 0, sizeof(pritap->pcalls[0]));
431 }
432 if (callref == pritap->pcalls[i].callref) {
433 pritap->pcalls[i].inuse = 1;
434
435 ftdm_mutex_unlock(pritap->pcalls_lock);
436
437 return &pritap->pcalls[i];
438 }
439 }
440
441 ftdm_mutex_unlock(pritap->pcalls_lock);
442
443 return NULL;
444 }
445
446 static void tap_pri_put_pcall(pritap_t *pritap, void *callref)
447 {
448 int i;
449 int crv;
450 int tstcrv;
451
452 if (!callref) {
453 ftdm_log(FTDM_LOG_ERROR, "Cannot put pcall for null callref in span %s\n", pritap->span->name);
454 return;
455 }
456
457 ftdm_mutex_lock(pritap->pcalls_lock);
458
459 crv = tap_pri_get_crv(pritap->pri, callref);
460 for (i = 0; i < ftdm_array_len(pritap->pcalls); i++) {
461 if (!pritap->pcalls[i].callref) {
462 continue;
463 }
464 tstcrv = tap_pri_get_crv(pritap->pri, pritap->pcalls[i].callref);
465 if (tstcrv == crv) {
466 ftdm_log(FTDM_LOG_DEBUG, "releasing slot %d in span %s used by callref %d/%p\n", i,
467 pritap->span->name, crv, pritap->pcalls[i].callref);
468 if (!pritap->pcalls[i].inuse) {
469 ftdm_log(FTDM_LOG_ERROR, "slot %d in span %s used by callref %d/%p was released already?\n",
470 i, pritap->span->name, crv, pritap->pcalls[i].callref);
471 }
472 pritap->pcalls[i].inuse = 0;
473 }
474 }
475
476 ftdm_mutex_unlock(pritap->pcalls_lock);
477 }
478
479 static __inline__ ftdm_channel_t *tap_pri_get_fchan(pritap_t *pritap, passive_call_t *pcall, int channel)
480 {
481 ftdm_channel_t *fchan = NULL;
482 int chanpos = PRI_CHANNEL(channel);
483 if (!chanpos || chanpos > pritap->span->chan_count) {
484 ftdm_log(FTDM_LOG_CRIT, "Invalid pri tap channel %d requested in span %s\n", channel, pritap->span->name);
485 return NULL;
486 }
487
488 fchan = pritap->span->channels[PRI_CHANNEL(channel)];
489 if (ftdm_test_flag(fchan, FTDM_CHANNEL_INUSE)) {
490 ftdm_log(FTDM_LOG_ERROR, "Channel %d requested in span %s is already in use!\n", channel, pritap->span->name);
491 return NULL;
492 }
493
494 if (ftdm_channel_open_chan(fchan) != FTDM_SUCCESS) {
495 ftdm_log(FTDM_LOG_ERROR, "Could not open tap channel %d requested in span %s\n", channel, pritap->span->name);
496 return NULL;
497 }
498
499 memset(&fchan->caller_data, 0, sizeof(fchan->caller_data));
500
501 ftdm_set_string(fchan->caller_data.cid_num.digits, pcall->callingnum.digits);
502 if (!ftdm_strlen_zero(pcall->callingname)) {
503 ftdm_set_string(fchan->caller_data.cid_name, pcall->callingname);
504 } else {
505 ftdm_set_string(fchan->caller_data.cid_name, pcall->callingnum.digits);
506 }
507 ftdm_set_string(fchan->caller_data.ani.digits, pcall->callingani.digits);
508 ftdm_set_string(fchan->caller_data.dnis.digits, pcall->callednum.digits);
509
510 return fchan;
511 }
512
513 static void handle_pri_passive_event(pritap_t *pritap, pri_event *e)
514 {
515 passive_call_t *pcall = NULL;
516 passive_call_t *peerpcall = NULL;
517 ftdm_channel_t *fchan = NULL;
518 ftdm_channel_t *peerfchan = NULL;
519 int layer1, transcap = 0;
520 int crv = 0;
521 pritap_t *peertap = pritap->peerspan->signal_data;
522
523 switch (e->e) {
524
525 case PRI_EVENT_RING:
526
527
528 crv = tap_pri_get_crv(pritap->pri, e->ring.call);
529 ftdm_log(FTDM_LOG_DEBUG, "Ring on channel %s:%d:%d with callref %d\n",
530 pritap->span->name, PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), crv);
531 pcall = tap_pri_get_pcall_bycrv(pritap, crv);
532 if (pcall) {
533 ftdm_log(FTDM_LOG_WARNING, "There is a call with callref %d already, ignoring duplicated ring event\n", crv);
534 break;
535 }
536 pcall = tap_pri_get_pcall(pritap, NULL);
537 if (!pcall) {
538 ftdm_log(FTDM_LOG_ERROR, "Failed to get a free passive PRI call slot for callref %d, this is a bug!\n", crv);
539 break;
540 }
541 pcall->callref = e->ring.call;
542 ftdm_set_string(pcall->callingnum.digits, e->ring.callingnum);
543 ftdm_set_string(pcall->callingani.digits, e->ring.callingani);
544 ftdm_set_string(pcall->callednum.digits, e->ring.callednum);
545 ftdm_set_string(pcall->callingname, e->ring.callingname);
546 break;
547
548 case PRI_EVENT_PROGRESS:
549 crv = tap_pri_get_crv(pritap->pri, e->ring.call);
550 ftdm_log(FTDM_LOG_DEBUG, "Progress on channel %s:%d:%d with callref %d\n",
551 pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
552 break;
553
554 case PRI_EVENT_PROCEEDING:
555 crv = tap_pri_get_crv(pritap->pri, e->proceeding.call);
556
557
558 ftdm_log(FTDM_LOG_DEBUG, "Proceeding on channel %s:%d:%d with callref %d\n",
559 pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
560
561
562 if (!(pcall = tap_pri_get_pcall_bycrv(peertap, crv))) {
563 ftdm_log(FTDM_LOG_DEBUG,
564 "ignoring proceeding in channel %s:%d:%d for callref %d since we don't know about it",
565 pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
566 break;
567 }
568 if (pcall->proceeding) {
569 ftdm_log(FTDM_LOG_DEBUG, "Ignoring duplicated proceeding with callref %d\n", crv);
570 break;
571 }
572 peerpcall = tap_pri_get_pcall(pritap, NULL);
573 if (!peerpcall) {
574 ftdm_log(FTDM_LOG_ERROR, "Failed to get a free peer PRI passive call slot for callref %d in span %s, this is a bug!\n",
575 crv, pritap->span->name);
576 break;
577 }
578 peerpcall->callref = e->proceeding.call;
579
580
581 layer1 = pri_get_layer1(peertap->pri, pcall->callref);
582 transcap = pri_get_transcap(peertap->pri, pcall->callref);
583
584 if (PRI_LAYER_1_ULAW != layer1 && PRI_LAYER_1_ALAW != layer1) {
585 ftdm_log(FTDM_LOG_NOTICE, "Not monitoring callref %d with unsupported layer 1 format %d\n", crv, layer1);
586 break;
587 }
588
589 if (transcap != PRI_TRANS_CAP_SPEECH && transcap != PRI_TRANS_CAP_3_1K_AUDIO && transcap != PRI_TRANS_CAP_7K_AUDIO) {
590 ftdm_log(FTDM_LOG_NOTICE, "Not monitoring callref %d with unsupported capability %d\n", crv, transcap);
591 break;
592 }
593
594 fchan = tap_pri_get_fchan(pritap, pcall, e->proceeding.channel);
595 if (!fchan) {
596 ftdm_log(FTDM_LOG_ERROR, "Proceeding requested on odd/unavailable channel %s:%d:%d for callref %d\n",
597 pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
598 break;
599 }
600 pcall->fchan = fchan;
601
602 peerfchan = tap_pri_get_fchan(peertap, pcall, e->proceeding.channel);
603 if (!peerfchan) {
604 ftdm_log(FTDM_LOG_ERROR, "Proceeding requested on odd/unavailable channel %s:%d:%d for callref %d\n",
605 peertap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
606 break;
607 }
608 peerpcall->fchan = fchan;
609
610 fchan->call_data = peerfchan;
611 peerfchan->call_data = fchan;
612
613 ftdm_set_state_locked(fchan, FTDM_CHANNEL_STATE_RING);
614 break;
615
616 case PRI_EVENT_ANSWER:
617 crv = tap_pri_get_crv(pritap->pri, e->answer.call);
618 ftdm_log(FTDM_LOG_DEBUG, "Answer on channel %s:%d:%d with callref %d\n",
619 pritap->span->name, PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), crv);
620 if (!(pcall = tap_pri_get_pcall_bycrv(pritap, crv))) {
621 ftdm_log(FTDM_LOG_DEBUG,
622 "ignoring answer in channel %s:%d:%d for callref %d since we don't know about it",
623 pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
624 break;
625 }
626 ftdm_log_chan(pcall->fchan, FTDM_LOG_NOTICE, "Tapped call was answered in state %s\n", ftdm_channel_state2str(pcall->fchan->state));
627 break;
628
629 case PRI_EVENT_HANGUP_REQ:
630 crv = tap_pri_get_crv(pritap->pri, e->hangup.call);
631 ftdm_log(FTDM_LOG_DEBUG, "Hangup on channel %s:%d:%d with callref %d\n",
632 pritap->span->name, PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), crv);
633
634 if (!(pcall = tap_pri_get_pcall_bycrv(pritap, crv))) {
635 ftdm_log(FTDM_LOG_DEBUG,
636 "ignoring hangup in channel %s:%d:%d for callref %d since we don't know about it",
637 pritap->span->name, PRI_SPAN(e->proceeding.channel), PRI_CHANNEL(e->proceeding.channel), crv);
638 break;
639 }
640
641 fchan = pcall->fchan;
642 ftdm_set_state_locked(fchan, FTDM_CHANNEL_STATE_TERMINATING);
643 break;
644
645 case PRI_EVENT_HANGUP_ACK:
646 crv = tap_pri_get_crv(pritap->pri, e->hangup.call);
647 ftdm_log(FTDM_LOG_DEBUG, "Hangup ack on channel %s:%d:%d with callref %d\n",
648 pritap->span->name, PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), crv);
649 tap_pri_put_pcall(pritap, e->hangup.call);
650 tap_pri_put_pcall(peertap, e->hangup.call);
651 break;
652
653 default:
654 ftdm_log(FTDM_LOG_DEBUG, "Ignoring passive event %s on span %s\n", pri_event2str(e->gen.e), pritap->span->name);
655 break;
656
657 }
658 }
659
660 static void *ftdm_pritap_run(ftdm_thread_t *me, void *obj)
661 {
662 ftdm_span_t *span = (ftdm_span_t *) obj;
663 pritap_t *pritap = span->signal_data;
664 pri_event *event = NULL;
665 struct pollfd dpoll = { 0, 0, 0 };
666 int rc = 0;
667
668 ftdm_log(FTDM_LOG_DEBUG, "Tapping PRI thread started on span %d\n", span->span_id);
669
670 pritap->span = span;
671
672 ftdm_set_flag(span, FTDM_SPAN_IN_THREAD);
673
674 if (ftdm_channel_open(span->span_id, pritap->dchan->chan_id, &pritap->dchan) != FTDM_SUCCESS) {
675 ftdm_log(FTDM_LOG_ERROR, "Failed to open D-channel for span %s\n", span->name);
676 goto done;
677 }
678
679 if ((pritap->pri = pri_new_cb(pritap->dchan->sockfd, PRI_NETWORK, PRI_SWITCH_NI2, pri_io_read, pri_io_write, pritap))){
680 pri_set_debug(pritap->pri, pritap->debug);
681 } else {
682 ftdm_log(FTDM_LOG_CRIT, "Failed to create tapping PRI\n");
683 goto done;
684 }
685
686 dpoll.fd = pritap->dchan->sockfd;
687
688 while (ftdm_running() && !ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD)) {
689
690
691 pritap_check_state(span);
692
693 dpoll.revents = 0;
694 dpoll.events = POLLIN;
695
696 rc = poll(&dpoll, 1, 10);
697
698 if (rc < 0) {
699 if (errno == EINTR) {
700 ftdm_log(FTDM_LOG_DEBUG, "D-channel waiting interrupted, continuing ...\n");
701 continue;
702 }
703 ftdm_log(FTDM_LOG_ERROR, "poll failed: %s\n", strerror(errno));
704 continue;
705 }
706
707 pri_schedule_run(pritap->pri);
708
709 if (rc) {
710 if (dpoll.revents & POLLIN) {
711 event = pri_read_event(pritap->pri);
712 if (event) {
713 handle_pri_passive_event(pritap, event);
714 }
715 } else {
716 ftdm_log(FTDM_LOG_WARNING, "nothing to read?\n");
717 }
718 }
719
720 pritap_check_state(span);
721 }
722
723 done:
724 ftdm_log(FTDM_LOG_DEBUG, "Tapping PRI thread ended on span %d\n", span->span_id);
725
726 ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
727 ftdm_clear_flag(pritap, PRITAP_RUNNING);
728
729 return NULL;
730 }
731
732 static ftdm_status_t ftdm_pritap_stop(ftdm_span_t *span)
733 {
734 pritap_t *pritap = span->signal_data;
735
736 if (!ftdm_test_flag(pritap, PRITAP_RUNNING)) {
737 return FTDM_FAIL;
738 }
739
740 ftdm_set_flag(span, FTDM_SPAN_STOP_THREAD);
741
742 while (ftdm_test_flag(span, FTDM_SPAN_IN_THREAD)) {
743 ftdm_sleep(100);
744 }
745
746 ftdm_mutex_destroy(&pritap->pcalls_lock);
747 return FTDM_SUCCESS;
748 }
749
750 static ftdm_status_t ftdm_pritap_sig_read(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t size)
751 {
752 ftdm_status_t status;
753 fio_codec_t codec_func;
754 ftdm_channel_t *peerchan = ftdmchan->call_data;
755 int16_t chanbuf[size];
756 int16_t peerbuf[size];
757 int16_t mixedbuf[size];
758 int i = 0;
759 ftdm_size_t sizeread = size;
760
761 if (!FTDM_IS_VOICE_CHANNEL(ftdmchan) || !ftdmchan->call_data) {
762 return FTDM_SUCCESS;
763 }
764
765 if (ftdmchan->native_codec != peerchan->native_codec) {
766 ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Invalid peer channel with format %d, ours = %d\n",
767 peerchan->native_codec, ftdmchan->native_codec);
768 return FTDM_FAIL;
769 }
770
771 memcpy(chanbuf, data, size);
772 status = peerchan->fio->read(peerchan, peerbuf, &sizeread);
773 if (status != FTDM_SUCCESS) {
774 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to read from peer channel!\n");
775 return FTDM_FAIL;
776 }
777 if (sizeread != size) {
778 ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "read from peer channel only %d bytes!\n", sizeread);
779 return FTDM_FAIL;
780 }
781
782 codec_func = peerchan->native_codec == FTDM_CODEC_ULAW ? fio_ulaw2slin : peerchan->native_codec == FTDM_CODEC_ALAW ? fio_alaw2slin : NULL;
783 if (codec_func) {
784 sizeread = size;
785 codec_func(chanbuf, sizeof(chanbuf), &sizeread);
786 sizeread = size;
787 codec_func(peerbuf, sizeof(peerbuf), &sizeread);
788 }
789
790 for (i = 0; i < size; i++) {
791 mixedbuf[i] = ftdm_saturated_add(chanbuf[i], peerbuf[i]);
792 }
793
794 codec_func = peerchan->native_codec == FTDM_CODEC_ULAW ? fio_slin2ulaw : peerchan->native_codec == FTDM_CODEC_ALAW ? fio_slin2alaw : NULL;
795 if (codec_func) {
796 size = sizeof(mixedbuf);
797 codec_func(mixedbuf, size, &size);
798 }
799 memcpy(data, mixedbuf, size);
800 return FTDM_SUCCESS;
801 }
802
803 static ftdm_status_t ftdm_pritap_start(ftdm_span_t *span)
804 {
805 ftdm_status_t ret;
806 pritap_t *pritap = span->signal_data;
807
808 if (ftdm_test_flag(pritap, PRITAP_RUNNING)) {
809 return FTDM_FAIL;
810 }
811
812 ftdm_mutex_create(&pritap->pcalls_lock);
813
814 ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD);
815 ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
816
817 ftdm_set_flag(pritap, PRITAP_RUNNING);
818 ret = ftdm_thread_create_detached(ftdm_pritap_run, span);
819
820 if (ret != FTDM_SUCCESS) {
821 return ret;
822 }
823
824 return ret;
825 }
826
827 static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_pritap_configure_span)
828 {
829 uint32_t i;
830 const char *var, *val;
831 const char *debug = NULL;
832 ftdm_channel_t *dchan = NULL;
833 pritap_t *pritap = NULL;
834 ftdm_span_t *peerspan = NULL;
835 unsigned paramindex = 0;
836
837 if (span->trunk_type >= FTDM_TRUNK_NONE) {
838 ftdm_log(FTDM_LOG_WARNING, "Invalid trunk type '%s' defaulting to T1.\n", ftdm_trunk_type2str(span->trunk_type));
839 span->trunk_type = FTDM_TRUNK_T1;
840 }
841
842 for (i = 1; i <= span->chan_count; i++) {
843 if (span->channels[i]->type == FTDM_CHAN_TYPE_DQ921) {
844 dchan = span->channels[i];
845 }
846 }
847
848 if (!dchan) {
849 ftdm_log(FTDM_LOG_ERROR, "No d-channel specified in freetdm.conf!\n", ftdm_trunk_type2str(span->trunk_type));
850 return FTDM_FAIL;
851 }
852
853 for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) {
854 var = ftdm_parameters[paramindex].var;
855 val = ftdm_parameters[paramindex].val;
856 ftdm_log(FTDM_LOG_DEBUG, "Tapping PRI key=value, %s=%s\n", var, val);
857
858 if (!strcasecmp(var, "debug")) {
859 debug = val;
860 } else if (!strcasecmp(var, "peerspan")) {
861 if (ftdm_span_find_by_name(val, &peerspan) != FTDM_SUCCESS) {
862 ftdm_log(FTDM_LOG_ERROR, "Invalid tapping peer span %s\n", val);
863 break;
864 }
865 } else {
866 ftdm_log(FTDM_LOG_ERROR, "Unknown pri tapping parameter [%s]", var);
867 }
868 }
869
870 if (!peerspan) {
871 ftdm_log(FTDM_LOG_ERROR, "No valid peerspan was specified!\n");
872 return FTDM_FAIL;
873 }
874
875 pritap = ftdm_calloc(1, sizeof(*pritap));
876 if (!pritap) {
877 return FTDM_FAIL;
878 }
879
880 pritap->debug = parse_debug(debug);
881 pritap->dchan = dchan;
882 pritap->peerspan = peerspan;
883
884 span->start = ftdm_pritap_start;
885 span->stop = ftdm_pritap_stop;
886 span->sig_read = ftdm_pritap_sig_read;
887 span->signal_cb = sig_cb;
888
889 span->signal_data = pritap;
890 span->signal_type = FTDM_SIGTYPE_ISDN;
891 span->outgoing_call = pritap_outgoing_call;
892
893 span->get_channel_sig_status = pritap_get_channel_sig_status;
894 span->get_span_sig_status = pritap_get_span_sig_status;
895
896 span->state_map = &pritap_state_map;
897 span->state_processor = state_advance;
898
899 return FTDM_SUCCESS;
900 }
901
902
903
904
905 ftdm_module_t ftdm_module = {
906 "pritap",
907 ftdm_pritap_io_init,
908 ftdm_pritap_unload,
909 ftdm_pritap_init,
910 NULL,
911 NULL,
912 ftdm_pritap_configure_span,
913 };
914
915
916
917
918
919
920
921
922
923
924
925