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_outgoing_channel
  24. ftdm_channel_from_event
  25. FIO_SIGNAL_CB_FUNCTION
  26. ftdm_enable_channel_dtmf
  27. FIO_SIGNAL_CB_FUNCTION
  28. FIO_SIGNAL_CB_FUNCTION
  29. FIO_SIGNAL_CB_FUNCTION
  30. FIO_SIGNAL_CB_FUNCTION
  31. FIO_SIGNAL_CB_FUNCTION
  32. ftdm_logger
  33. enable_analog_option
  34. add_config_list_nodes
  35. get_ss7_config_node
  36. add_profile_parameters
  37. parse_bri_pri_spans
  38. load_config
  39. dump_chan
  40. dump_chan_xml
  41. SWITCH_STANDARD_API
  42. SWITCH_STANDARD_APP
  43. SWITCH_STANDARD_APP
  44. SWITCH_STANDARD_APP
  45. SWITCH_MODULE_LOAD_FUNCTION
  46. SWITCH_MODULE_SHUTDOWN_FUNCTION

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

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