root/mod_freetdm/mod_freetdm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ftdm_channel_get_session
  2. ftdm_channel_get_uuid
  3. stop_hold
  4. start_hold
  5. cycle_foreground
  6. tech_init
  7. channel_on_init
  8. channel_on_routing
  9. channel_on_execute
  10. channel_on_destroy
  11. channel_on_hangup
  12. channel_kill_channel
  13. channel_on_exchange_media
  14. channel_on_soft_execute
  15. channel_send_dtmf
  16. channel_read_frame
  17. channel_write_frame
  18. channel_receive_message_cas
  19. channel_receive_message_b
  20. channel_receive_message_fxo
  21. channel_receive_message_fxs
  22. channel_receive_message
  23. channel_get_variable
  24. on_channel_found
  25. channel_outgoing_channel
  26. ftdm_enable_channel_dtmf
  27. ftdm_channel_from_event
  28. FIO_SIGNAL_CB_FUNCTION
  29. FIO_SIGNAL_CB_FUNCTION
  30. FIO_SIGNAL_CB_FUNCTION
  31. FIO_SIGNAL_CB_FUNCTION
  32. FIO_SIGNAL_CB_FUNCTION
  33. FIO_SIGNAL_CB_FUNCTION
  34. ftdm_logger
  35. enable_analog_option
  36. add_config_list_nodes
  37. get_ss7_config_node
  38. add_profile_parameters
  39. parse_bri_pri_spans
  40. load_config
  41. dump_chan
  42. dump_chan_xml
  43. SWITCH_STANDARD_API
  44. SWITCH_STANDARD_APP
  45. SWITCH_STANDARD_APP
  46. SWITCH_STANDARD_APP
  47. SWITCH_MODULE_LOAD_FUNCTION
  48. SWITCH_MODULE_SHUTDOWN_FUNCTION

   1 /* 
   2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
   3  * Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
   4  *
   5  * Version: MPL 1.1
   6  *
   7  * The contents of this file are subject to the Mozilla Public License Version
   8  * 1.1 (the "License"); you may not use this file except in compliance with
   9  * the License. You may obtain a copy of the License at
  10  * http://www.mozilla.org/MPL/
  11  *
  12  * Software distributed under the License is distributed on an "AS IS" basis,
  13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  14  * for the specific language governing rights and limitations under the
  15  * License.
  16  *
  17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
  18  *
  19  * The Initial Developer of the Original Code is
  20  * Anthony Minessale II <anthm@freeswitch.org>
  21  * Portions created by the Initial Developer are Copyright (C)
  22  * the Initial Developer. All Rights Reserved.
  23  *
  24  * Contributor(s):
  25  * 
  26  * Anthony Minessale II <anthm@freeswitch.org>
  27  * Moises Silva <moy@sangoma.com>
  28  * David Yat Sin <dyatsin@sangoma.com>
  29  *
  30  *
  31  * mod_freetdm.c -- FreeTDM Endpoint Module
  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 /* private data attached to each fs session */
  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 /* private data attached to FTDM channels (only FXS for now) */
 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         /* Move channel's state machine to ROUTING */
 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         //switch_channel_set_flag(channel, CF_ACCEPT_CNG);
 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         /* Digium Cards sometimes timeout several times in a row here. 
 629            Yes, we support digium cards, ain't we nice.......
 630            6 double length intervals should compensate */
 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         /*.on_init */ channel_on_init,
1032         /*.on_routing */ channel_on_routing,
1033         /*.on_execute */ channel_on_execute,
1034         /*.on_hangup */ channel_on_hangup,
1035         /*.on_exchange_media */ channel_on_exchange_media,
1036         /*.on_soft_execute */ channel_on_soft_execute,
1037         /*.on_consume_media */ NULL,
1038     /*.on_hibernate */ NULL,
1039     /*.on_reset */ NULL,
1040     /*.on_park*/ NULL,
1041     /*.on_reporting*/ NULL,
1042     /*.on_destroy*/ channel_on_destroy
1043 
1044 };
1045 
1046 switch_io_routines_t freetdm_io_routines = {
1047         /*.outgoing_channel */ channel_outgoing_channel,
1048         /*.read_frame */ channel_read_frame,
1049         /*.write_frame */ channel_write_frame,
1050         /*.kill_channel */ channel_kill_channel,
1051         /*.send_dtmf */ channel_send_dtmf,
1052         /*.receive_message*/ 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 /* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines
1137 that allocate memory or you will have 1 channel with memory allocated from another channel's pool!
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                 //Look for a group
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         /* blindly copy data from outbound_profile. They will be overwritten
1362          * by calling ftdm_caller_data if needed after */
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                 /* the variable is not present or has a negative value then proceed to enable DTMF ... */
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         /* I guess we always want DTMF detection */
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         /* Add any channel variable to the dial plan */
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         /* Add any call variable to the dial plan */
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                         /* clear any rate limit resource for this span */
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                         /* Swallow these events */
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: { /* twiddle */ } 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                 /* on_call_disconnect from the R2 side */
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                 /* on_call_offered from the R2 side */
2037                 case FTDM_SIGEVENT_START: 
2038                 {
2039                         status = ftdm_channel_from_event(sigmsg, &session);
2040                 }
2041                 break;
2042                 
2043                 /* on DNIS received from the R2 forward side, return status == FTDM_BREAK to stop requesting DNIS */
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                 /* FS does not have handlers for these messages, so ignore them for now */
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 /* create ftdm_conf_node_t tree based on a fixed pattern XML configuration list 
2307  * last 2 args are for limited aka dumb recursivity
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         /* try to find the conf in the hash first */
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         /* search the isup config */
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         /* found our XML chunk, create the root node */
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         /* add mtp linksets */
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         /* add mtp routes */
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         /* add isup interfaces */
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         /* search the profile */
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                 /* some defaults first */
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                         /* some defaults first */
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                         /* common non r2 stuff */
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                                 /* string parameters */
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         /* start all boost spans now that we're done configuring. Unfortunately at this point boost modules have the limitation
3391          * of needing all spans to be configured before starting them */
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                 /*Q931ToPcap enhancement*/
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                 /*Look for a given file name or use default file name*/
3867                 if (argc > 3) {
3868                         if(argv[3]){
3869                                 pcapfn=argv[3];
3870                         }
3871                 }
3872                 else {
3873                         pcapfn="q931";
3874                 }
3875 
3876                 /*Add log directory path to file name*/
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         /*Q931ToPcap enhancement done*/
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         /* indicate that the module should continue to be loaded */
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         /* destroy ss7 configs */
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         // this breaks pika but they are MIA so *shrug*
4237         //return SWITCH_STATUS_NOUNLOAD;
4238         return SWITCH_STATUS_SUCCESS;
4239 }
4240 
4241 /* For Emacs:
4242  * Local Variables:
4243  * mode:c
4244  * indent-tabs-mode:t
4245  * tab-width:4
4246  * c-basic-offset:4
4247  * End:
4248  * For VIM:
4249  * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
4250  */

/* [<][>][^][v][top][bottom][index][help] */