This source file includes following definitions.
- ftdm_channel_get_session
- ftdm_channel_get_uuid
- stop_hold
- start_hold
- cycle_foreground
- tech_init
- channel_on_init
- channel_on_routing
- channel_on_execute
- channel_on_destroy
- channel_on_hangup
- channel_kill_channel
- channel_on_exchange_media
- channel_on_soft_execute
- channel_send_dtmf
- channel_read_frame
- channel_write_frame
- channel_receive_message_cas
- channel_receive_message_b
- channel_receive_message_fxo
- channel_receive_message_fxs
- channel_receive_message
- channel_get_variable
- on_channel_found
- channel_outgoing_channel
- ftdm_enable_channel_dtmf
- ftdm_channel_from_event
- FIO_SIGNAL_CB_FUNCTION
- FIO_SIGNAL_CB_FUNCTION
- FIO_SIGNAL_CB_FUNCTION
- FIO_SIGNAL_CB_FUNCTION
- FIO_SIGNAL_CB_FUNCTION
- FIO_SIGNAL_CB_FUNCTION
- ftdm_logger
- enable_analog_option
- add_config_list_nodes
- get_ss7_config_node
- add_profile_parameters
- parse_bri_pri_spans
- load_config
- dump_chan
- dump_chan_xml
- SWITCH_STANDARD_API
- SWITCH_STANDARD_APP
- SWITCH_STANDARD_APP
- SWITCH_STANDARD_APP
- SWITCH_MODULE_LOAD_FUNCTION
- SWITCH_MODULE_SHUTDOWN_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 <switch.h>
35 #include "freetdm.h"
36
37 #ifndef __FUNCTION__
38 #define __FUNCTION__ __SWITCH_FUNC__
39 #endif
40
41 #define FREETDM_LIMIT_REALM "__freetdm"
42 #define FREETDM_VAR_PREFIX "freetdm_"
43 #define FREETDM_VAR_PREFIX_LEN (sizeof(FREETDM_VAR_PREFIX)-1)
44
45 SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load);
46 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_freetdm_shutdown);
47 SWITCH_MODULE_DEFINITION(mod_freetdm, mod_freetdm_load, mod_freetdm_shutdown, NULL);
48
49 switch_endpoint_interface_t *freetdm_endpoint_interface;
50
51 static switch_memory_pool_t *module_pool = NULL;
52
53 typedef enum {
54 ANALOG_OPTION_NONE = 0,
55 ANALOG_OPTION_3WAY = (1 << 0),
56 ANALOG_OPTION_CALL_SWAP = (1 << 1)
57 } analog_option_t;
58
59 typedef enum {
60 FTDM_LIMIT_RESET_ON_TIMEOUT = 0,
61 FTDM_LIMIT_RESET_ON_ANSWER = 1
62 } limit_reset_event_t;
63
64 typedef enum {
65 TFLAG_IO = (1 << 0),
66 TFLAG_DTMF = (1 << 1),
67 TFLAG_CODEC = (1 << 2),
68 TFLAG_BREAK = (1 << 3),
69 TFLAG_HOLD = (1 << 4),
70 TFLAG_DEAD = (1 << 5)
71 } TFLAGS;
72
73 static struct {
74 int debug;
75 char *dialplan;
76 char *codec_string;
77 char *codec_order[SWITCH_MAX_CODECS];
78 int codec_order_last;
79 char *codec_rates_string;
80 char *codec_rates[SWITCH_MAX_CODECS];
81 int codec_rates_last;
82 unsigned int flags;
83 int fd;
84 int calls;
85 char hold_music[256];
86 switch_mutex_t *mutex;
87 analog_option_t analog_options;
88 switch_hash_t *ss7_configs;
89 int sip_headers;
90 uint8_t crash_on_assert;
91 } globals;
92
93
94 struct private_object {
95 unsigned int flags;
96 switch_codec_t read_codec;
97 switch_codec_t write_codec;
98 switch_frame_t read_frame;
99 unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
100 switch_frame_t cng_frame;
101 unsigned char cng_databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
102 switch_core_session_t *session;
103 switch_caller_profile_t *caller_profile;
104 unsigned int codec;
105 unsigned int codecs;
106 unsigned short samprate;
107 switch_mutex_t *mutex;
108 switch_mutex_t *flag_mutex;
109 ftdm_channel_t *ftdmchan;
110 uint32_t wr_error;
111 };
112
113
114 typedef struct chan_pvt {
115 unsigned int flags;
116 } chan_pvt_t;
117
118 typedef struct private_object private_t;
119
120 struct span_config {
121 ftdm_span_t *span;
122 char dialplan[80];
123 char context[80];
124 char dial_regex[256];
125 char fail_dial_regex[256];
126 char hold_music[256];
127 char type[256];
128 analog_option_t analog_options;
129 const char *limit_backend;
130 int limit_calls;
131 int limit_seconds;
132 limit_reset_event_t limit_reset_event;
133 chan_pvt_t pvts[FTDM_MAX_CHANNELS_SPAN];
134 };
135
136 static struct span_config SPAN_CONFIG[FTDM_MAX_SPANS_INTERFACE] = {{0}};
137
138 static switch_status_t channel_on_init(switch_core_session_t *session);
139 static switch_status_t channel_on_hangup(switch_core_session_t *session);
140 static switch_status_t channel_on_destroy(switch_core_session_t *session);
141 static switch_status_t channel_on_routing(switch_core_session_t *session);
142 static switch_status_t channel_on_exchange_media(switch_core_session_t *session);
143 static switch_status_t channel_on_soft_execute(switch_core_session_t *session);
144 static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
145 switch_caller_profile_t *outbound_profile,
146 switch_core_session_t **new_session,
147 switch_memory_pool_t **pool,
148 switch_originate_flag_t flags, switch_call_cause_t *cancel_cause);
149 static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
150 static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
151 static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
152 static const char* channel_get_variable(switch_core_session_t *session, switch_event_t *var_event, const char *variable_name);
153 ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session_t **sp);
154 void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream);
155 void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream);
156
157 static switch_core_session_t *ftdm_channel_get_session(ftdm_channel_t *channel, int32_t id)
158 {
159 switch_core_session_t *session = NULL;
160 const char *token = ftdm_channel_get_token(channel, id);
161
162 if (!zstr(token)) {
163 if (!(session = switch_core_session_locate(token))) {
164 ftdm_channel_clear_token(channel, token);
165 }
166 }
167
168 return session;
169 }
170
171 static const char *ftdm_channel_get_uuid(ftdm_channel_t *channel, int32_t id)
172 {
173 return ftdm_channel_get_token(channel, id);
174 }
175
176 static void stop_hold(switch_core_session_t *session_a, const char *uuid)
177 {
178 switch_core_session_t *session;
179 switch_channel_t *channel, *channel_a;
180 ;
181
182 if (!uuid) {
183 return;
184 }
185
186 if ((session = switch_core_session_locate(uuid))) {
187 channel = switch_core_session_get_channel(session);
188
189 if (switch_channel_test_flag(channel, CF_HOLD)) {
190 channel_a = switch_core_session_get_channel(session_a);
191 switch_ivr_unhold(session);
192 switch_channel_clear_flag(channel_a, CF_SUSPEND);
193 switch_channel_clear_flag(channel_a, CF_HOLD);
194 } else {
195 switch_channel_stop_broadcast(channel);
196 switch_channel_wait_for_flag(channel, CF_BROADCAST, SWITCH_FALSE, 2000, NULL);
197 }
198
199 switch_core_session_rwunlock(session);
200 }
201 }
202
203 static void start_hold(ftdm_channel_t *ftdmchan, switch_core_session_t *session_a, const char *uuid, const char *stream)
204 {
205 switch_core_session_t *session;
206 switch_channel_t *channel, *channel_a;
207 int32_t spanid = 0;
208
209 if (!uuid) {
210 return;
211 }
212
213 spanid = ftdm_channel_get_span_id(ftdmchan);
214 if ((session = switch_core_session_locate(uuid))) {
215 channel = switch_core_session_get_channel(session);
216 if (zstr(stream)) {
217 if (!strcasecmp(globals.hold_music, "indicate_hold")) {
218 stream = "indicate_hold";
219 }
220 if (!strcasecmp(SPAN_CONFIG[spanid].hold_music, "indicate_hold")) {
221 stream = "indicate_hold";
222 }
223 }
224
225 if (zstr(stream)) {
226 stream = switch_channel_get_variable(channel, SWITCH_HOLD_MUSIC_VARIABLE);
227 }
228
229 if (zstr(stream)) {
230 stream = SPAN_CONFIG[spanid].hold_music;
231 }
232
233 if (zstr(stream)) {
234 stream = globals.hold_music;
235 }
236
237
238 if (zstr(stream) && !(stream = switch_channel_get_variable(channel, SWITCH_HOLD_MUSIC_VARIABLE))) {
239 stream = globals.hold_music;
240 }
241
242 if (!zstr(stream)) {
243 if (!strcasecmp(stream, "indicate_hold")) {
244 channel_a = switch_core_session_get_channel(session_a);
245 switch_ivr_hold_uuid(uuid, NULL, 0);
246 switch_channel_set_flag(channel_a, CF_SUSPEND);
247 switch_channel_set_flag(channel_a, CF_HOLD);
248 } else {
249 switch_ivr_broadcast(switch_core_session_get_uuid(session), stream, SMF_ECHO_ALEG | SMF_LOOP);
250 }
251 }
252
253 switch_core_session_rwunlock(session);
254 }
255 }
256
257
258 static void cycle_foreground(ftdm_channel_t *ftdmchan, int flash, const char *bcast) {
259 uint32_t i = 0;
260 switch_core_session_t *session;
261 switch_channel_t *channel;
262 private_t *tech_pvt;
263 uint32_t tokencnt = ftdm_channel_get_token_count(ftdmchan);
264
265
266 for (i = 0; i < tokencnt; i++) {
267 if ((session = ftdm_channel_get_session(ftdmchan, i))) {
268 const char *buuid;
269 tech_pvt = switch_core_session_get_private(session);
270 channel = switch_core_session_get_channel(session);
271 buuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE);
272
273
274 if (tokencnt == 1 && flash) {
275 if (switch_test_flag(tech_pvt, TFLAG_HOLD)) {
276 stop_hold(session, buuid);
277 switch_clear_flag_locked(tech_pvt, TFLAG_HOLD);
278 } else {
279 start_hold(ftdmchan, session, buuid, bcast);
280 switch_set_flag_locked(tech_pvt, TFLAG_HOLD);
281 }
282 } else if (i) {
283 start_hold(ftdmchan, session, buuid, bcast);
284 switch_set_flag_locked(tech_pvt, TFLAG_HOLD);
285 } else {
286 stop_hold(session, buuid);
287 switch_clear_flag_locked(tech_pvt, TFLAG_HOLD);
288 if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
289 switch_channel_mark_answered(channel);
290 }
291 }
292 switch_core_session_rwunlock(session);
293 }
294 }
295 }
296
297
298
299
300 static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *session, ftdm_channel_t *ftdmchan)
301 {
302 const char *dname = NULL;
303 uint32_t interval = 0, srate = 8000;
304 ftdm_codec_t codec;
305
306 tech_pvt->ftdmchan = ftdmchan;
307 tech_pvt->read_frame.data = tech_pvt->databuf;
308 tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf);
309 tech_pvt->cng_frame.data = tech_pvt->cng_databuf;
310 tech_pvt->cng_frame.buflen = sizeof(tech_pvt->cng_databuf);
311 tech_pvt->cng_frame.flags = SFF_CNG;
312 tech_pvt->cng_frame.codec = &tech_pvt->read_codec;
313 memset(tech_pvt->cng_frame.data, 255, tech_pvt->cng_frame.buflen);
314 switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
315 switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
316 switch_core_session_set_private(session, tech_pvt);
317 tech_pvt->session = session;
318
319 if (FTDM_SUCCESS != ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_INTERVAL, &interval)) {
320 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to retrieve channel interval.\n");
321 return SWITCH_STATUS_GENERR;
322 }
323
324 if (FTDM_SUCCESS != ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_CODEC, &codec)) {
325 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to retrieve channel codec.\n");
326 return SWITCH_STATUS_GENERR;
327 }
328
329 switch(codec) {
330 case FTDM_CODEC_ULAW:
331 {
332 dname = "PCMU";
333 }
334 break;
335 case FTDM_CODEC_ALAW:
336 {
337 dname = "PCMA";
338 }
339 break;
340 case FTDM_CODEC_SLIN:
341 {
342 dname = "L16";
343 }
344 break;
345 default:
346 {
347 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid codec value retrieved from channel, codec value: %d\n", codec);
348 return SWITCH_STATUS_GENERR;
349 }
350 }
351
352
353 if (switch_core_codec_init(&tech_pvt->read_codec,
354 dname,
355 NULL,
356 srate,
357 interval,
358 1,
359 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
360 NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
361 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
362 return SWITCH_STATUS_GENERR;
363 } else {
364 if (switch_core_codec_init(&tech_pvt->write_codec,
365 dname,
366 NULL,
367 srate,
368 interval,
369 1,
370 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
371 NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
372 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
373 switch_core_codec_destroy(&tech_pvt->read_codec);
374 return SWITCH_STATUS_GENERR;
375 }
376 }
377
378 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set codec %s %dms\n", dname, interval);
379 switch_core_session_set_read_codec(tech_pvt->session, &tech_pvt->read_codec);
380 switch_core_session_set_write_codec(tech_pvt->session, &tech_pvt->write_codec);
381 switch_set_flag_locked(tech_pvt, TFLAG_CODEC);
382 tech_pvt->read_frame.codec = &tech_pvt->read_codec;
383 switch_set_flag_locked(tech_pvt, TFLAG_IO);
384
385 return SWITCH_STATUS_SUCCESS;
386
387 }
388
389 static switch_status_t channel_on_init(switch_core_session_t *session)
390 {
391 switch_channel_t *channel;
392 private_t *tech_pvt = NULL;
393
394 tech_pvt = switch_core_session_get_private(session);
395 assert(tech_pvt != NULL);
396
397 channel = switch_core_session_get_channel(session);
398 assert(channel != NULL);
399
400 if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
401 switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE);
402 return SWITCH_STATUS_SUCCESS;
403 }
404
405
406 switch_channel_set_state(channel, CS_ROUTING);
407 switch_mutex_lock(globals.mutex);
408 globals.calls++;
409 switch_mutex_unlock(globals.mutex);
410
411 ftdm_channel_init(tech_pvt->ftdmchan);
412
413
414
415 return SWITCH_STATUS_SUCCESS;
416 }
417
418 static switch_status_t channel_on_routing(switch_core_session_t *session)
419 {
420 switch_channel_t *channel = NULL;
421 private_t *tech_pvt = NULL;
422
423 channel = switch_core_session_get_channel(session);
424 switch_assert(channel != NULL);
425
426 tech_pvt = switch_core_session_get_private(session);
427 switch_assert(tech_pvt != NULL);
428
429 switch_assert(tech_pvt->ftdmchan != NULL);
430
431 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel));
432
433 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
434 ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROCEED);
435 }
436 return SWITCH_STATUS_SUCCESS;
437 }
438
439 static switch_status_t channel_on_execute(switch_core_session_t *session)
440 {
441
442 switch_channel_t *channel = NULL;
443 private_t *tech_pvt = NULL;
444
445 channel = switch_core_session_get_channel(session);
446 switch_assert(channel != NULL);
447
448 tech_pvt = switch_core_session_get_private(session);
449 switch_assert(tech_pvt != NULL);
450
451 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL EXECUTE\n", switch_channel_get_name(channel));
452
453
454 return SWITCH_STATUS_SUCCESS;
455 }
456
457 static switch_status_t channel_on_destroy(switch_core_session_t *session)
458 {
459 private_t *tech_pvt = NULL;
460
461 if ((tech_pvt = switch_core_session_get_private(session))) {
462
463 if (tech_pvt->read_codec.implementation) {
464 switch_core_codec_destroy(&tech_pvt->read_codec);
465 }
466
467 if (tech_pvt->write_codec.implementation) {
468 switch_core_codec_destroy(&tech_pvt->write_codec);
469 }
470 }
471
472 return SWITCH_STATUS_SUCCESS;
473 }
474
475 static switch_status_t channel_on_hangup(switch_core_session_t *session)
476 {
477 switch_channel_t *channel = NULL;
478 private_t *tech_pvt = NULL;
479 ftdm_chan_type_t chantype;
480 uint32_t tokencnt;
481
482 channel = switch_core_session_get_channel(session);
483 assert(channel != NULL);
484
485 tech_pvt = switch_core_session_get_private(session);
486 assert(tech_pvt != NULL);
487
488 if (!tech_pvt->ftdmchan) {
489 goto end;
490 }
491
492 ftdm_channel_clear_token(tech_pvt->ftdmchan, switch_core_session_get_uuid(session));
493
494 chantype = ftdm_channel_get_type(tech_pvt->ftdmchan);
495 switch (chantype) {
496 case FTDM_CHAN_TYPE_FXO:
497 case FTDM_CHAN_TYPE_EM:
498 case FTDM_CHAN_TYPE_CAS:
499 {
500 ftdm_channel_call_hangup(tech_pvt->ftdmchan);
501 }
502 break;
503 case FTDM_CHAN_TYPE_FXS:
504 {
505 if (!ftdm_channel_call_check_busy(tech_pvt->ftdmchan) && !ftdm_channel_call_check_done(tech_pvt->ftdmchan)) {
506 tokencnt = ftdm_channel_get_token_count(tech_pvt->ftdmchan);
507 if (tokencnt) {
508 cycle_foreground(tech_pvt->ftdmchan, 0, NULL);
509 } else {
510 ftdm_channel_call_hangup(tech_pvt->ftdmchan);
511 }
512 }
513 }
514 break;
515 case FTDM_CHAN_TYPE_B:
516 {
517 ftdm_call_cause_t hcause = switch_channel_get_cause_q850(channel);
518 if (hcause < 1 || hcause > 127) {
519 hcause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;
520 }
521 ftdm_channel_call_hangup_with_cause(tech_pvt->ftdmchan, hcause);
522 }
523 break;
524 default:
525 {
526 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unhandled channel type %d for channel %s\n", chantype,
527 switch_channel_get_name(channel));
528 }
529 break;
530 }
531
532 end:
533
534 switch_clear_flag_locked(tech_pvt, TFLAG_IO);
535
536 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel));
537 switch_mutex_lock(globals.mutex);
538 globals.calls--;
539 if (globals.calls < 0) {
540 globals.calls = 0;
541 }
542 switch_mutex_unlock(globals.mutex);
543
544 return SWITCH_STATUS_SUCCESS;
545 }
546
547 static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig)
548 {
549 switch_channel_t *channel = NULL;
550 private_t *tech_pvt = NULL;
551
552 channel = switch_core_session_get_channel(session);
553 assert(channel != NULL);
554
555 tech_pvt = switch_core_session_get_private(session);
556 assert(tech_pvt != NULL);
557
558 switch (sig) {
559 case SWITCH_SIG_KILL:
560 switch_clear_flag_locked(tech_pvt, TFLAG_IO);
561 switch_set_flag_locked(tech_pvt, TFLAG_DEAD);
562 break;
563 case SWITCH_SIG_BREAK:
564 switch_set_flag_locked(tech_pvt, TFLAG_BREAK);
565 break;
566 default:
567 break;
568 }
569
570 return SWITCH_STATUS_SUCCESS;
571 }
572
573 static switch_status_t channel_on_exchange_media(switch_core_session_t *session)
574 {
575 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL EXCHANGE_MEDIA\n");
576 return SWITCH_STATUS_SUCCESS;
577 }
578
579 static switch_status_t channel_on_soft_execute(switch_core_session_t *session)
580 {
581 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHANNEL SOFT_EXECUTE\n");
582 return SWITCH_STATUS_SUCCESS;
583 }
584
585 static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
586 {
587 private_t *tech_pvt = NULL;
588 char tmp[2] = "";
589
590 tech_pvt = switch_core_session_get_private(session);
591 assert(tech_pvt != NULL);
592
593 if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
594 switch_channel_hangup(switch_core_session_get_channel(session), SWITCH_CAUSE_LOSE_RACE);
595 return SWITCH_STATUS_FALSE;
596 }
597
598 tmp[0] = dtmf->digit;
599 ftdm_channel_command(tech_pvt->ftdmchan, FTDM_COMMAND_SEND_DTMF, tmp);
600
601 return SWITCH_STATUS_SUCCESS;
602 }
603
604 static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
605 {
606 switch_channel_t *channel = NULL;
607 private_t *tech_pvt = NULL;
608 ftdm_size_t len;
609 ftdm_wait_flag_t wflags = FTDM_READ;
610 char dtmf[128] = "";
611 ftdm_status_t status;
612 int total_to;
613 int chunk, do_break = 0;
614
615
616 channel = switch_core_session_get_channel(session);
617 assert(channel != NULL);
618
619
620 tech_pvt = switch_core_session_get_private(session);
621 assert(tech_pvt != NULL);
622
623 if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
624 ftdm_log(FTDM_LOG_DEBUG, "TFLAG_DEAD is set\n");
625 return SWITCH_STATUS_FALSE;
626 }
627
628
629
630
631 chunk = ftdm_channel_get_io_interval(tech_pvt->ftdmchan) * 2;
632 total_to = chunk * 6;
633
634 top:
635
636 if (switch_channel_test_flag(channel, CF_SUSPEND)) {
637 do_break = 1;
638 }
639
640 if (switch_test_flag(tech_pvt, TFLAG_BREAK)) {
641 switch_clear_flag_locked(tech_pvt, TFLAG_BREAK);
642 do_break = 1;
643 }
644
645 if (switch_test_flag(tech_pvt, TFLAG_HOLD) || do_break) {
646 switch_yield(ftdm_channel_get_io_interval(tech_pvt->ftdmchan) * 1000);
647 tech_pvt->cng_frame.datalen = ftdm_channel_get_io_packet_len(tech_pvt->ftdmchan);
648 tech_pvt->cng_frame.samples = tech_pvt->cng_frame.datalen;
649 tech_pvt->cng_frame.flags = SFF_CNG;
650 *frame = &tech_pvt->cng_frame;
651 if (ftdm_channel_get_codec(tech_pvt->ftdmchan) == FTDM_CODEC_SLIN) {
652 tech_pvt->cng_frame.samples /= 2;
653 }
654 return SWITCH_STATUS_SUCCESS;
655 }
656
657 if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
658 ftdm_log(FTDM_LOG_DEBUG, "TFLAG_IO is not set\n");
659 goto fail;
660 }
661
662 wflags = FTDM_READ;
663 status = ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, chunk);
664
665 if (status == FTDM_FAIL) {
666 ftdm_log(FTDM_LOG_ERROR, "Failed to wait for I/O\n");
667 goto fail;
668 }
669
670 if (status == FTDM_TIMEOUT) {
671 if (!switch_test_flag(tech_pvt, TFLAG_HOLD)) {
672 total_to -= chunk;
673 if (total_to <= 0) {
674 ftdm_log(FTDM_LOG_WARNING, "Too many timeouts while waiting for I/O\n");
675 goto fail;
676 }
677 }
678 goto top;
679 }
680
681 if (!(wflags & FTDM_READ)) {
682 goto top;
683 }
684
685 len = tech_pvt->read_frame.buflen;
686 if (ftdm_channel_read(tech_pvt->ftdmchan, tech_pvt->read_frame.data, &len) != FTDM_SUCCESS) {
687 ftdm_log(FTDM_LOG_WARNING, "failed to read from device\n");
688 goto fail;
689 }
690
691 *frame = &tech_pvt->read_frame;
692 tech_pvt->read_frame.datalen = (uint32_t)len;
693 tech_pvt->read_frame.samples = tech_pvt->read_frame.datalen;
694
695 if (ftdm_channel_get_codec(tech_pvt->ftdmchan) == FTDM_CODEC_SLIN) {
696 tech_pvt->read_frame.samples /= 2;
697 }
698
699 while (ftdm_channel_dequeue_dtmf(tech_pvt->ftdmchan, dtmf, sizeof(dtmf))) {
700 switch_dtmf_t _dtmf = { 0, SWITCH_DEFAULT_DTMF_DURATION };
701 char *p;
702 for (p = dtmf; p && *p; p++) {
703 if (is_dtmf(*p)) {
704 _dtmf.digit = *p;
705 ftdm_log(FTDM_LOG_DEBUG, "Queuing DTMF [%c] in channel %s\n", *p, switch_channel_get_name(channel));
706 switch_channel_queue_dtmf(channel, &_dtmf);
707 }
708 }
709 }
710 return SWITCH_STATUS_SUCCESS;
711
712 fail:
713 switch_clear_flag_locked(tech_pvt, TFLAG_IO);
714 return SWITCH_STATUS_GENERR;
715
716
717 }
718
719 static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
720 {
721 switch_channel_t *channel = NULL;
722 private_t *tech_pvt = NULL;
723 ftdm_size_t len;
724 unsigned char data[SWITCH_RECOMMENDED_BUFFER_SIZE] = {0};
725 ftdm_wait_flag_t wflags = FTDM_WRITE;
726 ftdm_status_t status;
727
728 channel = switch_core_session_get_channel(session);
729 assert(channel != NULL);
730
731 tech_pvt = switch_core_session_get_private(session);
732 assert(tech_pvt != NULL);
733
734 if (!tech_pvt->ftdmchan) {
735 return SWITCH_STATUS_FALSE;
736 }
737
738 if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
739 return SWITCH_STATUS_FALSE;
740 }
741
742 if (switch_test_flag(tech_pvt, TFLAG_HOLD)) {
743 return SWITCH_STATUS_SUCCESS;
744 }
745
746 if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
747 goto fail;
748 }
749
750 if (switch_test_flag(frame, SFF_CNG)) {
751 frame->data = data;
752 frame->buflen = sizeof(data);
753 if ((frame->datalen = tech_pvt->write_codec.implementation->encoded_bytes_per_packet) > frame->buflen) {
754 goto fail;
755 }
756 memset(data, 255, frame->datalen);
757 }
758
759
760 wflags = FTDM_WRITE;
761 status = ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, ftdm_channel_get_io_interval(tech_pvt->ftdmchan) * 10);
762
763 if (!(wflags & FTDM_WRITE)) {
764 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Dropping frame! (write not ready)\n");
765 return SWITCH_STATUS_SUCCESS;
766 }
767
768 len = frame->datalen;
769 if (ftdm_channel_write(tech_pvt->ftdmchan, frame->data, frame->buflen, &len) != FTDM_SUCCESS) {
770 if (++tech_pvt->wr_error > 10) {
771 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "too many I/O write errors!\n");
772 goto fail;
773 }
774 } else {
775 tech_pvt->wr_error = 0;
776 }
777
778 return SWITCH_STATUS_SUCCESS;
779
780 fail:
781
782 switch_clear_flag_locked(tech_pvt, TFLAG_IO);
783 return SWITCH_STATUS_GENERR;
784
785 }
786
787 static switch_status_t channel_receive_message_cas(switch_core_session_t *session, switch_core_session_message_t *msg)
788 {
789 switch_channel_t *channel;
790 private_t *tech_pvt;
791 uint32_t phy_id;
792
793 channel = switch_core_session_get_channel(session);
794 assert(channel != NULL);
795
796 tech_pvt = (private_t *) switch_core_session_get_private(session);
797 assert(tech_pvt != NULL);
798
799 if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
800 switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE);
801 return SWITCH_STATUS_FALSE;
802 }
803
804 phy_id = ftdm_channel_get_ph_id(tech_pvt->ftdmchan);
805 ftdm_log(FTDM_LOG_DEBUG, "Got Freeswitch message in R2 channel %d [%d]\n", phy_id, msg->message_id);
806
807 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
808 return SWITCH_STATUS_SUCCESS;
809 }
810
811 switch (msg->message_id) {
812 case SWITCH_MESSAGE_INDICATE_RINGING:
813 {
814 ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROGRESS);
815 }
816 break;
817 case SWITCH_MESSAGE_INDICATE_PROGRESS:
818 {
819 ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA);
820 }
821 break;
822 case SWITCH_MESSAGE_INDICATE_ANSWER:
823 {
824 ftdm_channel_call_answer(tech_pvt->ftdmchan);
825 }
826 break;
827 default:
828 break;
829 }
830
831 return SWITCH_STATUS_SUCCESS;
832 }
833
834 static switch_status_t channel_receive_message_b(switch_core_session_t *session, switch_core_session_message_t *msg)
835 {
836 switch_channel_t *channel;
837 private_t *tech_pvt;
838
839 channel = switch_core_session_get_channel(session);
840 assert(channel != NULL);
841
842 tech_pvt = (private_t *) switch_core_session_get_private(session);
843 assert(tech_pvt != NULL);
844
845 if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
846 switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE);
847 return SWITCH_STATUS_FALSE;
848 }
849
850 if (ftdm_channel_call_check_hangup(tech_pvt->ftdmchan)) {
851 return SWITCH_STATUS_SUCCESS;
852 }
853
854 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
855 return SWITCH_STATUS_SUCCESS;
856 }
857
858 switch (msg->message_id) {
859 case SWITCH_MESSAGE_INDICATE_RINGING:
860 {
861 ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RINGING);
862 }
863 break;
864 case SWITCH_MESSAGE_INDICATE_PROGRESS:
865 {
866 ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA);
867 }
868 break;
869 case SWITCH_MESSAGE_INDICATE_ANSWER:
870 {
871 ftdm_channel_call_answer(tech_pvt->ftdmchan);
872 }
873 break;
874 default:
875 break;
876 }
877
878 return SWITCH_STATUS_SUCCESS;
879 }
880
881 static switch_status_t channel_receive_message_fxo(switch_core_session_t *session, switch_core_session_message_t *msg)
882 {
883 switch_channel_t *channel;
884 private_t *tech_pvt;
885
886 channel = switch_core_session_get_channel(session);
887 assert(channel != NULL);
888
889 tech_pvt = (private_t *) switch_core_session_get_private(session);
890 assert(tech_pvt != NULL);
891
892 if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
893 switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE);
894 return SWITCH_STATUS_FALSE;
895 }
896
897 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
898 return SWITCH_STATUS_SUCCESS;
899 }
900
901 switch (msg->message_id) {
902 case SWITCH_MESSAGE_INDICATE_PROGRESS:
903 case SWITCH_MESSAGE_INDICATE_ANSWER:
904 ftdm_channel_call_answer(tech_pvt->ftdmchan);
905 break;
906 default:
907 break;
908 }
909
910 return SWITCH_STATUS_SUCCESS;
911 }
912
913 static switch_status_t channel_receive_message_fxs(switch_core_session_t *session, switch_core_session_message_t *msg)
914 {
915 switch_channel_t *channel;
916 private_t *tech_pvt;
917
918 channel = switch_core_session_get_channel(session);
919 assert(channel != NULL);
920
921 tech_pvt = (private_t *) switch_core_session_get_private(session);
922 assert(tech_pvt != NULL);
923
924 if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
925 switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE);
926 return SWITCH_STATUS_FALSE;
927 }
928
929 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
930 return SWITCH_STATUS_SUCCESS;
931 }
932
933 switch (msg->message_id) {
934 case SWITCH_MESSAGE_INDICATE_PROGRESS:
935 case SWITCH_MESSAGE_INDICATE_ANSWER:
936 ftdm_channel_call_answer(tech_pvt->ftdmchan);
937 switch_channel_mark_answered(channel);
938 break;
939 case SWITCH_MESSAGE_INDICATE_RINGING:
940 if (!switch_channel_test_flag(channel, CF_ANSWERED) &&
941 !switch_channel_test_flag(channel, CF_EARLY_MEDIA) &&
942 !switch_channel_test_flag(channel, CF_RING_READY)
943 ) {
944 ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RINGING);
945 switch_channel_mark_ring_ready(channel);
946 }
947 break;
948 default:
949 break;
950 }
951
952 return SWITCH_STATUS_SUCCESS;
953 }
954
955 static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
956 {
957 private_t *tech_pvt;
958 switch_status_t status;
959 switch_channel_t *channel;
960 const char *var;
961 ftdm_channel_t *ftdmchan = NULL;
962
963 tech_pvt = (private_t *) switch_core_session_get_private(session);
964 assert(tech_pvt != NULL);
965
966 channel = switch_core_session_get_channel(session);
967
968 if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
969 switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE);
970 return SWITCH_STATUS_FALSE;
971 }
972
973 if (!(ftdmchan = tech_pvt->ftdmchan)) {
974 switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE);
975 return SWITCH_STATUS_FALSE;
976 }
977
978 if (!tech_pvt->ftdmchan) {
979 switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE);
980 return SWITCH_STATUS_FALSE;
981 }
982
983 switch (msg->message_id) {
984 case SWITCH_MESSAGE_INDICATE_PROGRESS:
985 case SWITCH_MESSAGE_INDICATE_ANSWER:
986 if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
987 if ((var = switch_channel_get_variable(channel, "freetdm_pre_buffer_size"))) {
988 int tmp = atoi(var);
989 if (tmp > -1) {
990 ftdm_channel_command(tech_pvt->ftdmchan, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, &tmp);
991 }
992 }
993 if ((var = switch_channel_get_variable(channel, "freetdm_disable_dtmf"))) {
994 ftdm_channel_command(tech_pvt->ftdmchan, FTDM_COMMAND_DISABLE_DTMF_DETECT, NULL);
995 }
996 }
997 break;
998 case SWITCH_MESSAGE_INDICATE_UUID_CHANGE:
999 {
1000 ftdm_channel_replace_token(tech_pvt->ftdmchan, msg->string_array_arg[0], msg->string_array_arg[1]);
1001 }
1002 break;
1003 default:
1004 break;
1005 }
1006
1007 switch (ftdm_channel_get_type(tech_pvt->ftdmchan)) {
1008 case FTDM_CHAN_TYPE_FXS:
1009 case FTDM_CHAN_TYPE_EM:
1010 status = channel_receive_message_fxs(session, msg);
1011 break;
1012 case FTDM_CHAN_TYPE_FXO:
1013 status = channel_receive_message_fxo(session, msg);
1014 break;
1015 case FTDM_CHAN_TYPE_B:
1016 status = channel_receive_message_b(session, msg);
1017 break;
1018 case FTDM_CHAN_TYPE_CAS:
1019 status = channel_receive_message_cas(session, msg);
1020 break;
1021 default:
1022 status = SWITCH_STATUS_FALSE;
1023 break;
1024 }
1025
1026 return status;
1027
1028 }
1029
1030 switch_state_handler_table_t freetdm_state_handlers = {
1031 channel_on_init,
1032 channel_on_routing,
1033 channel_on_execute,
1034 channel_on_hangup,
1035 channel_on_exchange_media,
1036 channel_on_soft_execute,
1037 NULL,
1038 NULL,
1039 NULL,
1040 NULL,
1041 NULL,
1042 channel_on_destroy
1043
1044 };
1045
1046 switch_io_routines_t freetdm_io_routines = {
1047 channel_outgoing_channel,
1048 channel_read_frame,
1049 channel_write_frame,
1050 channel_kill_channel,
1051 channel_send_dtmf,
1052 channel_receive_message
1053 };
1054
1055 static const char* channel_get_variable(switch_core_session_t *session, switch_event_t *var_event, const char *variable_name)
1056 {
1057 const char *variable = NULL;
1058
1059 if (var_event) {
1060 if ((variable = switch_event_get_header(var_event, variable_name))) {
1061 return variable;
1062 }
1063 }
1064 if (session) {
1065 switch_channel_t *channel = switch_core_session_get_channel(session);
1066 if ((variable = switch_channel_get_variable(channel, variable_name))) {
1067 return variable;
1068 }
1069 }
1070 if ((variable = switch_core_get_variable(variable_name))) {
1071 return variable;
1072 }
1073 return NULL;
1074 }
1075
1076 typedef struct {
1077 switch_event_t *var_event;
1078 switch_core_session_t *new_session;
1079 private_t *tech_pvt;
1080 switch_caller_profile_t *caller_profile;
1081 } hunt_data_t;
1082
1083 static ftdm_status_t on_channel_found(ftdm_channel_t *fchan, ftdm_caller_data_t *caller_data)
1084 {
1085 uint32_t span_id, chan_id;
1086 const char *var;
1087 char *sess_uuid;
1088 char name[128];
1089 ftdm_status_t status;
1090 hunt_data_t *hdata = caller_data->priv;
1091 switch_channel_t *channel = switch_core_session_get_channel(hdata->new_session);
1092
1093 if ((var = switch_event_get_header(hdata->var_event, "freetdm_pre_buffer_size"))) {
1094 int tmp = atoi(var);
1095 if (tmp > -1) {
1096 ftdm_channel_command(fchan, FTDM_COMMAND_SET_PRE_BUFFER_SIZE, &tmp);
1097 }
1098 }
1099
1100 span_id = ftdm_channel_get_span_id(fchan);
1101 chan_id = ftdm_channel_get_id(fchan);
1102
1103 tech_init(hdata->tech_pvt, hdata->new_session, fchan);
1104
1105 snprintf(name, sizeof(name), "FreeTDM/%u:%u/%s", span_id, chan_id, caller_data->dnis.digits);
1106 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connect outbound channel %s\n", name);
1107 switch_channel_set_name(channel, name);
1108 switch_channel_set_variable(channel, "freetdm_span_name", ftdm_channel_get_span_name(fchan));
1109 switch_channel_set_variable_printf(channel, "freetdm_span_number", "%d", span_id);
1110 switch_channel_set_variable_printf(channel, "freetdm_chan_number", "%d", chan_id);
1111
1112 switch_channel_set_caller_profile(channel, hdata->caller_profile);
1113 hdata->tech_pvt->caller_profile = hdata->caller_profile;
1114
1115 switch_channel_set_state(channel, CS_INIT);
1116 sess_uuid = switch_core_session_get_uuid(hdata->new_session);
1117 status = ftdm_channel_add_token(fchan, sess_uuid, ftdm_channel_get_token_count(fchan));
1118 switch_assert(status == FTDM_SUCCESS);
1119
1120 if (SPAN_CONFIG[span_id].limit_calls) {
1121 char spanresource[512];
1122 snprintf(spanresource, sizeof(spanresource), "span_%s_%s", ftdm_channel_get_span_name(fchan),
1123 caller_data->dnis.digits);
1124 ftdm_log(FTDM_LOG_DEBUG, "Adding rate limit resource on channel %d:%d (%s/%s/%d/%d)\n",
1125 span_id, chan_id, FREETDM_LIMIT_REALM,
1126 spanresource, SPAN_CONFIG[span_id].limit_calls, SPAN_CONFIG[span_id].limit_seconds);
1127 if (switch_limit_incr("hash", hdata->new_session, FREETDM_LIMIT_REALM, spanresource,
1128 SPAN_CONFIG[span_id].limit_calls, SPAN_CONFIG[span_id].limit_seconds) != SWITCH_STATUS_SUCCESS) {
1129 return FTDM_BREAK;
1130 }
1131 }
1132 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Attached session %s to channel %d:%d\n", sess_uuid, span_id, chan_id);
1133 return FTDM_SUCCESS;
1134 }
1135
1136
1137
1138
1139 static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
1140 switch_caller_profile_t *outbound_profile,
1141 switch_core_session_t **new_session, switch_memory_pool_t **pool,
1142 switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
1143 {
1144 hunt_data_t hunt_data;
1145 const char *dest = NULL;
1146 char *data = NULL;
1147 int span_id = -1, group_id = -1, chan_id = 0;
1148 switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1149 ftdm_status_t status;
1150 int direction = FTDM_TOP_DOWN;
1151 ftdm_caller_data_t caller_data = {{ 0 }};
1152 char *span_name = NULL;
1153 switch_event_header_t *h;
1154 char *argv[3];
1155 int argc = 0;
1156 const char *var;
1157 const char *dest_num = NULL, *callerid_num = NULL;
1158 ftdm_hunting_scheme_t hunting;
1159
1160 if (!outbound_profile) {
1161 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing caller profile\n");
1162 return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1163 }
1164
1165 if (zstr(outbound_profile->destination_number)) {
1166 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid dial string\n");
1167 return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1168 }
1169
1170
1171 data = switch_core_strdup(outbound_profile->pool, outbound_profile->destination_number);
1172
1173 if (!zstr(outbound_profile->destination_number)) {
1174 dest_num = switch_sanitize_number(switch_core_strdup(outbound_profile->pool, outbound_profile->destination_number));
1175 }
1176
1177 if (!zstr(outbound_profile->caller_id_number)) {
1178 callerid_num = switch_sanitize_number(switch_core_strdup(outbound_profile->pool, outbound_profile->caller_id_number));
1179 }
1180
1181 if (!zstr(callerid_num) && !strcmp(callerid_num, "0000000000")) {
1182 callerid_num = NULL;
1183 }
1184
1185 if ((argc = switch_separate_string(data, '/', argv, (sizeof(argv) / sizeof(argv[0])))) < 2) {
1186 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid dial string\n");
1187 return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1188 }
1189
1190 if (switch_is_number(argv[0])) {
1191 span_id = atoi(argv[0]);
1192 } else {
1193 span_name = argv[0];
1194 }
1195
1196 if (*argv[1] == 'A') {
1197 direction = FTDM_BOTTOM_UP;
1198 } else if (*argv[1] == 'a') {
1199 direction = FTDM_TOP_DOWN;
1200 } else if (*argv[1] == 'r') {
1201 direction = FTDM_RR_DOWN;
1202 } else if (*argv[1] == 'R') {
1203 direction = FTDM_RR_UP;
1204 } else {
1205 chan_id = atoi(argv[1]);
1206 }
1207
1208 if (!(dest = argv[2])) {
1209 dest = "";
1210 }
1211
1212 if (span_id == 0 && chan_id != 0) {
1213 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Span 0 is used to pick the first available span, selecting a channel is not supported (and doesn't make sense)\n");
1214 return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1215 }
1216
1217 if (span_id == -1 && !zstr(span_name)) {
1218 ftdm_span_t *span;
1219 ftdm_status_t zstatus = ftdm_span_find_by_name(span_name, &span);
1220 if (zstatus == FTDM_SUCCESS && span) {
1221 span_id = ftdm_span_get_id(span);
1222 }
1223 }
1224
1225 if (span_id == -1) {
1226
1227 ftdm_group_t *group;
1228 ftdm_status_t zstatus = ftdm_group_find_by_name(span_name, &group);
1229 if (zstatus == FTDM_SUCCESS && group) {
1230 group_id = ftdm_group_get_id(group);
1231 } else {
1232 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing ftdm span or group: %s\n", span_name);
1233 return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1234 }
1235 }
1236
1237 if (group_id < 0 && chan_id < 0) {
1238 direction = FTDM_BOTTOM_UP;
1239 chan_id = 0;
1240 }
1241
1242 if (session && globals.sip_headers) {
1243 switch_channel_t *channel = switch_core_session_get_channel(session);
1244 const char *sipvar;
1245 sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-CallerName");
1246 if (sipvar) {
1247 ftdm_set_string(caller_data.cid_name, sipvar);
1248 }
1249
1250 sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-CallerNumber");
1251 if (sipvar) {
1252 ftdm_set_string(caller_data.cid_num.digits, sipvar);
1253 }
1254
1255 sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-ANI");
1256 if (sipvar) {
1257 ftdm_set_string(caller_data.ani.digits, sipvar);
1258 }
1259
1260 sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-ANI-TON");
1261 if (sipvar) {
1262 caller_data.ani.type = (uint8_t)atoi(sipvar);
1263 }
1264
1265 sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-ANI-Plan");
1266 if (sipvar) {
1267 caller_data.ani.plan = (uint8_t)atoi(sipvar);
1268 }
1269
1270 sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-ANI2");
1271 if (sipvar) {
1272 ftdm_set_string(caller_data.aniII, sipvar);
1273 }
1274
1275 sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-DNIS");
1276 if (sipvar) {
1277 ftdm_set_string(caller_data.dnis.digits, sipvar);
1278 }
1279
1280 sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-DNIS-TON");
1281 if (sipvar) {
1282 caller_data.dnis.type = (uint8_t)atoi(sipvar);
1283 }
1284
1285 sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-DNIS-Plan");
1286 if (sipvar) {
1287 caller_data.dnis.plan = (uint8_t)atoi(sipvar);
1288 }
1289
1290 sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-RDNIS");
1291 if (sipvar) {
1292 ftdm_set_string(caller_data.rdnis.digits, sipvar);
1293 }
1294
1295 sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-RDNIS-TON");
1296 if (sipvar) {
1297 caller_data.rdnis.type = (uint8_t)atoi(sipvar);
1298 }
1299
1300 sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-RDNIS-Plan");
1301 if (sipvar) {
1302 caller_data.rdnis.plan = (uint8_t)atoi(sipvar);
1303 }
1304
1305 sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-Screen");
1306 if (sipvar) {
1307 caller_data.screen = (uint8_t)atoi(sipvar);
1308 }
1309
1310 sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-Presentation");
1311 if (sipvar) {
1312 caller_data.pres = (uint8_t)atoi(sipvar);
1313 }
1314 }
1315
1316 if (switch_test_flag(outbound_profile, SWITCH_CPF_SCREEN)) {
1317 caller_data.screen = FTDM_SCREENING_VERIFIED_PASSED;
1318 }
1319
1320 if (switch_test_flag(outbound_profile, SWITCH_CPF_HIDE_NUMBER)) {
1321 caller_data.pres = FTDM_PRES_RESTRICTED;
1322 }
1323
1324 if ((var = channel_get_variable(session, var_event, "freetdm_bearer_capability"))) {
1325 caller_data.bearer_capability = (uint8_t)atoi(var);
1326 }
1327
1328 if ((var = channel_get_variable(session, var_event, "freetdm_bearer_layer1"))) {
1329 caller_data.bearer_layer1 = (uint8_t)atoi(var);
1330 }
1331
1332 if ((var = channel_get_variable(session, var_event, "freetdm_screening_ind"))) {
1333 ftdm_set_screening_ind(var, &caller_data.screen);
1334 }
1335
1336 if ((var = channel_get_variable(session, var_event, "freetdm_presentation_ind"))) {
1337 ftdm_set_presentation_ind(var, &caller_data.pres);
1338 }
1339
1340 if ((var = channel_get_variable(session, var_event, "freetdm_outbound_ton"))) {
1341 ftdm_set_ton(var, &caller_data.dnis.type);
1342 } else {
1343 caller_data.dnis.type = outbound_profile->destination_number_ton;
1344 }
1345
1346 if ((var = channel_get_variable(session, var_event, "freetdm_calling_party_category"))) {
1347 ftdm_set_calling_party_category(var, (uint8_t *)&caller_data.cpc);
1348 }
1349
1350 if ((var = channel_get_variable(session, var_event, "freetdm_custom_call_data"))) {
1351 ftdm_set_string(caller_data.raw_data, var);
1352 caller_data.raw_data_len = (uint32_t)strlen(var);
1353 }
1354
1355 if (!zstr(dest)) {
1356 ftdm_set_string(caller_data.dnis.digits, dest);
1357 }
1358
1359 caller_data.dnis.plan = outbound_profile->destination_number_numplan;
1360
1361
1362
1363 caller_data.cid_num.type = outbound_profile->caller_ton;
1364 caller_data.cid_num.plan = outbound_profile->caller_numplan;
1365 caller_data.rdnis.type = outbound_profile->rdnis_ton;
1366 caller_data.rdnis.plan = outbound_profile->rdnis_numplan;
1367
1368 ftdm_set_string(caller_data.cid_name, outbound_profile->caller_id_name);
1369 ftdm_set_string(caller_data.cid_num.digits, switch_str_nil(outbound_profile->caller_id_number));
1370
1371 memset(&hunting, 0, sizeof(hunting));
1372
1373 if (group_id >= 0) {
1374 hunting.mode = FTDM_HUNT_GROUP;
1375 hunting.mode_data.group.group_id = group_id;
1376 hunting.mode_data.group.direction = direction;
1377 } else if (chan_id) {
1378 hunting.mode = FTDM_HUNT_CHAN;
1379 hunting.mode_data.chan.span_id = span_id;
1380 hunting.mode_data.chan.chan_id = chan_id;
1381 } else {
1382 hunting.mode = FTDM_HUNT_SPAN;
1383 hunting.mode_data.span.span_id = span_id;
1384 hunting.mode_data.span.direction = direction;
1385 }
1386
1387 for (h = var_event->headers; h; h = h->next) {
1388 if (!strncasecmp(h->name, FREETDM_VAR_PREFIX, FREETDM_VAR_PREFIX_LEN)) {
1389 char *v = h->name + FREETDM_VAR_PREFIX_LEN;
1390 if (!zstr(v)) {
1391 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding outbound freetdm variable %s=%s to channel %d:%d\n", v, h->value, span_id, chan_id);
1392 ftdm_call_add_var(&caller_data, v, h->value);
1393 }
1394 }
1395 }
1396
1397 if ((*new_session = switch_core_session_request(freetdm_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool)) != 0) {
1398 private_t *tech_pvt;
1399 switch_caller_profile_t *caller_profile;
1400
1401 switch_core_session_add_stream(*new_session, NULL);
1402 if (!(tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t)))) {
1403 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
1404 switch_core_session_destroy(new_session);
1405 cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1406 goto fail;
1407 }
1408
1409 caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
1410 caller_profile->destination_number = switch_core_strdup(caller_profile->pool, switch_str_nil(dest_num));
1411 caller_profile->caller_id_number = switch_core_strdup(caller_profile->pool, switch_str_nil(callerid_num));
1412
1413 hunting.result_cb = on_channel_found;
1414 hunt_data.var_event = var_event;
1415 hunt_data.new_session = *new_session;
1416 hunt_data.caller_profile = caller_profile;
1417 hunt_data.tech_pvt = tech_pvt;
1418 caller_data.priv = &hunt_data;
1419
1420 if ((status = ftdm_call_place(&caller_data, &hunting)) != FTDM_SUCCESS) {
1421 if (tech_pvt->read_codec.implementation) {
1422 switch_core_codec_destroy(&tech_pvt->read_codec);
1423 }
1424
1425 if (tech_pvt->write_codec.implementation) {
1426 switch_core_codec_destroy(&tech_pvt->write_codec);
1427 }
1428 switch_core_session_destroy(new_session);
1429 if (status == FTDM_BREAK || status == FTDM_EBUSY) {
1430 cause = SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION;
1431 } else {
1432 cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1433 }
1434 goto fail;
1435 }
1436
1437 ftdm_channel_init(caller_data.fchan);
1438
1439 return SWITCH_CAUSE_SUCCESS;
1440 }
1441
1442 fail:
1443
1444 return cause;
1445 }
1446
1447 static void ftdm_enable_channel_dtmf(ftdm_channel_t *fchan, switch_channel_t *channel)
1448 {
1449 if (channel) {
1450 const char *var;
1451 if ((var = switch_channel_get_variable(channel, "freetdm_disable_dtmf"))) {
1452 if (switch_true(var)) {
1453 ftdm_channel_command(fchan, FTDM_COMMAND_DISABLE_DTMF_DETECT, NULL);
1454 ftdm_log(FTDM_LOG_INFO, "DTMF detection disabled in channel %d:%d\n", ftdm_channel_get_span_id(fchan), ftdm_channel_get_id(fchan));
1455 return;
1456 }
1457 }
1458
1459 }
1460 if (ftdm_channel_command(fchan, FTDM_COMMAND_ENABLE_DTMF_DETECT, NULL) != FTDM_SUCCESS) {
1461 ftdm_log(FTDM_LOG_ERROR, "Failed to enable DTMF detection in channel %d:%d\n", ftdm_channel_get_span_id(fchan), ftdm_channel_get_id(fchan));
1462 }
1463 }
1464
1465 ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session_t **sp)
1466 {
1467 switch_core_session_t *session = NULL;
1468 private_t *tech_pvt = NULL;
1469 switch_channel_t *channel = NULL;
1470 ftdm_iterator_t *iter = NULL;
1471 ftdm_iterator_t *curr = NULL;
1472 const char *var_name = NULL;
1473 const char *var_value = NULL;
1474 uint32_t spanid, chanid;
1475 char name[128];
1476 ftdm_caller_data_t *channel_caller_data = ftdm_channel_get_caller_data(sigmsg->channel);
1477
1478 *sp = NULL;
1479
1480 spanid = ftdm_channel_get_span_id(sigmsg->channel);
1481 chanid = ftdm_channel_get_id(sigmsg->channel);
1482
1483 if (!(session = switch_core_session_request(freetdm_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL))) {
1484 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Initilization Error!\n");
1485 return FTDM_FAIL;
1486 }
1487
1488
1489 ftdm_enable_channel_dtmf(sigmsg->channel, NULL);
1490
1491 switch_core_session_add_stream(session, NULL);
1492
1493 tech_pvt = (private_t *) switch_core_session_alloc(session, sizeof(private_t));
1494 assert(tech_pvt != NULL);
1495 channel = switch_core_session_get_channel(session);
1496 if (tech_init(tech_pvt, session, sigmsg->channel) != SWITCH_STATUS_SUCCESS) {
1497 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Initilization Error!\n");
1498 switch_core_session_destroy(&session);
1499 return FTDM_FAIL;
1500 }
1501
1502 channel_caller_data->collected[0] = '\0';
1503
1504 if (zstr(channel_caller_data->cid_name)) {
1505 switch_set_string(channel_caller_data->cid_name, ftdm_channel_get_name(sigmsg->channel));
1506 }
1507
1508 if (zstr(channel_caller_data->cid_num.digits)) {
1509 if (!zstr(channel_caller_data->ani.digits)) {
1510 switch_set_string(channel_caller_data->cid_num.digits, channel_caller_data->ani.digits);
1511 } else {
1512 switch_set_string(channel_caller_data->cid_num.digits, ftdm_channel_get_number(sigmsg->channel));
1513 }
1514 }
1515
1516 tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session),
1517 "FreeTDM",
1518 SPAN_CONFIG[spanid].dialplan,
1519 channel_caller_data->cid_name,
1520 channel_caller_data->cid_num.digits,
1521 NULL,
1522 channel_caller_data->ani.digits,
1523 channel_caller_data->aniII,
1524 channel_caller_data->rdnis.digits,
1525 (char *)modname,
1526 SPAN_CONFIG[spanid].context,
1527 channel_caller_data->dnis.digits);
1528
1529 assert(tech_pvt->caller_profile != NULL);
1530
1531 if (channel_caller_data->screen == 1 || channel_caller_data->screen == 3) {
1532 switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_SCREEN);
1533 }
1534
1535 tech_pvt->caller_profile->caller_ton = channel_caller_data->cid_num.type;
1536 tech_pvt->caller_profile->caller_numplan = channel_caller_data->cid_num.plan;
1537 tech_pvt->caller_profile->ani_ton = channel_caller_data->ani.type;
1538 tech_pvt->caller_profile->ani_numplan = channel_caller_data->ani.plan;
1539 tech_pvt->caller_profile->destination_number_ton = channel_caller_data->dnis.type;
1540 tech_pvt->caller_profile->destination_number_numplan = channel_caller_data->dnis.plan;
1541 tech_pvt->caller_profile->rdnis_ton = channel_caller_data->rdnis.type;
1542 tech_pvt->caller_profile->rdnis_numplan = channel_caller_data->rdnis.plan;
1543
1544 if (channel_caller_data->pres) {
1545 switch_set_flag(tech_pvt->caller_profile, SWITCH_CPF_HIDE_NAME | SWITCH_CPF_HIDE_NUMBER);
1546 }
1547
1548 snprintf(name, sizeof(name), "FreeTDM/%u:%u/%s", spanid, chanid, tech_pvt->caller_profile->destination_number);
1549 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connect inbound channel %s\n", name);
1550 switch_channel_set_name(channel, name);
1551 switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
1552
1553 switch_channel_set_variable(channel, "freetdm_span_name", ftdm_channel_get_span_name(sigmsg->channel));
1554 switch_channel_set_variable_printf(channel, "freetdm_span_number", "%d", spanid);
1555 switch_channel_set_variable_printf(channel, "freetdm_chan_number", "%d", chanid);
1556 switch_channel_set_variable_printf(channel, "freetdm_bearer_capability", "%d", channel_caller_data->bearer_capability);
1557 switch_channel_set_variable_printf(channel, "freetdm_bearer_layer1", "%d", channel_caller_data->bearer_layer1);
1558
1559 if (globals.sip_headers) {
1560 switch_channel_set_variable(channel, "sip_h_X-FreeTDM-SpanName", ftdm_channel_get_span_name(sigmsg->channel));
1561 switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-SpanNumber", "%d", spanid);
1562 switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-ChanNumber", "%d", chanid);
1563
1564 switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-CallerName", "%s", channel_caller_data->cid_name);
1565 switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-CallerNumber", "%s", channel_caller_data->cid_num.digits);
1566
1567 switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-ANI", "%s", channel_caller_data->ani.digits);
1568 switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-ANI-TON", "%d", channel_caller_data->ani.type);
1569 switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-ANI-Plan", "%d", channel_caller_data->ani.plan);
1570 switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-ANI2", "%s", channel_caller_data->aniII);
1571
1572 switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-DNIS", "%s", channel_caller_data->dnis.digits);
1573 switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-DNIS-TON", "%s", channel_caller_data->dnis.type);
1574 switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-DNIS-Plan", "%s", channel_caller_data->dnis.plan);
1575
1576 switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDNIS", "%s", channel_caller_data->rdnis.digits);
1577 switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDNIS-TON", "%d", channel_caller_data->rdnis.type);
1578 switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-RDNIS-Plan", "%d", channel_caller_data->rdnis.plan);
1579
1580 switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-Screen", "%d", channel_caller_data->screen);
1581 switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-Presentation", "%d", channel_caller_data->pres);
1582 }
1583 if (channel_caller_data->raw_data_len) {
1584 switch_channel_set_variable_printf(channel, "freetdm_custom_call_data", "%s", channel_caller_data->raw_data);
1585 }
1586
1587 iter = ftdm_channel_get_var_iterator(sigmsg->channel, NULL);
1588 for (curr = iter ; curr; curr = ftdm_iterator_next(curr)) {
1589 ftdm_channel_get_current_var(curr, &var_name, &var_value);
1590 snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name);
1591 switch_channel_set_variable_printf(channel, name, "%s", var_value);
1592 }
1593
1594
1595 iter = ftdm_call_get_var_iterator(channel_caller_data, iter);
1596 for (curr = iter ; curr; curr = ftdm_iterator_next(curr)) {
1597 ftdm_call_get_current_var(curr, &var_name, &var_value);
1598 snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name);
1599 switch_channel_set_variable_printf(channel, name, "%s", var_value);
1600 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call Variable: %s=%s\n", name, var_value);
1601 }
1602 ftdm_iterator_free(iter);
1603
1604
1605 switch_channel_set_state(channel, CS_INIT);
1606 if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
1607 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error spawning thread\n");
1608 switch_core_session_destroy(&session);
1609 return FTDM_FAIL;
1610 }
1611
1612 if (ftdm_channel_add_token(sigmsg->channel, switch_core_session_get_uuid(session), 0) != FTDM_SUCCESS) {
1613 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error adding token\n");
1614 switch_core_session_destroy(&session);
1615 return FTDM_FAIL;
1616 }
1617 *sp = session;
1618
1619 return FTDM_SUCCESS;
1620 }
1621
1622 static FIO_SIGNAL_CB_FUNCTION(on_common_signal)
1623 {
1624 switch_event_t *event = NULL;
1625 ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE;
1626 uint32_t chanid, spanid;
1627 chanid = ftdm_channel_get_id(sigmsg->channel);
1628 spanid = ftdm_channel_get_span_id(sigmsg->channel);
1629 switch (sigmsg->event_id) {
1630
1631 case FTDM_SIGEVENT_ALARM_CLEAR:
1632 case FTDM_SIGEVENT_ALARM_TRAP:
1633 {
1634 if (ftdm_channel_get_alarms(sigmsg->channel, &alarmbits) != FTDM_SUCCESS) {
1635 ftdm_log(FTDM_LOG_ERROR, "failed to retrieve alarms\n");
1636 return FTDM_FAIL;
1637 }
1638 if (switch_event_create(&event, SWITCH_EVENT_TRAP) != SWITCH_STATUS_SUCCESS) {
1639 ftdm_log(FTDM_LOG_ERROR, "failed to create alarms events\n");
1640 return FTDM_FAIL;
1641 }
1642 if (sigmsg->event_id == FTDM_SIGEVENT_ALARM_CLEAR) {
1643 ftdm_log(FTDM_LOG_NOTICE, "Alarm cleared on channel %d:%d\n", spanid, chanid);
1644 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-clear");
1645 } else {
1646 ftdm_log(FTDM_LOG_NOTICE, "Alarm raised on channel %d:%d\n", spanid, chanid);
1647 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "condition", "ftdm-alarm-trap");
1648 }
1649 }
1650 break;
1651 case FTDM_SIGEVENT_UP:
1652 {
1653
1654 char spanresource[512];
1655 if (SPAN_CONFIG[spanid].limit_reset_event == FTDM_LIMIT_RESET_ON_ANSWER && SPAN_CONFIG[spanid].limit_calls) {
1656 ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(sigmsg->channel);
1657 snprintf(spanresource, sizeof(spanresource), "span_%s_%s", ftdm_channel_get_span_name(sigmsg->channel), caller_data->dnis.digits);
1658 ftdm_log(FTDM_LOG_DEBUG, "Clearing rate limit resource on channel %d:%d (%s/%s)\n", spanid, chanid, FREETDM_LIMIT_REALM, spanresource);
1659 switch_limit_interval_reset("hash", FREETDM_LIMIT_REALM, spanresource);
1660 }
1661 return FTDM_SUCCESS;
1662 }
1663
1664 case FTDM_SIGEVENT_RELEASED:
1665 case FTDM_SIGEVENT_INDICATION_COMPLETED:
1666 case FTDM_SIGEVENT_DIALING:
1667 {
1668
1669 return FTDM_BREAK;
1670 }
1671 break;
1672 default:
1673 return FTDM_SUCCESS;
1674 break;
1675 }
1676
1677 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-name", "%s", ftdm_channel_get_span_name(sigmsg->channel));
1678 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-number", "%d", ftdm_channel_get_span_id(sigmsg->channel));
1679 switch_event_add_header(event, SWITCH_STACK_BOTTOM, "chan-number", "%d", ftdm_channel_get_id(sigmsg->channel));
1680
1681 if (alarmbits & FTDM_ALARM_RED) {
1682 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "red");
1683 }
1684 if (alarmbits & FTDM_ALARM_YELLOW) {
1685 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "yellow");
1686 }
1687 if (alarmbits & FTDM_ALARM_RAI) {
1688 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "rai");
1689 }
1690 if (alarmbits & FTDM_ALARM_BLUE) {
1691 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "blue");
1692 }
1693 if (alarmbits & FTDM_ALARM_AIS) {
1694 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "ais");
1695 }
1696 if (alarmbits & FTDM_ALARM_GENERAL) {
1697 switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "general");
1698 }
1699 switch_event_fire(&event);
1700
1701 return FTDM_BREAK;
1702 }
1703
1704 static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
1705 {
1706 switch_core_session_t *session = NULL;
1707 switch_channel_t *channel = NULL;
1708 ftdm_status_t status;
1709 uint32_t spanid;
1710 uint32_t chanid;
1711 ftdm_caller_data_t *caller_data;
1712
1713 spanid = ftdm_channel_get_span_id(sigmsg->channel);
1714 chanid = ftdm_channel_get_id(sigmsg->channel);
1715 caller_data = ftdm_channel_get_caller_data(sigmsg->channel);
1716
1717 ftdm_log(FTDM_LOG_DEBUG, "got FXO sig %d:%d [%s]\n", spanid, chanid, ftdm_signal_event2str(sigmsg->event_id));
1718
1719 switch(sigmsg->event_id) {
1720
1721 case FTDM_SIGEVENT_PROGRESS_MEDIA:
1722 {
1723 if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
1724 channel = switch_core_session_get_channel(session);
1725 switch_channel_mark_pre_answered(channel);
1726 switch_core_session_rwunlock(session);
1727 }
1728 }
1729 break;
1730 case FTDM_SIGEVENT_STOP:
1731 {
1732 private_t *tech_pvt = NULL;
1733 while((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
1734 tech_pvt = switch_core_session_get_private(session);
1735 switch_set_flag_locked(tech_pvt, TFLAG_DEAD);
1736 ftdm_channel_clear_token(sigmsg->channel, 0);
1737 channel = switch_core_session_get_channel(session);
1738 switch_channel_hangup(channel, caller_data->hangup_cause);
1739 ftdm_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session));
1740 switch_core_session_rwunlock(session);
1741 }
1742 }
1743 break;
1744 case FTDM_SIGEVENT_UP:
1745 {
1746 if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
1747 channel = switch_core_session_get_channel(session);
1748 switch_channel_mark_answered(channel);
1749 ftdm_enable_channel_dtmf(sigmsg->channel, channel);
1750 switch_core_session_rwunlock(session);
1751 }
1752 }
1753 break;
1754 case FTDM_SIGEVENT_START:
1755 {
1756 status = ftdm_channel_from_event(sigmsg, &session);
1757 if (status != FTDM_SUCCESS) {
1758 ftdm_channel_call_hangup(sigmsg->channel);
1759 }
1760 }
1761 break;
1762 case FTDM_SIGEVENT_SIGSTATUS_CHANGED: { } break;
1763
1764 default:
1765 {
1766 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled msg type %d for channel %d:%d\n",
1767 sigmsg->event_id, spanid, chanid);
1768 }
1769 break;
1770
1771 }
1772
1773 return FTDM_SUCCESS;
1774 }
1775
1776 static FIO_SIGNAL_CB_FUNCTION(on_fxs_signal)
1777 {
1778 switch_core_session_t *session = NULL;
1779 switch_channel_t *channel = NULL;
1780 ftdm_status_t status = FTDM_SUCCESS;
1781 uint32_t chanid, spanid, tokencount;
1782
1783 chanid = ftdm_channel_get_id(sigmsg->channel);
1784 spanid = ftdm_channel_get_span_id(sigmsg->channel);
1785 tokencount = ftdm_channel_get_token_count(sigmsg->channel);
1786
1787 ftdm_log(FTDM_LOG_DEBUG, "got FXS sig [%s]\n", ftdm_signal_event2str(sigmsg->event_id));
1788
1789 switch(sigmsg->event_id) {
1790 case FTDM_SIGEVENT_UP:
1791 {
1792 if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
1793 channel = switch_core_session_get_channel(session);
1794 switch_channel_mark_answered(channel);
1795 ftdm_enable_channel_dtmf(sigmsg->channel, channel);
1796 switch_core_session_rwunlock(session);
1797 }
1798 }
1799 break;
1800 case FTDM_SIGEVENT_PROGRESS:
1801 {
1802 if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
1803 channel = switch_core_session_get_channel(session);
1804 switch_channel_mark_ring_ready(channel);
1805 switch_core_session_rwunlock(session);
1806 }
1807 }
1808 break;
1809 case FTDM_SIGEVENT_START:
1810 {
1811 status = ftdm_channel_from_event(sigmsg, &session);
1812 if (status != FTDM_SUCCESS) {
1813 ftdm_channel_call_indicate(sigmsg->channel, FTDM_CHANNEL_INDICATE_BUSY);
1814 }
1815 }
1816 break;
1817
1818 case FTDM_SIGEVENT_STOP:
1819 {
1820 private_t *tech_pvt = NULL;
1821 switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
1822 if (tokencount) {
1823 ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(sigmsg->channel);
1824 switch_core_session_t *session_a, *session_b, *session_t = NULL;
1825 switch_channel_t *channel_a = NULL, *channel_b = NULL;
1826 int digits = !zstr(caller_data->collected);
1827 const char *br_a_uuid = NULL, *br_b_uuid = NULL;
1828 private_t *tech_pvt = NULL;
1829
1830
1831 if ((session_a = switch_core_session_locate(ftdm_channel_get_token(sigmsg->channel, 0)))) {
1832 channel_a = switch_core_session_get_channel(session_a);
1833 br_a_uuid = switch_channel_get_variable(channel_a, SWITCH_SIGNAL_BOND_VARIABLE);
1834
1835 tech_pvt = switch_core_session_get_private(session_a);
1836 stop_hold(session_a, switch_channel_get_variable(channel_a, SWITCH_SIGNAL_BOND_VARIABLE));
1837 switch_clear_flag_locked(tech_pvt, TFLAG_HOLD);
1838 }
1839
1840 if ((session_b = switch_core_session_locate(ftdm_channel_get_token(sigmsg->channel, 1)))) {
1841 channel_b = switch_core_session_get_channel(session_b);
1842 br_b_uuid = switch_channel_get_variable(channel_b, SWITCH_SIGNAL_BOND_VARIABLE);
1843
1844 tech_pvt = switch_core_session_get_private(session_b);
1845 stop_hold(session_a, switch_channel_get_variable(channel_b, SWITCH_SIGNAL_BOND_VARIABLE));
1846 switch_clear_flag_locked(tech_pvt, TFLAG_HOLD);
1847 }
1848
1849 if (channel_a && channel_b && switch_channel_direction(channel_a) == SWITCH_CALL_DIRECTION_INBOUND &&
1850 switch_channel_direction(channel_b) == SWITCH_CALL_DIRECTION_INBOUND) {
1851
1852 cause = SWITCH_CAUSE_ATTENDED_TRANSFER;
1853 if (br_a_uuid && br_b_uuid) {
1854 switch_ivr_uuid_bridge(br_a_uuid, br_b_uuid);
1855 } else if (br_a_uuid && digits) {
1856 session_t = switch_core_session_locate(br_a_uuid);
1857 } else if (br_b_uuid && digits) {
1858 session_t = switch_core_session_locate(br_b_uuid);
1859 }
1860 }
1861
1862 if (session_t) {
1863 switch_ivr_session_transfer(session_t, caller_data->collected, NULL, NULL);
1864 switch_core_session_rwunlock(session_t);
1865 }
1866
1867 if (session_a) {
1868 switch_core_session_rwunlock(session_a);
1869 }
1870
1871 if (session_b) {
1872 switch_core_session_rwunlock(session_b);
1873 }
1874
1875
1876 }
1877
1878 while((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
1879 tech_pvt = switch_core_session_get_private(session);
1880 switch_set_flag_locked(tech_pvt, TFLAG_DEAD);
1881 channel = switch_core_session_get_channel(session);
1882 switch_channel_hangup(channel, cause);
1883 ftdm_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session));
1884 switch_core_session_rwunlock(session);
1885 }
1886 ftdm_channel_clear_token(sigmsg->channel, NULL);
1887
1888 }
1889 break;
1890
1891 case FTDM_SIGEVENT_ADD_CALL:
1892 {
1893 cycle_foreground(sigmsg->channel, 1, NULL);
1894 }
1895 break;
1896 case FTDM_SIGEVENT_FLASH:
1897 {
1898 chan_pvt_t *chanpvt = ftdm_channel_get_private(sigmsg->channel);
1899 if (!chanpvt) {
1900 ftdm_log(FTDM_LOG_ERROR, "%d:%d has no private data, can't handle FXS features! (this is a bug)\n",
1901 chanid, spanid);
1902 break;
1903 }
1904 if (ftdm_channel_call_check_hold(sigmsg->channel) && tokencount == 1) {
1905 switch_core_session_t *session;
1906 if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
1907 const char *buuid;
1908 switch_channel_t *channel;
1909 private_t *tech_pvt;
1910
1911 tech_pvt = switch_core_session_get_private(session);
1912 channel = switch_core_session_get_channel(session);
1913 buuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE);
1914 ftdm_channel_call_unhold(sigmsg->channel);
1915 stop_hold(session, buuid);
1916 switch_clear_flag_locked(tech_pvt, TFLAG_HOLD);
1917 switch_core_session_rwunlock(session);
1918 }
1919 } else if (tokencount == 2 && (SPAN_CONFIG[sigmsg->span_id].analog_options & ANALOG_OPTION_3WAY)) {
1920 if (switch_test_flag(chanpvt, ANALOG_OPTION_3WAY)) {
1921 switch_clear_flag(chanpvt, ANALOG_OPTION_3WAY);
1922 if ((session = ftdm_channel_get_session(sigmsg->channel, 1))) {
1923 channel = switch_core_session_get_channel(session);
1924 switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
1925 ftdm_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session));
1926 switch_core_session_rwunlock(session);
1927 }
1928 cycle_foreground(sigmsg->channel, 1, NULL);
1929 } else {
1930 char *cmd;
1931 cmd = switch_mprintf("three_way::%s", ftdm_channel_get_token(sigmsg->channel, 0));
1932 switch_set_flag(chanpvt, ANALOG_OPTION_3WAY);
1933 cycle_foreground(sigmsg->channel, 1, cmd);
1934 free(cmd);
1935 }
1936 } else if ((SPAN_CONFIG[sigmsg->span_id].analog_options & ANALOG_OPTION_CALL_SWAP)
1937 || (SPAN_CONFIG[sigmsg->span_id].analog_options & ANALOG_OPTION_3WAY)
1938 ) {
1939 cycle_foreground(sigmsg->channel, 1, NULL);
1940 if (tokencount == 1) {
1941 ftdm_channel_call_hold(sigmsg->channel);
1942 }
1943 }
1944
1945 }
1946 break;
1947
1948 case FTDM_SIGEVENT_COLLECTED_DIGIT:
1949 {
1950 int span_id = ftdm_channel_get_span_id(sigmsg->channel);
1951 char *dtmf = sigmsg->ev_data.collected.digits;
1952 char *regex = SPAN_CONFIG[span_id].dial_regex;
1953 char *fail_regex = SPAN_CONFIG[span_id].fail_dial_regex;
1954 ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(sigmsg->channel);
1955
1956 if (zstr(regex)) {
1957 regex = NULL;
1958 }
1959
1960 if (zstr(fail_regex)) {
1961 fail_regex = NULL;
1962 }
1963
1964 ftdm_log(FTDM_LOG_DEBUG, "got DTMF sig [%s]\n", dtmf);
1965 switch_set_string(caller_data->collected, dtmf);
1966
1967 if ((regex || fail_regex) && !zstr(dtmf)) {
1968 switch_regex_t *re = NULL;
1969 int ovector[30];
1970 int match = 0;
1971
1972 if (fail_regex) {
1973 match = switch_regex_perform(dtmf, fail_regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0]));
1974 status = match ? FTDM_SUCCESS : FTDM_BREAK;
1975 switch_regex_safe_free(re);
1976 ftdm_log(FTDM_LOG_DEBUG, "DTMF [%s] vs fail regex %s %s\n", dtmf, fail_regex, match ? "matched" : "did not match");
1977 }
1978
1979 if (status == FTDM_SUCCESS && regex) {
1980 match = switch_regex_perform(dtmf, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0]));
1981 status = match ? FTDM_BREAK : FTDM_SUCCESS;
1982 switch_regex_safe_free(re);
1983 ftdm_log(FTDM_LOG_DEBUG, "DTMF [%s] vs dial regex %s %s\n", dtmf, regex, match ? "matched" : "did not match");
1984 }
1985 ftdm_log(FTDM_LOG_DEBUG, "returning %s to COLLECT event with DTMF %s\n", status == FTDM_SUCCESS ? "success" : "break", dtmf);
1986 }
1987 }
1988 break;
1989
1990 default:
1991 {
1992 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled msg type %d for channel %d:%d\n",
1993 sigmsg->event_id, spanid, chanid);
1994 }
1995 break;
1996
1997 }
1998
1999 return status;
2000 }
2001
2002 static FIO_SIGNAL_CB_FUNCTION(on_r2_signal)
2003 {
2004 uint32_t phyid, chanid, spanid;
2005 switch_core_session_t *session = NULL;
2006 switch_channel_t *channel = NULL;
2007 ftdm_status_t status = FTDM_SUCCESS;
2008 ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(sigmsg->channel);
2009
2010 phyid = ftdm_channel_get_ph_id(sigmsg->channel);
2011 chanid = ftdm_channel_get_id(sigmsg->channel);
2012 spanid = ftdm_channel_get_span_id(sigmsg->channel);
2013
2014 ftdm_log(FTDM_LOG_DEBUG, "Got R2 channel sig [%s] in channel %d\n", ftdm_signal_event2str(sigmsg->event_id), phyid);
2015
2016 if (on_common_signal(sigmsg) == FTDM_BREAK) {
2017 return FTDM_SUCCESS;
2018 }
2019
2020 switch(sigmsg->event_id) {
2021
2022 case FTDM_SIGEVENT_STOP:
2023 {
2024 private_t *tech_pvt = NULL;
2025 while((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
2026 tech_pvt = switch_core_session_get_private(session);
2027 switch_set_flag_locked(tech_pvt, TFLAG_DEAD);
2028 channel = switch_core_session_get_channel(session);
2029 switch_channel_hangup(channel, caller_data->hangup_cause);
2030 ftdm_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session));
2031 switch_core_session_rwunlock(session);
2032 }
2033 }
2034 break;
2035
2036
2037 case FTDM_SIGEVENT_START:
2038 {
2039 status = ftdm_channel_from_event(sigmsg, &session);
2040 }
2041 break;
2042
2043
2044 case FTDM_SIGEVENT_COLLECTED_DIGIT:
2045 {
2046 ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(sigmsg->channel);
2047 int span_id = ftdm_channel_get_span_id(sigmsg->channel);
2048 char *regex = SPAN_CONFIG[span_id].dial_regex;
2049 char *fail_regex = SPAN_CONFIG[span_id].fail_dial_regex;
2050
2051 if (zstr(regex)) {
2052 regex = NULL;
2053 }
2054
2055 if (zstr(fail_regex)) {
2056 fail_regex = NULL;
2057 }
2058
2059 ftdm_log(FTDM_LOG_DEBUG, "R2 DNIS so far [%s]\n", caller_data->dnis.digits);
2060
2061 if ((regex || fail_regex) && !zstr(caller_data->dnis.digits)) {
2062 switch_regex_t *re = NULL;
2063 int ovector[30];
2064 int match = 0;
2065
2066 if (fail_regex) {
2067 match = switch_regex_perform(caller_data->dnis.digits, fail_regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0]));
2068 status = match ? FTDM_SUCCESS : FTDM_BREAK;
2069 switch_regex_safe_free(re);
2070 }
2071
2072 if (status == FTDM_SUCCESS && regex) {
2073 match = switch_regex_perform(caller_data->dnis.digits, regex, &re, ovector, sizeof(ovector) / sizeof(ovector[0]));
2074 status = match ? FTDM_BREAK : FTDM_SUCCESS;
2075 }
2076
2077 switch_regex_safe_free(re);
2078 }
2079 }
2080 break;
2081
2082 case FTDM_SIGEVENT_PROGRESS:
2083 {
2084 if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
2085 channel = switch_core_session_get_channel(session);
2086 switch_channel_mark_ring_ready(channel);
2087 switch_core_session_rwunlock(session);
2088 }
2089 }
2090 break;
2091
2092 case FTDM_SIGEVENT_PROGRESS_MEDIA:
2093 {
2094 if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
2095 channel = switch_core_session_get_channel(session);
2096 switch_channel_mark_pre_answered(channel);
2097 switch_core_session_rwunlock(session);
2098 }
2099 }
2100 break;
2101
2102 case FTDM_SIGEVENT_UP:
2103 {
2104 if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
2105 channel = switch_core_session_get_channel(session);
2106 switch_channel_mark_answered(channel);
2107 ftdm_enable_channel_dtmf(sigmsg->channel, channel);
2108 switch_core_session_rwunlock(session);
2109 }
2110 }
2111 break;
2112
2113 case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
2114 {
2115 ftdm_signaling_status_t sigstatus = sigmsg->ev_data.sigstatus.status;
2116 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d:%d signalling changed to: %s\n",
2117 spanid, chanid, ftdm_signaling_status2str(sigstatus));
2118 }
2119 break;
2120
2121 case FTDM_SIGEVENT_PROCEED:{} break;
2122 case FTDM_SIGEVENT_INDICATION_COMPLETED:{} break;
2123
2124 default:
2125 {
2126 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled event %d from R2 for channel %d:%d\n",
2127 sigmsg->event_id, spanid, chanid);
2128 }
2129 break;
2130 }
2131
2132 return status;
2133 }
2134
2135 static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
2136 {
2137 switch_core_session_t *session = NULL;
2138 switch_channel_t *channel = NULL;
2139 ftdm_caller_data_t *caller_data;
2140 uint32_t spanid, chanid;
2141
2142 ftdm_log(FTDM_LOG_DEBUG, "got clear channel sig [%s]\n", ftdm_signal_event2str(sigmsg->event_id));
2143
2144 caller_data = ftdm_channel_get_caller_data(sigmsg->channel);
2145 chanid = ftdm_channel_get_id(sigmsg->channel);
2146 spanid = ftdm_channel_get_span_id(sigmsg->channel);
2147
2148 if (on_common_signal(sigmsg) == FTDM_BREAK) {
2149 return FTDM_SUCCESS;
2150 }
2151
2152 switch(sigmsg->event_id) {
2153 case FTDM_SIGEVENT_START:
2154 {
2155 ftdm_call_add_var(caller_data, "screening_ind", ftdm_screening2str(caller_data->screen));
2156 ftdm_call_add_var(caller_data, "presentation_ind", ftdm_presentation2str(caller_data->pres));
2157 return ftdm_channel_from_event(sigmsg, &session);
2158 }
2159 break;
2160
2161 case FTDM_SIGEVENT_STOP:
2162 case FTDM_SIGEVENT_RESTART:
2163 {
2164 private_t *tech_pvt = NULL;
2165 while((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
2166 tech_pvt = switch_core_session_get_private(session);
2167 switch_set_flag_locked(tech_pvt, TFLAG_DEAD);
2168 channel = switch_core_session_get_channel(session);
2169 switch_channel_hangup(channel, caller_data->hangup_cause);
2170 ftdm_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session));
2171 switch_core_session_rwunlock(session);
2172 }
2173 }
2174 break;
2175 case FTDM_SIGEVENT_UP:
2176 {
2177 if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
2178 channel = switch_core_session_get_channel(session);
2179 switch_channel_mark_answered(channel);
2180 ftdm_enable_channel_dtmf(sigmsg->channel, channel);
2181 switch_core_session_rwunlock(session);
2182 } else {
2183 const char *uuid = ftdm_channel_get_uuid(sigmsg->channel, 0);
2184
2185 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session for channel %d:%d not found [UUID: %s]\n",
2186 spanid, chanid, (uuid) ? uuid : "N/A");
2187 }
2188 }
2189 case FTDM_SIGEVENT_PROGRESS_MEDIA:
2190 {
2191 if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
2192 channel = switch_core_session_get_channel(session);
2193 switch_channel_mark_pre_answered(channel);
2194 switch_core_session_rwunlock(session);
2195 } else {
2196 const char *uuid = ftdm_channel_get_uuid(sigmsg->channel, 0);
2197
2198 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session for channel %d:%d not found [UUID: %s]\n",
2199 spanid, chanid, (uuid) ? uuid : "N/A");
2200 }
2201 }
2202 break;
2203 case FTDM_SIGEVENT_PROGRESS:
2204 case FTDM_SIGEVENT_RINGING:
2205 {
2206 if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
2207 channel = switch_core_session_get_channel(session);
2208 switch_channel_mark_ring_ready(channel);
2209 switch_core_session_rwunlock(session);
2210 } else {
2211 const char *uuid = ftdm_channel_get_uuid(sigmsg->channel, 0);
2212
2213 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Session for channel %d:%d not found [UUID: %s]\n",
2214 spanid, chanid, (uuid) ? uuid : "N/A");
2215 }
2216 }
2217 break;
2218 case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
2219 {
2220 ftdm_signaling_status_t sigstatus = sigmsg->ev_data.sigstatus.status;
2221 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d:%d signalling changed to :%s\n",
2222 spanid, chanid, ftdm_signaling_status2str(sigstatus));
2223 }
2224 break;
2225 case FTDM_SIGEVENT_PROCEED:
2226 case FTDM_SIGEVENT_FACILITY:
2227
2228 break;
2229 default:
2230 {
2231 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled msg type %d for channel %d:%d\n",
2232 sigmsg->event_id, spanid, chanid);
2233 }
2234 break;
2235 }
2236
2237 return FTDM_SUCCESS;
2238 }
2239
2240 static FIO_SIGNAL_CB_FUNCTION(on_analog_signal)
2241 {
2242 uint32_t spanid, chanid;
2243 ftdm_chan_type_t type;
2244 switch_status_t status = SWITCH_STATUS_FALSE;
2245
2246 spanid = ftdm_channel_get_span_id(sigmsg->channel);
2247 chanid = ftdm_channel_get_span_id(sigmsg->channel);
2248 type = ftdm_channel_get_type(sigmsg->channel);
2249
2250 if (on_common_signal(sigmsg) == FTDM_BREAK) {
2251 return FTDM_SUCCESS;
2252 }
2253
2254 switch (type) {
2255 case FTDM_CHAN_TYPE_FXO:
2256 case FTDM_CHAN_TYPE_EM:
2257 {
2258 status = on_fxo_signal(sigmsg);
2259 }
2260 break;
2261 case FTDM_CHAN_TYPE_FXS:
2262 {
2263 status = on_fxs_signal(sigmsg);
2264 }
2265 break;
2266 default:
2267 {
2268 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled analog channel type %d for channel %d:%d\n",
2269 type, spanid, chanid);
2270 }
2271 break;
2272 }
2273
2274 return status;
2275 }
2276
2277 static void ftdm_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
2278 {
2279 char *data = NULL;
2280 va_list ap;
2281
2282 va_start(ap, fmt);
2283
2284 if (switch_vasprintf(&data, fmt, ap) != -1) {
2285 switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, (char *)func, line, NULL, level, "%s", data);
2286 }
2287 if (data) free(data);
2288 va_end(ap);
2289
2290 }
2291
2292 static uint32_t enable_analog_option(const char *str, uint32_t current_options)
2293 {
2294 if (!strcasecmp(str, "3-way")) {
2295 current_options |= ANALOG_OPTION_3WAY;
2296 current_options &= ~ANALOG_OPTION_CALL_SWAP;
2297 } else if (!strcasecmp(str, "call-swap")) {
2298 current_options |= ANALOG_OPTION_CALL_SWAP;
2299 current_options &= ~ANALOG_OPTION_3WAY;
2300 }
2301
2302 return current_options;
2303
2304 }
2305
2306
2307
2308
2309 static int add_config_list_nodes(switch_xml_t swnode, ftdm_conf_node_t *rootnode,
2310 const char *list_name, const char *list_element_name,
2311 const char *sub_list_name, const char *sub_list_element_name)
2312 {
2313 char *var, *val;
2314 switch_xml_t list;
2315 switch_xml_t element;
2316 switch_xml_t param;
2317
2318 ftdm_conf_node_t *n_list;
2319 ftdm_conf_node_t *n_element;
2320
2321 list = switch_xml_child(swnode, list_name);
2322 if (!list) {
2323 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no list %s found\n", list_name);
2324 return -1;
2325 }
2326
2327 if ((FTDM_SUCCESS != ftdm_conf_node_create(list_name, &n_list, rootnode))) {
2328 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create %s node\n", list_name);
2329 return -1;
2330 }
2331
2332 for (element = switch_xml_child(list, list_element_name); element; element = element->next) {
2333 char *element_name = (char *) switch_xml_attr(element, "name");
2334
2335 if (!element_name) {
2336 continue;
2337 }
2338
2339 if ((FTDM_SUCCESS != ftdm_conf_node_create(list_element_name, &n_element, n_list))) {
2340 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create %s node for %s\n", list_element_name, element_name);
2341 return -1;
2342 }
2343 ftdm_conf_node_add_param(n_element, "name", element_name);
2344
2345 for (param = switch_xml_child(element, "param"); param; param = param->next) {
2346 var = (char *) switch_xml_attr_soft(param, "name");
2347 val = (char *) switch_xml_attr_soft(param, "value");
2348 ftdm_conf_node_add_param(n_element, var, val);
2349 }
2350
2351 if (sub_list_name && sub_list_element_name) {
2352 if (add_config_list_nodes(element, n_element, sub_list_name, sub_list_element_name, NULL, NULL)) {
2353 return -1;
2354 }
2355 }
2356 }
2357
2358 return 0;
2359 }
2360
2361 static ftdm_conf_node_t *get_ss7_config_node(switch_xml_t cfg, const char *confname)
2362 {
2363 switch_xml_t signode, ss7configs, isup;
2364 ftdm_conf_node_t *rootnode;
2365
2366
2367 rootnode = switch_core_hash_find(globals.ss7_configs, confname);
2368 if (rootnode) {
2369 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "ss7 config %s was found in the hash already\n", confname);
2370 return rootnode;
2371 }
2372 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "not found %s config in hash, searching in xml ...\n", confname);
2373
2374 signode = switch_xml_child(cfg, "signaling_configs");
2375 if (!signode) {
2376 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not found 'signaling_configs' XML config section\n");
2377 return NULL;
2378 }
2379
2380 ss7configs = switch_xml_child(signode, "sngss7_configs");
2381 if (!ss7configs) {
2382 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not found 'sngss7_configs' XML config section\n");
2383 return NULL;
2384 }
2385
2386
2387 for (isup = switch_xml_child(ss7configs, "sng_isup"); isup; isup = isup->next) {
2388 char *name = (char *) switch_xml_attr(isup, "name");
2389 if (!name) {
2390 continue;
2391 }
2392 if (!strcasecmp(name, confname)) {
2393 break;
2394 }
2395 }
2396
2397 if (!isup) {
2398 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not found '%s' sng_isup XML config section\n", confname);
2399 return NULL;
2400 }
2401
2402
2403 if ((FTDM_SUCCESS != ftdm_conf_node_create("sng_isup", &rootnode, NULL))) {
2404 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create root node for sng_isup config %s\n", confname);
2405 return NULL;
2406 }
2407
2408
2409 if (add_config_list_nodes(isup, rootnode, "mtp_linksets", "mtp_linkset", "mtp_links", "mtp_link")) {
2410 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp_linksets for sng_isup config %s\n", confname);
2411 ftdm_conf_node_destroy(rootnode);
2412 return NULL;
2413 }
2414
2415
2416 if (add_config_list_nodes(isup, rootnode, "mtp_routes", "mtp_route", NULL, NULL)) {
2417 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp_routes for sng_isup config %s\n", confname);
2418 ftdm_conf_node_destroy(rootnode);
2419 return NULL;
2420 }
2421
2422
2423 if (add_config_list_nodes(isup, rootnode, "isup_interfaces", "isup_interface", NULL, NULL)) {
2424 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process isup_interfaces for sng_isup config %s\n", confname);
2425 ftdm_conf_node_destroy(rootnode);
2426 return NULL;
2427 }
2428
2429 switch_core_hash_insert(globals.ss7_configs, confname, rootnode);
2430
2431 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Added SS7 node configuration %s\n", confname);
2432 return rootnode;
2433 }
2434
2435 static int add_profile_parameters(switch_xml_t cfg, const char *profname, ftdm_conf_parameter_t *parameters, int len)
2436 {
2437 switch_xml_t profnode, profile, param;
2438 int paramindex = 0;
2439
2440 profnode = switch_xml_child(cfg, "config_profiles");
2441 if (!profnode) {
2442 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot find profile '%s', there is no 'config_profiles' XML section\n", profname);
2443 return 0;
2444 }
2445
2446
2447 for (profile = switch_xml_child(profnode, "profile"); profile; profile = profile->next) {
2448 char *name = (char *) switch_xml_attr(profile, "name");
2449 if (!name) {
2450 continue;
2451 }
2452 if (!strcasecmp(name, profname)) {
2453 break;
2454 }
2455 }
2456
2457 if (!profile) {
2458 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to find profile '%s'\n", profname);
2459 return 0;
2460 }
2461
2462 for (param = switch_xml_child(profile, "param"); param; param = param->next) {
2463 char *var = (char *) switch_xml_attr_soft(param, "name");
2464 char *val = (char *) switch_xml_attr_soft(param, "value");
2465 if (!var || !val) {
2466 continue;
2467 }
2468 parameters[paramindex].var = var;
2469 parameters[paramindex].val = val;
2470 paramindex++;
2471 }
2472
2473 return paramindex;
2474 }
2475
2476 static void parse_bri_pri_spans(switch_xml_t cfg, switch_xml_t spans)
2477 {
2478 switch_xml_t myspan, param;
2479
2480 for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
2481 ftdm_status_t zstatus = FTDM_FAIL;
2482 const char *context = "default";
2483 const char *dialplan = "XML";
2484 ftdm_conf_parameter_t spanparameters[30];
2485 char *id = (char *) switch_xml_attr(myspan, "id");
2486 char *name = (char *) switch_xml_attr(myspan, "name");
2487 char *configname = (char *) switch_xml_attr(myspan, "cfgprofile");
2488 ftdm_span_t *span = NULL;
2489 uint32_t span_id = 0;
2490 unsigned paramindex = 0;
2491
2492 if (!name && !id) {
2493 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sangoma isdn span missing required attribute 'id' or 'name', skipping ...\n");
2494 continue;
2495 }
2496
2497 if (name) {
2498 zstatus = ftdm_span_find_by_name(name, &span);
2499 } else {
2500 if (switch_is_number(id)) {
2501 span_id = atoi(id);
2502 zstatus = ftdm_span_find(span_id, &span);
2503 }
2504
2505 if (zstatus != FTDM_SUCCESS) {
2506 zstatus = ftdm_span_find_by_name(id, &span);
2507 }
2508 }
2509
2510 if (zstatus != FTDM_SUCCESS) {
2511 ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
2512 continue;
2513 }
2514
2515 if (!span_id) {
2516 span_id = ftdm_span_get_id(span);
2517 }
2518
2519 memset(spanparameters, 0, sizeof(spanparameters));
2520 paramindex = 0;
2521
2522 if (configname) {
2523 paramindex = add_profile_parameters(cfg, configname, spanparameters, ftdm_array_len(spanparameters));
2524 if (paramindex) {
2525 ftdm_log(FTDM_LOG_DEBUG, "Added %d parameters from profile %s for span %d\n", paramindex, configname, span_id);
2526 }
2527 }
2528
2529
2530 SPAN_CONFIG[span_id].limit_backend = "hash";
2531 SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_TIMEOUT;
2532
2533 for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
2534 char *var = (char *) switch_xml_attr_soft(param, "name");
2535 char *val = (char *) switch_xml_attr_soft(param, "value");
2536
2537 if (ftdm_array_len(spanparameters) - 1 == paramindex) {
2538 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Too many parameters for ss7 span, ignoring any parameter after %s\n", var);
2539 break;
2540 }
2541
2542 if (!strcasecmp(var, "context")) {
2543 context = val;
2544 } else if (!strcasecmp(var, "dialplan")) {
2545 dialplan = val;
2546 } else if (!strcasecmp(var, "call_limit_backend")) {
2547 SPAN_CONFIG[span_id].limit_backend = val;
2548 ftdm_log(FTDM_LOG_DEBUG, "Using limit backend %s for span %d\n", SPAN_CONFIG[span_id].limit_backend, span_id);
2549 } else if (!strcasecmp(var, "call_limit_rate")) {
2550 int calls;
2551 int seconds;
2552 if (sscanf(val, "%d/%d", &calls, &seconds) != 2) {
2553 ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter, format example: 3/1 for 3 calls per second\n", var);
2554 } else {
2555 if (calls < 1 || seconds < 1) {
2556 ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter value, minimum call limit must be 1 per second\n", var);
2557 } else {
2558 SPAN_CONFIG[span_id].limit_calls = calls;
2559 SPAN_CONFIG[span_id].limit_seconds = seconds;
2560 }
2561 }
2562 } else if (!strcasecmp(var, "call_limit_reset_event")) {
2563 if (!strcasecmp(val, "answer")) {
2564 SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_ANSWER;
2565 } else {
2566 ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter value, only accepted event is 'answer'\n", var);
2567 }
2568 } else {
2569 spanparameters[paramindex].var = var;
2570 spanparameters[paramindex].val = val;
2571 paramindex++;
2572 }
2573 }
2574
2575 if (ftdm_configure_span_signaling(span,
2576 "sangoma_isdn",
2577 on_clear_channel_signal,
2578 spanparameters) != FTDM_SUCCESS) {
2579 ftdm_log(FTDM_LOG_ERROR, "Error configuring Sangoma ISDN FreeTDM span %d\n", span_id);
2580 continue;
2581 }
2582 SPAN_CONFIG[span_id].span = span;
2583 switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context));
2584 switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan));
2585 switch_copy_string(SPAN_CONFIG[span_id].type, "Sangoma (ISDN)", sizeof(SPAN_CONFIG[span_id].type));
2586 ftdm_log(FTDM_LOG_DEBUG, "Configured Sangoma ISDN FreeTDM span %d\n", span_id);
2587 ftdm_span_start(span);
2588 }
2589 }
2590
2591 static switch_status_t load_config(void)
2592 {
2593 const char *cf = "freetdm.conf";
2594 switch_xml_t cfg, xml, settings, param, spans, myspan;
2595 ftdm_conf_node_t *ss7confnode = NULL;
2596 ftdm_span_t *boost_spans[FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN];
2597 ftdm_span_t *boost_span = NULL;
2598 unsigned boosti = 0;
2599 unsigned int i = 0;
2600 ftdm_channel_t *fchan = NULL;
2601 ftdm_iterator_t *chaniter = NULL;
2602 ftdm_iterator_t *curr = NULL;
2603
2604 memset(boost_spans, 0, sizeof(boost_spans));
2605 memset(&globals, 0, sizeof(globals));
2606 switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, module_pool);
2607 if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
2608 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open of %s failed\n", cf);
2609 return SWITCH_STATUS_TERM;
2610 }
2611
2612 if ((settings = switch_xml_child(cfg, "settings"))) {
2613 for (param = switch_xml_child(settings, "param"); param; param = param->next) {
2614 char *var = (char *) switch_xml_attr_soft(param, "name");
2615 char *val = (char *) switch_xml_attr_soft(param, "value");
2616
2617 if (!strcasecmp(var, "debug")) {
2618 globals.debug = atoi(val);
2619 } else if (!strcasecmp(var, "hold-music")) {
2620 switch_set_string(globals.hold_music, val);
2621 } else if (!strcasecmp(var, "crash-on-assert")) {
2622 globals.crash_on_assert = switch_true(val);
2623 } else if (!strcasecmp(var, "sip-headers")) {
2624 globals.sip_headers = switch_true(val);
2625 } else if (!strcasecmp(var, "enable-analog-option")) {
2626 globals.analog_options = enable_analog_option(val, globals.analog_options);
2627 }
2628 }
2629 }
2630
2631 if ((spans = switch_xml_child(cfg, "sangoma_pri_spans"))) {
2632 parse_bri_pri_spans(cfg, spans);
2633 }
2634
2635 if ((spans = switch_xml_child(cfg, "sangoma_bri_spans"))) {
2636 parse_bri_pri_spans(cfg, spans);
2637 }
2638
2639 switch_core_hash_init(&globals.ss7_configs, module_pool);
2640 if ((spans = switch_xml_child(cfg, "sangoma_ss7_spans"))) {
2641 for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
2642 ftdm_status_t zstatus = FTDM_FAIL;
2643 const char *context = "default";
2644 const char *dialplan = "XML";
2645 ftdm_conf_parameter_t spanparameters[30];
2646 char *id = (char *) switch_xml_attr(myspan, "id");
2647 char *name = (char *) switch_xml_attr(myspan, "name");
2648 char *configname = (char *) switch_xml_attr(myspan, "config");
2649 ftdm_span_t *span = NULL;
2650 uint32_t span_id = 0;
2651 unsigned paramindex = 0;
2652 if (!name && !id) {
2653 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ss7 span missing required attribute 'id' or 'name', skipping ...\n");
2654 continue;
2655 }
2656 if (!configname) {
2657 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ss7 span missing required attribute, skipping ...\n");
2658 continue;
2659 }
2660 if (name) {
2661 zstatus = ftdm_span_find_by_name(name, &span);
2662 } else {
2663 if (switch_is_number(id)) {
2664 span_id = atoi(id);
2665 zstatus = ftdm_span_find(span_id, &span);
2666 }
2667
2668 if (zstatus != FTDM_SUCCESS) {
2669 zstatus = ftdm_span_find_by_name(id, &span);
2670 }
2671 }
2672
2673 if (zstatus != FTDM_SUCCESS) {
2674 ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
2675 continue;
2676 }
2677
2678 if (!span_id) {
2679 span_id = ftdm_span_get_id(span);
2680 }
2681
2682 ss7confnode = get_ss7_config_node(cfg, configname);
2683 if (!ss7confnode) {
2684 ftdm_log(FTDM_LOG_ERROR, "Error finding ss7config '%s' for FreeTDM span id: %s\n", configname, switch_str_nil(id));
2685 continue;
2686 }
2687
2688 memset(spanparameters, 0, sizeof(spanparameters));
2689 paramindex = 0;
2690 spanparameters[paramindex].var = "confnode";
2691 spanparameters[paramindex].ptr = ss7confnode;
2692 paramindex++;
2693 for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
2694 char *var = (char *) switch_xml_attr_soft(param, "name");
2695 char *val = (char *) switch_xml_attr_soft(param, "value");
2696
2697 if (ftdm_array_len(spanparameters) - 1 == paramindex) {
2698 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Too many parameters for ss7 span, ignoring any parameter after %s\n", var);
2699 break;
2700 }
2701
2702 if (!strcasecmp(var, "context")) {
2703 context = val;
2704 } else if (!strcasecmp(var, "dialplan")) {
2705 dialplan = val;
2706 } else {
2707 spanparameters[paramindex].var = var;
2708 spanparameters[paramindex].val = val;
2709 paramindex++;
2710 }
2711 }
2712
2713 if (ftdm_configure_span_signaling(span,
2714 "sangoma_ss7",
2715 on_clear_channel_signal,
2716 spanparameters) != FTDM_SUCCESS) {
2717 ftdm_log(FTDM_LOG_ERROR, "Error configuring ss7 FreeTDM span %d\n", span_id);
2718 continue;
2719 }
2720 SPAN_CONFIG[span_id].span = span;
2721 switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context));
2722 switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan));
2723 switch_copy_string(SPAN_CONFIG[span_id].type, "Sangoma (SS7)", sizeof(SPAN_CONFIG[span_id].type));
2724 ftdm_log(FTDM_LOG_DEBUG, "Configured ss7 FreeTDM span %d with config node %s\n", span_id, configname);
2725 ftdm_span_start(span);
2726 }
2727 }
2728
2729 if ((spans = switch_xml_child(cfg, "analog_spans"))) {
2730 for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
2731 char *id = (char *) switch_xml_attr(myspan, "id");
2732 char *name = (char *) switch_xml_attr(myspan, "name");
2733 ftdm_status_t zstatus = FTDM_FAIL;
2734 const char *context = "default";
2735 const char *dialplan = "XML";
2736 const char *tonegroup = NULL;
2737 char *digit_timeout = NULL;
2738 char *max_digits = NULL;
2739 char *hotline = NULL;
2740 char *dial_regex = NULL;
2741 char *hold_music = NULL;
2742 char *fail_dial_regex = NULL;
2743 const char *enable_callerid = "true";
2744 const char *answer_polarity = "false";
2745 const char *hangup_polarity = "false";
2746 int polarity_delay = 600;
2747 int callwaiting = 1;
2748
2749 uint32_t span_id = 0, to = 0, max = 0;
2750 ftdm_span_t *span = NULL;
2751 analog_option_t analog_options = ANALOG_OPTION_NONE;
2752
2753 if (name) {
2754 zstatus = ftdm_span_find_by_name(name, &span);
2755 } else {
2756 if (switch_is_number(id)) {
2757 span_id = atoi(id);
2758 zstatus = ftdm_span_find(span_id, &span);
2759 }
2760
2761 if (zstatus != FTDM_SUCCESS) {
2762 zstatus = ftdm_span_find_by_name(id, &span);
2763 }
2764 }
2765
2766 if (zstatus != FTDM_SUCCESS) {
2767 ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
2768 continue;
2769 }
2770
2771 if (!span_id) {
2772 span_id = ftdm_span_get_id(span);
2773 }
2774
2775
2776 SPAN_CONFIG[span_id].limit_backend = "hash";
2777 SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_TIMEOUT;
2778
2779 for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
2780 char *var = (char *) switch_xml_attr_soft(param, "name");
2781 char *val = (char *) switch_xml_attr_soft(param, "value");
2782
2783 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "analog_spans var = %s\n", var);
2784 if (!strcasecmp(var, "tonegroup")) {
2785 tonegroup = val;
2786 } else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "digit-timeout")) {
2787 digit_timeout = val;
2788 } else if (!strcasecmp(var, "context")) {
2789 context = val;
2790 } else if (!strcasecmp(var, "dialplan")) {
2791 dialplan = val;
2792 } else if (!strcasecmp(var, "call_limit_backend")) {
2793 SPAN_CONFIG[span_id].limit_backend = val;
2794 ftdm_log(FTDM_LOG_DEBUG, "Using limit backend %s for span %d\n", SPAN_CONFIG[span_id].limit_backend, span_id);
2795 } else if (!strcasecmp(var, "call_limit_rate")) {
2796 int calls;
2797 int seconds;
2798 if (sscanf(val, "%d/%d", &calls, &seconds) != 2) {
2799 ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter, format example: 3/1 for 3 calls per second\n", var);
2800 } else {
2801 if (calls < 1 || seconds < 1) {
2802 ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter value, minimum call limit must be 1 per second\n", var);
2803 } else {
2804 SPAN_CONFIG[span_id].limit_calls = calls;
2805 SPAN_CONFIG[span_id].limit_seconds = seconds;
2806 }
2807 }
2808 } else if (!strcasecmp(var, "call_limit_reset_event")) {
2809 if (!strcasecmp(val, "answer")) {
2810 SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_ANSWER;
2811 } else {
2812 ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter value, only accepted event is 'answer'\n", var);
2813 }
2814 } else if (!strcasecmp(var, "dial-regex")) {
2815 dial_regex = val;
2816 } else if (!strcasecmp(var, "enable-callerid")) {
2817 enable_callerid = val;
2818 } else if (!strcasecmp(var, "answer-polarity-reverse")) {
2819 answer_polarity = val;
2820 } else if (!strcasecmp(var, "hangup-polarity-reverse")) {
2821 hangup_polarity = val;
2822 } else if (!strcasecmp(var, "polarity-delay")) {
2823 polarity_delay = atoi(val);
2824 } else if (!strcasecmp(var, "fail-dial-regex")) {
2825 fail_dial_regex = val;
2826 } else if (!strcasecmp(var, "hold-music")) {
2827 hold_music = val;
2828 } else if (!strcasecmp(var, "max_digits") || !strcasecmp(var, "max-digits")) {
2829 max_digits = val;
2830 } else if (!strcasecmp(var, "hotline")) {
2831 hotline = val;
2832 } else if (!strcasecmp(var, "callwaiting")) {
2833 callwaiting = switch_true(val) ? 1 : 0;
2834 } else if (!strcasecmp(var, "enable-analog-option")) {
2835 analog_options = enable_analog_option(val, analog_options);
2836 }
2837 }
2838
2839 if (!id && !name) {
2840 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\n");
2841 continue;
2842 }
2843
2844 if (!tonegroup) {
2845 tonegroup = "us";
2846 }
2847
2848 if (digit_timeout) {
2849 to = atoi(digit_timeout);
2850 }
2851
2852 if (max_digits) {
2853 max = atoi(max_digits);
2854 }
2855
2856 if (name) {
2857 zstatus = ftdm_span_find_by_name(name, &span);
2858 } else {
2859 if (switch_is_number(id)) {
2860 span_id = atoi(id);
2861 zstatus = ftdm_span_find(span_id, &span);
2862 }
2863
2864 if (zstatus != FTDM_SUCCESS) {
2865 zstatus = ftdm_span_find_by_name(id, &span);
2866 }
2867 }
2868
2869 if (zstatus != FTDM_SUCCESS) {
2870 ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
2871 continue;
2872 }
2873
2874 if (!span_id) {
2875 span_id = ftdm_span_get_id(span);
2876 }
2877
2878 if (ftdm_configure_span(span, "analog", on_analog_signal,
2879 "tonemap", tonegroup,
2880 "digit_timeout", &to,
2881 "max_dialstr", &max,
2882 "hotline", hotline ? hotline : "",
2883 "enable_callerid", enable_callerid,
2884 "answer_polarity_reverse", answer_polarity,
2885 "hangup_polarity_reverse", hangup_polarity,
2886 "polarity_delay", &polarity_delay,
2887 "callwaiting", &callwaiting,
2888 FTDM_TAG_END) != FTDM_SUCCESS) {
2889 ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM analog span %s\n", ftdm_span_get_name(span));
2890 continue;
2891 }
2892
2893 SPAN_CONFIG[span_id].span = span;
2894 switch_set_string(SPAN_CONFIG[span_id].context, context);
2895 switch_set_string(SPAN_CONFIG[span_id].dialplan, dialplan);
2896 SPAN_CONFIG[span_id].analog_options = analog_options | globals.analog_options;
2897
2898 chaniter = ftdm_span_get_chan_iterator(span, NULL);
2899 curr = chaniter;
2900 for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
2901 fchan = ftdm_iterator_current(curr);
2902 ftdm_channel_set_private(fchan, &SPAN_CONFIG[span_id].pvts[i]);
2903 }
2904 ftdm_iterator_free(chaniter);
2905
2906 if (dial_regex) {
2907 switch_set_string(SPAN_CONFIG[span_id].dial_regex, dial_regex);
2908 }
2909
2910 if (fail_dial_regex) {
2911 switch_set_string(SPAN_CONFIG[span_id].fail_dial_regex, fail_dial_regex);
2912 }
2913
2914 if (hold_music) {
2915 switch_set_string(SPAN_CONFIG[span_id].hold_music, hold_music);
2916 }
2917 switch_copy_string(SPAN_CONFIG[span_id].type, "analog", sizeof(SPAN_CONFIG[span_id].type));
2918 ftdm_span_start(span);
2919 }
2920 }
2921
2922 if ((spans = switch_xml_child(cfg, "analog_em_spans"))) {
2923 for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
2924 char *id = (char *) switch_xml_attr(myspan, "id");
2925 char *name = (char *) switch_xml_attr(myspan, "name");
2926 ftdm_status_t zstatus = FTDM_FAIL;
2927 const char *context = "default";
2928 const char *dialplan = "XML";
2929 const char *tonegroup = NULL;
2930 char *digit_timeout = NULL;
2931 char *max_digits = NULL;
2932 char *dial_regex = NULL;
2933 char *hold_music = NULL;
2934 char *fail_dial_regex = NULL;
2935 uint32_t span_id = 0, to = 0, max = 0;
2936 ftdm_span_t *span = NULL;
2937 analog_option_t analog_options = ANALOG_OPTION_NONE;
2938
2939 for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
2940 char *var = (char *) switch_xml_attr_soft(param, "name");
2941 char *val = (char *) switch_xml_attr_soft(param, "value");
2942
2943 if (!strcasecmp(var, "tonegroup")) {
2944 tonegroup = val;
2945 } else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "digit-timeout")) {
2946 digit_timeout = val;
2947 } else if (!strcasecmp(var, "context")) {
2948 context = val;
2949 } else if (!strcasecmp(var, "dialplan")) {
2950 dialplan = val;
2951 } else if (!strcasecmp(var, "dial-regex")) {
2952 dial_regex = val;
2953 } else if (!strcasecmp(var, "fail-dial-regex")) {
2954 fail_dial_regex = val;
2955 } else if (!strcasecmp(var, "hold-music")) {
2956 hold_music = val;
2957 } else if (!strcasecmp(var, "max_digits") || !strcasecmp(var, "max-digits")) {
2958 max_digits = val;
2959 } else if (!strcasecmp(var, "enable-analog-option")) {
2960 analog_options = enable_analog_option(val, analog_options);
2961 }
2962 }
2963
2964 if (!id && !name) {
2965 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\n");
2966 continue;
2967 }
2968
2969
2970 if (!tonegroup) {
2971 tonegroup = "us";
2972 }
2973
2974 if (digit_timeout) {
2975 to = atoi(digit_timeout);
2976 }
2977
2978 if (max_digits) {
2979 max = atoi(max_digits);
2980 }
2981
2982
2983 if (name) {
2984 zstatus = ftdm_span_find_by_name(name, &span);
2985 } else {
2986 if (switch_is_number(id)) {
2987 span_id = atoi(id);
2988 zstatus = ftdm_span_find(span_id, &span);
2989 }
2990
2991 if (zstatus != FTDM_SUCCESS) {
2992 zstatus = ftdm_span_find_by_name(id, &span);
2993 }
2994 }
2995
2996 if (zstatus != FTDM_SUCCESS) {
2997 ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
2998 continue;
2999 }
3000
3001 if (!span_id) {
3002 span_id = ftdm_span_get_id(span);
3003 }
3004
3005
3006 if (ftdm_configure_span(span, "analog_em", on_analog_signal,
3007 "tonemap", tonegroup,
3008 "digit_timeout", &to,
3009 "max_dialstr", &max,
3010 FTDM_TAG_END) != FTDM_SUCCESS) {
3011 ftdm_log(FTDM_LOG_ERROR, "Error starting FreeTDM span %d\n", span_id);
3012 continue;
3013 }
3014
3015 SPAN_CONFIG[span_id].span = span;
3016 switch_set_string(SPAN_CONFIG[span_id].context, context);
3017 switch_set_string(SPAN_CONFIG[span_id].dialplan, dialplan);
3018 SPAN_CONFIG[span_id].analog_options = analog_options | globals.analog_options;
3019
3020 if (dial_regex) {
3021 switch_set_string(SPAN_CONFIG[span_id].dial_regex, dial_regex);
3022 }
3023
3024 if (fail_dial_regex) {
3025 switch_set_string(SPAN_CONFIG[span_id].fail_dial_regex, fail_dial_regex);
3026 }
3027
3028 if (hold_music) {
3029 switch_set_string(SPAN_CONFIG[span_id].hold_music, hold_music);
3030 }
3031 switch_copy_string(SPAN_CONFIG[span_id].type, "analog_em", sizeof(SPAN_CONFIG[span_id].type));
3032 ftdm_span_start(span);
3033 }
3034 }
3035
3036 if ((spans = switch_xml_child(cfg, "pri_spans"))) {
3037 for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
3038 char *name = (char *) switch_xml_attr(myspan, "name");
3039 ftdm_conf_parameter_t spanparameters[10];
3040 ftdm_status_t zstatus = FTDM_FAIL;
3041 const char *context = "default";
3042 const char *dialplan = "XML";
3043 unsigned paramindex = 0;
3044 ftdm_span_t *span = NULL;
3045 uint32_t span_id = 0;
3046
3047 if (!name) {
3048 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required attribute 'name'\n");
3049 continue;
3050 }
3051
3052 memset(spanparameters, 0, sizeof(spanparameters));
3053
3054 for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
3055 char *var = (char *) switch_xml_attr_soft(param, "name");
3056 char *val = (char *) switch_xml_attr_soft(param, "value");
3057
3058 if (ftdm_array_len(spanparameters) - 1 == paramindex) {
3059 ftdm_log(FTDM_LOG_ERROR, "Too many parameters for pri span '%s', ignoring everything after '%s'\n", name, var);
3060 break;
3061 }
3062
3063 if (ftdm_strlen_zero(var) || ftdm_strlen_zero(val)) {
3064 ftdm_log(FTDM_LOG_WARNING, "Skipping parameter with empty name or value\n");
3065 continue;
3066 }
3067
3068 if (!strcasecmp(var, "context")) {
3069 context = val;
3070 } else if (!strcasecmp(var, "dialplan")) {
3071 dialplan = val;
3072 } else {
3073 spanparameters[paramindex].var = var;
3074 spanparameters[paramindex].val = val;
3075 paramindex++;
3076 }
3077 }
3078
3079 zstatus = ftdm_span_find_by_name(name, &span);
3080 if (zstatus != FTDM_SUCCESS) {
3081 ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span %s\n", name);
3082 continue;
3083 }
3084
3085 span_id = ftdm_span_get_id(span);
3086 if (ftdm_configure_span_signaling(span, "isdn", on_clear_channel_signal, spanparameters) != FTDM_SUCCESS) {
3087 ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM span %s\n", name);
3088 continue;
3089 }
3090
3091 SPAN_CONFIG[span_id].span = span;
3092 switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context));
3093 switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan));
3094 switch_copy_string(SPAN_CONFIG[span_id].type, "isdn", sizeof(SPAN_CONFIG[span_id].type));
3095
3096 ftdm_span_start(span);
3097 }
3098 }
3099
3100 if ((spans = switch_xml_child(cfg, "pritap_spans"))) {
3101 for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
3102
3103 char *name = (char *) switch_xml_attr(myspan, "name");
3104
3105 ftdm_status_t zstatus = FTDM_FAIL;
3106 unsigned paramindex = 0;
3107 ftdm_conf_parameter_t spanparameters[10];
3108 const char *context = "default";
3109 const char *dialplan = "XML";
3110 ftdm_span_t *span = NULL;
3111 int span_id = 0;
3112
3113 if (!name) {
3114 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required attribute 'name'\n");
3115 continue;
3116 }
3117
3118 memset(spanparameters, 0, sizeof(spanparameters));
3119
3120 for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
3121 char *var = (char *) switch_xml_attr_soft(param, "name");
3122 char *val = (char *) switch_xml_attr_soft(param, "value");
3123
3124 if (ftdm_array_len(spanparameters) - 1 == paramindex) {
3125 ftdm_log(FTDM_LOG_ERROR, "Too many parameters for pritap span '%s', ignoring everything after '%s'\n", name, var);
3126 break;
3127 }
3128
3129 if (!strcasecmp(var, "context")) {
3130 context = val;
3131 } else if (!strcasecmp(var, "dialplan")) {
3132 dialplan = val;
3133 } else {
3134 spanparameters[paramindex].var = var;
3135 spanparameters[paramindex].val = val;
3136 paramindex++;
3137 }
3138 }
3139
3140 zstatus = ftdm_span_find_by_name(name, &span);
3141 if (zstatus != FTDM_SUCCESS) {
3142 ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span %s\n", name);
3143 continue;
3144 }
3145
3146 span_id = ftdm_span_get_id(span);
3147 if (ftdm_configure_span_signaling(span, "pritap", on_clear_channel_signal, spanparameters) != FTDM_SUCCESS) {
3148 ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM span %s\n", name);
3149 continue;
3150 }
3151
3152 SPAN_CONFIG[span_id].span = span;
3153 switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context));
3154 switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan));
3155 switch_copy_string(SPAN_CONFIG[span_id].type, "isdn", sizeof(SPAN_CONFIG[span_id].type));
3156
3157 ftdm_span_start(span);
3158 }
3159 }
3160
3161
3162 if ((spans = switch_xml_child(cfg, "libpri_spans"))) {
3163 for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
3164 char *name = (char *) switch_xml_attr(myspan, "name");
3165 ftdm_conf_parameter_t spanparameters[10];
3166 ftdm_status_t zstatus = FTDM_FAIL;
3167 const char *context = "default";
3168 const char *dialplan = "XML";
3169 unsigned paramindex = 0;
3170 ftdm_span_t *span = NULL;
3171 uint32_t span_id = 0;
3172
3173 if (!name) {
3174 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required attribute 'name'\n");
3175 continue;
3176 }
3177
3178 memset(spanparameters, 0, sizeof(spanparameters));
3179
3180 for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
3181 char *var = (char *) switch_xml_attr_soft(param, "name");
3182 char *val = (char *) switch_xml_attr_soft(param, "value");
3183
3184 if (ftdm_array_len(spanparameters) - 1 == paramindex) {
3185 ftdm_log(FTDM_LOG_ERROR, "Too many parameters for libpri span, ignoring everything after '%s'\n", var);
3186 break;
3187 }
3188
3189 if (ftdm_strlen_zero(var) || ftdm_strlen_zero(val)) {
3190 ftdm_log(FTDM_LOG_WARNING, "Skipping parameter with empty name or value\n");
3191 continue;
3192 }
3193
3194 if (!strcasecmp(var, "context")) {
3195 context = val;
3196 } else if (!strcasecmp(var, "dialplan")) {
3197 dialplan = val;
3198 } else {
3199 spanparameters[paramindex].var = var;
3200 spanparameters[paramindex].val = val;
3201 paramindex++;
3202 }
3203 }
3204
3205 zstatus = ftdm_span_find_by_name(name, &span);
3206 if (zstatus != FTDM_SUCCESS) {
3207 ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span %s\n", name);
3208 continue;
3209 }
3210
3211 span_id = ftdm_span_get_id(span);
3212 if (ftdm_configure_span_signaling(span, "libpri", on_clear_channel_signal, spanparameters) != FTDM_SUCCESS) {
3213 ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM span %s\n", name);
3214 continue;
3215 }
3216
3217 SPAN_CONFIG[span_id].span = span;
3218 switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context));
3219 switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan));
3220 switch_copy_string(SPAN_CONFIG[span_id].type, "isdn", sizeof(SPAN_CONFIG[span_id].type));
3221
3222 ftdm_span_start(span);
3223 }
3224 }
3225
3226 if ((spans = switch_xml_child(cfg, "boost_spans"))) {
3227 for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
3228 char *id = (char *) switch_xml_attr(myspan, "id");
3229 char *name = (char *) switch_xml_attr(myspan, "name");
3230 char *sigmod = (char *) switch_xml_attr(myspan, "sigmod");
3231 ftdm_status_t zstatus = FTDM_FAIL;
3232 const char *context = "default";
3233 const char *dialplan = "XML";
3234 uint32_t span_id = 0;
3235 ftdm_span_t *span = NULL;
3236 ftdm_conf_parameter_t spanparameters[30];
3237 unsigned paramindex = 0;
3238
3239 if (!id && !name) {
3240 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "boost span requires an id or name as attribute: <span id=ftid|name=ftname>\n");
3241 continue;
3242 }
3243 memset(spanparameters, 0, sizeof(spanparameters));
3244 if (sigmod) {
3245 spanparameters[paramindex].var = "sigmod";
3246 spanparameters[paramindex].val = sigmod;
3247 paramindex++;
3248 }
3249
3250 for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
3251 char *var = (char *) switch_xml_attr_soft(param, "name");
3252 char *val = (char *) switch_xml_attr_soft(param, "value");
3253
3254 if (ftdm_array_len(spanparameters) - 1 == paramindex) {
3255 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Too many parameters for boost span, ignoring any parameter after %s\n", var);
3256 break;
3257 }
3258
3259 if (!strcasecmp(var, "context")) {
3260 context = val;
3261 } else if (!strcasecmp(var, "dialplan")) {
3262 dialplan = val;
3263 } else {
3264 spanparameters[paramindex].var = var;
3265 spanparameters[paramindex].val = val;
3266 paramindex++;
3267 }
3268 }
3269
3270 if (name) {
3271 zstatus = ftdm_span_find_by_name(name, &span);
3272 } else {
3273 if (switch_is_number(id)) {
3274 span_id = atoi(id);
3275 zstatus = ftdm_span_find(span_id, &span);
3276 }
3277
3278 if (zstatus != FTDM_SUCCESS) {
3279 zstatus = ftdm_span_find_by_name(id, &span);
3280 }
3281 }
3282
3283 if (zstatus != FTDM_SUCCESS) {
3284 ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
3285 continue;
3286 }
3287
3288 if (!span_id) {
3289 span_id = ftdm_span_get_id(span);
3290 }
3291
3292 if (ftdm_configure_span_signaling(span, "sangoma_boost", on_clear_channel_signal, spanparameters) != FTDM_SUCCESS) {
3293 ftdm_log(FTDM_LOG_ERROR, "Error starting FreeTDM span %d error: %s\n", span_id, ftdm_span_get_last_error(span));
3294 continue;
3295 }
3296
3297 SPAN_CONFIG[span_id].span = span;
3298 switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context));
3299 switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan));
3300
3301 switch_copy_string(SPAN_CONFIG[span_id].type, "Sangoma (boost)", sizeof(SPAN_CONFIG[span_id].type));
3302 boost_spans[boosti++] = span;
3303 }
3304 }
3305
3306 if ((spans = switch_xml_child(cfg, "r2_spans"))) {
3307 for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
3308 char *name = (char *) switch_xml_attr(myspan, "name");
3309 char *configname = (char *) switch_xml_attr(myspan, "cfgprofile");
3310 ftdm_status_t zstatus = FTDM_FAIL;
3311
3312
3313 const char *context = "default";
3314 const char *dialplan = "XML";
3315 char *dial_regex = NULL;
3316 char *fail_dial_regex = NULL;
3317 uint32_t span_id = 0;
3318 ftdm_span_t *span = NULL;
3319
3320 ftdm_conf_parameter_t spanparameters[30];
3321 unsigned paramindex = 0;
3322
3323 if (!name) {
3324 switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "'name' attribute required for R2 spans!\n");
3325 continue;
3326 }
3327
3328 memset(spanparameters, 0, sizeof(spanparameters));
3329
3330 if (configname) {
3331 paramindex = add_profile_parameters(cfg, configname, spanparameters, ftdm_array_len(spanparameters));
3332 if (paramindex) {
3333 ftdm_log(FTDM_LOG_DEBUG, "Added %d parameters from profile %s for span %d\n", paramindex, configname, span_id);
3334 }
3335 }
3336
3337 for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
3338 char *var = (char *) switch_xml_attr_soft(param, "name");
3339 char *val = (char *) switch_xml_attr_soft(param, "value");
3340
3341
3342 if (!strcasecmp(var, "context")) {
3343 context = val;
3344 } else if (!strcasecmp(var, "dialplan")) {
3345 dialplan = val;
3346 } else if (!strcasecmp(var, "dial-regex")) {
3347 dial_regex = val;
3348 } else if (!strcasecmp(var, "fail-dial-regex")) {
3349 fail_dial_regex = val;
3350 } else {
3351 spanparameters[paramindex].var = var;
3352 spanparameters[paramindex].val = val;
3353 paramindex++;
3354 }
3355 }
3356
3357 zstatus = ftdm_span_find_by_name(name, &span);
3358 if (zstatus != FTDM_SUCCESS) {
3359 ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM R2 Span '%s'\n", name);
3360 continue;
3361 }
3362 span_id = ftdm_span_get_id(span);
3363
3364 if (ftdm_configure_span_signaling(span, "r2", on_r2_signal, spanparameters) != FTDM_SUCCESS) {
3365 ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM R2 span %s, error: %s\n",
3366 name, ftdm_span_get_last_error(span));
3367 continue;
3368 }
3369
3370 if (dial_regex) {
3371 switch_set_string(SPAN_CONFIG[span_id].dial_regex, dial_regex);
3372 }
3373
3374 if (fail_dial_regex) {
3375 switch_set_string(SPAN_CONFIG[span_id].fail_dial_regex, fail_dial_regex);
3376 }
3377
3378 SPAN_CONFIG[span_id].span = span;
3379 switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context));
3380 switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan));
3381 switch_copy_string(SPAN_CONFIG[span_id].type, "R2", sizeof(SPAN_CONFIG[span_id].type));
3382
3383 if (ftdm_span_start(span) == FTDM_FAIL) {
3384 ftdm_log(FTDM_LOG_ERROR, "Error starting FreeTDM R2 span %s, error: %s\n", name, ftdm_span_get_last_error(span));
3385 continue;
3386 }
3387 }
3388 }
3389
3390
3391
3392 for (i=0 ; i < boosti; i++) {
3393 boost_span = boost_spans[i];
3394 ftdm_log(FTDM_LOG_DEBUG, "Starting boost span %d\n", ftdm_span_get_id(boost_span));
3395 if (ftdm_span_start(boost_span) == FTDM_FAIL) {
3396 ftdm_log(FTDM_LOG_ERROR, "Error starting boost FreeTDM span %d, error: %s\n",
3397 ftdm_span_get_id(boost_span), ftdm_span_get_last_error(boost_span));
3398 continue;
3399 }
3400 }
3401
3402 if (globals.crash_on_assert) {
3403 ftdm_log(FTDM_LOG_WARNING, "Crash on assert enabled\n");
3404 ftdm_global_set_crash_policy(FTDM_CRASH_ON_ASSERT);
3405 }
3406
3407 switch_xml_free(xml);
3408
3409 return SWITCH_STATUS_SUCCESS;
3410 }
3411
3412 void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream)
3413 {
3414 uint32_t span_id;
3415 uint32_t phspan_id, phchan_id;
3416 const char *chan_type;
3417 const char *state;
3418 const char *last_state;
3419 const char *uuid = NULL;
3420 char sessionid[255];
3421 float txgain, rxgain;
3422 switch_core_session_t *session = NULL;
3423 ftdm_alarm_flag_t alarmflag;
3424 ftdm_caller_data_t *caller_data;
3425 ftdm_channel_t *ftdmchan;
3426 ftdm_signaling_status_t sigstatus = FTDM_SIG_STATE_DOWN;
3427
3428 if (chan_id > ftdm_span_get_chan_count(span)) {
3429 return;
3430 }
3431
3432 strcpy(sessionid, "(none)");
3433 ftdmchan = ftdm_span_get_channel(span, chan_id);
3434 span_id = ftdm_span_get_id(span);
3435
3436 phspan_id = ftdm_channel_get_ph_span_id(ftdmchan);
3437 phchan_id = ftdm_channel_get_ph_id(ftdmchan);
3438 chan_type = ftdm_chan_type2str(ftdm_channel_get_type(ftdmchan));
3439 state = ftdm_channel_get_state_str(ftdmchan);
3440 last_state = ftdm_channel_get_last_state_str(ftdmchan);
3441 ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_RX_GAIN, &rxgain);
3442 ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_TX_GAIN, &txgain);
3443 caller_data = ftdm_channel_get_caller_data(ftdmchan);
3444 ftdm_channel_get_sig_status(ftdmchan, &sigstatus);
3445 ftdm_channel_get_alarms(ftdmchan, &alarmflag);
3446
3447 uuid = ftdm_channel_get_uuid(ftdmchan, 0);
3448 if (!zstr(uuid)) {
3449 if (!(session = switch_core_session_locate(uuid))) {
3450 snprintf(sessionid, sizeof(sessionid), "%s (dead)", uuid);
3451 } else {
3452 snprintf(sessionid, sizeof(sessionid), "%s", uuid);
3453 switch_core_session_rwunlock(session);
3454 }
3455 }
3456
3457 stream->write_function(stream,
3458 "span_id: %u\n"
3459 "chan_id: %u\n"
3460 "physical_span_id: %u\n"
3461 "physical_chan_id: %u\n"
3462 "physical_status: %s\n"
3463 "signaling_status: %s\n"
3464 "type: %s\n"
3465 "state: %s\n"
3466 "last_state: %s\n"
3467 "txgain: %3.2f\n"
3468 "rxgain: %3.2f\n"
3469 "cid_date: %s\n"
3470 "cid_name: %s\n"
3471 "cid_num: %s\n"
3472 "ani: %s\n"
3473 "aniII: %s\n"
3474 "dnis: %s\n"
3475 "rdnis: %s\n"
3476 "cause: %s\n"
3477 "session: %s\n\n",
3478 span_id,
3479 chan_id,
3480 phspan_id,
3481 phchan_id,
3482 alarmflag ? "alarmed" : "ok",
3483 ftdm_signaling_status2str(sigstatus),
3484 chan_type,
3485 state,
3486 last_state,
3487 txgain,
3488 rxgain,
3489 caller_data->cid_date,
3490 caller_data->cid_name,
3491 caller_data->cid_num.digits,
3492 caller_data->ani.digits,
3493 caller_data->aniII,
3494 caller_data->dnis.digits,
3495 caller_data->rdnis.digits,
3496 switch_channel_cause2str(caller_data->hangup_cause),
3497 sessionid);
3498 }
3499
3500 void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream)
3501 {
3502 uint32_t span_id;
3503 uint32_t phspan_id, phchan_id;
3504 const char *chan_type;
3505 const char *state;
3506 const char *last_state;
3507 float txgain, rxgain;
3508 ftdm_caller_data_t *caller_data;
3509 ftdm_channel_t *ftdmchan;
3510 ftdm_alarm_flag_t alarmflag;
3511 ftdm_signaling_status_t sigstatus = FTDM_SIG_STATE_DOWN;
3512
3513 if (chan_id > ftdm_span_get_chan_count(span)) {
3514 return;
3515 }
3516
3517 ftdmchan = ftdm_span_get_channel(span, chan_id);
3518 span_id = ftdm_span_get_id(span);
3519
3520 phspan_id = ftdm_channel_get_ph_span_id(ftdmchan);
3521 phchan_id = ftdm_channel_get_ph_id(ftdmchan);
3522 chan_type = ftdm_chan_type2str(ftdm_channel_get_type(ftdmchan));
3523 state = ftdm_channel_get_state_str(ftdmchan);
3524 last_state = ftdm_channel_get_last_state_str(ftdmchan);
3525 ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_RX_GAIN, &rxgain);
3526 ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_TX_GAIN, &txgain);
3527 caller_data = ftdm_channel_get_caller_data(ftdmchan);
3528 ftdm_channel_get_sig_status(ftdmchan, &sigstatus);
3529 ftdm_channel_get_alarms(ftdmchan, &alarmflag);
3530
3531
3532 stream->write_function(stream,
3533 " <channel>\n"
3534 " <span-id>%u</span-id>\n"
3535 " <chan-id>%u</chan-id>>\n"
3536 " <physical-span-id>%u</physical-span-id>\n"
3537 " <physical-chan-id>%u</physical-chan-id>\n"
3538 " <physical-status>%s</physical-status>\n"
3539 " <signaling-status>%s</signaling-status>\n"
3540 " <type>%s</type>\n"
3541 " <state>%s</state>\n"
3542 " <last-state>%s</last-state>\n"
3543 " <txgain>%3.2f</txgain>\n"
3544 " <rxgain>%3.2f</rxgain>\n"
3545 " <cid-date>%s</cid-date>\n"
3546 " <cid-name>%s</cid-name>\n"
3547 " <cid-num>%s</cid-num>\n"
3548 " <ani>%s</ani>\n"
3549 " <aniII>%s</aniII>\n"
3550 " <dnis>%s</dnis>\n"
3551 " <rdnis>%s</rdnis>\n"
3552 " <cause>%s</cause>\n"
3553 " </channel>\n",
3554 span_id,
3555 chan_id,
3556 phspan_id,
3557 phchan_id,
3558 alarmflag ? "alarmed" : "ok",
3559 ftdm_signaling_status2str(sigstatus),
3560 chan_type,
3561 state,
3562 last_state,
3563 txgain,
3564 rxgain,
3565 caller_data->cid_date,
3566 caller_data->cid_name,
3567 caller_data->cid_num.digits,
3568 caller_data->ani.digits,
3569 caller_data->aniII,
3570 caller_data->dnis.digits,
3571 caller_data->rdnis.digits,
3572 switch_channel_cause2str(caller_data->hangup_cause));
3573 }
3574
3575 #define FT_SYNTAX "USAGE:\n" \
3576 "--------------------------------------------------------------------------------\n" \
3577 "ftdm list\n" \
3578 "ftdm start|stop <span_name|span_id>\n" \
3579 "ftdm restart <span_id|span_name> <chan_id>\n" \
3580 "ftdm dump <span_id|span_name> [<chan_id>]\n" \
3581 "ftdm sigstatus get|set [<span_id|span_name>] [<channel>] [<sigstatus>]\n" \
3582 "ftdm trace <path> <span_id|span_name> [<chan_id>]\n" \
3583 "ftdm notrace <span_id|span_name> [<chan_id>]\n" \
3584 "ftdm q931_pcap <span_id> on|off [pcapfilename without suffix]\n" \
3585 "ftdm gains <txgain> <rxgain> <span_id> [<chan_id>]\n" \
3586 "ftdm dtmf on|off <span_id> [<chan_id>]\n" \
3587 "--------------------------------------------------------------------------------\n"
3588 SWITCH_STANDARD_API(ft_function)
3589 {
3590 char *mycmd = NULL, *argv[10] = { 0 };
3591 int argc = 0;
3592 ftdm_iterator_t *chaniter = NULL;
3593 ftdm_iterator_t *curr = NULL;
3594
3595 if (!zstr(cmd) && (mycmd = strdup(cmd))) {
3596 argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
3597 }
3598
3599 if (!argc) {
3600 stream->write_function(stream, "%s", FT_SYNTAX);
3601 goto end;
3602 }
3603
3604 if (!strcasecmp(argv[0], "sigstatus")) {
3605 ftdm_span_t *span = NULL;
3606 ftdm_signaling_status_t sigstatus;
3607
3608 if (argc < 3) {
3609 stream->write_function(stream, "-ERR Usage: ftdm sigstatus get|set [<span_id>] [<channel>] [<sigstatus>]\n");
3610 goto end;
3611 }
3612 if (!strcasecmp(argv[1], "get") && argc < 3) {
3613 stream->write_function(stream, "-ERR sigstatus get usage: get <span_id>\n");
3614 goto end;
3615 }
3616 if (!strcasecmp(argv[1], "set") && argc != 5) {
3617 stream->write_function(stream, "-ERR sigstatus set usage: set <span_id> <channel>|all <sigstatus>\n");
3618 goto end;
3619 }
3620
3621 ftdm_span_find_by_name(argv[2], &span);
3622 if (!span) {
3623 stream->write_function(stream, "-ERR invalid span\n");
3624 goto end;
3625 }
3626
3627 if (!strcasecmp(argv[1], "get")) {
3628 if (argc == 4) {
3629 uint32_t chan_id = atol(argv[3]);
3630 ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id);
3631 if (!fchan) {
3632 stream->write_function(stream, "-ERR failed to get channel id '%d'\n", chan_id);
3633 goto end;
3634 }
3635
3636 if ((FTDM_SUCCESS == ftdm_channel_get_sig_status(fchan, &sigstatus))) {
3637 stream->write_function(stream, "channel %d signaling status: %s\n", chan_id, ftdm_signaling_status2str(sigstatus));
3638 } else {
3639 stream->write_function(stream, "-ERR failed to get channel sigstatus\n");
3640 }
3641 goto end;
3642 } else {
3643 if ((FTDM_SUCCESS == ftdm_span_get_sig_status(span, &sigstatus))) {
3644 stream->write_function(stream, "signaling_status: %s\n", ftdm_signaling_status2str(sigstatus));
3645 } else {
3646 stream->write_function(stream, "-ERR failed to read span status: %s\n", ftdm_span_get_last_error(span));
3647 }
3648 }
3649 goto end;
3650 }
3651 if (!strcasecmp(argv[1], "set")) {
3652 sigstatus = ftdm_str2ftdm_signaling_status(argv[4]);
3653
3654 if (!strcasecmp(argv[3], "all")) {
3655 if ((FTDM_SUCCESS == ftdm_span_set_sig_status(span, sigstatus))) {
3656 stream->write_function(stream, "Signaling status of all channels from span %s set to %s\n",
3657 ftdm_span_get_name(span), ftdm_signaling_status2str(sigstatus));
3658 } else {
3659 stream->write_function(stream, "-ERR failed to set span sigstatus to '%s'\n", ftdm_signaling_status2str(sigstatus));
3660 }
3661 goto end;
3662 } else {
3663 uint32_t chan_id = atol(argv[3]);
3664 ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id);
3665 if (!fchan) {
3666 stream->write_function(stream, "-ERR failed to get channel id '%d'\n", chan_id);
3667 goto end;
3668 }
3669
3670 if ((FTDM_SUCCESS == ftdm_channel_set_sig_status(fchan, sigstatus))) {
3671 stream->write_function(stream, "Signaling status of channel %d set to %s\n", chan_id,
3672 ftdm_signaling_status2str(sigstatus));
3673 } else {
3674 stream->write_function(stream, "-ERR failed to set span sigstatus to '%s'\n", ftdm_signaling_status2str(sigstatus));
3675 }
3676 goto end;
3677 }
3678 }
3679
3680 } else if (!strcasecmp(argv[0], "dump")) {
3681 if (argc < 2) {
3682 stream->write_function(stream, "-ERR Usage: ftdm dump <span_id> [<chan_id>]\n");
3683 goto end;
3684 } else {
3685 uint32_t chan_id = 0;
3686 ftdm_span_t *span;
3687 char *as = NULL;
3688
3689 ftdm_span_find_by_name(argv[1], &span);
3690
3691 if (argc > 2) {
3692 if (argv[3] && !strcasecmp(argv[2], "as")) {
3693 as = argv[3];
3694 } else {
3695 chan_id = atoi(argv[2]);
3696 }
3697 }
3698
3699 if (argv[4] && !strcasecmp(argv[3], "as")) {
3700 as = argv[4];
3701 }
3702
3703 if (!zstr(as) && !strcasecmp(as, "xml")) {
3704 stream->write_function(stream, "<channels>\n");
3705 if (!span) {
3706 stream->write_function(stream, "<error>invalid span</error>\n");
3707 } else {
3708 if (chan_id) {
3709 if(chan_id > ftdm_span_get_chan_count(span)) {
3710 stream->write_function(stream, "<error>invalid channel</error>\n");
3711 } else {
3712 dump_chan_xml(span, chan_id, stream);
3713 }
3714 } else {
3715 chaniter = ftdm_span_get_chan_iterator(span, NULL);
3716 for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
3717 dump_chan_xml(span, ftdm_channel_get_id(ftdm_iterator_current(curr)), stream);
3718 }
3719 ftdm_iterator_free(chaniter);
3720
3721 }
3722 }
3723 stream->write_function(stream, "</channels>\n");
3724 } else {
3725 if (!span) {
3726 stream->write_function(stream, "-ERR invalid span\n");
3727 } else {
3728 if (chan_id) {
3729 if(chan_id > ftdm_span_get_chan_count(span)) {
3730 stream->write_function(stream, "-ERR invalid channel\n");
3731 } else {
3732 char *dbgstr = NULL;
3733 ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id);
3734 dump_chan(span, chan_id, stream);
3735 dbgstr = ftdm_channel_get_history_str(fchan);
3736 stream->write_function(stream, "%s\n", dbgstr);
3737 ftdm_free(dbgstr);
3738 }
3739 } else {
3740 stream->write_function(stream, "+OK\n");
3741 chaniter = ftdm_span_get_chan_iterator(span, NULL);
3742 for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
3743 dump_chan(span, ftdm_channel_get_id(ftdm_iterator_current(curr)), stream);
3744 }
3745 ftdm_iterator_free(chaniter);
3746
3747 }
3748 }
3749 }
3750 }
3751 } else if (!strcasecmp(argv[0], "list")) {
3752 int j;
3753 for (j = 0 ; j < FTDM_MAX_SPANS_INTERFACE; j++) {
3754 if (SPAN_CONFIG[j].span) {
3755 ftdm_channel_t *fchan;
3756 ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE;
3757 const char *flags = "none";
3758 ftdm_signaling_status_t sigstatus;
3759
3760 if (SPAN_CONFIG[j].analog_options & ANALOG_OPTION_3WAY) {
3761 flags = "3way";
3762 } else if (SPAN_CONFIG[j].analog_options & ANALOG_OPTION_CALL_SWAP) {
3763 flags = "call swap";
3764 }
3765 fchan = ftdm_span_get_channel(SPAN_CONFIG[j].span, 1);
3766 if (fchan) {
3767 ftdm_channel_get_alarms(fchan, &alarmbits);
3768 }
3769
3770 if ((FTDM_SUCCESS == ftdm_span_get_sig_status(SPAN_CONFIG[j].span, &sigstatus))) {
3771 stream->write_function(stream,
3772 "+OK\n"
3773 "span: %u (%s)\n"
3774 "type: %s\n"
3775 "physical_status: %s\n"
3776 "signaling_status: %s\n"
3777 "chan_count: %u\n"
3778 "dialplan: %s\n"
3779 "context: %s\n"
3780 "dial_regex: %s\n"
3781 "fail_dial_regex: %s\n"
3782 "hold_music: %s\n"
3783 "analog_options %s\n",
3784 j,
3785 ftdm_span_get_name(SPAN_CONFIG[j].span),
3786 SPAN_CONFIG[j].type,
3787 alarmbits ? "alarmed" : "ok",
3788 ftdm_signaling_status2str(sigstatus),
3789 ftdm_span_get_chan_count(SPAN_CONFIG[j].span),
3790 SPAN_CONFIG[j].dialplan,
3791 SPAN_CONFIG[j].context,
3792 SPAN_CONFIG[j].dial_regex,
3793 SPAN_CONFIG[j].fail_dial_regex,
3794 SPAN_CONFIG[j].hold_music,
3795 flags
3796 );
3797 } else {
3798 stream->write_function(stream,
3799 "+OK\n"
3800 "span: %u (%s)\n"
3801 "type: %s\n"
3802 "physical_status: %s\n"
3803 "chan_count: %u\n"
3804 "dialplan: %s\n"
3805 "context: %s\n"
3806 "dial_regex: %s\n"
3807 "fail_dial_regex: %s\n"
3808 "hold_music: %s\n"
3809 "analog_options %s\n",
3810 j,
3811 ftdm_span_get_name(SPAN_CONFIG[j].span),
3812 SPAN_CONFIG[j].type,
3813 alarmbits ? "alarmed" : "ok",
3814 ftdm_span_get_chan_count(SPAN_CONFIG[j].span),
3815 SPAN_CONFIG[j].dialplan,
3816 SPAN_CONFIG[j].context,
3817 SPAN_CONFIG[j].dial_regex,
3818 SPAN_CONFIG[j].fail_dial_regex,
3819 SPAN_CONFIG[j].hold_music,
3820 flags
3821 );
3822 }
3823 }
3824 }
3825 } else if (!strcasecmp(argv[0], "stop") || !strcasecmp(argv[0], "start")) {
3826 char *span_name = argv[1];
3827 ftdm_span_t *span = NULL;
3828 ftdm_status_t status;
3829
3830 if (span_name) {
3831 ftdm_span_find_by_name(span_name, &span);
3832 }
3833
3834 if (!span) {
3835 stream->write_function(stream, "-ERR no span\n");
3836 goto end;
3837 }
3838
3839 if (!strcasecmp(argv[0], "stop")) {
3840 status = ftdm_span_stop(span);
3841 } else {
3842 status = ftdm_span_start(span);
3843 }
3844
3845 stream->write_function(stream, status == FTDM_SUCCESS ? "+OK\n" : "-ERR failure\n");
3846
3847 goto end;
3848
3849
3850 } else if (!strcasecmp(argv[0], "q931_pcap")) {
3851 int32_t span_id = 0;
3852 ftdm_span_t *span;
3853 const char *pcapfn = NULL;
3854 char *tmp_path = NULL;
3855
3856 if (argc < 3) {
3857 stream->write_function(stream, "-ERR Usage: ftdm q931_pcap <span_id> on|off [pcapfilename without suffix]\n");
3858 goto end;
3859 }
3860 span_id = atoi(argv[1]);
3861 if (!(span_id && (span = SPAN_CONFIG[span_id].span))) {
3862 stream->write_function(stream, "-ERR invalid span\n");
3863 goto end;
3864 }
3865
3866
3867 if (argc > 3) {
3868 if(argv[3]){
3869 pcapfn=argv[3];
3870 }
3871 }
3872 else {
3873 pcapfn="q931";
3874 }
3875
3876
3877 tmp_path=switch_mprintf("%s%s%s.pcap", SWITCH_GLOBAL_dirs.log_dir, SWITCH_PATH_SEPARATOR, pcapfn);
3878
3879 if(!strcasecmp(argv[2], "on")) {
3880 if (ftdm_configure_span(span, "isdn", on_clear_channel_signal, "q931topcap", 1, "pcapfilename", tmp_path, FTDM_TAG_END) != FTDM_SUCCESS) {
3881 ftdm_log(FTDM_LOG_WARNING, "Error couldn't (re-)enable Q931-To-Pcap!\n");
3882 goto end;
3883 } else {
3884 stream->write_function(stream, "+OK\n");
3885 }
3886 } else if(!strcasecmp(argv[2], "off")) {
3887 if (ftdm_configure_span(span, "isdn", on_clear_channel_signal, "q931topcap", 0, FTDM_TAG_END) != FTDM_SUCCESS) {
3888 ftdm_log(FTDM_LOG_ERROR, "Error couldn't enable Q931-To-Pcap!\n");
3889 goto end;
3890 } else {
3891 stream->write_function(stream, "+OK\n");
3892 }
3893 } else {
3894 stream->write_function(stream, "-ERR Usage: ft q931_pcap <span_id> on|off [pcapfilename without suffix]\n");
3895 goto end;
3896 }
3897
3898 } else if (!strcasecmp(argv[0], "dtmf")) {
3899 unsigned i = 0;
3900 uint32_t chan_id = 0;
3901 unsigned schan_count = 0;
3902 ftdm_span_t *span = NULL;
3903 ftdm_command_t fcmd = FTDM_COMMAND_ENABLE_DTMF_DETECT;
3904 ftdm_channel_t *fchan;
3905 if (argc < 3) {
3906 stream->write_function(stream, "-ERR Usage: dtmf on|off <span_id> [<chan_id>]\n");
3907 goto end;
3908 }
3909
3910 if (switch_true(argv[1])) {
3911 fcmd = FTDM_COMMAND_ENABLE_DTMF_DETECT;
3912 } else {
3913 fcmd = FTDM_COMMAND_DISABLE_DTMF_DETECT;
3914 }
3915
3916 ftdm_span_find_by_name(argv[2], &span);
3917 if (!span) {
3918 stream->write_function(stream, "-ERR invalid span\n");
3919 goto end;
3920 }
3921 schan_count = ftdm_span_get_chan_count(span);
3922 if (argc > 3) {
3923 chan_id = atoi(argv[3]);
3924 if (chan_id > schan_count) {
3925 stream->write_function(stream, "-ERR invalid chan\n");
3926 goto end;
3927 }
3928 }
3929
3930 if (chan_id) {
3931 fchan = ftdm_span_get_channel(span, chan_id);
3932 ftdm_channel_command(fchan, fcmd, NULL);
3933 } else {
3934 for (i = 1; i <= schan_count; i++) {
3935 fchan = ftdm_span_get_channel(span, i);
3936 ftdm_channel_command(fchan, fcmd, NULL);
3937 }
3938 }
3939
3940 stream->write_function(stream, "+OK DTMF detection was %s\n", fcmd == FTDM_COMMAND_ENABLE_DTMF_DETECT ? "enabled" : "disabled");
3941 } else if (!strcasecmp(argv[0], "trace")) {
3942 char tracepath[255];
3943 unsigned i = 0;
3944 uint32_t chan_id = 0;
3945 uint32_t span_id = 0;
3946 uint32_t chan_count = 0;
3947 ftdm_span_t *span = NULL;
3948 ftdm_channel_t *chan = NULL;
3949 if (argc < 3) {
3950 stream->write_function(stream, "-ERR Usage: ftdm trace <path> <span_id> [<chan_id>]\n");
3951 goto end;
3952 }
3953 ftdm_span_find_by_name(argv[2], &span);
3954 if (!span) {
3955 stream->write_function(stream, "-ERR invalid span\n");
3956 goto end;
3957 }
3958 chan_count = ftdm_span_get_chan_count(span);
3959 if (argc > 3) {
3960 chan_id = atoi(argv[3]);
3961 if (chan_id > chan_count) {
3962 stream->write_function(stream, "-ERR invalid chan\n");
3963 goto end;
3964 }
3965 }
3966 span_id = ftdm_span_get_id(span);
3967 if (chan_id) {
3968 chan = ftdm_span_get_channel(span, chan_id);
3969 snprintf(tracepath, sizeof(tracepath), "%s-in-s%dc%d", argv[1], span_id, chan_id);
3970 ftdm_channel_command(chan, FTDM_COMMAND_TRACE_INPUT, tracepath);
3971 snprintf(tracepath, sizeof(tracepath), "%s-out-s%dc%d", argv[1], span_id, chan_id);
3972 ftdm_channel_command(chan, FTDM_COMMAND_TRACE_OUTPUT, tracepath);
3973 } else {
3974 for (i = 1; i <= chan_count; i++) {
3975 chan = ftdm_span_get_channel(span, i);
3976 snprintf(tracepath, sizeof(tracepath), "%s-in-s%dc%d", argv[1], span_id, i);
3977 ftdm_channel_command(chan, FTDM_COMMAND_TRACE_INPUT, tracepath);
3978 snprintf(tracepath, sizeof(tracepath), "%s-out-s%dc%d", argv[1], span_id, i);
3979 ftdm_channel_command(chan, FTDM_COMMAND_TRACE_OUTPUT, tracepath);
3980 }
3981 }
3982 stream->write_function(stream, "+OK trace enabled with prefix path %s\n", argv[1]);
3983 } else if (!strcasecmp(argv[0], "notrace")) {
3984 uint32_t i = 0;
3985 uint32_t chan_id = 0;
3986 uint32_t chan_count = 0;
3987 ftdm_channel_t *fchan = NULL;
3988 ftdm_span_t *span = NULL;
3989 if (argc < 2) {
3990 stream->write_function(stream, "-ERR Usage: ftdm notrace <span_id> [<chan_id>]\n");
3991 goto end;
3992 }
3993 ftdm_span_find_by_name(argv[1], &span);
3994 if (!span) {
3995 stream->write_function(stream, "-ERR invalid span\n");
3996 goto end;
3997 }
3998 chan_count = ftdm_span_get_chan_count(span);
3999 if (argc > 2) {
4000 chan_id = atoi(argv[2]);
4001 if (chan_id > chan_count) {
4002 stream->write_function(stream, "-ERR invalid chan\n");
4003 goto end;
4004 }
4005 }
4006 if (chan_id) {
4007 fchan = ftdm_span_get_channel(span, chan_id);
4008 ftdm_channel_command(fchan, FTDM_COMMAND_TRACE_END_ALL, NULL);
4009 } else {
4010 for (i = 1; i <= chan_count; i++) {
4011 fchan = ftdm_span_get_channel(span, i);
4012 ftdm_channel_command(fchan, FTDM_COMMAND_TRACE_END_ALL, NULL);
4013 }
4014 }
4015 stream->write_function(stream, "+OK trace disabled\n");
4016 } else if (!strcasecmp(argv[0], "gains")) {
4017 unsigned int i = 0;
4018 float txgain = 0.0;
4019 float rxgain = 0.0;
4020 uint32_t chan_id = 0;
4021 uint32_t ccount = 0;
4022 ftdm_channel_t *chan;
4023 ftdm_span_t *span = NULL;
4024 if (argc < 4) {
4025 stream->write_function(stream, "-ERR Usage: ft gains <txgain> <rxgain> <span_id> [<chan_id>]\n");
4026 goto end;
4027 }
4028 ftdm_span_find_by_name(argv[3], &span);
4029 if (!span) {
4030 stream->write_function(stream, "-ERR invalid span\n");
4031 goto end;
4032 }
4033 if (argc > 4) {
4034 chan_id = atoi(argv[4]);
4035 if (chan_id > ftdm_span_get_chan_count(span)) {
4036 stream->write_function(stream, "-ERR invalid chan\n");
4037 goto end;
4038 }
4039 }
4040 i = sscanf(argv[1], "%f", &rxgain);
4041 i += sscanf(argv[2], "%f", &txgain);
4042 if (i != 2) {
4043 stream->write_function(stream, "-ERR invalid gains\n");
4044 goto end;
4045 }
4046
4047 if (chan_id) {
4048 chan = ftdm_span_get_channel(span, chan_id);
4049 ftdm_channel_command(chan, FTDM_COMMAND_SET_RX_GAIN, &rxgain);
4050 ftdm_channel_command(chan, FTDM_COMMAND_SET_TX_GAIN, &txgain);
4051 } else {
4052 ccount = ftdm_span_get_chan_count(span);
4053 for (i = 1; i < ccount; i++) {
4054 chan = ftdm_span_get_channel(span, i);
4055 ftdm_channel_command(chan, FTDM_COMMAND_SET_RX_GAIN, &rxgain);
4056 ftdm_channel_command(chan, FTDM_COMMAND_SET_TX_GAIN, &txgain);
4057 }
4058 }
4059 stream->write_function(stream, "+OK gains set to Rx %f and Tx %f\n", rxgain, txgain);
4060 } else if (!strcasecmp(argv[0], "restart")) {
4061 uint32_t chan_id = 0;
4062 ftdm_channel_t *chan;
4063 ftdm_span_t *span = NULL;
4064 if (argc < 3) {
4065 stream->write_function(stream, "-ERR Usage: ftdm restart <span_id> <chan_id>\n");
4066 goto end;
4067 }
4068 ftdm_span_find_by_name(argv[1], &span);
4069 if (!span) {
4070 stream->write_function(stream, "-ERR invalid span\n");
4071 goto end;
4072 }
4073
4074 chan_id = atoi(argv[2]);
4075 chan = ftdm_span_get_channel(span, chan_id);
4076 if (!chan) {
4077 stream->write_function(stream, "-ERR Could not find chan\n");
4078 goto end;
4079 }
4080 stream->write_function(stream, "Resetting channel %s:%s\n", argv[2], argv[3]);
4081 ftdm_channel_reset(chan);
4082 } else {
4083
4084 char *rply = ftdm_api_execute(cmd);
4085
4086 if (rply) {
4087 stream->write_function(stream, "%s", rply);
4088 ftdm_free(rply);
4089 } else {
4090 stream->write_function(stream, "-ERR Usage: %s\n", FT_SYNTAX);
4091 }
4092 }
4093
4094
4095 end:
4096
4097 switch_safe_free(mycmd);
4098
4099 return SWITCH_STATUS_SUCCESS;
4100 }
4101
4102 SWITCH_STANDARD_APP(enable_dtmf_function)
4103 {
4104 private_t *tech_pvt;
4105 if (!switch_core_session_check_interface(session, freetdm_endpoint_interface)) {
4106 ftdm_log(FTDM_LOG_ERROR, "This application is only for FreeTDM channels.\n");
4107 return;
4108 }
4109
4110 tech_pvt = switch_core_session_get_private(session);
4111
4112 if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
4113 switch_channel_hangup(switch_core_session_get_channel(session), SWITCH_CAUSE_LOSE_RACE);
4114 return;
4115 }
4116
4117 ftdm_channel_command(tech_pvt->ftdmchan, FTDM_COMMAND_ENABLE_DTMF_DETECT, NULL);
4118 ftdm_log(FTDM_LOG_INFO, "DTMF detection enabled in channel %d:%d\n", ftdm_channel_get_id(tech_pvt->ftdmchan), ftdm_channel_get_span_id(tech_pvt->ftdmchan));
4119 }
4120
4121 SWITCH_STANDARD_APP(disable_dtmf_function)
4122 {
4123 private_t *tech_pvt;
4124 if (!switch_core_session_check_interface(session, freetdm_endpoint_interface)) {
4125 ftdm_log(FTDM_LOG_ERROR, "This application is only for FreeTDM channels.\n");
4126 return;
4127 }
4128
4129 tech_pvt = switch_core_session_get_private(session);
4130
4131 if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
4132 switch_channel_hangup(switch_core_session_get_channel(session), SWITCH_CAUSE_LOSE_RACE);
4133 return;
4134 }
4135
4136 ftdm_channel_command(tech_pvt->ftdmchan, FTDM_COMMAND_DISABLE_DTMF_DETECT, NULL);
4137 ftdm_log(FTDM_LOG_INFO, "DTMF detection Disabled in channel %d:%d\n", ftdm_channel_get_id(tech_pvt->ftdmchan), ftdm_channel_get_span_id(tech_pvt->ftdmchan));
4138 }
4139
4140 SWITCH_STANDARD_APP(disable_ec_function)
4141 {
4142 private_t *tech_pvt;
4143 int x = 0;
4144
4145 if (!switch_core_session_check_interface(session, freetdm_endpoint_interface)) {
4146 ftdm_log(FTDM_LOG_ERROR, "This application is only for FreeTDM channels.\n");
4147 return;
4148 }
4149
4150 tech_pvt = switch_core_session_get_private(session);
4151
4152 if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
4153 switch_channel_hangup(switch_core_session_get_channel(session), SWITCH_CAUSE_LOSE_RACE);
4154 return;
4155 }
4156
4157 ftdm_channel_command(tech_pvt->ftdmchan, FTDM_COMMAND_DISABLE_ECHOCANCEL, &x);
4158 ftdm_channel_command(tech_pvt->ftdmchan, FTDM_COMMAND_DISABLE_ECHOTRAIN, &x);
4159 ftdm_log(FTDM_LOG_INFO, "Echo Canceller Disabled\n");
4160 }
4161
4162
4163 SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load)
4164 {
4165
4166 switch_api_interface_t *commands_api_interface;
4167 switch_application_interface_t *app_interface;
4168
4169 module_pool = pool;
4170
4171 ftdm_global_set_logger(ftdm_logger);
4172
4173 ftdm_global_set_mod_directory(SWITCH_GLOBAL_dirs.mod_dir);
4174
4175 ftdm_global_set_config_directory(SWITCH_GLOBAL_dirs.conf_dir);
4176
4177 if (ftdm_global_init() != FTDM_SUCCESS) {
4178 ftdm_log(FTDM_LOG_ERROR, "Error loading FreeTDM\n");
4179 return SWITCH_STATUS_TERM;
4180 }
4181
4182 if (ftdm_global_configuration() != FTDM_SUCCESS) {
4183 ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM\n");
4184 return SWITCH_STATUS_TERM;
4185 }
4186
4187 if (load_config() != SWITCH_STATUS_SUCCESS) {
4188 ftdm_global_destroy();
4189 return SWITCH_STATUS_TERM;
4190 }
4191
4192 *module_interface = switch_loadable_module_create_module_interface(pool, modname);
4193 freetdm_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
4194 freetdm_endpoint_interface->interface_name = "freetdm";
4195 freetdm_endpoint_interface->io_routines = &freetdm_io_routines;
4196 freetdm_endpoint_interface->state_handler = &freetdm_state_handlers;
4197
4198 SWITCH_ADD_API(commands_api_interface, "ftdm", "FreeTDM commands", ft_function, FT_SYNTAX);
4199 switch_console_set_complete("add ftdm start");
4200 switch_console_set_complete("add ftdm stop");
4201 switch_console_set_complete("add ftdm retart");
4202 switch_console_set_complete("add ftdm dump");
4203 switch_console_set_complete("add ftdm sigstatus get");
4204 switch_console_set_complete("add ftdm sigstatus set");
4205 switch_console_set_complete("add ftdm trace");
4206 switch_console_set_complete("add ftdm notrace");
4207 switch_console_set_complete("add ftdm q931_pcap");
4208 switch_console_set_complete("add ftdm gains");
4209 switch_console_set_complete("add ftdm dtmf on");
4210 switch_console_set_complete("add ftdm dtmf off");
4211
4212
4213 SWITCH_ADD_APP(app_interface, "disable_ec", "Disable Echo Canceller", "Disable Echo Canceller", disable_ec_function, "", SAF_NONE);
4214 SWITCH_ADD_APP(app_interface, "disable_dtmf", "Disable DTMF Detection", "Disable DTMF Detection", disable_dtmf_function, "", SAF_NONE);
4215 SWITCH_ADD_APP(app_interface, "enable_dtmf", "Enable DTMF Detection", "Enable DTMF Detection", enable_dtmf_function, "", SAF_NONE);
4216
4217
4218 return SWITCH_STATUS_SUCCESS;
4219 }
4220
4221 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_freetdm_shutdown)
4222 {
4223 switch_hash_index_t *hi;
4224
4225 const void *var;
4226 void *val;
4227
4228
4229 for (hi = switch_hash_first(NULL, globals.ss7_configs); hi; hi = switch_hash_next(hi)) {
4230 switch_hash_this(hi, &var, NULL, &val);
4231 ftdm_conf_node_destroy(val);
4232 }
4233
4234 ftdm_global_destroy();
4235
4236
4237
4238 return SWITCH_STATUS_SUCCESS;
4239 }
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250