root/src/ftdm_io.c

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

DEFINITIONS

This source file includes following definitions.
  1. time_init
  2. time_end
  3. FT_DECLARE
  4. FTDM_ENUM_NAMES
  5. null_logger
  6. default_logger
  7. ftdm_std_malloc
  8. ftdm_std_calloc
  9. ftdm_std_realloc
  10. ftdm_std_free
  11. ftdm_set_echocancel_call_begin
  12. ftdm_set_echocancel_call_end
  13. ftdm_set_caller_data
  14. FT_DECLARE
  15. FT_DECLARE
  16. FT_DECLARE
  17. FT_DECLARE
  18. FT_DECLARE
  19. FT_DECLARE_NONSTD
  20. FT_DECLARE_NONSTD
  21. ftdm_channel_destroy
  22. ftdm_span_destroy
  23. FT_DECLARE
  24. ftdm_span_add
  25. FT_DECLARE
  26. FT_DECLARE
  27. FT_DECLARE
  28. FT_DECLARE
  29. reset_gain_table
  30. FT_DECLARE
  31. FT_DECLARE
  32. FT_DECLARE
  33. FT_DECLARE
  34. FT_DECLARE
  35. ftdmchan_fsk_write_sample
  36. FT_DECLARE
  37. FT_DECLARE
  38. FT_DECLARE
  39. FT_DECLARE
  40. FT_DECLARE
  41. FT_DECLARE
  42. FT_DECLARE
  43. FT_DECLARE
  44. FT_DECLARE
  45. FT_DECLARE
  46. FT_DECLARE
  47. FT_DECLARE
  48. FT_DECLARE
  49. FT_DECLARE
  50. ftdm_parse_state_map
  51. FT_DECLARE
  52. FT_DECLARE
  53. FT_DECLARE
  54. chan_is_avail
  55. chan_voice_is_avail
  56. request_voice_channel
  57. calculate_best_rate
  58. get_best_rated
  59. FT_DECLARE
  60. FT_DECLARE
  61. FT_DECLARE
  62. ftdm_channel_reset
  63. FT_DECLARE
  64. FT_DECLARE
  65. FT_DECLARE
  66. FT_DECLARE
  67. FT_DECLARE
  68. FT_DECLARE
  69. FT_DECLARE
  70. FT_DECLARE
  71. FT_DECLARE
  72. FT_DECLARE
  73. FT_DECLARE
  74. FT_DECLARE
  75. FT_DECLARE
  76. FT_DECLARE
  77. FT_DECLARE
  78. FT_DECLARE
  79. FT_DECLARE
  80. FT_DECLARE
  81. FT_DECLARE
  82. FT_DECLARE
  83. FT_DECLARE
  84. FT_DECLARE
  85. call_hangup
  86. FT_DECLARE
  87. FT_DECLARE
  88. FT_DECLARE
  89. FT_DECLARE
  90. FT_DECLARE
  91. FT_DECLARE
  92. FT_DECLARE
  93. FT_DECLARE
  94. FT_DECLARE
  95. FT_DECLARE
  96. FT_DECLARE
  97. FT_DECLARE
  98. FT_DECLARE
  99. FT_DECLARE
  100. FT_DECLARE
  101. FT_DECLARE
  102. close_dtmf_debug
  103. FT_DECLARE
  104. FT_DECLARE
  105. FT_DECLARE
  106. ftdmchan_activate_dtmf_buffer
  107. FT_DECLARE
  108. FT_DECLARE
  109. FIO_CODEC_FUNCTION
  110. FIO_CODEC_FUNCTION
  111. FIO_CODEC_FUNCTION
  112. FIO_CODEC_FUNCTION
  113. FIO_CODEC_FUNCTION
  114. FIO_CODEC_FUNCTION
  115. FT_DECLARE
  116. FT_DECLARE
  117. FT_DECLARE
  118. FT_DECLARE
  119. FT_DECLARE
  120. FIO_WRITE_FUNCTION
  121. FIO_READ_FUNCTION
  122. handle_dtmf
  123. FT_DECLARE
  124. FT_DECLARE
  125. FT_DECLARE
  126. ftdm_channel_clear_vars
  127. FT_DECLARE
  128. FT_DECLARE
  129. get_iterator
  130. FT_DECLARE
  131. FT_DECLARE
  132. FT_DECLARE
  133. FT_DECLARE
  134. FT_DECLARE
  135. FT_DECLARE
  136. print_channels_by_state
  137. handle_core_command
  138. FT_DECLARE
  139. ftdm_set_channels_gains
  140. ftdm_set_channels_alarms
  141. FT_DECLARE
  142. load_config
  143. process_module_config
  144. FT_DECLARE
  145. FT_DECLARE
  146. FT_DECLARE
  147. FT_DECLARE
  148. FT_DECLARE
  149. post_configure_span_channels
  150. FT_DECLARE
  151. FT_DECLARE
  152. FT_DECLARE
  153. FT_DECLARE
  154. FT_DECLARE
  155. ftdm_group_add_channels
  156. FT_DECLARE
  157. FT_DECLARE
  158. ftdm_group_add
  159. FT_DECLARE
  160. ftdm_span_trigger_signal
  161. ftdm_span_queue_signal
  162. FT_DECLARE
  163. execute_safety_hangup
  164. FT_DECLARE
  165. ftdm_cpu_monitor_run
  166. ftdm_cpu_monitor_start
  167. ftdm_cpu_monitor_stop
  168. FT_DECLARE
  169. FT_DECLARE
  170. FT_DECLARE
  171. FT_DECLARE
  172. FT_DECLARE
  173. FT_DECLARE
  174. FT_DECLARE
  175. FT_DECLARE
  176. FT_DECLARE
  177. FT_DECLARE_NONSTD
  178. FT_DECLARE
  179. FT_DECLARE_NONSTD
  180. FT_DECLARE
  181. FT_DECLARE
  182. FT_DECLARE

   1 /*
   2  * Copyright (c) 2007, Anthony Minessale II
   3  * All rights reserved.
   4  * 
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 
   9  * * Redistributions of source code must retain the above copyright
  10  * notice, this list of conditions and the following disclaimer.
  11  * 
  12  * * Redistributions in binary form must reproduce the above copyright
  13  * notice, this list of conditions and the following disclaimer in the
  14  * documentation and/or other materials provided with the distribution.
  15  * 
  16  * * Neither the name of the original author; nor the names of any contributors
  17  * may be used to endorse or promote products derived from this software
  18  * without specific prior written permission.
  19  * 
  20  * 
  21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
  25  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  28  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  29  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  30  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32  *
  33  * Contributors: 
  34  *
  35  * Moises Silva <moy@sangoma.com>
  36  * David Yat Sin <dyatsin@sangoma.com>
  37  *
  38  */
  39 
  40 #define _GNU_SOURCE
  41 #ifndef WIN32
  42 #endif
  43 #include "private/ftdm_core.h"
  44 #include <stdarg.h>
  45 #ifdef WIN32
  46 #include <io.h>
  47 #endif
  48 #ifdef FTDM_PIKA_SUPPORT
  49 #include "ftdm_pika.h"
  50 #endif
  51 #include "ftdm_cpu_monitor.h"
  52 
  53 #define FORCE_HANGUP_TIMER 3000
  54 #define SPAN_PENDING_CHANS_QUEUE_SIZE 1000
  55 #define SPAN_PENDING_SIGNALS_QUEUE_SIZE 1000
  56 #define FTDM_READ_TRACE_INDEX 0
  57 #define FTDM_WRITE_TRACE_INDEX 1
  58 
  59 static int time_is_init = 0;
  60 
  61 static void time_init(void)
  62 {
  63 #ifdef WIN32
  64         timeBeginPeriod(1);
  65 #endif
  66         time_is_init = 1;
  67 }
  68 
  69 static void time_end(void)
  70 {
  71 #ifdef WIN32
  72         timeEndPeriod(1);
  73 #endif
  74         time_is_init = 0;
  75 }
  76 
  77 FT_DECLARE(ftdm_time_t) ftdm_current_time_in_ms(void)
  78 {
  79 #ifdef WIN32
  80         return timeGetTime();
  81 #else
  82         struct timeval tv;
  83         gettimeofday(&tv, NULL);
  84         return ((tv.tv_sec * 1000) + (tv.tv_usec / 1000));
  85 #endif
  86 }
  87 
  88 typedef struct {
  89         uint8_t         enabled;
  90         uint8_t         running;
  91         uint8_t         alarm;
  92         uint32_t        interval;
  93         uint8_t         alarm_action_flags;
  94         uint8_t         set_alarm_threshold;
  95         uint8_t         reset_alarm_threshold;
  96         ftdm_interrupt_t *interrupt;
  97 } cpu_monitor_t;
  98 
  99 static struct {
 100         ftdm_hash_t *interface_hash;
 101         ftdm_hash_t *module_hash;
 102         ftdm_hash_t *span_hash;
 103         ftdm_hash_t *group_hash;
 104         ftdm_mutex_t *mutex;
 105         ftdm_mutex_t *span_mutex;
 106         ftdm_mutex_t *group_mutex;
 107         ftdm_sched_t *timingsched;
 108         uint32_t span_index;
 109         uint32_t group_index;
 110         uint32_t running;
 111         ftdm_span_t *spans;
 112         ftdm_group_t *groups;
 113         cpu_monitor_t cpu_monitor;
 114 } globals;
 115 
 116 enum ftdm_enum_cpu_alarm_action_flags
 117 {
 118         FTDM_CPU_ALARM_ACTION_WARN   = (1 << 0),
 119         FTDM_CPU_ALARM_ACTION_REJECT = (1 << 1)
 120 };
 121 
 122 /* enum lookup funcs */
 123 FTDM_ENUM_NAMES(TONEMAP_NAMES, TONEMAP_STRINGS)
 124 FTDM_STR2ENUM(ftdm_str2ftdm_tonemap, ftdm_tonemap2str, ftdm_tonemap_t, TONEMAP_NAMES, FTDM_TONEMAP_INVALID)
 125 
 126 FTDM_ENUM_NAMES(OOB_NAMES, OOB_STRINGS)
 127 FTDM_STR2ENUM(ftdm_str2ftdm_oob_event, ftdm_oob_event2str, ftdm_oob_event_t, OOB_NAMES, FTDM_OOB_INVALID)
 128 
 129 FTDM_ENUM_NAMES(TRUNK_TYPE_NAMES, TRUNK_STRINGS)
 130 FTDM_STR2ENUM(ftdm_str2ftdm_trunk_type, ftdm_trunk_type2str, ftdm_trunk_type_t, TRUNK_TYPE_NAMES, FTDM_TRUNK_NONE)
 131 
 132 FTDM_ENUM_NAMES(START_TYPE_NAMES, START_TYPE_STRINGS)
 133 FTDM_STR2ENUM(ftdm_str2ftdm_analog_start_type, ftdm_analog_start_type2str, ftdm_analog_start_type_t, START_TYPE_NAMES, FTDM_ANALOG_START_NA)
 134 
 135 FTDM_ENUM_NAMES(SIGNAL_NAMES, SIGNAL_STRINGS)
 136 FTDM_STR2ENUM(ftdm_str2ftdm_signal_event, ftdm_signal_event2str, ftdm_signal_event_t, SIGNAL_NAMES, FTDM_SIGEVENT_INVALID)
 137 
 138 FTDM_ENUM_NAMES(CHANNEL_STATE_NAMES, CHANNEL_STATE_STRINGS)
 139 FTDM_STR2ENUM(ftdm_str2ftdm_channel_state, ftdm_channel_state2str, ftdm_channel_state_t, CHANNEL_STATE_NAMES, FTDM_CHANNEL_STATE_INVALID)
 140 
 141 FTDM_ENUM_NAMES(MDMF_TYPE_NAMES, MDMF_STRINGS)
 142 FTDM_STR2ENUM(ftdm_str2ftdm_mdmf_type, ftdm_mdmf_type2str, ftdm_mdmf_type_t, MDMF_TYPE_NAMES, MDMF_INVALID)
 143 
 144 FTDM_ENUM_NAMES(CHAN_TYPE_NAMES, CHAN_TYPE_STRINGS)
 145 FTDM_STR2ENUM(ftdm_str2ftdm_chan_type, ftdm_chan_type2str, ftdm_chan_type_t, CHAN_TYPE_NAMES, FTDM_CHAN_TYPE_COUNT)
 146 
 147 FTDM_ENUM_NAMES(SIGNALING_STATUS_NAMES, SIGSTATUS_STRINGS)
 148 FTDM_STR2ENUM(ftdm_str2ftdm_signaling_status, ftdm_signaling_status2str, ftdm_signaling_status_t, SIGNALING_STATUS_NAMES, FTDM_SIG_STATE_INVALID)
 149 
 150 static ftdm_status_t ftdm_group_add_channels(ftdm_span_t* span, int currindex, const char* name);
 151 
 152 static const char *cut_path(const char *in)
 153 {
 154         const char *p, *ret = in;
 155         char delims[] = "/\\";
 156         char *i;
 157 
 158         for (i = delims; *i; i++) {
 159                 p = in;
 160                 while ((p = strchr(p, *i)) != 0) {
 161                         ret = ++p;
 162                 }
 163         }
 164         return ret;
 165 }
 166 
 167 static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
 168 {
 169         if (file && func && line && level && fmt) {
 170                 return;
 171         }
 172         return;
 173 }
 174 
 175 
 176 const char *FTDM_LEVEL_NAMES[9] = {
 177         "EMERG",
 178         "ALERT",
 179         "CRIT",
 180         "ERROR",
 181         "WARNING",
 182         "NOTICE",
 183         "INFO",
 184         "DEBUG",
 185         NULL
 186 };
 187 
 188 static int ftdm_log_level = FTDM_LOG_LEVEL_DEBUG;
 189 
 190 static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
 191 {
 192         const char *fp;
 193         char data[1024];
 194         va_list ap;
 195 
 196         if (level < 0 || level > 7) {
 197                 level = 7;
 198         }
 199         if (level > ftdm_log_level) {
 200                 return;
 201         }
 202         
 203         fp = cut_path(file);
 204 
 205         va_start(ap, fmt);
 206 
 207         vsnprintf(data, sizeof(data), fmt, ap);
 208 
 209 
 210         fprintf(stderr, "[%s] %s:%d %s() %s", FTDM_LEVEL_NAMES[level], file, line, func, data);
 211 
 212         va_end(ap);
 213 
 214 }
 215 
 216 static __inline__ void *ftdm_std_malloc(void *pool, ftdm_size_t size)
 217 {
 218         void *ptr = malloc(size);
 219         pool = NULL; /* fix warning */
 220         ftdm_assert_return(ptr != NULL, NULL, "Out of memory");
 221         return ptr;
 222 }
 223 
 224 static __inline__ void *ftdm_std_calloc(void *pool, ftdm_size_t elements, ftdm_size_t size)
 225 {
 226         void *ptr = calloc(elements, size);
 227         pool = NULL;
 228         ftdm_assert_return(ptr != NULL, NULL, "Out of memory");
 229         return ptr;
 230 }
 231 
 232 static __inline__ void *ftdm_std_realloc(void *pool, void *buff, ftdm_size_t size)
 233 {
 234         buff = realloc(buff, size);
 235         pool = NULL;
 236         ftdm_assert_return(buff != NULL, NULL, "Out of memory");
 237         return buff;
 238 }
 239 
 240 static __inline__ void ftdm_std_free(void *pool, void *ptr)
 241 {
 242         pool = NULL;
 243         ftdm_assert_return(ptr != NULL, , "Attempted to free null pointer");
 244         free(ptr);
 245 }
 246 
 247 static void ftdm_set_echocancel_call_begin(ftdm_channel_t *chan)
 248 {
 249         ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
 250         if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC)) {
 251                 if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE)) {
 252                         if (caller_data->bearer_capability != FTDM_BEARER_CAP_64K_UNRESTRICTED) {
 253                                 ftdm_channel_command(chan, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL);
 254                         }
 255                 } else {
 256                         if (caller_data->bearer_capability == FTDM_BEARER_CAP_64K_UNRESTRICTED) {
 257                                 ftdm_channel_command(chan, FTDM_COMMAND_DISABLE_ECHOCANCEL, NULL);
 258                         }
 259                 }
 260         }
 261 }
 262 
 263 static void ftdm_set_echocancel_call_end(ftdm_channel_t *chan)
 264 {
 265         ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
 266         if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC)) {
 267                 if (ftdm_channel_test_feature(chan, FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE)) {
 268                         if (caller_data->bearer_capability != FTDM_BEARER_CAP_64K_UNRESTRICTED) {
 269                                 ftdm_channel_command(chan, FTDM_COMMAND_DISABLE_ECHOCANCEL, NULL);
 270                         }
 271                 } else {
 272                         if (caller_data->bearer_capability == FTDM_BEARER_CAP_64K_UNRESTRICTED) {
 273                                 ftdm_channel_command(chan, FTDM_COMMAND_ENABLE_ECHOCANCEL, NULL);
 274                         }
 275                 }
 276         }
 277 }
 278 
 279 
 280 FT_DECLARE_DATA ftdm_memory_handler_t g_ftdm_mem_handler = 
 281 {
 282         /*.pool =*/ NULL,
 283         /*.malloc =*/ ftdm_std_malloc,
 284         /*.calloc =*/ ftdm_std_calloc,
 285         /*.realloc =*/ ftdm_std_realloc,
 286         /*.free =*/ ftdm_std_free
 287 };
 288 
 289 FT_DECLARE_DATA ftdm_crash_policy_t g_ftdm_crash_policy = FTDM_CRASH_NEVER;
 290 
 291 static ftdm_status_t ftdm_set_caller_data(ftdm_span_t *span, ftdm_caller_data_t *caller_data)
 292 {
 293         if (!caller_data) {
 294                 ftdm_log(FTDM_LOG_CRIT, "Error: trying to set caller data, but no caller_data!\n");
 295                 return FTDM_FAIL;
 296         }
 297 
 298         if (caller_data->dnis.plan == FTDM_NPI_INVALID) {
 299                 caller_data->dnis.plan = span->default_caller_data.dnis.plan;
 300         }
 301 
 302         if (caller_data->dnis.type == FTDM_TON_INVALID) {
 303                 caller_data->dnis.type = span->default_caller_data.dnis.type;
 304         }
 305 
 306         if (caller_data->cid_num.plan == FTDM_NPI_INVALID) {
 307                 caller_data->cid_num.plan = span->default_caller_data.cid_num.plan;
 308         }
 309 
 310         if (caller_data->cid_num.type == FTDM_TON_INVALID) {
 311                 caller_data->cid_num.type = span->default_caller_data.cid_num.type;
 312         }
 313 
 314         if (caller_data->ani.plan == FTDM_NPI_INVALID) {
 315                 caller_data->ani.plan = span->default_caller_data.ani.plan;
 316         }
 317 
 318         if (caller_data->ani.type == FTDM_TON_INVALID) {
 319                 caller_data->ani.type = span->default_caller_data.ani.type;
 320         }
 321 
 322         if (caller_data->rdnis.plan == FTDM_NPI_INVALID) {
 323                 caller_data->rdnis.plan = span->default_caller_data.rdnis.plan;
 324         }
 325 
 326         if (caller_data->rdnis.type == FTDM_NPI_INVALID) {
 327                 caller_data->rdnis.type = span->default_caller_data.rdnis.type;
 328         }
 329 
 330         if (caller_data->bearer_capability == FTDM_INVALID_INT_PARM) {
 331                 caller_data->bearer_capability = span->default_caller_data.bearer_capability;
 332         }
 333 
 334         if (caller_data->bearer_layer1 == FTDM_INVALID_INT_PARM) {
 335                 caller_data->bearer_layer1 = span->default_caller_data.bearer_layer1;
 336         }
 337 
 338         if (FTDM_FAIL == ftdm_is_number(caller_data->cid_num.digits)) {
 339                 ftdm_log(FTDM_LOG_DEBUG, "dropping caller id number %s since we only accept digits\n", caller_data->cid_num.digits);
 340                 caller_data->cid_num.digits[0] = '\0';
 341         }
 342 
 343         return FTDM_SUCCESS;
 344 }
 345 
 346 FT_DECLARE(ftdm_status_t) ftdm_channel_set_caller_data(ftdm_channel_t *ftdmchan, ftdm_caller_data_t *caller_data)
 347 {
 348         ftdm_status_t err = FTDM_SUCCESS;
 349         if (!ftdmchan) {
 350                 ftdm_log(FTDM_LOG_CRIT, "Error: trying to set caller data, but no ftdmchan!\n");
 351                 return FTDM_FAIL;
 352         }
 353         if ((err = ftdm_set_caller_data(ftdmchan->span, caller_data)) != FTDM_SUCCESS) {
 354                 return err; 
 355         }
 356         ftdmchan->caller_data = *caller_data;
 357         return FTDM_SUCCESS;
 358 }
 359 
 360 FT_DECLARE_DATA ftdm_logger_t ftdm_log = null_logger;
 361 
 362 FT_DECLARE(void) ftdm_global_set_crash_policy(ftdm_crash_policy_t policy)
 363 {
 364         g_ftdm_crash_policy |= policy;
 365 }
 366 
 367 FT_DECLARE(ftdm_status_t) ftdm_global_set_memory_handler(ftdm_memory_handler_t *handler)
 368 {
 369         if (!handler) {
 370                 return FTDM_FAIL;
 371         }
 372         if (!handler->malloc) {
 373                 return FTDM_FAIL;
 374         }
 375         if (!handler->calloc) {
 376                 return FTDM_FAIL;
 377         }
 378         if (!handler->free) {
 379                 return FTDM_FAIL;
 380         }
 381         memcpy(&g_ftdm_mem_handler, handler, sizeof(*handler));
 382         return FTDM_SUCCESS;
 383 }
 384 
 385 FT_DECLARE(void) ftdm_global_set_logger(ftdm_logger_t logger)
 386 {
 387         if (logger) {
 388                 ftdm_log = logger;
 389         } else {
 390                 ftdm_log = null_logger;
 391         }
 392 }
 393 
 394 FT_DECLARE(void) ftdm_global_set_default_logger(int level)
 395 {
 396         if (level < 0 || level > 7) {
 397                 level = 7;
 398         }
 399 
 400         ftdm_log = default_logger;
 401         ftdm_log_level = level;
 402 }
 403 
 404 FT_DECLARE_NONSTD(int) ftdm_hash_equalkeys(void *k1, void *k2)
 405 {
 406     return strcmp((char *) k1, (char *) k2) ? 0 : 1;
 407 }
 408 
 409 FT_DECLARE_NONSTD(uint32_t) ftdm_hash_hashfromstring(void *ky)
 410 {
 411         unsigned char *str = (unsigned char *) ky;
 412         uint32_t hash = 0;
 413     int c;
 414         
 415         while ((c = *str++)) {
 416         hash = c + (hash << 6) + (hash << 16) - hash;
 417         }
 418 
 419     return hash;
 420 }
 421 
 422 static ftdm_status_t ftdm_channel_destroy(ftdm_channel_t *ftdmchan)
 423 {
 424 
 425         if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CONFIGURED)) {
 426 
 427                 while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INTHREAD)) {
 428                         ftdm_log(FTDM_LOG_INFO, "Waiting for thread to exit on channel %u:%u\n", ftdmchan->span_id, ftdmchan->chan_id);
 429                         ftdm_sleep(500);
 430                 }
 431 
 432 #ifdef FTDM_DEBUG_DTMF
 433                 ftdm_mutex_destroy(&ftdmchan->dtmfdbg.mutex);
 434 #endif
 435 
 436                 ftdm_mutex_lock(ftdmchan->pre_buffer_mutex);
 437                 ftdm_buffer_destroy(&ftdmchan->pre_buffer);
 438                 ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex);
 439 
 440                 ftdm_buffer_destroy(&ftdmchan->digit_buffer);
 441                 ftdm_buffer_destroy(&ftdmchan->gen_dtmf_buffer);
 442                 ftdm_buffer_destroy(&ftdmchan->dtmf_buffer);
 443                 ftdm_buffer_destroy(&ftdmchan->fsk_buffer);
 444                 ftdmchan->pre_buffer_size = 0;
 445 
 446                 ftdm_safe_free(ftdmchan->dtmf_hangup_buf);
 447 
 448                 if (ftdmchan->tone_session.buffer) {
 449                         teletone_destroy_session(&ftdmchan->tone_session);
 450                         memset(&ftdmchan->tone_session, 0, sizeof(ftdmchan->tone_session));
 451                 }
 452 
 453                 
 454                 if (ftdmchan->span->fio->channel_destroy) {
 455                         ftdm_log(FTDM_LOG_INFO, "Closing channel %s:%u:%u fd:%d\n", ftdmchan->span->type, ftdmchan->span_id, ftdmchan->chan_id, ftdmchan->sockfd);
 456                         if (ftdmchan->span->fio->channel_destroy(ftdmchan) == FTDM_SUCCESS) {
 457                                 ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_CONFIGURED);
 458                         } else {
 459                                 ftdm_log(FTDM_LOG_ERROR, "Error Closing channel %u:%u fd:%d\n", ftdmchan->span_id, ftdmchan->chan_id, ftdmchan->sockfd);
 460                         }
 461                 }
 462 
 463                 ftdm_mutex_destroy(&ftdmchan->mutex);
 464                 ftdm_mutex_destroy(&ftdmchan->pre_buffer_mutex);
 465         }
 466         
 467         return FTDM_SUCCESS;
 468 }
 469 
 470 static ftdm_status_t ftdm_span_destroy(ftdm_span_t *span)
 471 {
 472         ftdm_status_t status = FTDM_SUCCESS;
 473         unsigned j;
 474 
 475         ftdm_mutex_lock(span->mutex);
 476 
 477         /* stop the signaling */
 478         ftdm_span_stop(span);
 479 
 480         /* destroy the channels */
 481         ftdm_clear_flag(span, FTDM_SPAN_CONFIGURED);
 482         for(j = 1; j <= span->chan_count && span->channels[j]; j++) {
 483                 ftdm_channel_t *cur_chan = span->channels[j];
 484                 if (cur_chan) {
 485                         if (ftdm_test_flag(cur_chan, FTDM_CHANNEL_CONFIGURED)) {
 486                                 ftdm_channel_destroy(cur_chan);
 487                         }
 488                         ftdm_safe_free(cur_chan);
 489                         cur_chan = NULL;
 490                 }
 491         }
 492 
 493         /* destroy the I/O for the span */
 494         if (span->fio && span->fio->span_destroy) {
 495                 ftdm_log(FTDM_LOG_INFO, "Destroying span %u type (%s)\n", span->span_id, span->type);
 496                 if (span->fio->span_destroy(span) != FTDM_SUCCESS) {
 497                         status = FTDM_FAIL;
 498                 }
 499                 ftdm_safe_free(span->type);
 500                 ftdm_safe_free(span->name);
 501                 ftdm_safe_free(span->dtmf_hangup);
 502         }
 503 
 504         /* destroy final basic resources of the span data structure */
 505         if (span->pendingchans) {
 506                 ftdm_queue_destroy(&span->pendingchans);
 507         }
 508         if (span->pendingsignals) {
 509                 ftdm_queue_destroy(&span->pendingsignals);
 510         }
 511         ftdm_mutex_unlock(span->mutex);
 512         ftdm_mutex_destroy(&span->mutex);
 513         ftdm_safe_free(span->signal_data);
 514 
 515         return status;
 516 }
 517 
 518 FT_DECLARE(ftdm_status_t) ftdm_channel_get_alarms(ftdm_channel_t *ftdmchan, ftdm_alarm_flag_t *alarmbits)
 519 {
 520         ftdm_status_t status = FTDM_FAIL;
 521 
 522         ftdm_assert_return(alarmbits != NULL, FTDM_FAIL, "null argument\n");
 523 
 524         *alarmbits = FTDM_ALARM_NONE;
 525 
 526         ftdm_channel_lock(ftdmchan);
 527 
 528         if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CONFIGURED)) {
 529                 if (ftdmchan->span->fio->get_alarms) {
 530                         if ((status = ftdmchan->span->fio->get_alarms(ftdmchan)) == FTDM_SUCCESS) {
 531                                 *ftdmchan->last_error = '\0';
 532                                 *alarmbits = ftdmchan->alarm_flags;
 533                                 if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_RED)) {
 534                                         snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "RED/");
 535                                 }
 536                                 if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_YELLOW)) {
 537                                         snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "YELLOW/");
 538                                 }
 539                                 if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_RAI)) {
 540                                         snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "RAI/");
 541                                 }
 542                                 if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_BLUE)) {
 543                                         snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "BLUE/");
 544                                 }
 545                                 if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_AIS)) {
 546                                         snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "AIS/");
 547                                 }
 548                                 if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_GENERAL)) {
 549                                         snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "GENERAL");
 550                                 }
 551                                 *(ftdmchan->last_error + strlen(ftdmchan->last_error) - 1) = '\0';
 552 
 553                         }
 554                 } else {
 555                         status = FTDM_NOTIMPL;
 556                 }
 557         }
 558 
 559         ftdm_channel_unlock(ftdmchan);  
 560 
 561         return status;
 562 }
 563 
 564 static void ftdm_span_add(ftdm_span_t *span)
 565 {
 566         ftdm_span_t *sp;
 567         ftdm_mutex_lock(globals.span_mutex);
 568         for (sp = globals.spans; sp && sp->next; sp = sp->next);
 569         if (sp) {
 570                 sp->next = span;
 571         } else {
 572                 globals.spans = span;
 573         }
 574         hashtable_insert(globals.span_hash, (void *)span->name, span, HASHTABLE_FLAG_FREE_VALUE);
 575         ftdm_mutex_unlock(globals.span_mutex);
 576 }
 577 
 578 FT_DECLARE(ftdm_status_t) ftdm_span_stop(ftdm_span_t *span)
 579 {
 580         ftdm_status_t status =  FTDM_FAIL;
 581         if (span->stop) {
 582                 status = span->stop(span);
 583                 span->stop = NULL;
 584         }
 585         return status;
 586 }
 587 
 588 FT_DECLARE(ftdm_status_t) ftdm_span_create(const char *iotype, const char *name, ftdm_span_t **span)
 589 {
 590         ftdm_span_t *new_span = NULL;
 591         ftdm_io_interface_t *fio = NULL;
 592         ftdm_status_t status = FTDM_FAIL;
 593         char buf[128] = "";
 594 
 595         ftdm_assert_return(iotype != NULL, FTDM_FAIL, "No IO type provided\n");
 596         ftdm_assert_return(name != NULL, FTDM_FAIL, "No span name provided\n");
 597         
 598         *span = NULL;
 599 
 600         ftdm_mutex_lock(globals.mutex);
 601         if (!(fio = (ftdm_io_interface_t *) hashtable_search(globals.interface_hash, (void *)iotype))) {
 602                 ftdm_load_module_assume(iotype);
 603                 if ((fio = (ftdm_io_interface_t *) hashtable_search(globals.interface_hash, (void *)iotype))) {
 604                         ftdm_log(FTDM_LOG_INFO, "Auto-loaded I/O module '%s'\n", iotype);
 605                 }
 606         }
 607         ftdm_mutex_unlock(globals.mutex);
 608 
 609         if (!fio) {
 610                 ftdm_log(FTDM_LOG_CRIT, "failure creating span, no such I/O type '%s'\n", iotype);
 611                 return FTDM_FAIL;
 612         }
 613 
 614         if (!fio->configure_span) {
 615                 ftdm_log(FTDM_LOG_CRIT, "failure creating span, no configure_span method for I/O type '%s'\n", iotype);
 616                 return FTDM_FAIL;
 617         }
 618 
 619         ftdm_mutex_lock(globals.mutex);
 620         if (globals.span_index < FTDM_MAX_SPANS_INTERFACE) {
 621                 new_span = ftdm_calloc(sizeof(*new_span), 1);
 622                 
 623                 ftdm_assert(new_span, "allocating span failed\n");
 624 
 625                 status = ftdm_mutex_create(&new_span->mutex);
 626                 ftdm_assert(status == FTDM_SUCCESS, "mutex creation failed\n");
 627 
 628                 ftdm_set_flag(new_span, FTDM_SPAN_CONFIGURED);
 629                 new_span->span_id = ++globals.span_index;
 630                 new_span->fio = fio;
 631                 ftdm_copy_string(new_span->tone_map[FTDM_TONEMAP_DIAL], "%(1000,0,350,440)", FTDM_TONEMAP_LEN);
 632                 ftdm_copy_string(new_span->tone_map[FTDM_TONEMAP_RING], "%(2000,4000,440,480)", FTDM_TONEMAP_LEN);
 633                 ftdm_copy_string(new_span->tone_map[FTDM_TONEMAP_BUSY], "%(500,500,480,620)", FTDM_TONEMAP_LEN);
 634                 ftdm_copy_string(new_span->tone_map[FTDM_TONEMAP_ATTN], "%(100,100,1400,2060,2450,2600)", FTDM_TONEMAP_LEN);
 635                 new_span->trunk_type = FTDM_TRUNK_NONE;
 636                 new_span->data_type = FTDM_TYPE_SPAN;
 637 
 638                 ftdm_mutex_lock(globals.span_mutex);
 639                 if (!ftdm_strlen_zero(name) && hashtable_search(globals.span_hash, (void *)name)) {
 640                         ftdm_log(FTDM_LOG_WARNING, "name %s is already used, substituting 'span%d' as the name\n", name, new_span->span_id);
 641                         name = NULL;
 642                 }
 643                 ftdm_mutex_unlock(globals.span_mutex);
 644                 
 645                 if (!name) {
 646                         snprintf(buf, sizeof(buf), "span%d", new_span->span_id);
 647                         name = buf;
 648                 }
 649                 new_span->name = ftdm_strdup(name);
 650                 new_span->type = ftdm_strdup(iotype);
 651                 ftdm_span_add(new_span);
 652                 *span = new_span;
 653                 status = FTDM_SUCCESS;
 654         }
 655         ftdm_mutex_unlock(globals.mutex);
 656         return status;
 657 }
 658 
 659 FT_DECLARE(ftdm_status_t) ftdm_span_close_all(void)
 660 {
 661         ftdm_span_t *span;
 662         uint32_t i = 0, j;
 663 
 664         ftdm_mutex_lock(globals.span_mutex);
 665         for (span = globals.spans; span; span = span->next) {
 666                 if (ftdm_test_flag(span, FTDM_SPAN_CONFIGURED)) {
 667                         for(j = 1; j <= span->chan_count && span->channels[j]; j++) {
 668                                 ftdm_channel_t *toclose = span->channels[j];
 669                                 if (ftdm_test_flag(toclose, FTDM_CHANNEL_INUSE)) {
 670                                         ftdm_channel_close(&toclose);
 671                                 }
 672                                 i++;
 673                         }
 674                 } 
 675         }
 676         ftdm_mutex_unlock(globals.span_mutex);
 677 
 678         return i ? FTDM_SUCCESS : FTDM_FAIL;
 679 }
 680 
 681 FT_DECLARE(ftdm_status_t) ftdm_span_load_tones(ftdm_span_t *span, const char *mapname)
 682 {
 683         ftdm_config_t cfg;
 684         char *var, *val;
 685         int x = 0;
 686 
 687         if (!ftdm_config_open_file(&cfg, "tones.conf")) {
 688                 snprintf(span->last_error, sizeof(span->last_error), "error loading tones.");
 689                 return FTDM_FAIL;
 690         }
 691         
 692         while (ftdm_config_next_pair(&cfg, &var, &val)) {
 693                 int detect = 0;
 694 
 695                 if (!strcasecmp(cfg.category, mapname) && var && val) {
 696                         uint32_t index;
 697                         char *name = NULL;
 698 
 699                         if (!strncasecmp(var, "detect-", 7)) {
 700                                 name = var + 7;
 701                                 detect = 1;
 702                         } else if (!strncasecmp(var, "generate-", 9)) {
 703                                 name = var + 9;
 704                         } else {
 705                                 ftdm_log(FTDM_LOG_WARNING, "Unknown tone name %s\n", var);
 706                                 continue;
 707                         }
 708 
 709                         index = ftdm_str2ftdm_tonemap(name);
 710 
 711                         if (index >= FTDM_TONEMAP_INVALID || index == FTDM_TONEMAP_NONE) {
 712                                 ftdm_log(FTDM_LOG_WARNING, "Unknown tone name %s\n", name);
 713                         } else {
 714                                 if (detect) {
 715                                         char *p = val, *next;
 716                                         int i = 0;
 717                                         do {
 718                                                 teletone_process_t this;
 719                                                 next = strchr(p, ',');
 720                                                 this = (teletone_process_t)atof(p);
 721                                                 span->tone_detect_map[index].freqs[i++] = this;
 722                                                 if (next) {
 723                                                         p = next + 1;
 724                                                 }
 725                                         } while (next);
 726                                         ftdm_log(FTDM_LOG_DEBUG, "added tone detect [%s] = [%s]\n", name, val);
 727                                 }  else {
 728                                         ftdm_log(FTDM_LOG_DEBUG, "added tone generation [%s] = [%s]\n", name, val);
 729                                         ftdm_copy_string(span->tone_map[index], val, sizeof(span->tone_map[index]));
 730                                 }
 731                                 x++;
 732                         }
 733                 }
 734         }
 735 
 736         ftdm_config_close_file(&cfg);
 737         
 738         if (!x) {
 739                 snprintf(span->last_error, sizeof(span->last_error), "error loading tones.");
 740                 return FTDM_FAIL;
 741         }
 742 
 743         return FTDM_SUCCESS;
 744         
 745 }
 746 
 747 #define FTDM_SLINEAR_MAX_VALUE 32767
 748 #define FTDM_SLINEAR_MIN_VALUE -32767
 749 static void reset_gain_table(uint8_t *gain_table, float new_gain, ftdm_codec_t codec_gain)
 750 {
 751         /* sample value */
 752         uint8_t sv = 0;
 753         /* linear gain factor */
 754         float lingain = 0;
 755         /* linear value for each table sample */
 756         float linvalue = 0;
 757         /* amplified (or attenuated in case of negative amplification) sample value */
 758         int ampvalue = 0;
 759 
 760         /* gain tables are only for alaw and ulaw */
 761         if (codec_gain != FTDM_CODEC_ALAW && codec_gain != FTDM_CODEC_ULAW) {
 762                 ftdm_log(FTDM_LOG_WARNING, "Not resetting gain table because codec is not ALAW or ULAW but %d\n", codec_gain);
 763                 return;
 764         }
 765 
 766         if (!new_gain) {
 767                 /* for a 0.0db gain table, each alaw/ulaw sample value is left untouched (0 ==0, 1 == 1, 2 == 2 etc)*/
 768                 sv = 0;
 769                 while (1) {
 770                         gain_table[sv] = sv;
 771                         if (sv == (FTDM_GAINS_TABLE_SIZE-1)) {
 772                                 break;
 773                         }
 774                         sv++;
 775                 }
 776                 return;
 777         }
 778 
 779         /* use the 20log rule to increase the gain: http://en.wikipedia.org/wiki/Gain, http:/en.wipedia.org/wiki/20_log_rule#Definitions */
 780         lingain = (float)pow(10.0, new_gain/ 20.0);
 781         sv = 0;
 782         while (1) {
 783                 /* get the linear value for this alaw/ulaw sample value */
 784                 linvalue = codec_gain == FTDM_CODEC_ALAW ? (float)alaw_to_linear(sv) : (float)ulaw_to_linear(sv);
 785 
 786                 /* multiply the linear value and the previously calculated linear gain */
 787                 ampvalue = (int)(linvalue * lingain);
 788 
 789                 /* chop it if goes beyond the limits */
 790                 if (ampvalue > FTDM_SLINEAR_MAX_VALUE) {
 791                         ampvalue = FTDM_SLINEAR_MAX_VALUE;
 792                 }
 793 
 794                 if (ampvalue < FTDM_SLINEAR_MIN_VALUE) {
 795                         ampvalue = FTDM_SLINEAR_MIN_VALUE;
 796                 }
 797                 gain_table[sv] = codec_gain == FTDM_CODEC_ALAW ? linear_to_alaw(ampvalue) : linear_to_ulaw(ampvalue);
 798                 if (sv == (FTDM_GAINS_TABLE_SIZE-1)) {
 799                         break;
 800                 }
 801                 sv++;
 802         }
 803 }
 804 
 805 FT_DECLARE(ftdm_status_t) ftdm_span_add_channel(ftdm_span_t *span, ftdm_socket_t sockfd, ftdm_chan_type_t type, ftdm_channel_t **chan)
 806 {
 807         unsigned char i = 0;
 808         if (span->chan_count < FTDM_MAX_CHANNELS_SPAN) {
 809                 ftdm_channel_t *new_chan = span->channels[++span->chan_count];
 810 
 811                 if (!new_chan) {
 812 #ifdef FTDM_DEBUG_CHAN_MEMORY
 813                         void *chanmem = NULL;
 814                         int pages = 1;
 815                         int pagesize = sysconf(_SC_PAGE_SIZE);
 816                         if (sizeof(*new_chan) > pagesize) {
 817                                 pages = sizeof(*new_chan)/pagesize;
 818                                 pages++;
 819                         }
 820                         ftdm_log(FTDM_LOG_DEBUG, "Allocating %d pages of %d bytes for channel of size %d\n", pages, pagesize, sizeof(*new_chan));
 821                         if (posix_memalign(&chanmem, pagesize, pagesize*pages)) {
 822                                 return FTDM_FAIL;
 823                         }
 824                         ftdm_log(FTDM_LOG_DEBUG, "Channel pages allocated start at mem %p\n", chanmem);
 825                         memset(chanmem, 0, sizeof(*new_chan));
 826                         new_chan = chanmem;
 827 #else
 828                         if (!(new_chan = ftdm_calloc(1, sizeof(*new_chan)))) {
 829                                 return FTDM_FAIL;
 830                         }
 831 #endif
 832                         span->channels[span->chan_count] = new_chan;
 833                 }
 834 
 835                 new_chan->type = type;
 836                 new_chan->sockfd = sockfd;
 837                 new_chan->fio = span->fio;
 838                 new_chan->span_id = span->span_id;
 839                 new_chan->chan_id = span->chan_count;
 840                 new_chan->span = span;
 841                 new_chan->fds[FTDM_READ_TRACE_INDEX] = -1;
 842                 new_chan->fds[FTDM_WRITE_TRACE_INDEX] = -1;
 843                 new_chan->data_type = FTDM_TYPE_CHANNEL;
 844                 if (!new_chan->dtmf_on) {
 845                         new_chan->dtmf_on = FTDM_DEFAULT_DTMF_ON;
 846                 }
 847 
 848                 if (!new_chan->dtmf_off) {
 849                         new_chan->dtmf_off = FTDM_DEFAULT_DTMF_OFF;
 850                 }
 851 
 852                 ftdm_mutex_create(&new_chan->mutex);
 853                 ftdm_mutex_create(&new_chan->pre_buffer_mutex);
 854 #ifdef FTDM_DEBUG_DTMF
 855                 ftdm_mutex_create(&new_chan->dtmfdbg.mutex);
 856 #endif
 857 
 858                 ftdm_buffer_create(&new_chan->digit_buffer, 128, 128, 0);
 859                 ftdm_buffer_create(&new_chan->gen_dtmf_buffer, 128, 128, 0);
 860 
 861                 new_chan->dtmf_hangup_buf = ftdm_calloc (span->dtmf_hangup_len + 1, sizeof (char));
 862 
 863                 /* set 0.0db gain table */
 864                 i = 0;
 865                 while (1) {
 866                         new_chan->txgain_table[i] = i;
 867                         new_chan->rxgain_table[i] = i;
 868                         if (i == (sizeof(new_chan->txgain_table)-1)) {
 869                                 break;
 870                         }
 871                         i++;
 872                 }
 873 
 874                 ftdm_set_flag(new_chan, FTDM_CHANNEL_CONFIGURED | FTDM_CHANNEL_READY);          
 875                 *chan = new_chan;
 876                 return FTDM_SUCCESS;
 877         }
 878 
 879         return FTDM_FAIL;
 880 }
 881 
 882 FT_DECLARE(ftdm_status_t) ftdm_span_find_by_name(const char *name, ftdm_span_t **span)
 883 {
 884         ftdm_status_t status = FTDM_FAIL;
 885 
 886         ftdm_mutex_lock(globals.span_mutex);
 887         if (!ftdm_strlen_zero(name)) {
 888                 if ((*span = hashtable_search(globals.span_hash, (void *)name))) {
 889                         status = FTDM_SUCCESS;
 890                 } else {
 891                         int span_id = atoi(name);
 892 
 893                         ftdm_span_find(span_id, span);
 894                         if (*span) {
 895                                 status = FTDM_SUCCESS;
 896                         }
 897                 }
 898         }
 899         ftdm_mutex_unlock(globals.span_mutex);
 900         
 901         return status;
 902 }
 903 
 904 FT_DECLARE(ftdm_status_t) ftdm_span_find(uint32_t id, ftdm_span_t **span)
 905 {
 906         ftdm_span_t *fspan = NULL, *sp;
 907 
 908         if (id > FTDM_MAX_SPANS_INTERFACE) {
 909                 return FTDM_FAIL;
 910         }
 911 
 912         ftdm_mutex_lock(globals.span_mutex);
 913         for (sp = globals.spans; sp; sp = sp->next) {
 914                 if (sp->span_id == id) {
 915                         fspan = sp;
 916                         break;
 917                 }
 918         }
 919         ftdm_mutex_unlock(globals.span_mutex);
 920 
 921         if (!fspan || !ftdm_test_flag(fspan, FTDM_SPAN_CONFIGURED)) {
 922                 return FTDM_FAIL;
 923         }
 924 
 925         *span = fspan;
 926 
 927         return FTDM_SUCCESS;
 928         
 929 }
 930 
 931 FT_DECLARE(ftdm_status_t) ftdm_span_poll_event(ftdm_span_t *span, uint32_t ms)
 932 {
 933         assert(span->fio != NULL);
 934 
 935         if (span->fio->poll_event) {
 936                 return span->fio->poll_event(span, ms);
 937         } else {
 938                 ftdm_log(FTDM_LOG_ERROR, "poll_event method not implemented in module %s!", span->fio->name);
 939         }
 940 
 941         return FTDM_NOTIMPL;
 942 }
 943 
 944 FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t **event)
 945 {
 946         ftdm_status_t status = FTDM_FAIL;
 947         ftdm_sigmsg_t sigmsg;
 948         ftdm_assert_return(span->fio != NULL, FTDM_FAIL, "No I/O module attached to this span!\n");
 949 
 950         if (!span->fio->next_event) {
 951                 ftdm_log(FTDM_LOG_ERROR, "next_event method not implemented in module %s!", span->fio->name);
 952                 return FTDM_NOTIMPL;
 953         }
 954 
 955         status = span->fio->next_event(span, event);
 956         if (status != FTDM_SUCCESS) {
 957                 return status;
 958         }
 959 
 960         /* before returning the event to the user we do some core operations with certain OOB events */
 961         memset(&sigmsg, 0, sizeof(sigmsg));
 962         sigmsg.span_id = span->span_id;
 963         sigmsg.chan_id = (*event)->channel->chan_id;
 964         sigmsg.channel = (*event)->channel;
 965         switch ((*event)->enum_id) {
 966         case FTDM_OOB_ALARM_CLEAR:
 967                 {
 968                         sigmsg.event_id = FTDM_SIGEVENT_ALARM_CLEAR;
 969                         ftdm_clear_flag_locked((*event)->channel, FTDM_CHANNEL_IN_ALARM);
 970                         ftdm_span_send_signal(span, &sigmsg);
 971                 }
 972                 break;
 973         case FTDM_OOB_ALARM_TRAP:
 974                 {
 975                         sigmsg.event_id = FTDM_SIGEVENT_ALARM_TRAP;
 976                         ftdm_set_flag_locked((*event)->channel, FTDM_CHANNEL_IN_ALARM);
 977                         ftdm_span_send_signal(span, &sigmsg);
 978                 }
 979                 break;
 980         default:
 981                 /* NOOP */
 982                 break;
 983         }
 984 
 985         return status;
 986 }
 987 
 988 static ftdm_status_t ftdmchan_fsk_write_sample(int16_t *buf, ftdm_size_t buflen, void *user_data)
 989 {
 990         ftdm_channel_t *ftdmchan = (ftdm_channel_t *) user_data;
 991         ftdm_buffer_write(ftdmchan->fsk_buffer, buf, buflen * 2);
 992         return FTDM_SUCCESS;
 993 }
 994 
 995 FT_DECLARE(ftdm_status_t) ftdm_channel_send_fsk_data(ftdm_channel_t *ftdmchan, ftdm_fsk_data_state_t *fsk_data, float db_level)
 996 {
 997         struct ftdm_fsk_modulator fsk_trans;
 998 
 999         if (!ftdmchan->fsk_buffer) {
1000                 ftdm_buffer_create(&ftdmchan->fsk_buffer, 128, 128, 0);
1001         } else {
1002                 ftdm_buffer_zero(ftdmchan->fsk_buffer);
1003         }
1004 
1005         if (ftdmchan->token_count > 1) {
1006                 ftdm_fsk_modulator_init(&fsk_trans, FSK_BELL202, ftdmchan->rate, fsk_data, db_level, 80, 5, 0, ftdmchan_fsk_write_sample, ftdmchan);
1007                 ftdm_fsk_modulator_send_all((&fsk_trans));
1008         } else {
1009                 ftdm_fsk_modulator_init(&fsk_trans, FSK_BELL202, ftdmchan->rate, fsk_data, db_level, 180, 5, 300, ftdmchan_fsk_write_sample, ftdmchan);
1010                 ftdm_fsk_modulator_send_all((&fsk_trans));
1011                 ftdmchan->buffer_delay = 3500 / ftdmchan->effective_interval;
1012         }
1013 
1014         return FTDM_SUCCESS;
1015 }
1016 
1017 FT_DECLARE(ftdm_status_t) ftdm_channel_clear_token(ftdm_channel_t *ftdmchan, const char *token)
1018 {
1019         ftdm_status_t status = FTDM_FAIL;
1020         
1021         ftdm_mutex_lock(ftdmchan->mutex);
1022         if (token == NULL) {
1023                 memset(ftdmchan->tokens, 0, sizeof(ftdmchan->tokens));
1024                 ftdmchan->token_count = 0;
1025         } else if (*token != '\0') {
1026                 char tokens[FTDM_MAX_TOKENS][FTDM_TOKEN_STRLEN];
1027                 int32_t i, count = ftdmchan->token_count;
1028                 memcpy(tokens, ftdmchan->tokens, sizeof(tokens));
1029                 memset(ftdmchan->tokens, 0, sizeof(ftdmchan->tokens));
1030                 ftdmchan->token_count = 0;              
1031 
1032                 for (i = 0; i < count; i++) {
1033                         if (strcmp(tokens[i], token)) {
1034                                 ftdm_copy_string(ftdmchan->tokens[ftdmchan->token_count], tokens[i], sizeof(ftdmchan->tokens[ftdmchan->token_count]));
1035                                 ftdmchan->token_count++;
1036                         }
1037                 }
1038 
1039                 status = FTDM_SUCCESS;
1040         }
1041         ftdm_mutex_unlock(ftdmchan->mutex);
1042 
1043         return status;
1044 }
1045 
1046 FT_DECLARE(void) ftdm_channel_rotate_tokens(ftdm_channel_t *ftdmchan)
1047 {
1048         if (ftdmchan->token_count) {
1049                 memmove(ftdmchan->tokens[1], ftdmchan->tokens[0], ftdmchan->token_count * FTDM_TOKEN_STRLEN);
1050                 ftdm_copy_string(ftdmchan->tokens[0], ftdmchan->tokens[ftdmchan->token_count], FTDM_TOKEN_STRLEN);
1051                 *ftdmchan->tokens[ftdmchan->token_count] = '\0';
1052         }
1053 }
1054 
1055 FT_DECLARE(void) ftdm_channel_replace_token(ftdm_channel_t *ftdmchan, const char *old_token, const char *new_token)
1056 {
1057         unsigned int i;
1058 
1059         if (ftdmchan->token_count) {
1060                 for(i = 0; i < ftdmchan->token_count; i++) {
1061                         if (!strcmp(ftdmchan->tokens[i], old_token)) {
1062                                 ftdm_copy_string(ftdmchan->tokens[i], new_token, FTDM_TOKEN_STRLEN);
1063                                 break;
1064                         }
1065                 }
1066         }
1067 }
1068 
1069 FT_DECLARE(void) ftdm_channel_set_private(ftdm_channel_t *ftdmchan, void *pvt)
1070 {
1071         ftdmchan->user_private = pvt;
1072 }
1073 
1074 FT_DECLARE(void *) ftdm_channel_get_private(const ftdm_channel_t *ftdmchan)
1075 {
1076         return ftdmchan->user_private;
1077 }
1078 
1079 FT_DECLARE(uint32_t) ftdm_channel_get_token_count(const ftdm_channel_t *ftdmchan)
1080 {
1081         uint32_t count;
1082         ftdm_mutex_lock(ftdmchan->mutex);
1083         count = ftdmchan->token_count;
1084         ftdm_mutex_unlock(ftdmchan->mutex);
1085         return count;
1086 }
1087 
1088 FT_DECLARE(uint32_t) ftdm_channel_get_io_interval(const ftdm_channel_t *ftdmchan)
1089 {
1090         uint32_t count;
1091         ftdm_mutex_lock(ftdmchan->mutex);
1092         count = ftdmchan->effective_interval;
1093         ftdm_mutex_unlock(ftdmchan->mutex);
1094         return count;
1095 }
1096 
1097 FT_DECLARE(uint32_t) ftdm_channel_get_io_packet_len(const ftdm_channel_t *ftdmchan)
1098 {
1099         uint32_t count;
1100         ftdm_mutex_lock(ftdmchan->mutex);
1101         count = ftdmchan->packet_len;
1102         ftdm_mutex_unlock(ftdmchan->mutex);
1103         return count;
1104 }
1105 
1106 FT_DECLARE(uint32_t) ftdm_channel_get_type(const ftdm_channel_t *ftdmchan)
1107 {
1108         return ftdmchan->type;
1109 }
1110 
1111 FT_DECLARE(ftdm_codec_t) ftdm_channel_get_codec(const ftdm_channel_t *ftdmchan)
1112 {
1113         return ftdmchan->effective_codec;
1114 }
1115 
1116 FT_DECLARE(const char *) ftdm_channel_get_token(const ftdm_channel_t *ftdmchan, uint32_t tokenid)
1117 {
1118         const char *token = NULL;
1119         ftdm_mutex_lock(ftdmchan->mutex);
1120 
1121         if (ftdmchan->token_count <= tokenid) {
1122                 ftdm_mutex_unlock(ftdmchan->mutex);
1123                 return NULL;
1124         }
1125 
1126         token = ftdmchan->tokens[tokenid];
1127         ftdm_mutex_unlock(ftdmchan->mutex);
1128         return token;
1129 }
1130 
1131 FT_DECLARE(ftdm_status_t) ftdm_channel_add_token(ftdm_channel_t *ftdmchan, char *token, int end)
1132 {
1133         ftdm_status_t status = FTDM_FAIL;
1134 
1135         ftdm_mutex_lock(ftdmchan->mutex);
1136         if (ftdmchan->token_count < FTDM_MAX_TOKENS) {
1137                 if (end) {
1138                         ftdm_copy_string(ftdmchan->tokens[ftdmchan->token_count++], token, FTDM_TOKEN_STRLEN);
1139                 } else {
1140                         memmove(ftdmchan->tokens[1], ftdmchan->tokens[0], ftdmchan->token_count * FTDM_TOKEN_STRLEN);
1141                         ftdm_copy_string(ftdmchan->tokens[0], token, FTDM_TOKEN_STRLEN);
1142                         ftdmchan->token_count++;
1143                 }
1144                 status = FTDM_SUCCESS;
1145         }
1146         ftdm_mutex_unlock(ftdmchan->mutex);
1147 
1148         return status;
1149 }
1150 
1151 
1152 FT_DECLARE(ftdm_status_t) ftdm_channel_complete_state(ftdm_channel_t *ftdmchan)
1153 {
1154         ftdm_channel_state_t state = ftdmchan->state;
1155 
1156         if (state == FTDM_CHANNEL_STATE_PROGRESS) {
1157                 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS);
1158         } else if (state == FTDM_CHANNEL_STATE_UP) {
1159                 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS);
1160                 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_MEDIA);    
1161                 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_ANSWERED); 
1162         } else if (state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA) {
1163                 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS); 
1164                 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_MEDIA);    
1165         }
1166 
1167         return FTDM_SUCCESS;
1168 }
1169 
1170 static int ftdm_parse_state_map(ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, ftdm_state_map_t *state_map)
1171 {
1172         int x = 0, ok = 0;
1173         ftdm_state_direction_t direction = ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) ? ZSD_OUTBOUND : ZSD_INBOUND;
1174 
1175         for(x = 0; x < FTDM_MAP_NODE_SIZE; x++) {
1176                 int i = 0, proceed = 0;
1177                 if (!state_map->nodes[x].type) {
1178                         break;
1179                 }
1180 
1181                 if (state_map->nodes[x].direction != direction) {
1182                         continue;
1183                 }
1184                 
1185                 if (state_map->nodes[x].check_states[0] == FTDM_ANY_STATE) {
1186                         proceed = 1;
1187                 } else {
1188                         for(i = 0; i < FTDM_MAP_MAX; i++) {
1189                                 if (state_map->nodes[x].check_states[i] == ftdmchan->state) {
1190                                         proceed = 1;
1191                                         break;
1192                                 }
1193                         }
1194                 }
1195 
1196                 if (!proceed) {
1197                         continue;
1198                 }
1199                 
1200                 for(i = 0; i < FTDM_MAP_MAX; i++) {
1201                         ok = (state_map->nodes[x].type == ZSM_ACCEPTABLE);
1202                         if (state_map->nodes[x].states[i] == FTDM_END) {
1203                                 break;
1204                         }
1205                         if (state_map->nodes[x].states[i] == state) {
1206                                 ok = !ok;
1207                                 goto end;
1208                         }
1209                 }
1210         }
1211  end:
1212         
1213         return ok;
1214 }
1215 
1216 /* this function MUST be called with the channel lock held. If waitrq == 1, the channel will be unlocked/locked (never call it with waitrq == 1 with an lock recursivity > 1) */
1217 #define DEFAULT_WAIT_TIME 1000
1218 FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_state_t state, int waitrq)
1219 {
1220         int ok = 1;
1221         int waitms = DEFAULT_WAIT_TIME; 
1222 
1223         if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_READY)) {
1224                 ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_ERROR, "Ignored state change request from %s to %s, the channel is not ready\n",
1225                                 ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state));
1226                 return FTDM_FAIL;
1227         }
1228 
1229         if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
1230                 ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_ERROR, "Ignored state change request from %s to %s, the previous state change has not been processed yet\n",
1231                                 ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state));
1232                 return FTDM_FAIL;
1233         }
1234 
1235         if (ftdmchan->state == state) {
1236                 ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "Why bother changing state from %s to %s\n", ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state));
1237                 return FTDM_FAIL;
1238         }
1239 
1240         if (ftdmchan->span->state_map) {
1241                 ok = ftdm_parse_state_map(ftdmchan, state, ftdmchan->span->state_map);
1242                 goto end;
1243         }
1244 
1245         /* basic core state validation (by-passed if the signaling module provides a state_map) */
1246         switch(ftdmchan->state) {
1247         case FTDM_CHANNEL_STATE_HANGUP:
1248         case FTDM_CHANNEL_STATE_TERMINATING:
1249                 {
1250                         ok = 0;
1251                         switch(state) {
1252                         case FTDM_CHANNEL_STATE_DOWN:
1253                         case FTDM_CHANNEL_STATE_BUSY:
1254                         case FTDM_CHANNEL_STATE_RESTART:
1255                                 ok = 1;
1256                                 break;
1257                         default:
1258                                 break;
1259                         }
1260                 }
1261                 break;
1262         case FTDM_CHANNEL_STATE_UP:
1263                 {
1264                         ok = 1;
1265                         switch(state) {
1266                         case FTDM_CHANNEL_STATE_PROGRESS:
1267                         case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
1268                         case FTDM_CHANNEL_STATE_RING:
1269                                 ok = 0;
1270                                 break;
1271                         default:
1272                                 break;
1273                         }
1274                 }
1275                 break;
1276         case FTDM_CHANNEL_STATE_DOWN:
1277                 {
1278                         ok = 0;
1279                         
1280                         switch(state) {
1281                         case FTDM_CHANNEL_STATE_DIALTONE:
1282                         case FTDM_CHANNEL_STATE_COLLECT:
1283                         case FTDM_CHANNEL_STATE_DIALING:
1284                         case FTDM_CHANNEL_STATE_RING:
1285                         case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
1286                         case FTDM_CHANNEL_STATE_PROGRESS:                               
1287                         case FTDM_CHANNEL_STATE_IDLE:                           
1288                         case FTDM_CHANNEL_STATE_GET_CALLERID:
1289                         case FTDM_CHANNEL_STATE_GENRING:
1290                                 ok = 1;
1291                                 break;
1292                         default:
1293                                 break;
1294                         }
1295                 }
1296                 break;
1297         case FTDM_CHANNEL_STATE_BUSY:
1298                 {
1299                         switch(state) {
1300                         case FTDM_CHANNEL_STATE_UP:
1301                                 ok = 0;
1302                                 break;
1303                         default:
1304                                 break;
1305                         }
1306                 }
1307                 break;
1308         case FTDM_CHANNEL_STATE_RING:
1309                 {
1310                         switch(state) {
1311                         case FTDM_CHANNEL_STATE_UP:
1312                                 ok = 1;
1313                                 break;
1314                         default:
1315                                 break;
1316                         }
1317                 }
1318                 break;
1319         default:
1320                 break;
1321         }
1322 
1323 end:
1324 
1325         if (ok) {
1326                 ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Changed state from %s to %s\n", ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state));
1327                 ftdmchan->last_state = ftdmchan->state; 
1328                 ftdmchan->state = state;
1329                 ftdmchan->history[ftdmchan->hindex].file = file;
1330                 ftdmchan->history[ftdmchan->hindex].func = func;
1331                 ftdmchan->history[ftdmchan->hindex].line = line;
1332                 ftdmchan->history[ftdmchan->hindex].state = ftdmchan->state;
1333                 ftdmchan->history[ftdmchan->hindex].last_state = ftdmchan->last_state;
1334                 ftdmchan->history[ftdmchan->hindex].time = ftdm_current_time_in_ms();
1335                 ftdmchan->hindex++;
1336                 if (ftdmchan->hindex == ftdm_array_len(ftdmchan->history)) {
1337                         ftdmchan->hindex = 0;
1338                 }
1339                 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
1340 
1341                 ftdm_mutex_lock(ftdmchan->span->mutex);
1342                 ftdm_set_flag(ftdmchan->span, FTDM_SPAN_STATE_CHANGE);
1343                 if (ftdmchan->span->pendingchans) {
1344                         ftdm_queue_enqueue(ftdmchan->span->pendingchans, ftdmchan);
1345                 }
1346                 ftdm_mutex_unlock(ftdmchan->span->mutex);
1347         } else {
1348                 ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "VETO state change from %s to %s\n", ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state));
1349         }
1350 
1351         /* there is an inherent race here between set and check of the change flag but we do not care because
1352          * the flag should never last raised for more than a few ms for any state change */
1353         while (waitrq && waitms > 0) {
1354                 /* give a chance to the signaling stack to process it */
1355                 ftdm_mutex_unlock(ftdmchan->mutex);
1356 
1357                 ftdm_sleep(10);
1358                 waitms -= 10;
1359 
1360                 ftdm_mutex_lock(ftdmchan->mutex);
1361                 
1362                 /* if the flag is no longer set, the state change was processed (or is being processed) */
1363                 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
1364                         break;
1365                 }
1366 
1367                 /* if the state is no longer what we set, the state change was 
1368                  * obviously processed (and the current state change flag is for other state change) */
1369                 if (ftdmchan->state != state) {
1370                         break;
1371                 }
1372         }
1373 
1374         if (waitms <= 0) {
1375                 ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "state change from %s to %s was most likely not processed after aprox %dms\n",
1376                                 ftdm_channel_state2str(ftdmchan->last_state), ftdm_channel_state2str(state), DEFAULT_WAIT_TIME);
1377         }
1378 
1379         return ok ? FTDM_SUCCESS : FTDM_FAIL;
1380 }
1381 
1382 FT_DECLARE(uint32_t) ftdm_group_get_id(const ftdm_group_t *group)
1383 {
1384         return group->group_id;
1385 }
1386 
1387 FT_DECLARE(ftdm_status_t) ftdm_group_channel_use_count(ftdm_group_t *group, uint32_t *count)
1388 {
1389         uint32_t j;
1390 
1391         *count = 0;
1392         
1393         if (!group) {
1394                 return FTDM_FAIL;
1395         }
1396         
1397         for(j = 0; j < group->chan_count && group->channels[j]; j++) {
1398                 if (group->channels[j]) {
1399                         if (ftdm_test_flag(group->channels[j], FTDM_CHANNEL_INUSE)) {
1400                                 (*count)++;
1401                         }
1402                 }
1403         }
1404         
1405         return FTDM_SUCCESS;
1406 }
1407 
1408 static __inline__ int chan_is_avail(ftdm_channel_t *check)
1409 {
1410         if (!ftdm_test_flag(check, FTDM_CHANNEL_READY) ||
1411                 !ftdm_test_flag(check, FTDM_CHANNEL_SIG_UP) ||
1412                 ftdm_test_flag(check, FTDM_CHANNEL_INUSE) ||
1413                 ftdm_test_flag(check, FTDM_CHANNEL_SUSPENDED) ||
1414                 ftdm_test_flag(check, FTDM_CHANNEL_IN_ALARM) ||
1415                 check->state != FTDM_CHANNEL_STATE_DOWN) {
1416                 return 0;
1417         }
1418         return 1;
1419 }
1420 
1421 static __inline__ int chan_voice_is_avail(ftdm_channel_t *check)
1422 {
1423         if (!FTDM_IS_VOICE_CHANNEL(check)) {
1424                 return 0;
1425         }
1426         return chan_is_avail(check);
1427 }
1428 
1429 static __inline__ int request_voice_channel(ftdm_channel_t *check, ftdm_channel_t **ftdmchan, 
1430                 ftdm_caller_data_t *caller_data, ftdm_direction_t direction)
1431 {
1432         ftdm_status_t status;
1433         if (chan_voice_is_avail(check)) {
1434                 /* unlocked testing passed, try again with the channel locked */
1435                 ftdm_mutex_lock(check->mutex);
1436                 if (chan_voice_is_avail(check)) {
1437                         if (check->span && check->span->channel_request) {
1438                                 /* I am only unlocking here cuz this function is called
1439                                  * sometimes with the group or span lock held and were
1440                                  * blocking anyone hunting for channels available and
1441                                  * I believe teh channel_request() function may take
1442                                  * a bit of time 
1443                                  * */
1444                                 ftdm_mutex_unlock(check->mutex);
1445                                 ftdm_set_caller_data(check->span, caller_data);
1446                                 status = check->span->channel_request(check->span, check->chan_id, 
1447                                         direction, caller_data, ftdmchan);
1448                                 if (status == FTDM_SUCCESS) {
1449                                         return 1;
1450                                 }
1451                         } else {
1452                                 status = ftdm_channel_open_chan(check);
1453                                 if (status == FTDM_SUCCESS) {
1454                                         *ftdmchan = check;
1455                                         ftdm_set_flag(check, FTDM_CHANNEL_OUTBOUND);
1456                                         ftdm_mutex_unlock(check->mutex);
1457                                         return 1;
1458                                 }
1459                         }
1460                 }
1461                 ftdm_mutex_unlock(check->mutex);
1462         } 
1463         return 0;
1464 }
1465 
1466 static void __inline__ calculate_best_rate(ftdm_channel_t *check, ftdm_channel_t **best_rated, int *best_rate)
1467 {
1468         if (ftdm_test_flag(check->span, FTDM_SPAN_USE_AV_RATE)) {
1469                 ftdm_mutex_lock(check->mutex);
1470                 if (ftdm_test_flag(check, FTDM_CHANNEL_INUSE)) {
1471                         /* twiddle */
1472                 } else if (ftdm_test_flag(check, FTDM_CHANNEL_SIG_UP)) {
1473                         /* twiddle */
1474                 } else if (check->availability_rate > *best_rate){
1475                         /* the channel is not in use and the signaling status is down, 
1476                          * it is a potential candidate to place a call */
1477                         *best_rated = check;
1478                         *best_rate = check->availability_rate;
1479                 }
1480                 ftdm_mutex_unlock(check->mutex);
1481         }
1482 }
1483 
1484 static ftdm_status_t __inline__ get_best_rated(ftdm_channel_t **fchan, ftdm_channel_t *best_rated)
1485 {
1486         ftdm_status_t status;
1487 
1488         if (!best_rated) {
1489                 return FTDM_FAIL;
1490         }
1491 
1492         ftdm_mutex_lock(best_rated->mutex);
1493 
1494         if (ftdm_test_flag(best_rated, FTDM_CHANNEL_INUSE)) {
1495                 ftdm_mutex_unlock(best_rated->mutex);
1496                 return FTDM_FAIL;
1497         }
1498 
1499         ftdm_log_chan_msg(best_rated, FTDM_LOG_DEBUG, "I may not be available but I had the best availability rate, trying to open I/O now\n");
1500 
1501         status = ftdm_channel_open_chan(best_rated);
1502         if (status != FTDM_SUCCESS) {
1503                 ftdm_mutex_unlock(best_rated->mutex);
1504                 return FTDM_FAIL;
1505         }
1506         *fchan = best_rated;
1507         ftdm_set_flag(best_rated, FTDM_CHANNEL_OUTBOUND);
1508         
1509         ftdm_mutex_unlock(best_rated->mutex);
1510 
1511         return FTDM_SUCCESS;
1512 }
1513 FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
1514 {
1515         ftdm_status_t status = FTDM_FAIL;
1516         ftdm_channel_t *check = NULL;
1517         ftdm_channel_t *best_rated = NULL;
1518         ftdm_group_t *group = NULL;
1519         int best_rate = 0;
1520         uint32_t i = 0;
1521         uint32_t count = 0;
1522 
1523         if (group_id) {
1524                 ftdm_group_find(group_id, &group);
1525         }
1526 
1527         if (!group) {
1528                 ftdm_log(FTDM_LOG_ERROR, "Group %d not defined!\n", group_id);
1529                 *ftdmchan = NULL;
1530                 return FTDM_FAIL;
1531         }
1532 
1533         ftdm_group_channel_use_count(group, &count);
1534 
1535         if (count >= group->chan_count) {
1536                 ftdm_log(FTDM_LOG_WARNING, "All circuits are busy (%d channels used out of %d available).\n", count, group->chan_count);
1537                 *ftdmchan = NULL;
1538                 return FTDM_FAIL;
1539         }
1540 
1541         
1542         if (direction == FTDM_TOP_DOWN) {
1543                 i = 0;
1544         } else {
1545                 i = group->chan_count-1;
1546         }
1547 
1548         ftdm_mutex_lock(group->mutex);
1549         for (;;) {
1550         
1551                 if (!(check = group->channels[i])) {
1552                         status = FTDM_FAIL;
1553                         break;
1554                 }
1555 
1556                 if (request_voice_channel(check, ftdmchan, caller_data, direction)) {
1557                         status = FTDM_SUCCESS;
1558                         break;
1559                 }
1560 
1561                 calculate_best_rate(check, &best_rated, &best_rate);
1562 
1563                 if (direction == FTDM_TOP_DOWN) {
1564                         if (i >= group->chan_count) {
1565                                 break;
1566                         }
1567                         i++;
1568                 } else {
1569                         if (i == 0) {
1570                                 break;
1571                         }
1572                         i--;
1573                 }
1574         }
1575 
1576         if (status == FTDM_FAIL) {
1577                 status = get_best_rated(ftdmchan, best_rated);
1578         }
1579 
1580         ftdm_mutex_unlock(group->mutex);
1581         return status;
1582 }
1583 
1584 
1585 FT_DECLARE(ftdm_status_t) ftdm_span_channel_use_count(ftdm_span_t *span, uint32_t *count)
1586 {
1587         uint32_t j;
1588 
1589         *count = 0;
1590         
1591         if (!span || !ftdm_test_flag(span, FTDM_SPAN_CONFIGURED)) {
1592                 return FTDM_FAIL;
1593         }
1594         
1595         for(j = 1; j <= span->chan_count && span->channels[j]; j++) {
1596                 if (span->channels[j]) {
1597                         if (ftdm_test_flag(span->channels[j], FTDM_CHANNEL_INUSE)) {
1598                                 (*count)++;
1599                         }
1600                 }
1601         }
1602         
1603         return FTDM_SUCCESS;
1604 }
1605 
1606 FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
1607 {
1608         ftdm_status_t status = FTDM_FAIL;
1609         ftdm_channel_t *check = NULL;
1610         ftdm_channel_t *best_rated = NULL;
1611         ftdm_span_t *span = NULL;
1612         int best_rate = 0;
1613         uint32_t i = 0;
1614         uint32_t count = 0;
1615 
1616         *ftdmchan = NULL;
1617 
1618         if (!span_id) {
1619                 ftdm_log(FTDM_LOG_CRIT, "No span supplied\n");
1620                 return FTDM_FAIL;
1621         }
1622 
1623         ftdm_span_find(span_id, &span);
1624 
1625         if (!span || !ftdm_test_flag(span, FTDM_SPAN_CONFIGURED)) {
1626                 ftdm_log(FTDM_LOG_CRIT, "span %d not defined or configured!\n", span_id);
1627                 return FTDM_FAIL;
1628         }
1629 
1630         ftdm_span_channel_use_count(span, &count);
1631 
1632         if (count >= span->chan_count) {
1633                 ftdm_log(FTDM_LOG_WARNING, "All circuits are busy: active=%i max=%i.\n", count, span->chan_count);
1634                 return FTDM_FAIL;
1635         }
1636 
1637         if (span->channel_request && !ftdm_test_flag(span, FTDM_SPAN_SUGGEST_CHAN_ID)) {
1638                 ftdm_set_caller_data(span, caller_data);
1639                 return span->channel_request(span, 0, direction, caller_data, ftdmchan);
1640         }
1641                 
1642         ftdm_mutex_lock(span->mutex);
1643         
1644         if (direction == FTDM_TOP_DOWN) {
1645                 i = 1;
1646         } else {
1647                 i = span->chan_count;
1648         }       
1649                 
1650         for(;;) {
1651 
1652                 if (direction == FTDM_TOP_DOWN) {
1653                         if (i > span->chan_count) {
1654                                 break;
1655                         }
1656                 } else {
1657                         if (i == 0) {
1658                                 break;
1659                         }
1660                 }
1661                         
1662                 if (!(check = span->channels[i])) {
1663                         status = FTDM_FAIL;
1664                         break;
1665                 }
1666 
1667                 if (request_voice_channel(check, ftdmchan, caller_data, direction)) {
1668                         status = FTDM_SUCCESS;
1669                         break;
1670                 }
1671                         
1672                 calculate_best_rate(check, &best_rated, &best_rate);
1673 
1674                 if (direction == FTDM_TOP_DOWN) {
1675                         i++;
1676                 } else {
1677                         i--;
1678                 }
1679         }
1680 
1681         if (status == FTDM_FAIL) {
1682                 status = get_best_rated(ftdmchan, best_rated);
1683         }
1684 
1685         ftdm_mutex_unlock(span->mutex);
1686 
1687         return status;
1688 }
1689 
1690 static ftdm_status_t ftdm_channel_reset(ftdm_channel_t *ftdmchan)
1691 {
1692         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OPEN);
1693         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
1694         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
1695         ftdm_channel_done(ftdmchan);
1696         ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_HOLD);
1697 
1698         memset(ftdmchan->tokens, 0, sizeof(ftdmchan->tokens));
1699         ftdmchan->token_count = 0;
1700 
1701         ftdm_channel_flush_dtmf(ftdmchan);
1702 
1703         if (ftdmchan->gen_dtmf_buffer) {
1704                 ftdm_buffer_zero(ftdmchan->gen_dtmf_buffer);
1705         }
1706 
1707         if (ftdmchan->digit_buffer) {
1708                 ftdm_buffer_zero(ftdmchan->digit_buffer);
1709         }
1710 
1711         if (!ftdmchan->dtmf_on) {
1712                 ftdmchan->dtmf_on = FTDM_DEFAULT_DTMF_ON;
1713         }
1714 
1715         if (!ftdmchan->dtmf_off) {
1716                 ftdmchan->dtmf_off = FTDM_DEFAULT_DTMF_OFF;
1717         }
1718         
1719         memset(ftdmchan->dtmf_hangup_buf, '\0', ftdmchan->span->dtmf_hangup_len);
1720 
1721         if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE)) {
1722                 ftdmchan->effective_codec = ftdmchan->native_codec;
1723                 ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8);
1724                 ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE);
1725         }
1726 
1727         return FTDM_SUCCESS;
1728 }
1729 
1730 FT_DECLARE(ftdm_status_t) ftdm_channel_init(ftdm_channel_t *ftdmchan)
1731 {
1732         if (ftdmchan->init_state != FTDM_CHANNEL_STATE_DOWN) {
1733                 ftdm_set_state(ftdmchan, ftdmchan->init_state);
1734                 ftdmchan->init_state = FTDM_CHANNEL_STATE_DOWN;
1735         }
1736 
1737         return FTDM_SUCCESS;
1738 }
1739 
1740 FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan)
1741 {
1742         ftdm_status_t status = FTDM_FAIL;
1743 
1744         ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "invalid ftdmchan pointer\n");
1745 
1746         ftdm_mutex_lock(ftdmchan->mutex);
1747 
1748         if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) {
1749                 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is suspended\n");
1750                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is suspended\n");
1751                 goto done;
1752         }
1753 
1754         if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) {
1755                 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is alarmed\n");
1756                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is alarmed\n");
1757                 goto done;
1758         }
1759 
1760         if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_READY)) {
1761                 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "Channel is not ready");
1762                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is not ready\n");
1763                 goto done;
1764         }
1765 
1766         if (globals.cpu_monitor.alarm && 
1767             globals.cpu_monitor.alarm_action_flags & FTDM_CPU_ALARM_ACTION_REJECT) {
1768                 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "CPU usage alarm is on - refusing to open channel\n");
1769                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "CPU usage alarm is on - refusing to open channel\n");
1770                 ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_SWITCH_CONGESTION;
1771                 goto done;
1772         }
1773 
1774 
1775         status = ftdmchan->fio->open(ftdmchan);
1776         if (status == FTDM_SUCCESS) {
1777                 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_OPEN | FTDM_CHANNEL_INUSE);
1778         } else {
1779                 ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "IO open failed: %d\n", status);
1780         }
1781 
1782 done:
1783         
1784         ftdm_mutex_unlock(ftdmchan->mutex);
1785 
1786         return status;
1787 }
1788 
1789 FT_DECLARE(ftdm_status_t) ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm_channel_t **ftdmchan)
1790 {
1791         ftdm_channel_t *check = NULL;
1792         ftdm_span_t *span = NULL;
1793         ftdm_channel_t *best_rated = NULL;
1794         ftdm_status_t status = FTDM_FAIL;
1795         int best_rate = 0;
1796 
1797         *ftdmchan = NULL;
1798 
1799         ftdm_mutex_lock(globals.mutex);
1800 
1801         ftdm_span_find(span_id, &span);
1802 
1803         if (!span) {
1804                 ftdm_log(FTDM_LOG_CRIT, "Could not find span!\n");
1805                 goto done;
1806         }
1807 
1808         if (!ftdm_test_flag(span, FTDM_SPAN_CONFIGURED)) {
1809                 ftdm_log(FTDM_LOG_CRIT, "Span %d is not configured\n", span_id);
1810                 goto done;
1811         }
1812 
1813         if (span->channel_request) {
1814                 ftdm_log(FTDM_LOG_ERROR, "Individual channel selection not implemented on this span.\n");
1815                 goto done;
1816         }
1817 
1818         if (chan_id < 1 || chan_id > span->chan_count) {
1819                 ftdm_log(FTDM_LOG_ERROR, "Invalid channel %d to open in span %d\n", chan_id, span_id);
1820                 goto done;
1821         }
1822 
1823         if (!(check = span->channels[chan_id])) {
1824                 ftdm_log(FTDM_LOG_CRIT, "Wow, no channel %d in span %d\n", chan_id, span_id);
1825                 goto done;
1826         }
1827 
1828         ftdm_mutex_lock(check->mutex);
1829 
1830         /* The following if's and gotos replace a big if (this || this || this || this) else { nothing; } */
1831 
1832         /* if it is not a voice channel, nothing else to check to open it */
1833         if (!FTDM_IS_VOICE_CHANNEL(check)) {
1834                 goto openchan;
1835         }
1836 
1837         /* if it's an FXS device with a call active and has callwaiting enabled, we allow to open it twice */
1838         if (check->type == FTDM_CHAN_TYPE_FXS 
1839             && check->token_count == 1 
1840             && ftdm_channel_test_feature(check, FTDM_CHANNEL_FEATURE_CALLWAITING)) {
1841                 goto openchan;
1842         }
1843 
1844         /* if channel is available, time to open it */
1845         if (chan_is_avail(check)) {
1846                 goto openchan;
1847         }
1848 
1849         /* not available, but still might be available ... */
1850         calculate_best_rate(check, &best_rated, &best_rate);
1851         if (best_rated) {
1852                 goto openchan;
1853         }
1854 
1855         /* channel is unavailable, do not open the channel */
1856         goto unlockchan;
1857 
1858 openchan:
1859         if (!ftdm_test_flag(check, FTDM_CHANNEL_OPEN)) {
1860                 status = check->fio->open(check);
1861                 if (status == FTDM_SUCCESS) {
1862                         ftdm_set_flag(check, FTDM_CHANNEL_OPEN);
1863                 }
1864         } else {
1865                 status = FTDM_SUCCESS;
1866         }
1867         ftdm_set_flag(check, FTDM_CHANNEL_INUSE);
1868         ftdm_set_flag(check, FTDM_CHANNEL_OUTBOUND);
1869         *ftdmchan = check;
1870 
1871 unlockchan:
1872         ftdm_mutex_unlock(check->mutex);
1873 
1874 done:
1875         ftdm_mutex_unlock(globals.mutex);
1876         if (status != FTDM_SUCCESS) {
1877                 ftdm_log(FTDM_LOG_ERROR, "Failed to open channel %d:%d\n", span_id, chan_id);
1878         }
1879 
1880         return status;
1881 }
1882 
1883 FT_DECLARE(uint32_t) ftdm_channel_get_id(const ftdm_channel_t *ftdmchan)
1884 {
1885         return ftdmchan->chan_id;
1886 }
1887 
1888 FT_DECLARE(uint32_t) ftdm_channel_get_ph_id(const ftdm_channel_t *ftdmchan)
1889 {
1890         return ftdmchan->physical_chan_id;
1891 }
1892 
1893 FT_DECLARE(uint32_t) ftdm_channel_get_span_id(const ftdm_channel_t *ftdmchan)
1894 {
1895         return ftdmchan->span_id;
1896 }
1897 
1898 FT_DECLARE(ftdm_span_t *) ftdm_channel_get_span(const ftdm_channel_t *ftdmchan)
1899 {
1900         return ftdmchan->span;
1901 }
1902 
1903 FT_DECLARE(const char *) ftdm_channel_get_span_name(const ftdm_channel_t *ftdmchan)
1904 {
1905         return ftdmchan->span->name;
1906 }
1907 
1908 FT_DECLARE(void) ftdm_span_set_trunk_type(ftdm_span_t *span, ftdm_trunk_type_t type)
1909 {
1910         span->trunk_type = type;
1911 }
1912 
1913 FT_DECLARE(ftdm_trunk_type_t) ftdm_span_get_trunk_type(const ftdm_span_t *span)
1914 {
1915         return span->trunk_type;
1916 }
1917 
1918 FT_DECLARE(uint32_t) ftdm_span_get_id(const ftdm_span_t *span)
1919 {
1920         return span->span_id;
1921 }
1922 
1923 FT_DECLARE(const char *) ftdm_span_get_name(const ftdm_span_t *span)
1924 {
1925         return span->name;
1926 }
1927 
1928 FT_DECLARE(const char *) ftdm_channel_get_name(const ftdm_channel_t *ftdmchan)
1929 {
1930         return ftdmchan->chan_name;
1931 }
1932 
1933 FT_DECLARE(const char *) ftdm_channel_get_number(const ftdm_channel_t *ftdmchan)
1934 {
1935         return ftdmchan->chan_number;
1936 }
1937 
1938 FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_hold(const ftdm_channel_t *ftdmchan)
1939 {
1940         ftdm_bool_t condition;
1941         ftdm_channel_lock(ftdmchan);
1942         condition = ftdm_test_flag(ftdmchan, FTDM_CHANNEL_HOLD) ? FTDM_TRUE : FTDM_FALSE;
1943         ftdm_channel_unlock(ftdmchan);
1944         return condition;
1945 }
1946 
1947 FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_answered(const ftdm_channel_t *ftdmchan)
1948 {
1949         ftdm_bool_t condition = FTDM_FALSE;
1950 
1951         ftdm_channel_lock(ftdmchan);
1952         condition = (ftdmchan->state == FTDM_CHANNEL_STATE_UP) ? FTDM_TRUE : FTDM_FALSE;
1953         ftdm_channel_unlock(ftdmchan);
1954 
1955         return condition;
1956 }
1957 
1958 FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_busy(const ftdm_channel_t *ftdmchan)
1959 {
1960         ftdm_bool_t condition = FTDM_FALSE;
1961 
1962         ftdm_channel_lock(ftdmchan);
1963         condition = (ftdmchan->state == FTDM_CHANNEL_STATE_BUSY) ? FTDM_TRUE : FTDM_FALSE;
1964         ftdm_channel_unlock(ftdmchan);
1965 
1966         return condition;
1967 }
1968 
1969 FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_hangup(const ftdm_channel_t *ftdmchan)
1970 {
1971         ftdm_bool_t condition = FTDM_FALSE;
1972 
1973         ftdm_channel_lock(ftdmchan);
1974         condition = (ftdmchan->state == FTDM_CHANNEL_STATE_HANGUP || ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) 
1975                 ? FTDM_TRUE : FTDM_FALSE;
1976         ftdm_channel_unlock(ftdmchan);
1977 
1978         return condition;
1979 }
1980 
1981 FT_DECLARE(ftdm_bool_t) ftdm_channel_call_check_done(const ftdm_channel_t *ftdmchan)
1982 {
1983         ftdm_bool_t condition = FTDM_FALSE;
1984 
1985         ftdm_channel_lock(ftdmchan);
1986         condition = (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) ? FTDM_TRUE : FTDM_FALSE;
1987         ftdm_channel_unlock(ftdmchan);
1988 
1989         return condition;
1990 }
1991 
1992 FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
1993 {
1994         ftdm_channel_lock(ftdmchan);
1995         ftdm_set_flag(ftdmchan, FTDM_CHANNEL_HOLD);
1996         ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_DIALTONE, 0);
1997         ftdm_channel_unlock(ftdmchan);
1998         return FTDM_SUCCESS;
1999 }
2000 
2001 FT_DECLARE(ftdm_status_t) _ftdm_channel_call_unhold(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
2002 {
2003         ftdm_channel_lock(ftdmchan);
2004         ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_UP, 0);
2005         ftdm_channel_unlock(ftdmchan);
2006         return FTDM_SUCCESS;
2007 }
2008 
2009 FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
2010 {
2011         ftdm_status_t status = FTDM_SUCCESS;
2012 
2013         ftdm_channel_lock(ftdmchan);
2014 
2015         if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
2016                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call is already TERMINATING\n");
2017                 goto done;
2018         }
2019 
2020         ftdm_set_flag(ftdmchan, FTDM_CHANNEL_ANSWERED);
2021         ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS);
2022         ftdm_set_flag(ftdmchan, FTDM_CHANNEL_MEDIA);
2023 
2024         if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
2025                 goto done;
2026         }
2027 
2028 
2029         if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) {
2030                 ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1);
2031         }
2032 
2033         /* set state unlocks the channel so we need to re-confirm that the channel hasn't gone to hell */
2034         if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
2035                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to PROGRESS\n");
2036                 goto done;
2037         }
2038 
2039         if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS_MEDIA) {
2040                 ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1);
2041         }
2042 
2043         /* set state unlocks the channel so we need to re-confirm that the channel hasn't gone to hell */
2044         if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
2045                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to UP\n");
2046                 goto done;
2047         }
2048 
2049         ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_UP, 1);
2050 
2051 done:
2052 
2053         ftdm_channel_unlock(ftdmchan);
2054         return status;
2055 }
2056 
2057 /* lock must be acquired by the caller! */
2058 static ftdm_status_t call_hangup(ftdm_channel_t *chan, const char *file, const char *func, int line)
2059 {
2060         ftdm_set_flag(chan, FTDM_CHANNEL_USER_HANGUP);
2061 
2062         ftdm_set_echocancel_call_end(chan);
2063         
2064         if (chan->state != FTDM_CHANNEL_STATE_DOWN) {
2065                 if (chan->state == FTDM_CHANNEL_STATE_HANGUP) {
2066                         /* make user's life easier, and just ignore double hangup requests */
2067                         return FTDM_SUCCESS;
2068                 }
2069                 if (chan->hangup_timer) {
2070                         ftdm_sched_cancel_timer(globals.timingsched, chan->hangup_timer);
2071                 }
2072                 ftdm_channel_set_state(file, func, line, chan, FTDM_CHANNEL_STATE_HANGUP, 1);
2073         } else {
2074                 /* the signaling stack did not touch the state, 
2075                  * core is responsible from clearing flags and stuff */
2076                 ftdm_channel_done(chan);
2077         }
2078         return FTDM_SUCCESS;
2079 }
2080 
2081 FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup_with_cause(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_call_cause_t cause)
2082 {
2083         ftdm_channel_lock(ftdmchan);
2084 
2085         ftdmchan->caller_data.hangup_cause = cause;
2086         
2087         call_hangup(ftdmchan, file, func, line);
2088 
2089         ftdm_channel_unlock(ftdmchan);
2090         return FTDM_SUCCESS;
2091 }
2092 
2093 FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
2094 {
2095         ftdm_channel_lock(ftdmchan);
2096         ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING;
2097         call_hangup(ftdmchan, file, func, line);
2098         ftdm_channel_unlock(ftdmchan);
2099         return FTDM_SUCCESS;
2100 }
2101 
2102 FT_DECLARE(const char *) ftdm_channel_get_last_error(const ftdm_channel_t *ftdmchan)
2103 {
2104         return ftdmchan->last_error;
2105 }
2106 
2107 FT_DECLARE(const char *) ftdm_span_get_last_error(const ftdm_span_t *span)
2108 {
2109         return span->last_error;
2110 }
2111 
2112 FT_DECLARE(ftdm_caller_data_t *) ftdm_channel_get_caller_data(ftdm_channel_t *ftdmchan)
2113 {
2114         return &ftdmchan->caller_data;
2115 }
2116 
2117 FT_DECLARE(const char *) ftdm_channel_get_state_str(const ftdm_channel_t *ftdmchan)
2118 {
2119         const char *state;
2120         ftdm_channel_lock(ftdmchan);
2121         state = ftdm_channel_state2str(ftdmchan->state);
2122         ftdm_channel_unlock(ftdmchan);
2123         return state;
2124 }
2125 
2126 FT_DECLARE(const char *) ftdm_channel_get_last_state_str(const ftdm_channel_t *ftdmchan)
2127 {
2128         const char *state;
2129         ftdm_channel_lock(ftdmchan);
2130         state = ftdm_channel_state2str(ftdmchan->last_state);
2131         ftdm_channel_unlock(ftdmchan);
2132         return state;
2133 }
2134 
2135 FT_DECLARE(ftdm_channel_t *) ftdm_span_get_channel(const ftdm_span_t *span, uint32_t chanid)
2136 {
2137         ftdm_channel_t *chan;
2138         ftdm_mutex_lock(span->mutex);
2139         if (chanid == 0 || chanid > span->chan_count) {
2140                 ftdm_mutex_unlock(span->mutex);
2141                 return NULL;
2142         }
2143         chan = span->channels[chanid];
2144         ftdm_mutex_unlock(span->mutex);
2145         return chan;
2146 }
2147 
2148 FT_DECLARE(uint32_t) ftdm_span_get_chan_count(const ftdm_span_t *span)
2149 {
2150         uint32_t count;
2151         ftdm_mutex_lock(span->mutex);
2152         count = span->chan_count;
2153         ftdm_mutex_unlock(span->mutex);
2154         return count;
2155 }
2156 
2157 FT_DECLARE(uint32_t) ftdm_channel_get_ph_span_id(const ftdm_channel_t *ftdmchan)
2158 {
2159         uint32_t id;
2160         ftdm_channel_lock(ftdmchan);
2161         id = ftdmchan->physical_span_id;
2162         ftdm_channel_unlock(ftdmchan);
2163         return id;
2164 }
2165 
2166 FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication)
2167 {
2168         ftdm_status_t status = FTDM_SUCCESS;
2169         ftdm_channel_lock(ftdmchan);
2170 
2171         if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
2172                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to PROGRESS\n");
2173                 goto done;
2174         }
2175 
2176         switch (indication) {
2177         /* FIXME: ring and busy cannot be used with all signaling stacks 
2178          * (particularly isdn stacks I think, we should emulate or just move to hangup with busy cause) */
2179         case FTDM_CHANNEL_INDICATE_RING:
2180                 ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RING, 1);
2181                 break;
2182 
2183         case FTDM_CHANNEL_INDICATE_BUSY:
2184                 ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_BUSY, 1);
2185                 break;
2186 
2187         case FTDM_CHANNEL_INDICATE_PROGRESS:
2188                 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
2189                         ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS);
2190                 } else {
2191                         ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1);
2192                 }
2193                 break;
2194 
2195         case FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA:
2196                 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
2197                         ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS);
2198                         ftdm_set_flag(ftdmchan, FTDM_CHANNEL_MEDIA);
2199                 } else {
2200                         if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) {
2201                                 ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1);
2202                         }
2203 
2204                         /* set state unlocks the channel so we need to re-confirm that the channel hasn't gone to hell */
2205                         if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
2206                                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to PROGRESS\n");
2207                                 goto done;
2208                         }
2209 
2210                         ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1);
2211                 }
2212                 break;
2213 
2214         default:
2215                 ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "Do not know how to indicate %d\n", indication);
2216                 status = FTDM_FAIL;
2217                 break;
2218         }
2219 
2220 done:
2221         ftdm_channel_unlock(ftdmchan);
2222 
2223         return FTDM_SUCCESS;
2224 }
2225 
2226 FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan)
2227 {
2228         ftdm_status_t status = FTDM_FAIL;
2229         
2230         ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel");
2231         ftdm_assert_return(ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND), FTDM_FAIL, "Call place, but outbound flag not set\n");
2232 
2233         ftdm_set_echocancel_call_begin(ftdmchan);
2234 
2235         ftdm_channel_lock(ftdmchan);
2236 
2237         if (ftdmchan->span->outgoing_call) {
2238                 status = ftdmchan->span->outgoing_call(ftdmchan);
2239         } else {
2240                 status = FTDM_NOTIMPL;
2241                 ftdm_log(FTDM_LOG_ERROR, "outgoing_call method not implemented in this span!\n");
2242         }
2243 
2244 #ifdef __WINDOWS__
2245         UNREFERENCED_PARAMETER(file);
2246         UNREFERENCED_PARAMETER(func);
2247         UNREFERENCED_PARAMETER(line);
2248 #endif
2249 
2250         ftdm_channel_unlock(ftdmchan);
2251 
2252         return status;
2253 }
2254 
2255 FT_DECLARE(ftdm_status_t) ftdm_channel_set_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t sigstatus)
2256 {
2257         ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel\n");
2258         ftdm_assert_return(ftdmchan->span != NULL, FTDM_FAIL, "Null span\n");
2259         
2260         if (ftdmchan->span->set_channel_sig_status) {
2261                 return ftdmchan->span->set_channel_sig_status(ftdmchan, sigstatus);
2262         } else {
2263                 ftdm_log(FTDM_LOG_ERROR, "set_channel_sig_status method not implemented!\n");
2264                 return FTDM_FAIL;
2265         }
2266 }
2267 
2268 FT_DECLARE(ftdm_status_t) ftdm_channel_get_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t *sigstatus)
2269 {
2270         ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel\n");
2271         ftdm_assert_return(ftdmchan->span != NULL, FTDM_FAIL, "Null span\n");
2272         ftdm_assert_return(sigstatus != NULL, FTDM_FAIL, "Null sig status parameter\n");
2273         
2274         if (ftdmchan->span->get_channel_sig_status) {
2275                 return ftdmchan->span->get_channel_sig_status(ftdmchan, sigstatus);
2276         } else {
2277                 /* don't log error here, it can be called just to test if its supported */
2278                 return FTDM_NOTIMPL;
2279         }
2280 }
2281 
2282 FT_DECLARE(ftdm_status_t) ftdm_span_set_sig_status(ftdm_span_t *span, ftdm_signaling_status_t sigstatus)
2283 {
2284         ftdm_assert_return(span != NULL, FTDM_FAIL, "Null span\n");
2285         
2286         if (span->set_span_sig_status) {
2287                 return span->set_span_sig_status(span, sigstatus);
2288         } else {
2289                 ftdm_log(FTDM_LOG_ERROR, "set_span_sig_status method not implemented!\n");
2290                 return FTDM_FAIL;
2291         }
2292 }
2293 
2294 FT_DECLARE(ftdm_status_t) ftdm_span_get_sig_status(ftdm_span_t *span, ftdm_signaling_status_t *sigstatus)
2295 {
2296         ftdm_assert_return(span != NULL, FTDM_FAIL, "Null span\n");
2297         ftdm_assert_return(sigstatus != NULL, FTDM_FAIL, "Null sig status parameter\n");
2298         
2299         if (span->get_span_sig_status) {
2300                 return span->get_span_sig_status(span, sigstatus);
2301         } else {
2302                 return FTDM_FAIL;
2303         }
2304 }
2305 
2306 #ifdef FTDM_DEBUG_DTMF
2307 static void close_dtmf_debug(ftdm_channel_t *ftdmchan)
2308 {
2309         ftdm_mutex_lock(ftdmchan->dtmfdbg.mutex);
2310 
2311         if (ftdmchan->dtmfdbg.file) {
2312                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "closing debug dtmf file\n");
2313                 fclose(ftdmchan->dtmfdbg.file);
2314                 ftdmchan->dtmfdbg.file = NULL;
2315         }
2316         ftdmchan->dtmfdbg.windex = 0;
2317         ftdmchan->dtmfdbg.wrapped = 0;
2318 
2319         ftdm_mutex_unlock(ftdmchan->dtmfdbg.mutex);
2320 }
2321 #endif
2322 
2323 static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan);
2324 FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
2325 {
2326         ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel can't be done!\n");
2327 
2328         ftdm_mutex_lock(ftdmchan->mutex);
2329 
2330         memset(&ftdmchan->caller_data, 0, sizeof(ftdmchan->caller_data));
2331 
2332         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_INUSE);
2333         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND);
2334         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_WINK);
2335         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_FLASH);
2336         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
2337         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_HOLD);
2338         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK);
2339         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_RINGING);
2340         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_PROGRESS_DETECT);
2341         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT);
2342         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_3WAY);
2343         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_PROGRESS);
2344         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_MEDIA);
2345         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_ANSWERED);
2346         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_USER_HANGUP);
2347         ftdm_mutex_lock(ftdmchan->pre_buffer_mutex);
2348         ftdm_buffer_destroy(&ftdmchan->pre_buffer);
2349         ftdmchan->pre_buffer_size = 0;
2350         ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex);
2351 #ifdef FTDM_DEBUG_DTMF
2352         close_dtmf_debug(ftdmchan);
2353 #endif
2354         ftdm_channel_clear_vars(ftdmchan);
2355         if (ftdmchan->hangup_timer) {
2356                 ftdm_sched_cancel_timer(globals.timingsched, ftdmchan->hangup_timer);
2357         }
2358 
2359         ftdmchan->init_state = FTDM_CHANNEL_STATE_DOWN;
2360         ftdmchan->state = FTDM_CHANNEL_STATE_DOWN;
2361 
2362         ftdm_log(FTDM_LOG_DEBUG, "channel done %u:%u\n", ftdmchan->span_id, ftdmchan->chan_id);
2363 
2364         ftdm_mutex_unlock(ftdmchan->mutex);
2365 
2366         return FTDM_SUCCESS;
2367 }
2368 
2369 FT_DECLARE(ftdm_status_t) ftdm_channel_use(ftdm_channel_t *ftdmchan)
2370 {
2371 
2372         assert(ftdmchan != NULL);
2373 
2374         ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_INUSE);
2375 
2376         return FTDM_SUCCESS;
2377 }
2378 
2379 FT_DECLARE(ftdm_status_t) ftdm_channel_close(ftdm_channel_t **ftdmchan)
2380 {
2381         ftdm_channel_t *check;
2382         ftdm_status_t status = FTDM_FAIL;
2383 
2384         ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel double pointer provided!\n");
2385         ftdm_assert_return(*ftdmchan != NULL, FTDM_FAIL, "null channel pointer provided!\n");
2386 
2387         check = *ftdmchan;
2388         *ftdmchan = NULL;
2389 
2390         if (ftdm_test_flag(check, FTDM_CHANNEL_CONFIGURED)) {
2391                 ftdm_mutex_lock(check->mutex);
2392                 if (ftdm_test_flag(check, FTDM_CHANNEL_OPEN)) {
2393                         status = check->fio->close(check);
2394                         if (status == FTDM_SUCCESS) {
2395                                 ftdm_clear_flag(check, FTDM_CHANNEL_INUSE);
2396                                 ftdm_channel_reset(check);
2397                                 *ftdmchan = NULL;
2398                         }
2399                 } else {
2400                         ftdm_log_chan_msg(check, FTDM_LOG_WARNING, "Called ftdm_channel_close but never ftdm_channel_open??\n");
2401                 }
2402                 check->ring_count = 0;
2403                 ftdm_mutex_unlock(check->mutex);
2404         }
2405         
2406         return status;
2407 }
2408 
2409 
2410 static ftdm_status_t ftdmchan_activate_dtmf_buffer(ftdm_channel_t *ftdmchan)
2411 {
2412 
2413         if (!ftdmchan->dtmf_buffer) {
2414                 if (ftdm_buffer_create(&ftdmchan->dtmf_buffer, 1024, 3192, 0) != FTDM_SUCCESS) {
2415                         ftdm_log(FTDM_LOG_ERROR, "Failed to allocate DTMF Buffer!\n");
2416                         snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "buffer error");
2417                         return FTDM_FAIL;
2418                 } else {
2419                         ftdm_log(FTDM_LOG_DEBUG, "Created DTMF Buffer!\n");
2420                 }
2421         }
2422 
2423         
2424         if (!ftdmchan->tone_session.buffer) {
2425                 memset(&ftdmchan->tone_session, 0, sizeof(ftdmchan->tone_session));
2426                 teletone_init_session(&ftdmchan->tone_session, 0, NULL, NULL);
2427         }
2428 
2429         ftdmchan->tone_session.rate = ftdmchan->rate;
2430         ftdmchan->tone_session.duration = ftdmchan->dtmf_on * (ftdmchan->tone_session.rate / 1000);
2431         ftdmchan->tone_session.wait = ftdmchan->dtmf_off * (ftdmchan->tone_session.rate / 1000);
2432         ftdmchan->tone_session.volume = -7;
2433 
2434         /*
2435           ftdmchan->tone_session.debug = 1;
2436           ftdmchan->tone_session.debug_stream = stdout;
2437         */
2438 
2439         return FTDM_SUCCESS;
2440 }
2441 
2442 FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_command_t command, void *obj)
2443 {
2444         ftdm_status_t status = FTDM_FAIL;
2445         
2446         assert(ftdmchan != NULL);
2447         assert(ftdmchan->fio != NULL);
2448 
2449         ftdm_mutex_lock(ftdmchan->mutex);
2450 
2451         switch(command) {
2452 
2453         case FTDM_COMMAND_ENABLE_CALLERID_DETECT:
2454                 {
2455                         if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_CALLERID)) {
2456                                 if (ftdm_fsk_demod_init(&ftdmchan->fsk, ftdmchan->rate, ftdmchan->fsk_buf, sizeof(ftdmchan->fsk_buf)) != FTDM_SUCCESS) {
2457                                         snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno));
2458                                         GOTO_STATUS(done, FTDM_FAIL);
2459                                 }
2460                                 ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT);
2461                         }
2462                 }
2463                 break;
2464         case FTDM_COMMAND_DISABLE_CALLERID_DETECT:
2465                 {
2466                         if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_CALLERID)) {
2467                                 ftdm_fsk_demod_destroy(&ftdmchan->fsk);
2468                                 ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT);
2469                         }
2470                 }
2471                 break;
2472         case FTDM_COMMAND_TRACE_INPUT:
2473                 {
2474                         char *path = (char *) obj;
2475                         if (ftdmchan->fds[FTDM_READ_TRACE_INDEX] > 0) {
2476                                 close(ftdmchan->fds[FTDM_READ_TRACE_INDEX]);
2477                                 ftdmchan->fds[FTDM_READ_TRACE_INDEX] = -1;
2478                         }
2479                         if ((ftdmchan->fds[FTDM_READ_TRACE_INDEX] = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) {
2480                                 ftdm_log(FTDM_LOG_DEBUG, "Tracing channel %u:%u input to [%s]\n", ftdmchan->span_id, ftdmchan->chan_id, path);  
2481                                 GOTO_STATUS(done, FTDM_SUCCESS);
2482                         }
2483                         
2484                         snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno));
2485                         GOTO_STATUS(done, FTDM_FAIL);
2486                 }
2487                 break;
2488         case FTDM_COMMAND_TRACE_OUTPUT:
2489                 {
2490                         char *path = (char *) obj;
2491                         if (ftdmchan->fds[FTDM_WRITE_TRACE_INDEX] > 0) {
2492                                 close(ftdmchan->fds[FTDM_WRITE_TRACE_INDEX]);
2493                                 ftdmchan->fds[FTDM_WRITE_TRACE_INDEX] = -1;
2494                         }
2495                         if ((ftdmchan->fds[FTDM_WRITE_TRACE_INDEX] = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)) > -1) {
2496                                 ftdm_log(FTDM_LOG_DEBUG, "Tracing channel %u:%u output to [%s]\n", ftdmchan->span_id, ftdmchan->chan_id, path); 
2497                                 GOTO_STATUS(done, FTDM_SUCCESS);
2498                         }
2499                         
2500                         snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno));
2501                         GOTO_STATUS(done, FTDM_FAIL);
2502                 }
2503                 break;
2504         case FTDM_COMMAND_TRACE_END_ALL:
2505                 {
2506                         if (ftdmchan->fds[FTDM_READ_TRACE_INDEX] > 0) {
2507                                 close(ftdmchan->fds[FTDM_READ_TRACE_INDEX]);
2508                                 ftdmchan->fds[FTDM_READ_TRACE_INDEX] = -1;
2509                         }
2510                         if (ftdmchan->fds[FTDM_WRITE_TRACE_INDEX] > 0) {
2511                                 close(ftdmchan->fds[FTDM_WRITE_TRACE_INDEX]);
2512                                 ftdmchan->fds[FTDM_WRITE_TRACE_INDEX] = -1;
2513                         }
2514                         GOTO_STATUS(done, FTDM_SUCCESS);
2515                 }
2516                 break;
2517         case FTDM_COMMAND_SET_INTERVAL:
2518                 {
2519                         if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_INTERVAL)) {
2520                                 ftdmchan->effective_interval = FTDM_COMMAND_OBJ_INT;
2521                                 if (ftdmchan->effective_interval == ftdmchan->native_interval) {
2522                                         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_BUFFER);
2523                                 } else {
2524                                         ftdm_set_flag(ftdmchan, FTDM_CHANNEL_BUFFER);
2525                                 }
2526                                 ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8);
2527                                 GOTO_STATUS(done, FTDM_SUCCESS);
2528                         }
2529                 }
2530                 break;
2531         case FTDM_COMMAND_GET_INTERVAL:
2532                 {
2533                         if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_INTERVAL)) {
2534                                 FTDM_COMMAND_OBJ_INT = ftdmchan->effective_interval;
2535                                 GOTO_STATUS(done, FTDM_SUCCESS);
2536                         }
2537                 }
2538                 break;
2539         case FTDM_COMMAND_SET_CODEC:
2540                 {
2541                         if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_CODECS)) {
2542                                 ftdmchan->effective_codec = FTDM_COMMAND_OBJ_INT;
2543                                 
2544                                 if (ftdmchan->effective_codec == ftdmchan->native_codec) {
2545                                         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE);
2546                                 } else {
2547                                         ftdm_set_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE);
2548                                 }
2549                                 ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8);
2550                                 GOTO_STATUS(done, FTDM_SUCCESS);
2551                         }
2552                 }
2553                 break;
2554 
2555         case FTDM_COMMAND_SET_NATIVE_CODEC:
2556                 {
2557                         if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_CODECS)) {
2558                                 ftdmchan->effective_codec = ftdmchan->native_codec;
2559                                 ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE);
2560                                 ftdmchan->packet_len = ftdmchan->native_interval * (ftdmchan->effective_codec == FTDM_CODEC_SLIN ? 16 : 8);
2561                                 GOTO_STATUS(done, FTDM_SUCCESS);
2562                         }
2563                 }
2564                 break;
2565 
2566         case FTDM_COMMAND_GET_CODEC: 
2567                 {
2568                         if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_CODECS)) {
2569                                 FTDM_COMMAND_OBJ_INT = ftdmchan->effective_codec;
2570                                 GOTO_STATUS(done, FTDM_SUCCESS);
2571                         }
2572                 }
2573                 break;
2574         case FTDM_COMMAND_GET_NATIVE_CODEC: 
2575                 {
2576                         if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_CODECS)) {
2577                                 FTDM_COMMAND_OBJ_INT = ftdmchan->native_codec;
2578                                 GOTO_STATUS(done, FTDM_SUCCESS);
2579                         }
2580                 }
2581                 break;
2582         case FTDM_COMMAND_ENABLE_PROGRESS_DETECT:
2583                 {
2584                         if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_PROGRESS)) {
2585                                 /* if they don't have thier own, use ours */
2586                                 ftdm_channel_clear_detected_tones(ftdmchan);
2587                                 ftdm_channel_clear_needed_tones(ftdmchan);
2588                                 teletone_multi_tone_init(&ftdmchan->span->tone_finder[FTDM_TONEMAP_DIAL], &ftdmchan->span->tone_detect_map[FTDM_TONEMAP_DIAL]);
2589                                 teletone_multi_tone_init(&ftdmchan->span->tone_finder[FTDM_TONEMAP_RING], &ftdmchan->span->tone_detect_map[FTDM_TONEMAP_RING]);
2590                                 teletone_multi_tone_init(&ftdmchan->span->tone_finder[FTDM_TONEMAP_BUSY], &ftdmchan->span->tone_detect_map[FTDM_TONEMAP_BUSY]);
2591                                 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS_DETECT);
2592                                 GOTO_STATUS(done, FTDM_SUCCESS);
2593                         }
2594                 }
2595                 break;
2596         case FTDM_COMMAND_DISABLE_PROGRESS_DETECT:
2597                 {
2598                         if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_PROGRESS)) {
2599                                 ftdm_clear_flag_locked(ftdmchan, FTDM_CHANNEL_PROGRESS_DETECT);
2600                                 ftdm_channel_clear_detected_tones(ftdmchan);
2601                                 ftdm_channel_clear_needed_tones(ftdmchan);
2602                                 GOTO_STATUS(done, FTDM_SUCCESS);
2603                         }
2604                 }
2605                 break;
2606         case FTDM_COMMAND_ENABLE_DTMF_DETECT:
2607                 {
2608                         /* if they don't have thier own, use ours */
2609                         if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
2610                                 teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate);
2611                                 ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
2612                                 ftdm_set_flag_locked(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
2613                                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Enabled software DTMF detector\n");
2614                                 GOTO_STATUS(done, FTDM_SUCCESS);
2615                         }
2616                 }
2617                 break;
2618         case FTDM_COMMAND_DISABLE_DTMF_DETECT:
2619                 {
2620                         if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
2621                                 teletone_dtmf_detect_init (&ftdmchan->dtmf_detect, ftdmchan->rate);
2622                                 ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
2623                                 ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
2624                                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Disabled software DTMF detector\n");
2625                                 GOTO_STATUS(done, FTDM_SUCCESS);
2626                         }
2627                 }
2628                 break;
2629         case FTDM_COMMAND_SET_PRE_BUFFER_SIZE:
2630                 {
2631                         int val = FTDM_COMMAND_OBJ_INT;
2632 
2633                         if (val < 0) {
2634                                 val = 0;
2635                         }
2636 
2637                         ftdmchan->pre_buffer_size = val * 8;
2638 
2639                         ftdm_mutex_lock(ftdmchan->pre_buffer_mutex);
2640                         if (!ftdmchan->pre_buffer_size) {
2641                                 ftdm_buffer_destroy(&ftdmchan->pre_buffer);
2642                         } else if (!ftdmchan->pre_buffer) {
2643                                 ftdm_buffer_create(&ftdmchan->pre_buffer, 1024, ftdmchan->pre_buffer_size, 0);
2644                         }
2645                         ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex);
2646 
2647                         GOTO_STATUS(done, FTDM_SUCCESS);
2648 
2649                 }
2650                 break;
2651         case FTDM_COMMAND_GET_DTMF_ON_PERIOD:
2652                 {
2653                         if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_GENERATE)) {
2654                                 FTDM_COMMAND_OBJ_INT = ftdmchan->dtmf_on;
2655                                 GOTO_STATUS(done, FTDM_SUCCESS);
2656                         }
2657                 }
2658                 break;
2659         case FTDM_COMMAND_GET_DTMF_OFF_PERIOD:
2660                 {
2661                         if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_GENERATE)) {
2662                                 FTDM_COMMAND_OBJ_INT = ftdmchan->dtmf_on;
2663                                 GOTO_STATUS(done, FTDM_SUCCESS);
2664                         }
2665                 }
2666                 break;
2667         case FTDM_COMMAND_SET_DTMF_ON_PERIOD:
2668                 {
2669                         if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_GENERATE)) {
2670                                 int val = FTDM_COMMAND_OBJ_INT;
2671                                 if (val > 10 && val < 1000) {
2672                                         ftdmchan->dtmf_on = val;
2673                                         GOTO_STATUS(done, FTDM_SUCCESS);
2674                                 } else {
2675                                         snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "invalid value %d range 10-1000", val);
2676                                         GOTO_STATUS(done, FTDM_FAIL);
2677                                 }
2678                         }
2679                 }
2680                 break;
2681         case FTDM_COMMAND_SET_DTMF_OFF_PERIOD:
2682                 {
2683                         if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_GENERATE)) {
2684                                 int val = FTDM_COMMAND_OBJ_INT;
2685                                 if (val > 10 && val < 1000) {
2686                                         ftdmchan->dtmf_off = val;
2687                                         GOTO_STATUS(done, FTDM_SUCCESS);
2688                                 } else {
2689                                         snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "invalid value %d range 10-1000", val);
2690                                         GOTO_STATUS(done, FTDM_FAIL);
2691                                 }
2692                         }
2693                 }
2694                 break;
2695         case FTDM_COMMAND_SEND_DTMF:
2696                 {
2697                         if (!ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_GENERATE)) {
2698                                 char *digits = FTDM_COMMAND_OBJ_CHAR_P;
2699                                 
2700                                 if ((status = ftdmchan_activate_dtmf_buffer(ftdmchan)) != FTDM_SUCCESS) {
2701                                         GOTO_STATUS(done, status);
2702                                 }
2703                                 
2704                                 ftdm_buffer_write(ftdmchan->gen_dtmf_buffer, digits, strlen(digits));
2705                                 
2706                                 GOTO_STATUS(done, FTDM_SUCCESS);
2707                         }
2708                 }
2709                 break;
2710 
2711         case FTDM_COMMAND_DISABLE_ECHOCANCEL:
2712                 {
2713                         ftdm_mutex_lock(ftdmchan->pre_buffer_mutex);
2714                         ftdm_buffer_destroy(&ftdmchan->pre_buffer);
2715                         ftdmchan->pre_buffer_size = 0;
2716                         ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex);
2717                 }
2718                 break;
2719 
2720         case FTDM_COMMAND_SET_RX_GAIN:
2721                 {
2722                         if (!FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
2723                                 ftdm_log(FTDM_LOG_ERROR, "Cannot set rx gain in non-voice channel of type: %s\n", ftdm_chan_type2str(ftdmchan->type));
2724                                 GOTO_STATUS(done, FTDM_FAIL);
2725                         }
2726                         ftdmchan->rxgain = FTDM_COMMAND_OBJ_FLOAT;
2727                         reset_gain_table(ftdmchan->rxgain_table, ftdmchan->rxgain, ftdmchan->native_codec);
2728                         if (ftdmchan->rxgain == 0.0) {
2729                                 ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_USE_RX_GAIN);
2730                         } else {
2731                                 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_USE_RX_GAIN);
2732                         }
2733                         GOTO_STATUS(done, FTDM_SUCCESS);
2734                 }
2735                 break;
2736         case FTDM_COMMAND_GET_RX_GAIN:
2737                 {
2738                         FTDM_COMMAND_OBJ_FLOAT = ftdmchan->rxgain;
2739                         GOTO_STATUS(done, FTDM_SUCCESS);
2740                 }
2741                 break;
2742         case FTDM_COMMAND_SET_TX_GAIN:
2743                 {
2744                         if (!FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
2745                                 ftdm_log(FTDM_LOG_ERROR, "Cannot set tx gain in non-voice channel of type: %s\n", ftdm_chan_type2str(ftdmchan->type));
2746                                 GOTO_STATUS(done, FTDM_FAIL);
2747                         }
2748                         ftdmchan->txgain = FTDM_COMMAND_OBJ_FLOAT;
2749                         reset_gain_table(ftdmchan->txgain_table, ftdmchan->txgain, ftdmchan->native_codec);
2750                         if (ftdmchan->txgain == 0.0) {
2751                                 ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_USE_TX_GAIN);
2752                         } else {
2753                                 ftdm_set_flag(ftdmchan, FTDM_CHANNEL_USE_TX_GAIN);
2754                         }
2755                         GOTO_STATUS(done, FTDM_SUCCESS);
2756                 }
2757                 break;
2758         case FTDM_COMMAND_GET_TX_GAIN:
2759                 {
2760                         FTDM_COMMAND_OBJ_FLOAT = ftdmchan->txgain;
2761                         GOTO_STATUS(done, FTDM_SUCCESS);
2762                 }
2763                 break;
2764         default:
2765                 break;
2766         }
2767 
2768         if (!ftdmchan->fio->command) {
2769                 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "method not implemented");
2770                 ftdm_log(FTDM_LOG_ERROR, "no command function defined by the I/O freetdm module!\n");   
2771                 GOTO_STATUS(done, FTDM_FAIL);
2772         }
2773 
2774         status = ftdmchan->fio->command(ftdmchan, command, obj);
2775 
2776         if (status == FTDM_NOTIMPL) {
2777                 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "I/O command %d not implemented in backend", command);
2778                 ftdm_log(FTDM_LOG_ERROR, "I/O backend does not support command %d!\n", command);        
2779         }
2780 done:
2781         ftdm_mutex_unlock(ftdmchan->mutex);
2782         return status;
2783 
2784 }
2785 
2786 FT_DECLARE(ftdm_status_t) ftdm_channel_wait(ftdm_channel_t *ftdmchan, ftdm_wait_flag_t *flags, int32_t to)
2787 {
2788         assert(ftdmchan != NULL);
2789         assert(ftdmchan->fio != NULL);
2790 
2791     if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
2792                 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "channel not open");
2793         return FTDM_FAIL;
2794     }
2795 
2796         if (!ftdmchan->fio->wait) {
2797                 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "method not implemented");
2798                 return FTDM_FAIL;
2799         }
2800 
2801     return ftdmchan->fio->wait(ftdmchan, flags, to);
2802 
2803 }
2804 
2805 /*******************************/
2806 FIO_CODEC_FUNCTION(fio_slin2ulaw)
2807 {
2808         int16_t sln_buf[512] = {0}, *sln = sln_buf;
2809         uint8_t *lp = data;
2810         uint32_t i;
2811         ftdm_size_t len = *datalen;
2812 
2813         if (max > len) {
2814                 max = len;
2815         }
2816 
2817         memcpy(sln, data, max);
2818         
2819         for(i = 0; i < max; i++) {
2820                 *lp++ = linear_to_ulaw(*sln++);
2821         }
2822 
2823         *datalen = max / 2;
2824 
2825         return FTDM_SUCCESS;
2826 
2827 }
2828 
2829 
2830 FIO_CODEC_FUNCTION(fio_ulaw2slin)
2831 {
2832         int16_t *sln = data;
2833         uint8_t law[1024] = {0}, *lp = law;
2834         uint32_t i;
2835         ftdm_size_t len = *datalen;
2836         
2837         if (max > len) {
2838                 max = len;
2839         }
2840 
2841         memcpy(law, data, max);
2842 
2843         for(i = 0; i < max; i++) {
2844                 *sln++ = ulaw_to_linear(*lp++);
2845         }
2846         
2847         *datalen = max * 2;
2848 
2849         return FTDM_SUCCESS;
2850 }
2851 
2852 FIO_CODEC_FUNCTION(fio_slin2alaw)
2853 {
2854         int16_t sln_buf[512] = {0}, *sln = sln_buf;
2855         uint8_t *lp = data;
2856         uint32_t i;
2857         ftdm_size_t len = *datalen;
2858 
2859         if (max > len) {
2860                 max = len;
2861         }
2862 
2863         memcpy(sln, data, max);
2864         
2865         for(i = 0; i < max; i++) {
2866                 *lp++ = linear_to_alaw(*sln++);
2867         }
2868 
2869         *datalen = max / 2;
2870 
2871         return FTDM_SUCCESS;
2872 
2873 }
2874 
2875 
2876 FIO_CODEC_FUNCTION(fio_alaw2slin)
2877 {
2878         int16_t *sln = data;
2879         uint8_t law[1024] = {0}, *lp = law;
2880         uint32_t i;
2881         ftdm_size_t len = *datalen;
2882         
2883         if (max > len) {
2884                 max = len;
2885         }
2886 
2887         memcpy(law, data, max);
2888 
2889         for(i = 0; i < max; i++) {
2890                 *sln++ = alaw_to_linear(*lp++);
2891         }
2892 
2893         *datalen = max * 2;
2894 
2895         return FTDM_SUCCESS;
2896 }
2897 
2898 FIO_CODEC_FUNCTION(fio_ulaw2alaw)
2899 {
2900         ftdm_size_t len = *datalen;
2901         uint32_t i;
2902         uint8_t *lp = data;
2903 
2904         if (max > len) {
2905         max = len;
2906     }
2907 
2908         for(i = 0; i < max; i++) {
2909                 *lp = ulaw_to_alaw(*lp);
2910                 lp++;
2911         }
2912 
2913         return FTDM_SUCCESS;
2914 }
2915 
2916 FIO_CODEC_FUNCTION(fio_alaw2ulaw)
2917 {
2918         ftdm_size_t len = *datalen;
2919         uint32_t i;
2920         uint8_t *lp = data;
2921 
2922         if (max > len) {
2923         max = len;
2924     }
2925 
2926         for(i = 0; i < max; i++) {
2927                 *lp = alaw_to_ulaw(*lp);
2928                 lp++;
2929         }
2930 
2931         return FTDM_SUCCESS;
2932 }
2933 
2934 /******************************/
2935 
2936 FT_DECLARE(void) ftdm_channel_clear_detected_tones(ftdm_channel_t *ftdmchan)
2937 {
2938         uint32_t i;
2939 
2940         memset(ftdmchan->detected_tones, 0, sizeof(ftdmchan->detected_tones[0]) * FTDM_TONEMAP_INVALID);
2941         
2942         for (i = 1; i < FTDM_TONEMAP_INVALID; i++) {
2943                 ftdmchan->span->tone_finder[i].tone_count = 0;
2944         }
2945 }
2946 
2947 FT_DECLARE(void) ftdm_channel_clear_needed_tones(ftdm_channel_t *ftdmchan)
2948 {
2949         memset(ftdmchan->needed_tones, 0, sizeof(ftdmchan->needed_tones[0]) * FTDM_TONEMAP_INVALID);
2950 }
2951 
2952 FT_DECLARE(ftdm_size_t) ftdm_channel_dequeue_dtmf(ftdm_channel_t *ftdmchan, char *dtmf, ftdm_size_t len)
2953 {
2954         ftdm_size_t bytes = 0;
2955 
2956         assert(ftdmchan != NULL);
2957 
2958         if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_READY)) {
2959                 return 0;
2960         }
2961 
2962         if (ftdmchan->digit_buffer && ftdm_buffer_inuse(ftdmchan->digit_buffer)) {
2963                 ftdm_mutex_lock(ftdmchan->mutex);
2964                 if ((bytes = ftdm_buffer_read(ftdmchan->digit_buffer, dtmf, len)) > 0) {
2965                         *(dtmf + bytes) = '\0';
2966                 }
2967                 ftdm_mutex_unlock(ftdmchan->mutex);
2968         }
2969 
2970         return bytes;
2971 }
2972 
2973 FT_DECLARE(void) ftdm_channel_flush_dtmf(ftdm_channel_t *ftdmchan)
2974 {
2975         if (ftdmchan->digit_buffer && ftdm_buffer_inuse(ftdmchan->digit_buffer)) {
2976                 ftdm_mutex_lock(ftdmchan->mutex);
2977                 ftdm_buffer_zero(ftdmchan->digit_buffer);
2978                 ftdm_mutex_unlock(ftdmchan->mutex);
2979         }
2980 }
2981 
2982 FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, const char *dtmf)
2983 {
2984         ftdm_status_t status;
2985         register ftdm_size_t len, inuse;
2986         ftdm_size_t wr = 0;
2987         const char *p;
2988         
2989         assert(ftdmchan != NULL);
2990 
2991         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Queuing DTMF %s\n", dtmf);
2992 
2993 #ifdef FTDM_DEBUG_DTMF
2994         ftdm_mutex_lock(ftdmchan->dtmfdbg.mutex);
2995         if (!ftdmchan->dtmfdbg.file) {
2996                 struct tm currtime;
2997                 time_t currsec;
2998                 char dfile[512];
2999 
3000                 currsec = time(NULL);
3001                 localtime_r(&currsec, &currtime);
3002 
3003                 snprintf(dfile, sizeof(dfile), "dtmf-s%dc%d-20%d-%d-%d-%d:%d:%d.%s", 
3004                                 ftdmchan->span_id, ftdmchan->chan_id, 
3005                                 currtime.tm_year-100, currtime.tm_mon+1, currtime.tm_mday,
3006                                 currtime.tm_hour, currtime.tm_min, currtime.tm_sec, ftdmchan->native_codec == FTDM_CODEC_ULAW ? "ulaw" : ftdmchan->native_codec == FTDM_CODEC_ALAW ? "alaw" : "sln");
3007                 ftdmchan->dtmfdbg.file = fopen(dfile, "w");
3008                 if (!ftdmchan->dtmfdbg.file) {
3009                         ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "failed to open debug dtmf file %s\n", dfile);
3010                 } else {
3011                         /* write the saved audio buffer */
3012                         int rc = 0;
3013                         int towrite = sizeof(ftdmchan->dtmfdbg.buffer) - ftdmchan->dtmfdbg.windex;
3014                 
3015                         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "created debug DTMF file %s\n", dfile);
3016                         ftdmchan->dtmfdbg.closetimeout = DTMF_DEBUG_TIMEOUT;
3017                         if (ftdmchan->dtmfdbg.wrapped) {
3018                                 rc = fwrite(&ftdmchan->dtmfdbg.buffer[ftdmchan->dtmfdbg.windex], 1, towrite, ftdmchan->dtmfdbg.file);
3019                                 if (rc != towrite) {
3020                                         ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "only wrote %d out of %d bytes in DTMF debug buffer\n", rc, towrite);
3021                                 }
3022                         }
3023                         if (ftdmchan->dtmfdbg.windex) {
3024                                 towrite = ftdmchan->dtmfdbg.windex;
3025                                 rc = fwrite(&ftdmchan->dtmfdbg.buffer[0], 1, towrite, ftdmchan->dtmfdbg.file);
3026                                 if (rc != towrite) {
3027                                         ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "only wrote %d out of %d bytes in DTMF debug buffer\n", rc, towrite);
3028                                 }
3029                         }
3030                         ftdmchan->dtmfdbg.windex = 0;
3031                         ftdmchan->dtmfdbg.wrapped = 0;
3032                 }
3033         } else {
3034                         ftdmchan->dtmfdbg.closetimeout = DTMF_DEBUG_TIMEOUT;
3035         }
3036         ftdm_mutex_unlock(ftdmchan->dtmfdbg.mutex);
3037 #endif
3038 
3039         if (ftdmchan->pre_buffer) {
3040                 ftdm_buffer_zero(ftdmchan->pre_buffer);
3041         }
3042 
3043         ftdm_mutex_lock(ftdmchan->mutex);
3044 
3045         inuse = ftdm_buffer_inuse(ftdmchan->digit_buffer);
3046         len = strlen(dtmf);
3047         
3048         if (len + inuse > ftdm_buffer_len(ftdmchan->digit_buffer)) {
3049                 ftdm_buffer_toss(ftdmchan->digit_buffer, strlen(dtmf));
3050         }
3051 
3052         if (ftdmchan->span->dtmf_hangup_len) {
3053                 for (p = dtmf; ftdm_is_dtmf(*p); p++) {
3054                         memmove (ftdmchan->dtmf_hangup_buf, ftdmchan->dtmf_hangup_buf + 1, ftdmchan->span->dtmf_hangup_len - 1);
3055                         ftdmchan->dtmf_hangup_buf[ftdmchan->span->dtmf_hangup_len - 1] = *p;
3056                         if (!strcmp(ftdmchan->dtmf_hangup_buf, ftdmchan->span->dtmf_hangup)) {
3057                                 ftdm_log(FTDM_LOG_DEBUG, "DTMF hangup detected.\n");
3058                                 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
3059                                 break;
3060                         }
3061                 }
3062         }
3063 
3064         p = dtmf;
3065         while (wr < len && p) {
3066                 if (ftdm_is_dtmf(*p)) {
3067                         wr++;
3068                 } else {
3069                         break;
3070                 }
3071                 p++;
3072         }
3073 
3074         status = ftdm_buffer_write(ftdmchan->digit_buffer, dtmf, wr) ? FTDM_SUCCESS : FTDM_FAIL;
3075         ftdm_mutex_unlock(ftdmchan->mutex);
3076         
3077         return status;
3078 }
3079 
3080 static FIO_WRITE_FUNCTION(ftdm_raw_write)
3081 {
3082         if (ftdmchan->fds[FTDM_WRITE_TRACE_INDEX] > -1) {
3083                 int dlen = (int) *datalen;
3084                 if ((write(ftdmchan->fds[FTDM_WRITE_TRACE_INDEX], data, dlen)) != dlen) {
3085                         ftdm_log(FTDM_LOG_WARNING, "Raw output trace failed to write all of the %zd bytes\n", dlen);
3086                 }
3087         }
3088         return ftdmchan->fio->write(ftdmchan, data, datalen);
3089 }
3090 
3091 
3092 static FIO_READ_FUNCTION(ftdm_raw_read)
3093 {
3094         ftdm_status_t  status = ftdmchan->fio->read(ftdmchan, data, datalen);
3095         if (status == FTDM_SUCCESS && ftdmchan->fds[FTDM_READ_TRACE_INDEX] > -1) {
3096                 int dlen = (int) *datalen;
3097                 if (write(ftdmchan->fds[FTDM_READ_TRACE_INDEX], data, dlen) != dlen) {
3098                         ftdm_log(FTDM_LOG_WARNING, "Raw input trace failed to write all of the %zd bytes\n", dlen);
3099                 }
3100         }
3101 
3102         if (status == FTDM_SUCCESS && ftdmchan->span->sig_read) {
3103                 ftdmchan->span->sig_read(ftdmchan, data, *datalen);
3104         }
3105 
3106 #ifdef FTDM_DEBUG_DTMF
3107         if (status == FTDM_SUCCESS) {
3108                 int dlen = (int) *datalen;
3109                 int rc = 0;
3110                 ftdm_mutex_lock(ftdmchan->dtmfdbg.mutex);
3111                 if (!ftdmchan->dtmfdbg.file) {
3112                         /* no file yet, write to our circular buffer */
3113                         int windex = ftdmchan->dtmfdbg.windex;
3114                         int avail = sizeof(ftdmchan->dtmfdbg.buffer) - windex;
3115                         char *dataptr = data;
3116 
3117                         if (dlen > avail) {
3118                                 int diff = dlen - avail;
3119                                 /* write only what we can and the rest at the beginning of the buffer */
3120                                 memcpy(&ftdmchan->dtmfdbg.buffer[windex], dataptr, avail);
3121                                 memcpy(&ftdmchan->dtmfdbg.buffer[0], &dataptr[avail], diff);
3122                                 windex = diff;
3123                                 /*ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "wrapping around dtmf read buffer up to index %d\n\n", windex);*/
3124                                 ftdmchan->dtmfdbg.wrapped = 1;
3125                         } else {
3126                                 memcpy(&ftdmchan->dtmfdbg.buffer[windex], dataptr, dlen);
3127                                 windex += dlen;
3128                         }
3129                         if (windex == sizeof(ftdmchan->dtmfdbg.buffer)) {
3130                                 /*ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "wrapping around dtmf read buffer\n");*/
3131                                 windex = 0;
3132                                 ftdmchan->dtmfdbg.wrapped = 1;
3133                         }
3134                         ftdmchan->dtmfdbg.windex = windex;
3135                 } else {
3136                         rc = fwrite(data, 1, dlen, ftdmchan->dtmfdbg.file);
3137                         if (rc != dlen) {
3138                                 ftdm_log(FTDM_LOG_WARNING, "DTMF debugger wrote only %d out of %d bytes: %s\n", rc, datalen, strerror(errno));
3139                         }
3140                         ftdmchan->dtmfdbg.closetimeout--;
3141                         if (!ftdmchan->dtmfdbg.closetimeout) {
3142                                 close_dtmf_debug(ftdmchan);
3143                         }
3144                 }
3145                 ftdm_mutex_unlock(ftdmchan->dtmfdbg.mutex);
3146         }
3147 #endif
3148         return status;
3149 }
3150 
3151 static ftdm_status_t handle_dtmf(ftdm_channel_t *ftdmchan, ftdm_size_t datalen)
3152 {
3153         ftdm_buffer_t *buffer = NULL;
3154         ftdm_size_t dblen = 0;
3155         int wrote = 0;
3156 
3157         if (ftdmchan->gen_dtmf_buffer && (dblen = ftdm_buffer_inuse(ftdmchan->gen_dtmf_buffer))) {
3158                 char digits[128] = "";
3159                 char *cur;
3160                 int x = 0;                               
3161                 
3162                 if (dblen > sizeof(digits) - 1) {
3163                         dblen = sizeof(digits) - 1;
3164                 }
3165 
3166                 if (ftdm_buffer_read(ftdmchan->gen_dtmf_buffer, digits, dblen) && !ftdm_strlen_zero_buf(digits)) {
3167                         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generating DTMF [%s]\n", digits);      
3168                 
3169                         cur = digits;
3170 
3171                         if (*cur == 'F') {
3172                                 ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLASH, NULL);
3173                                 cur++;
3174                         }
3175 
3176                         for (; *cur; cur++) {
3177                                 if ((wrote = teletone_mux_tones(&ftdmchan->tone_session, &ftdmchan->tone_session.TONES[(int)*cur]))) {
3178                                         ftdm_buffer_write(ftdmchan->dtmf_buffer, ftdmchan->tone_session.buffer, wrote * 2);
3179                                         x++;
3180                                 } else {
3181                                         ftdm_log(FTDM_LOG_ERROR, "%d:%d Problem Adding DTMF SEQ [%s]\n", ftdmchan->span_id, ftdmchan->chan_id, digits);
3182                                         return FTDM_FAIL;
3183                                 }
3184                         }
3185 
3186                         if (x) {
3187                                 ftdmchan->skip_read_frames = (wrote / (ftdmchan->effective_interval * 8)) + 4;
3188                         }
3189                 }
3190         }
3191         
3192 
3193         if (!ftdmchan->buffer_delay || --ftdmchan->buffer_delay == 0) {
3194                 if (ftdmchan->dtmf_buffer && (dblen = ftdm_buffer_inuse(ftdmchan->dtmf_buffer))) {
3195                         buffer = ftdmchan->dtmf_buffer;
3196                 } else if (ftdmchan->fsk_buffer && (dblen = ftdm_buffer_inuse(ftdmchan->fsk_buffer))) {
3197                         buffer = ftdmchan->fsk_buffer;                  
3198                 }
3199         }
3200 
3201         if (buffer) {
3202                 ftdm_size_t dlen = datalen;
3203                 uint8_t auxbuf[1024];
3204                 ftdm_size_t len, br, max = sizeof(auxbuf);
3205                 
3206                 if (ftdmchan->native_codec != FTDM_CODEC_SLIN) {
3207                         dlen *= 2;
3208                 }
3209                 
3210                 len = dblen > dlen ? dlen : dblen;
3211 
3212                 br = ftdm_buffer_read(buffer, auxbuf, len);             
3213                 if (br < dlen) {
3214                         memset(auxbuf + br, 0, dlen - br);
3215                 }
3216 
3217                 if (ftdmchan->native_codec != FTDM_CODEC_SLIN) {
3218                         if (ftdmchan->native_codec == FTDM_CODEC_ULAW) {
3219                                 fio_slin2ulaw(auxbuf, max, &dlen);
3220                         } else if (ftdmchan->native_codec == FTDM_CODEC_ALAW) {
3221                                 fio_slin2alaw(auxbuf, max, &dlen);
3222                         }
3223                 }
3224                 
3225                 return ftdm_raw_write(ftdmchan, auxbuf, &dlen);
3226         } 
3227 
3228         return FTDM_SUCCESS;
3229 
3230 }
3231 
3232 FT_DECLARE(void) ftdm_generate_sln_silence(int16_t *data, uint32_t samples, uint32_t divisor)
3233 {
3234     int16_t x;
3235     uint32_t i;
3236     int sum_rnd = 0;
3237     int16_t rnd2 = (int16_t) ftdm_current_time_in_ms() * (int16_t) (intptr_t) data;
3238 
3239     assert(divisor);
3240 
3241     for (i = 0; i < samples; i++, sum_rnd = 0) {
3242         for (x = 0; x < 6; x++) {
3243             rnd2 = rnd2 * 31821U + 13849U;
3244             sum_rnd += rnd2 ;
3245         }
3246         //switch_normalize_to_16bit(sum_rnd);
3247         *data = (int16_t) ((int16_t) sum_rnd / (int) divisor);
3248 
3249         data++;
3250     }
3251 }
3252 
3253 FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen)
3254 {
3255         ftdm_status_t status = FTDM_FAIL;
3256         fio_codec_t codec_func = NULL;
3257         ftdm_size_t max = *datalen;
3258         unsigned i = 0;
3259 
3260         ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "ftdmchan is null\n");
3261         ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "No I/O module attached to ftdmchan\n");
3262 
3263         ftdm_channel_lock(ftdmchan);
3264         
3265         if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
3266                 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "channel not open");
3267                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "cannot read from channel that is not open\n");
3268                 status = FTDM_FAIL;
3269                 goto done;
3270         }
3271 
3272         if (!ftdmchan->fio->read) {
3273                 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "method not implemented");
3274                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "read method not implemented\n");
3275                 status = FTDM_FAIL;
3276                 goto done;
3277         }
3278 
3279         status = ftdm_raw_read(ftdmchan, data, datalen);
3280 
3281         if (status != FTDM_SUCCESS) {
3282                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "raw I/O read filed\n");
3283         }
3284 
3285         if (status == FTDM_SUCCESS) {
3286                 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_USE_RX_GAIN) 
3287                         && (ftdmchan->native_codec == FTDM_CODEC_ALAW || ftdmchan->native_codec == FTDM_CODEC_ULAW)) {
3288                         unsigned char *rdata = data;
3289                         for (i = 0; i < *datalen; i++) {
3290                                 rdata[i] = ftdmchan->rxgain_table[rdata[i]];
3291                         }
3292                 }
3293                 handle_dtmf(ftdmchan, *datalen);
3294         }
3295 
3296         if (status == FTDM_SUCCESS && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE) && ftdmchan->effective_codec != ftdmchan->native_codec) {
3297                 if (ftdmchan->native_codec == FTDM_CODEC_ULAW && ftdmchan->effective_codec == FTDM_CODEC_SLIN) {
3298                         codec_func = fio_ulaw2slin;
3299                 } else if (ftdmchan->native_codec == FTDM_CODEC_ULAW && ftdmchan->effective_codec == FTDM_CODEC_ALAW) {
3300                         codec_func = fio_ulaw2alaw;
3301                 } else if (ftdmchan->native_codec == FTDM_CODEC_ALAW && ftdmchan->effective_codec == FTDM_CODEC_SLIN) {
3302                         codec_func = fio_alaw2slin;
3303                 } else if (ftdmchan->native_codec == FTDM_CODEC_ALAW && ftdmchan->effective_codec == FTDM_CODEC_ULAW) {
3304                         codec_func = fio_alaw2ulaw;
3305                 }
3306 
3307                 if (codec_func) {
3308                         status = codec_func(data, max, datalen);
3309                 } else {
3310                         snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!");
3311                         ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "no codec function to perform transcoding from %d to %d\n", ftdmchan->native_codec, ftdmchan->effective_codec);
3312                         status = FTDM_FAIL;
3313                 }
3314         }
3315 
3316         if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT) || ftdm_test_flag(ftdmchan, FTDM_CHANNEL_PROGRESS_DETECT) || 
3317                 ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT)) {
3318                 uint8_t sln_buf[1024] = {0};
3319                 int16_t *sln;
3320                 ftdm_size_t slen = 0;
3321                 char digit_str[80] = "";
3322 
3323                 if (ftdmchan->effective_codec == FTDM_CODEC_SLIN) {
3324                         sln = data;
3325                         slen = *datalen / 2;
3326                 } else {
3327                         ftdm_size_t len = *datalen;
3328                         uint32_t i;
3329                         uint8_t *lp = data;
3330 
3331                         slen = sizeof(sln_buf) / 2;
3332                         if (len > slen) {
3333                                 len = slen;
3334                         }
3335 
3336                         sln = (int16_t *) sln_buf;
3337                         for(i = 0; i < len; i++) {
3338                                 if (ftdmchan->effective_codec == FTDM_CODEC_ULAW) {
3339                                         *sln++ = ulaw_to_linear(*lp++);
3340                                 } else if (ftdmchan->effective_codec == FTDM_CODEC_ALAW) {
3341                                         *sln++ = alaw_to_linear(*lp++);
3342                                 } else {
3343                                         snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!");
3344                                         ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "invalid effective codec %d\n", ftdmchan->effective_codec);
3345                                         status = FTDM_FAIL;
3346                                         goto done;
3347                                 }
3348                         }
3349                         sln = (int16_t *) sln_buf;
3350                         slen = len;
3351                 }
3352 
3353                 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT)) {
3354                         if (ftdm_fsk_demod_feed(&ftdmchan->fsk, sln, slen) != FTDM_SUCCESS) {
3355                                 ftdm_size_t type, mlen;
3356                                 char str[128], *sp;
3357                                 
3358                                 while(ftdm_fsk_data_parse(&ftdmchan->fsk, &type, &sp, &mlen) == FTDM_SUCCESS) {
3359                                         *(str+mlen) = '\0';
3360                                         ftdm_copy_string(str, sp, ++mlen);
3361                                         ftdm_clean_string(str);
3362                                         ftdm_log(FTDM_LOG_DEBUG, "FSK: TYPE %s LEN %d VAL [%s]\n", ftdm_mdmf_type2str(type), mlen-1, str);
3363                                         
3364                                         switch(type) {
3365                                         case MDMF_DDN:
3366                                         case MDMF_PHONE_NUM:
3367                                                 {
3368                                                         if (mlen > sizeof(ftdmchan->caller_data.ani)) {
3369                                                                 mlen = sizeof(ftdmchan->caller_data.ani);
3370                                                         }
3371                                                         ftdm_set_string(ftdmchan->caller_data.ani.digits, str);
3372                                                         ftdm_set_string(ftdmchan->caller_data.cid_num.digits, ftdmchan->caller_data.ani.digits);
3373                                                 }
3374                                                 break;
3375                                         case MDMF_NO_NUM:
3376                                                 {
3377                                                         ftdm_set_string(ftdmchan->caller_data.ani.digits, *str == 'P' ? "private" : "unknown");
3378                                                         ftdm_set_string(ftdmchan->caller_data.cid_name, ftdmchan->caller_data.ani.digits);
3379                                                 }
3380                                                 break;
3381                                         case MDMF_PHONE_NAME:
3382                                                 {
3383                                                         if (mlen > sizeof(ftdmchan->caller_data.cid_name)) {
3384                                                                 mlen = sizeof(ftdmchan->caller_data.cid_name);
3385                                                         }
3386                                                         ftdm_set_string(ftdmchan->caller_data.cid_name, str);
3387                                                 }
3388                                                 break;
3389                                         case MDMF_NO_NAME:
3390                                                 {
3391                                                         ftdm_set_string(ftdmchan->caller_data.cid_name, *str == 'P' ? "private" : "unknown");
3392                                                 }
3393                                         case MDMF_DATETIME:
3394                                                 {
3395                                                         if (mlen > sizeof(ftdmchan->caller_data.cid_date)) {
3396                                                                 mlen = sizeof(ftdmchan->caller_data.cid_date);
3397                                                         }
3398                                                         ftdm_set_string(ftdmchan->caller_data.cid_date, str);
3399                                                 }
3400                                                 break;
3401                                         }
3402                                 }
3403                                 ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_CALLERID_DETECT, NULL);
3404                         }
3405                 }
3406 
3407                 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_PROGRESS_DETECT) && !ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_PROGRESS)) {
3408                         uint32_t i;
3409 
3410                         for (i = 1; i < FTDM_TONEMAP_INVALID; i++) {
3411                                 if (ftdmchan->span->tone_finder[i].tone_count) {
3412                                         if (ftdmchan->needed_tones[i] && teletone_multi_tone_detect(&ftdmchan->span->tone_finder[i], sln, (int)slen)) {
3413                                                 if (++ftdmchan->detected_tones[i]) {
3414                                                         ftdmchan->needed_tones[i] = 0;
3415                                                         ftdmchan->detected_tones[0]++;
3416                                                 }
3417                                         }
3418                                 }
3419                         }
3420                 }
3421         
3422                 
3423                 if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT) && !ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
3424                         teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen);
3425                         teletone_dtmf_get(&ftdmchan->dtmf_detect, digit_str, sizeof(digit_str));
3426 
3427                         if(*digit_str) {
3428                                 if (ftdmchan->state == FTDM_CHANNEL_STATE_CALLWAITING && (*digit_str == 'D' || *digit_str == 'A')) {
3429                                         ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK]++;
3430                                 } else {
3431                                         ftdm_channel_queue_dtmf(ftdmchan, digit_str);
3432 
3433                                         if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF)) {
3434                                                 ftdmchan->skip_read_frames = 20;
3435                                         }
3436                                 }
3437                         }
3438                 }
3439         }
3440 
3441         if (ftdmchan->skip_read_frames > 0 || ftdm_test_flag(ftdmchan, FTDM_CHANNEL_MUTE)) {
3442                 
3443                 ftdm_mutex_lock(ftdmchan->pre_buffer_mutex);
3444                 if (ftdmchan->pre_buffer && ftdm_buffer_inuse(ftdmchan->pre_buffer)) {
3445                         ftdm_buffer_zero(ftdmchan->pre_buffer);
3446                 }
3447                 ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex);
3448 
3449 
3450                 memset(data, 255, *datalen);
3451 
3452                 if (ftdmchan->skip_read_frames > 0) {
3453                         ftdmchan->skip_read_frames--;
3454                 }
3455         }  else {
3456                 ftdm_mutex_lock(ftdmchan->pre_buffer_mutex);
3457                 if (ftdmchan->pre_buffer_size && ftdmchan->pre_buffer) {
3458                         ftdm_buffer_write(ftdmchan->pre_buffer, data, *datalen);
3459                         if (ftdm_buffer_inuse(ftdmchan->pre_buffer) >= ftdmchan->pre_buffer_size) {
3460                                 ftdm_buffer_read(ftdmchan->pre_buffer, data, *datalen);
3461                         } else {
3462                                 memset(data, 255, *datalen);
3463                         }
3464                 }
3465                 ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex);
3466         }
3467 
3468 done:
3469 
3470         ftdm_channel_unlock(ftdmchan);
3471 
3472         return status;
3473 }
3474 
3475 
3476 FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t datasize, ftdm_size_t *datalen)
3477 {
3478         ftdm_status_t status = FTDM_FAIL;
3479         fio_codec_t codec_func = NULL;
3480         ftdm_size_t max = datasize;
3481         unsigned int i = 0;
3482 
3483         ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel on write!\n");
3484         ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "null I/O on write!\n");
3485 
3486         if (!ftdmchan->buffer_delay && 
3487                 ((ftdmchan->dtmf_buffer && ftdm_buffer_inuse(ftdmchan->dtmf_buffer)) ||
3488                  (ftdmchan->fsk_buffer && ftdm_buffer_inuse(ftdmchan->fsk_buffer)))) {
3489                 /* read size writing DTMF ATM */
3490                 return FTDM_SUCCESS;
3491         }
3492 
3493 
3494         if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
3495                 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "channel not open");
3496                 return FTDM_FAIL;
3497         }
3498 
3499         if (!ftdmchan->fio->write) {
3500                 snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "method not implemented");
3501                 return FTDM_FAIL;
3502         }
3503         
3504         if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE) && ftdmchan->effective_codec != ftdmchan->native_codec) {
3505                 if (ftdmchan->native_codec == FTDM_CODEC_ULAW && ftdmchan->effective_codec == FTDM_CODEC_SLIN) {
3506                         codec_func = fio_slin2ulaw;
3507                 } else if (ftdmchan->native_codec == FTDM_CODEC_ULAW && ftdmchan->effective_codec == FTDM_CODEC_ALAW) {
3508                         codec_func = fio_alaw2ulaw;
3509                 } else if (ftdmchan->native_codec == FTDM_CODEC_ALAW && ftdmchan->effective_codec == FTDM_CODEC_SLIN) {
3510                         codec_func = fio_slin2alaw;
3511                 } else if (ftdmchan->native_codec == FTDM_CODEC_ALAW && ftdmchan->effective_codec == FTDM_CODEC_ULAW) {
3512                         codec_func = fio_ulaw2alaw;
3513                 }
3514 
3515                 if (codec_func) {
3516                         status = codec_func(data, max, datalen);
3517                 } else {
3518                         snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!");
3519                         status = FTDM_FAIL;
3520                 }
3521         }       
3522         
3523         if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_USE_TX_GAIN) 
3524                 && (ftdmchan->native_codec == FTDM_CODEC_ALAW || ftdmchan->native_codec == FTDM_CODEC_ULAW)) {
3525                 unsigned char *wdata = data;
3526                 for (i = 0; i < *datalen; i++) {
3527                         wdata[i] = ftdmchan->txgain_table[wdata[i]];
3528                 }
3529         }
3530 
3531         status = ftdm_raw_write(ftdmchan, data, datalen);
3532 
3533         return status;
3534 }
3535 
3536 static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan)
3537 {
3538         ftdm_channel_lock(ftdmchan);
3539 
3540         if (ftdmchan->variable_hash) {
3541                 hashtable_destroy(ftdmchan->variable_hash);
3542         }
3543         ftdmchan->variable_hash = NULL;
3544 
3545         ftdm_channel_unlock(ftdmchan);
3546         return FTDM_SUCCESS;
3547 }
3548 
3549 FT_DECLARE(ftdm_status_t) ftdm_channel_add_var(ftdm_channel_t *ftdmchan, const char *var_name, const char *value)
3550 {
3551         char *t_name = 0, *t_val = 0;
3552 
3553         ftdm_status_t status = FTDM_FAIL;
3554 
3555         if (!var_name || !value) {
3556                 return FTDM_FAIL;
3557         }
3558 
3559         ftdm_channel_lock(ftdmchan);
3560 
3561         if (!ftdmchan->variable_hash) {
3562                 /* initialize on first use */
3563                 ftdmchan->variable_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys);
3564                 if (!ftdmchan->variable_hash) {
3565                         goto done;
3566                 }
3567         }
3568 
3569         t_name = ftdm_strdup(var_name);
3570         t_val = ftdm_strdup(value);
3571 
3572         hashtable_insert(ftdmchan->variable_hash, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE);
3573 
3574         status = FTDM_SUCCESS;
3575 
3576 done:
3577         ftdm_channel_unlock(ftdmchan);
3578 
3579         return status;
3580 }
3581 
3582 FT_DECLARE(const char *) ftdm_channel_get_var(ftdm_channel_t *ftdmchan, const char *var_name)
3583 {
3584         const char *var = NULL;
3585 
3586         ftdm_channel_lock(ftdmchan);
3587 
3588         if (!ftdmchan->variable_hash || !var_name) {
3589                 goto done;
3590         }
3591         
3592         var = (const char *)hashtable_search(ftdmchan->variable_hash, (void *)var_name);
3593 
3594 done:
3595         ftdm_channel_unlock(ftdmchan);
3596 
3597         return var;
3598 }
3599 
3600 static ftdm_iterator_t *get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t *iter)
3601 {
3602         int allocated = 0;
3603         if (iter) {
3604                 if (iter->type != type) {
3605                         ftdm_log(FTDM_LOG_ERROR, "Cannot switch iterator types\n");
3606                         return NULL;
3607                 }
3608                 allocated = iter->allocated;
3609                 memset(iter, 0, sizeof(*iter));
3610                 iter->type = type;
3611                 iter->allocated = allocated;
3612                 return iter;
3613         }
3614 
3615         iter = ftdm_calloc(1, sizeof(*iter));
3616         if (!iter) {
3617                 return NULL;
3618         }
3619         iter->type = type;
3620         iter->allocated = 1;
3621         return iter;
3622 }
3623 
3624 FT_DECLARE(ftdm_iterator_t *) ftdm_channel_get_var_iterator(const ftdm_channel_t *ftdmchan, ftdm_iterator_t *iter)
3625 {
3626         ftdm_hash_iterator_t *hashiter = NULL;
3627         ftdm_channel_lock(ftdmchan);
3628         hashiter = ftdmchan->variable_hash == NULL ? NULL : hashtable_first(ftdmchan->variable_hash);
3629         ftdm_channel_unlock(ftdmchan);
3630 
3631 
3632         if (hashiter == NULL) {
3633                 return NULL;
3634         }
3635         
3636         if (!(iter = get_iterator(FTDM_ITERATOR_VARS, iter))) {
3637                 return NULL;
3638         }
3639         iter->pvt.hashiter = hashiter;
3640         return iter;
3641 }
3642 
3643 FT_DECLARE(ftdm_iterator_t *) ftdm_span_get_chan_iterator(const ftdm_span_t *span, ftdm_iterator_t *iter)
3644 {
3645         if (!(iter = get_iterator(FTDM_ITERATOR_CHANS, iter))) {
3646                 return NULL;
3647         }
3648         iter->pvt.chaniter.index = 1;
3649         iter->pvt.chaniter.span = span;
3650         return iter;
3651 }
3652 
3653 FT_DECLARE(ftdm_status_t) ftdm_channel_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val)
3654 {
3655         const void *key = NULL;
3656         void *val = NULL;
3657 
3658         *var_name = NULL;
3659         *var_val = NULL;
3660 
3661         ftdm_assert_return(iter && (iter->type == FTDM_ITERATOR_VARS) && iter->pvt.hashiter, FTDM_FAIL, "Cannot get variable from invalid iterator!\n");
3662 
3663         hashtable_this(iter->pvt.hashiter, &key, NULL, &val);
3664 
3665         *var_name = key;
3666         *var_val = val;
3667 
3668         return FTDM_SUCCESS;
3669 }
3670 
3671 FT_DECLARE(ftdm_iterator_t *) ftdm_iterator_next(ftdm_iterator_t *iter)
3672 {
3673         ftdm_assert_return(iter && iter->type, NULL, "Invalid iterator\n");
3674 
3675         switch (iter->type) {
3676         case FTDM_ITERATOR_VARS:
3677                 if (!iter->pvt.hashiter) {
3678                         return NULL;
3679                 }
3680                 iter->pvt.hashiter = hashtable_next(iter->pvt.hashiter);
3681                 if (!iter->pvt.hashiter) {
3682                         return NULL;
3683                 }
3684                 return iter;
3685         case FTDM_ITERATOR_CHANS:
3686                 ftdm_assert_return(iter->pvt.chaniter.index, NULL, "channel iterator index cannot be zero!\n");
3687                 if (iter->pvt.chaniter.index == iter->pvt.chaniter.span->chan_count) {
3688                         return NULL;
3689                 }
3690                 iter->pvt.chaniter.index++;
3691                 return iter;
3692         default:
3693                 break;
3694         }
3695 
3696         ftdm_assert_return(0, NULL, "Unknown iterator type\n");
3697         return NULL;
3698 }
3699 
3700 FT_DECLARE(void *) ftdm_iterator_current(ftdm_iterator_t *iter)
3701 {
3702         const void *key = NULL;
3703         void *val = NULL;
3704 
3705         ftdm_assert_return(iter && iter->type, NULL, "Invalid iterator\n");
3706 
3707         switch (iter->type) {
3708         case FTDM_ITERATOR_VARS:
3709                 hashtable_this(iter->pvt.hashiter, &key, NULL, &val);
3710                 /* I decided to return the key instead of the value since the value can be retrieved using the key */
3711                 return (void *)key;
3712         case FTDM_ITERATOR_CHANS:
3713                 ftdm_assert_return(iter->pvt.chaniter.index, NULL, "channel iterator index cannot be zero!\n");
3714                 ftdm_assert_return(iter->pvt.chaniter.index <= iter->pvt.chaniter.span->chan_count, NULL, "channel iterator index bigger than span chan count!\n");
3715                 return iter->pvt.chaniter.span->channels[iter->pvt.chaniter.index];
3716         default:
3717                 break;
3718         }
3719 
3720         ftdm_assert_return(0, NULL, "Unknown iterator type\n");
3721         return NULL;
3722 }
3723 
3724 FT_DECLARE(ftdm_status_t) ftdm_iterator_free(ftdm_iterator_t *iter)
3725 {
3726         /* it's valid to pass a NULL iterator, do not return failure  */
3727         if (!iter) {
3728                 return FTDM_SUCCESS;
3729         }
3730 
3731         if (!iter->allocated) {
3732                 memset(iter, 0, sizeof(*iter));
3733                 return FTDM_SUCCESS;
3734         }
3735 
3736         ftdm_assert_return(iter->type, FTDM_FAIL, "Cannot free invalid iterator\n");
3737         ftdm_safe_free(iter);
3738 
3739         return FTDM_SUCCESS;
3740 }
3741 
3742 static struct {
3743         ftdm_io_interface_t *pika_interface;
3744 } interfaces;
3745 
3746 static void print_channels_by_state(ftdm_stream_handle_t *stream, ftdm_channel_state_t state, int not, int *count)
3747 {
3748         ftdm_hash_iterator_t *i = NULL;
3749         ftdm_span_t *span;
3750         ftdm_channel_t *fchan = NULL;
3751         ftdm_iterator_t *citer = NULL;
3752         ftdm_iterator_t *curr = NULL;
3753         const void *key = NULL;
3754         void *val = NULL;
3755 
3756         *count = 0;
3757 
3758         ftdm_mutex_lock(globals.mutex);
3759 
3760         for (i = hashtable_first(globals.span_hash); i; i = hashtable_next(i)) {
3761                 hashtable_this(i, &key, NULL, &val);
3762                 if (!key || !val) {
3763                         break;
3764                 }
3765                 span = val;
3766                 citer = ftdm_span_get_chan_iterator(span, NULL);
3767                 if (!citer) {
3768                         continue;
3769                 }
3770                 for (curr = citer ; curr; curr = ftdm_iterator_next(curr)) {
3771                         fchan = ftdm_iterator_current(curr);
3772                         if (not && (fchan->state != state)) {
3773                                 stream->write_function(stream, "[s%dc%d][%d:%d] in state %s\n", 
3774                                                 fchan->span_id, fchan->chan_id, 
3775                                                 fchan->physical_span_id, fchan->physical_chan_id, ftdm_channel_state2str(fchan->state));
3776                                 (*count)++;
3777                         } else if (!not && (fchan->state == state)) {
3778                                 stream->write_function(stream, "[s%dc%d][%d:%d] in state %s\n", 
3779                                                 fchan->span_id, fchan->chan_id, 
3780                                                 fchan->physical_span_id, fchan->physical_chan_id, ftdm_channel_state2str(fchan->state));
3781                                 (*count)++;
3782                         }
3783                 }
3784                 ftdm_iterator_free(citer);
3785         }
3786 
3787         ftdm_mutex_unlock(globals.mutex);
3788 }
3789 
3790 static char *handle_core_command(const char *cmd)
3791 {
3792         char *mycmd = NULL;
3793         int argc = 0;
3794         int count = 0;
3795         int not = 0;
3796         char *argv[10] = { 0 };
3797         char *state = NULL;
3798         ftdm_channel_state_t i = FTDM_CHANNEL_STATE_INVALID;
3799         ftdm_stream_handle_t stream = { 0 };
3800 
3801         FTDM_STANDARD_STREAM(stream);
3802 
3803         if (cmd) {
3804                 mycmd = ftdm_strdup(cmd);
3805                 argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
3806         } else {
3807                 stream.write_function(&stream, "invalid core command\n");
3808                 goto done;
3809         }
3810 
3811         if (!strcasecmp(argv[0], "state")) {
3812                 if (argc < 2) {
3813                         stream.write_function(&stream, "core state command requires an argument\n");
3814                         goto done;
3815                 }
3816                 state = argv[1];
3817                 if (argv[1][0] == '!') {
3818                         not = 1;
3819                         state++;
3820                 }
3821                 for (i = FTDM_CHANNEL_STATE_DOWN; i < FTDM_CHANNEL_STATE_INVALID; i++) {
3822                         if (!strcasecmp(state, ftdm_channel_state2str(i))) {
3823                                 break;
3824                         }
3825                 }
3826                 if (i == FTDM_CHANNEL_STATE_INVALID) {
3827                         stream.write_function(&stream, "invalid state %s\n", state);
3828                         goto done;
3829                 }
3830                 print_channels_by_state(&stream, i, not, &count);
3831                 stream.write_function(&stream, "\nTotal channels %s %s: %d\n", not ? "not in state" : "in state", ftdm_channel_state2str(i), count);
3832         } else {
3833                 stream.write_function(&stream, "invalid core command %s\n", argv[0]);
3834         }
3835 
3836 done:
3837         ftdm_safe_free(mycmd);
3838 
3839         return stream.data;
3840 }
3841 
3842 FT_DECLARE(char *) ftdm_api_execute(const char *cmd)
3843 {
3844         ftdm_io_interface_t *fio = NULL;
3845         char *dup = NULL, *p;
3846         char *rval = NULL;
3847         char *type = NULL;
3848 
3849         dup = ftdm_strdup(cmd);
3850         if ((p = strchr(dup, ' '))) {
3851                 *p++ = '\0';
3852                 cmd = p;
3853         }
3854 
3855         type = dup;
3856 
3857         if (!strcasecmp(type, "core")) {
3858                 return handle_core_command(cmd);
3859         }
3860         
3861         ftdm_mutex_lock(globals.mutex);
3862         if (!(fio = (ftdm_io_interface_t *) hashtable_search(globals.interface_hash, (void *)type))) {
3863                 ftdm_load_module_assume(type);
3864                 if ((fio = (ftdm_io_interface_t *) hashtable_search(globals.interface_hash, (void *)type))) {
3865                         ftdm_log(FTDM_LOG_INFO, "auto-loaded '%s'\n", type);
3866                 }
3867         }
3868         ftdm_mutex_unlock(globals.mutex);
3869 
3870         if (fio && fio->api) {
3871                 ftdm_stream_handle_t stream = { 0 };
3872                 ftdm_status_t status;
3873                 FTDM_STANDARD_STREAM(stream);
3874                 status = fio->api(&stream, cmd);
3875                 
3876                 if (status != FTDM_SUCCESS) {
3877                         ftdm_safe_free(stream.data);
3878                 } else {
3879                         rval = (char *) stream.data;
3880                 }
3881         }
3882 
3883         ftdm_safe_free(dup);
3884         
3885         return rval;
3886 }
3887 
3888 static ftdm_status_t ftdm_set_channels_gains(ftdm_span_t *span, int currindex, float rxgain, float txgain)
3889 {
3890         unsigned chan_index = 0;
3891 
3892         if (!span->chan_count) {
3893                 ftdm_log(FTDM_LOG_ERROR, "Failed to set channel gains because span %s has no channels\n", span->name);
3894                 return FTDM_FAIL;
3895         }
3896 
3897         for (chan_index = currindex+1; chan_index <= span->chan_count; chan_index++) {
3898                 if (!FTDM_IS_VOICE_CHANNEL(span->channels[chan_index])) {
3899                         continue;
3900                 }
3901                 if (ftdm_channel_command(span->channels[chan_index], FTDM_COMMAND_SET_RX_GAIN, &rxgain) != FTDM_SUCCESS) {
3902                         return FTDM_FAIL;
3903                 }
3904                 if (ftdm_channel_command(span->channels[chan_index], FTDM_COMMAND_SET_TX_GAIN, &txgain) != FTDM_SUCCESS) {
3905                         return FTDM_FAIL;
3906                 }
3907         }
3908         return FTDM_SUCCESS;
3909 }
3910 
3911 static ftdm_status_t ftdm_set_channels_alarms(ftdm_span_t *span, int currindex) {
3912         unsigned chan_index = 0;
3913 
3914         if (!span->chan_count) {
3915                 ftdm_log(FTDM_LOG_ERROR, "%d:Failed to set alarms because span has no channels\n");
3916                 return FTDM_FAIL;
3917         }
3918 
3919         if (!span->fio->get_alarms) {
3920                 ftdm_log(FTDM_LOG_WARNING, "%d: Span does not support alarms\n", span->span_id);
3921                 return FTDM_SUCCESS;
3922         }
3923 
3924         for (chan_index = currindex+1; chan_index <= span->chan_count; chan_index++) {
3925                 /* fio->get_alarms will update ftdm_chan->alarm_flags */
3926                 if (span->fio->get_alarms(span->channels[chan_index]) != FTDM_SUCCESS) {
3927                         ftdm_log(FTDM_LOG_ERROR, "%d:%d: Failed to get alarms\n", span->channels[chan_index]->physical_span_id, span->channels[chan_index]->physical_chan_id);
3928                         return FTDM_FAIL;
3929                 }
3930         }
3931         return FTDM_SUCCESS;
3932 }
3933 
3934 
3935 FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const char* str, ftdm_channel_config_t *chan_config, unsigned *configured)
3936 {
3937         int currindex;
3938 
3939         ftdm_assert_return(span != NULL, FTDM_EINVAL, "span is null\n");
3940         ftdm_assert_return(chan_config != NULL, FTDM_EINVAL, "config is null\n");
3941         ftdm_assert_return(configured != NULL, FTDM_EINVAL, "configured pointer is null\n");
3942         ftdm_assert_return(span->fio != NULL, FTDM_EINVAL, "span with no I/O configured\n");
3943         ftdm_assert_return(span->fio->configure_span != NULL, FTDM_NOTIMPL, "span I/O with no channel configuration implemented\n");
3944 
3945         currindex = span->chan_count;
3946         *configured = 0;
3947         *configured = span->fio->configure_span(span, str, chan_config->type, chan_config->name, chan_config->number);
3948         if (!*configured) {
3949                 ftdm_log(FTDM_LOG_ERROR, "%d:Failed to configure span", span->span_id);
3950                 return FTDM_FAIL;
3951         }
3952 
3953         if (chan_config->group_name[0]) {
3954                 if (ftdm_group_add_channels(span, currindex, chan_config->group_name) != FTDM_SUCCESS) {
3955                         ftdm_log(FTDM_LOG_ERROR, "%d:Failed to add channels to group %s\n", span->span_id, chan_config->group_name);
3956                         return FTDM_FAIL;
3957                 }
3958         }
3959 
3960         if (ftdm_set_channels_gains(span, currindex, chan_config->rxgain, chan_config->txgain) != FTDM_SUCCESS) {
3961                 ftdm_log(FTDM_LOG_ERROR, "%d:Failed to set channel gains\n", span->span_id);
3962                 return FTDM_FAIL;
3963         }
3964 
3965 
3966         if (ftdm_set_channels_alarms(span, currindex) != FTDM_SUCCESS) {
3967                 ftdm_log(FTDM_LOG_ERROR, "%d:Failed to set channel alarms\n", span->span_id);
3968                 return FTDM_FAIL;
3969         }
3970 
3971         return FTDM_SUCCESS;
3972 }
3973 
3974 
3975 static ftdm_status_t load_config(void)
3976 {
3977         char cfg_name[] = "freetdm.conf";
3978         ftdm_config_t cfg;
3979         char *var, *val;
3980         int catno = -1;
3981         int intparam = 0;
3982         ftdm_span_t *span = NULL;
3983         unsigned configured = 0, d = 0;
3984         ftdm_analog_start_type_t tmp;
3985         ftdm_size_t len = 0;
3986         ftdm_channel_config_t chan_config;
3987 
3988         memset(&chan_config, 0, sizeof(chan_config));
3989         sprintf(chan_config.group_name,"default");
3990 
3991         if (!ftdm_config_open_file(&cfg, cfg_name)) {
3992                 return FTDM_FAIL;
3993         }
3994         ftdm_log(FTDM_LOG_DEBUG, "Reading FreeTDM configuration file\n");       
3995         while (ftdm_config_next_pair(&cfg, &var, &val)) {
3996                 if (*cfg.category == '#') {
3997                         if (cfg.catno != catno) {
3998                                 ftdm_log(FTDM_LOG_DEBUG, "Skipping %s\n", cfg.category);
3999                                 catno = cfg.catno;
4000                         }
4001                 } else if (!strncasecmp(cfg.category, "span", 4)) {
4002                         if (cfg.catno != catno) {
4003                                 char *type = cfg.category + 4;
4004                                 char *name;
4005                                 
4006                                 if (*type == ' ') {
4007                                         type++;
4008                                 }
4009                                 
4010                                 ftdm_log(FTDM_LOG_DEBUG, "found config for span\n");
4011                                 catno = cfg.catno;
4012                                 
4013                                 if (ftdm_strlen_zero(type)) {
4014                                         ftdm_log(FTDM_LOG_CRIT, "failure creating span, no type specified.\n");
4015                                         span = NULL;
4016                                         continue;
4017                                 }
4018 
4019                                 if ((name = strchr(type, ' '))) {
4020                                         *name++ = '\0';
4021                                 }
4022 
4023                                 if (ftdm_span_create(type, name, &span) == FTDM_SUCCESS) {
4024                                         ftdm_log(FTDM_LOG_DEBUG, "created span %d (%s) of type %s\n", span->span_id, span->name, type);
4025                                         d = 0;
4026                                 } else {
4027                                         ftdm_log(FTDM_LOG_CRIT, "failure creating span of type %s\n", type);
4028                                         span = NULL;
4029                                         continue;
4030                                 }
4031                         }
4032 
4033                         if (!span) {
4034                                 continue;
4035                         }
4036 
4037                         ftdm_log(FTDM_LOG_DEBUG, "span %d [%s]=[%s]\n", span->span_id, var, val);
4038                         
4039                         if (!strcasecmp(var, "trunk_type")) {
4040                                 ftdm_trunk_type_t trtype = ftdm_str2ftdm_trunk_type(val);
4041                                 ftdm_span_set_trunk_type(span, trtype);
4042                                 ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s'\n", ftdm_trunk_type2str(trtype)); 
4043                         } else if (!strcasecmp(var, "name")) {
4044                                 if (!strcasecmp(val, "undef")) {
4045                                         chan_config.name[0] = '\0';
4046                                 } else {
4047                                         ftdm_copy_string(chan_config.name, val, FTDM_MAX_NAME_STR_SZ);
4048                                 }
4049                         } else if (!strcasecmp(var, "number")) {
4050                                 if (!strcasecmp(val, "undef")) {
4051                                         chan_config.number[0] = '\0';
4052                                 } else {
4053                                         ftdm_copy_string(chan_config.number, val, FTDM_MAX_NUMBER_STR_SZ);
4054                                 }
4055                         } else if (!strcasecmp(var, "analog-start-type")) {
4056                                 if (span->trunk_type == FTDM_TRUNK_FXS || span->trunk_type == FTDM_TRUNK_FXO || span->trunk_type == FTDM_TRUNK_EM) {
4057                                         if ((tmp = ftdm_str2ftdm_analog_start_type(val)) != FTDM_ANALOG_START_NA) {
4058                                                 span->start_type = tmp;
4059                                                 ftdm_log(FTDM_LOG_DEBUG, "changing start type to '%s'\n", ftdm_analog_start_type2str(span->start_type)); 
4060                                         }
4061                                 } else {
4062                                         ftdm_log(FTDM_LOG_ERROR, "This option is only valid on analog trunks!\n");
4063                                 }
4064                         } else if (!strcasecmp(var, "fxo-channel")) {
4065                                 if (span->trunk_type == FTDM_TRUNK_NONE) {
4066                                         span->trunk_type = FTDM_TRUNK_FXO;                                                                              
4067                                         ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s)\n", ftdm_trunk_type2str(span->trunk_type), 
4068                                                         ftdm_analog_start_type2str(span->start_type));
4069                                 }
4070                                 if (span->trunk_type == FTDM_TRUNK_FXO) {
4071                                         unsigned chans_configured = 0;
4072                                         chan_config.type = FTDM_CHAN_TYPE_FXO;
4073                                         if (ftdm_configure_span_channels(span, val, &chan_config, &chans_configured) == FTDM_SUCCESS) {
4074                                                 configured += chans_configured;
4075                                         }
4076                                 } else {
4077                                         ftdm_log(FTDM_LOG_WARNING, "Cannot add FXO channels to an FXS trunk!\n");
4078                                 }
4079                         } else if (!strcasecmp(var, "fxs-channel")) {
4080                                 if (span->trunk_type == FTDM_TRUNK_NONE) {
4081                                         span->trunk_type = FTDM_TRUNK_FXS;
4082                                         ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s)\n", ftdm_trunk_type2str(span->trunk_type), 
4083                                                         ftdm_analog_start_type2str(span->start_type));
4084                                 }
4085                                 if (span->trunk_type == FTDM_TRUNK_FXS) {
4086                                         unsigned chans_configured = 0;
4087                                         chan_config.type = FTDM_CHAN_TYPE_FXS;
4088                                         if (ftdm_configure_span_channels(span, val, &chan_config, &chans_configured) == FTDM_SUCCESS) {
4089                                                 configured += chans_configured;
4090                                         }
4091                                 } else {
4092                                         ftdm_log(FTDM_LOG_WARNING, "Cannot add FXS channels to an FXO trunk!\n");
4093                                 }
4094                         } else if (!strcasecmp(var, "em-channel")) {
4095                                 if (span->trunk_type == FTDM_TRUNK_NONE) {
4096                                         span->trunk_type = FTDM_TRUNK_EM;
4097                                         ftdm_log(FTDM_LOG_DEBUG, "setting trunk type to '%s' start(%s)\n", ftdm_trunk_type2str(span->trunk_type), 
4098                                                         ftdm_analog_start_type2str(span->start_type));
4099                                 }
4100                                 if (span->trunk_type == FTDM_TRUNK_EM) {
4101                                         unsigned chans_configured = 0;
4102                                         chan_config.type = FTDM_CHAN_TYPE_EM;
4103                                         if (ftdm_configure_span_channels(span, val, &chan_config, &chans_configured) == FTDM_SUCCESS) {
4104                                                 configured += chans_configured;
4105                                         }
4106                                 } else {
4107                                         ftdm_log(FTDM_LOG_WARNING, "Cannot add EM channels to a non-EM trunk!\n");
4108                                 }
4109                         } else if (!strcasecmp(var, "b-channel")) {
4110                                 unsigned chans_configured = 0;
4111                                 chan_config.type = FTDM_CHAN_TYPE_B;
4112                                 if (ftdm_configure_span_channels(span, val, &chan_config, &chans_configured) == FTDM_SUCCESS) {
4113                                         configured += chans_configured;
4114                                 }
4115                         } else if (!strcasecmp(var, "d-channel")) {
4116                                 if (d) {
4117                                         ftdm_log(FTDM_LOG_WARNING, "ignoring extra d-channel\n");
4118                                 } else {
4119                                         unsigned chans_configured = 0;
4120                                         if (!strncasecmp(val, "lapd:", 5)) {
4121                                                 chan_config.type = FTDM_CHAN_TYPE_DQ931;
4122                                                 val += 5;
4123                                         } else {
4124                                                 chan_config.type = FTDM_CHAN_TYPE_DQ921;
4125                                         }
4126                                         if (ftdm_configure_span_channels(span, val, &chan_config, &chans_configured) == FTDM_SUCCESS) {
4127                                                 configured += chans_configured;
4128                                         }
4129                                         d++;
4130                                 }
4131                         } else if (!strcasecmp(var, "cas-channel")) {
4132                                 unsigned chans_configured = 0;
4133                                 chan_config.type = FTDM_CHAN_TYPE_CAS;
4134                                 
4135                                 if (ftdm_configure_span_channels(span, val, &chan_config, &chans_configured) == FTDM_SUCCESS) {
4136                                         configured += chans_configured;
4137                                 }
4138                         } else if (!strcasecmp(var, "dtmf_hangup")) {
4139                                 span->dtmf_hangup = ftdm_strdup(val);
4140                                 span->dtmf_hangup_len = strlen(val);
4141                         } else if (!strcasecmp(var, "txgain")) {
4142                                 if (sscanf(val, "%f", &(chan_config.txgain)) != 1) {
4143                                         ftdm_log(FTDM_LOG_ERROR, "invalid txgain: '%s'\n", val);
4144                                 }
4145                         } else if (!strcasecmp(var, "rxgain")) {
4146                                 if (sscanf(val, "%f", &(chan_config.rxgain)) != 1) {
4147                                         ftdm_log(FTDM_LOG_ERROR, "invalid rxgain: '%s'\n", val);
4148                                 }
4149                         } else if (!strcasecmp(var, "group")) {
4150                                 len = strlen(val);
4151                                 if (len >= FTDM_MAX_NAME_STR_SZ) {
4152                                         len = FTDM_MAX_NAME_STR_SZ - 1;
4153                                         ftdm_log(FTDM_LOG_WARNING, "Truncating group name %s to %zd length\n", val, len);
4154                                 }
4155                                 memcpy(chan_config.group_name, val, len);
4156                                 chan_config.group_name[len] = '\0';
4157                         } else {
4158                                 ftdm_log(FTDM_LOG_ERROR, "unknown span variable '%s'\n", var);
4159                         }
4160                 } else if (!strncasecmp(cfg.category, "general", 7)) {
4161                         if (!strncasecmp(var, "cpu_monitor", sizeof("cpu_monitor")-1)) {
4162                                 if (!strncasecmp(val, "yes", 3)) {
4163                                         globals.cpu_monitor.enabled = 1;
4164                                         if (!globals.cpu_monitor.alarm_action_flags) {
4165                                                 globals.cpu_monitor.alarm_action_flags |= FTDM_CPU_ALARM_ACTION_WARN;
4166                                         }
4167                                 }
4168                         } else if (!strncasecmp(var, "cpu_monitoring_interval", sizeof("cpu_monitoring_interval")-1)) {
4169                                 if (atoi(val) > 0) {
4170                                         globals.cpu_monitor.interval = atoi(val);
4171                                 } else {
4172                                         ftdm_log(FTDM_LOG_ERROR, "Invalid cpu monitoring interval %s\n", val);
4173                                 }
4174                         } else if (!strncasecmp(var, "cpu_set_alarm_threshold", sizeof("cpu_set_alarm_threshold")-1)) {
4175                                 intparam = atoi(val);
4176                                 if (intparam > 0 && intparam < 100) {
4177                                         globals.cpu_monitor.set_alarm_threshold = (uint8_t)intparam;
4178                                 } else {
4179                                         ftdm_log(FTDM_LOG_ERROR, "Invalid cpu alarm set threshold %s\n", val);
4180                                 }
4181                         } else if (!strncasecmp(var, "cpu_reset_alarm_threshold", sizeof("cpu_reset_alarm_threshold")-1)) {
4182                                 intparam = atoi(val);
4183                                 if (intparam > 0 && intparam < 100) {
4184                                         globals.cpu_monitor.reset_alarm_threshold = (uint8_t)intparam;
4185                                         if (globals.cpu_monitor.reset_alarm_threshold > globals.cpu_monitor.set_alarm_threshold) {
4186                                                 globals.cpu_monitor.reset_alarm_threshold = globals.cpu_monitor.set_alarm_threshold - 10;
4187                                                 ftdm_log(FTDM_LOG_ERROR, "Cpu alarm reset threshold must be lower than set threshold"
4188                                                                 ", setting threshold to %d\n", globals.cpu_monitor.reset_alarm_threshold);
4189                                         }
4190                                 } else {
4191                                         ftdm_log(FTDM_LOG_ERROR, "Invalid cpu alarm reset threshold %s\n", val);
4192                                 }
4193                         } else if (!strncasecmp(var, "cpu_alarm_action", sizeof("cpu_alarm_action")-1)) {
4194                                 char* p = val;
4195                                 do {
4196                                         if (!strncasecmp(p, "reject", sizeof("reject")-1)) {
4197                                                 globals.cpu_monitor.alarm_action_flags |= FTDM_CPU_ALARM_ACTION_REJECT;
4198                                         } else if (!strncasecmp(p, "warn", sizeof("warn")-1)) {
4199                                                 globals.cpu_monitor.alarm_action_flags |= FTDM_CPU_ALARM_ACTION_WARN;
4200                                         }
4201                                         p = strchr(p, ',');
4202                                         if (p) {
4203                                                 while(*p++) if (*p != 0x20) break;
4204                                         }
4205                                 } while (p);
4206                         }
4207                 } else {
4208                         ftdm_log(FTDM_LOG_ERROR, "unknown param [%s] '%s' / '%s'\n", cfg.category, var, val);
4209                 }
4210         }
4211         ftdm_config_close_file(&cfg);
4212 
4213         ftdm_log(FTDM_LOG_INFO, "Configured %u channel(s)\n", configured);
4214         
4215         return configured ? FTDM_SUCCESS : FTDM_FAIL;
4216 }
4217 
4218 static ftdm_status_t process_module_config(ftdm_io_interface_t *fio)
4219 {
4220         ftdm_config_t cfg;
4221         char *var, *val;
4222         char filename[256] = "";
4223         
4224         ftdm_assert_return(fio != NULL, FTDM_FAIL, "fio argument is null\n");
4225 
4226         snprintf(filename, sizeof(filename), "%s.conf", fio->name);
4227 
4228         if (!fio->configure) {
4229                 ftdm_log(FTDM_LOG_DEBUG, "Module %s does not support configuration.\n", fio->name);     
4230                 return FTDM_FAIL;
4231         }
4232 
4233         if (!ftdm_config_open_file(&cfg, filename)) {
4234                 ftdm_log(FTDM_LOG_ERROR, "Cannot open %s\n", filename); 
4235                 return FTDM_FAIL;
4236         }
4237 
4238         while (ftdm_config_next_pair(&cfg, &var, &val)) {
4239                 fio->configure(cfg.category, var, val, cfg.lineno);
4240         }
4241 
4242         ftdm_config_close_file(&cfg);   
4243 
4244         return FTDM_SUCCESS;
4245 }
4246 
4247 FT_DECLARE(ftdm_status_t) ftdm_global_add_io_interface(ftdm_io_interface_t *interface1)
4248 {
4249         ftdm_status_t ret = FTDM_SUCCESS;
4250         ftdm_mutex_lock(globals.mutex);
4251         if (hashtable_search(globals.interface_hash, (void *)interface1->name)) {
4252                 ftdm_log(FTDM_LOG_ERROR, "Interface %s already loaded!\n", interface1->name);
4253         } else {
4254                 hashtable_insert(globals.interface_hash, (void *)interface1->name, interface1, HASHTABLE_FLAG_NONE);
4255         }
4256         ftdm_mutex_unlock(globals.mutex);
4257         return ret;
4258 }
4259 
4260 FT_DECLARE(int) ftdm_load_module(const char *name)
4261 {
4262         ftdm_dso_lib_t lib;
4263         int count = 0, x = 0;
4264         char path[128] = "";
4265         char *err;
4266         ftdm_module_t *mod;
4267 
4268         ftdm_build_dso_path(name, path, sizeof(path));
4269 
4270         if (!(lib = ftdm_dso_open(path, &err))) {
4271                 ftdm_log(FTDM_LOG_ERROR, "Error loading %s [%s]\n", path, err);
4272                 ftdm_safe_free(err);
4273                 return 0;
4274         }
4275         
4276         if (!(mod = (ftdm_module_t *) ftdm_dso_func_sym(lib, "ftdm_module", &err))) {
4277                 ftdm_log(FTDM_LOG_ERROR, "Error loading %s [%s]\n", path, err);
4278                 ftdm_safe_free(err);
4279                 return 0;
4280         }
4281 
4282         if (mod->io_load) {
4283                 ftdm_io_interface_t *interface1 = NULL; /* name conflict w/windows here */
4284 
4285                 if (mod->io_load(&interface1) != FTDM_SUCCESS || !interface1 || !interface1->name) {
4286                         ftdm_log(FTDM_LOG_ERROR, "Error loading %s\n", path);
4287                 } else {
4288                         ftdm_log(FTDM_LOG_INFO, "Loading IO from %s [%s]\n", path, interface1->name);
4289                         if (ftdm_global_add_io_interface(interface1) == FTDM_SUCCESS) {
4290                                 process_module_config(interface1);
4291                                 x++;
4292                         }
4293                 }
4294         }
4295 
4296         if (mod->sig_load) {
4297                 if (mod->sig_load() != FTDM_SUCCESS) {
4298                         ftdm_log(FTDM_LOG_ERROR, "Error loading %s\n", path);
4299                 } else {
4300                         ftdm_log(FTDM_LOG_INFO, "Loading SIG from %s\n", path);
4301                         x++;
4302                 }
4303         }
4304 
4305         if (x) {
4306                 char *p;
4307                 mod->lib = lib;
4308                 ftdm_set_string(mod->path, path);
4309                 if (mod->name[0] == '\0') {
4310                         if (!(p = strrchr(path, *FTDM_PATH_SEPARATOR))) {
4311                                 p = path;
4312                         }
4313                         ftdm_set_string(mod->name, p);
4314                 }
4315 
4316                 ftdm_mutex_lock(globals.mutex);
4317                 if (hashtable_search(globals.module_hash, (void *)mod->name)) {
4318                         ftdm_log(FTDM_LOG_ERROR, "Module %s already loaded!\n", mod->name);
4319                         ftdm_dso_destroy(&lib);
4320                 } else {
4321                         hashtable_insert(globals.module_hash, (void *)mod->name, mod, HASHTABLE_FLAG_NONE);
4322                         count++;
4323                 }
4324                 ftdm_mutex_unlock(globals.mutex);
4325         } else {
4326                 ftdm_log(FTDM_LOG_ERROR, "Unloading %s\n", path);
4327                 ftdm_dso_destroy(&lib);
4328         }
4329         
4330         return count;
4331 }
4332 
4333 FT_DECLARE(int) ftdm_load_module_assume(const char *name)
4334 {
4335         char buf[256] = "";
4336 
4337         snprintf(buf, sizeof(buf), "ftmod_%s", name);
4338         return ftdm_load_module(buf);
4339 }
4340 
4341 FT_DECLARE(int) ftdm_load_modules(void)
4342 {
4343         char cfg_name[] = "modules.conf";
4344         ftdm_config_t cfg;
4345         char *var, *val;
4346         int count = 0;
4347 
4348         if (!ftdm_config_open_file(&cfg, cfg_name)) {
4349         return FTDM_FAIL;
4350     }
4351 
4352         while (ftdm_config_next_pair(&cfg, &var, &val)) {
4353         if (!strcasecmp(cfg.category, "modules")) {
4354                         if (!strcasecmp(var, "load")) {
4355                                 count += ftdm_load_module(val);
4356                         }
4357                 }
4358         }
4359                         
4360         return count;
4361 }
4362 
4363 FT_DECLARE(ftdm_status_t) ftdm_unload_modules(void)
4364 {
4365         ftdm_hash_iterator_t *i = NULL;
4366         ftdm_dso_lib_t lib = NULL;
4367         char modpath[255] = { 0 };
4368 
4369         /* stop signaling interfaces first as signaling depends on I/O and not the other way around */
4370         for (i = hashtable_first(globals.module_hash); i; i = hashtable_next(i)) {
4371                 const void *key = NULL;
4372                 void *val = NULL;
4373                 ftdm_module_t *mod = NULL;
4374 
4375                 hashtable_this(i, &key, NULL, &val);
4376                 
4377                 if (!key || !val) {
4378                         continue;
4379                 }
4380                 
4381                 mod = (ftdm_module_t *) val;
4382 
4383                 if (!mod->sig_unload) {
4384                         continue;
4385                 }
4386 
4387                 ftdm_log(FTDM_LOG_INFO, "Unloading signaling interface %s\n", mod->name);
4388                 
4389                 if (mod->sig_unload() != FTDM_SUCCESS) {
4390                         ftdm_log(FTDM_LOG_ERROR, "Error unloading signaling interface %s\n", mod->name);
4391                         continue;
4392                 }
4393 
4394                 ftdm_log(FTDM_LOG_INFO, "Unloaded signaling interface %s\n", mod->name);
4395         }
4396 
4397         /* Now go ahead with I/O interfaces */
4398         for (i = hashtable_first(globals.module_hash); i; i = hashtable_next(i)) {
4399                 const void *key = NULL;
4400                 void *val = NULL;
4401                 ftdm_module_t *mod = NULL;
4402 
4403                 hashtable_this(i, &key, NULL, &val);
4404                 
4405                 if (!key || !val) {
4406                         continue;
4407                 }
4408                 
4409                 mod = (ftdm_module_t *) val;
4410 
4411                 if (!mod->io_unload) {
4412                         continue;
4413                 }
4414 
4415                 ftdm_log(FTDM_LOG_INFO, "Unloading I/O interface %s\n", mod->name);
4416                 
4417                 if (mod->io_unload() != FTDM_SUCCESS) {
4418                         ftdm_log(FTDM_LOG_ERROR, "Error unloading I/O interface %s\n", mod->name);
4419                         continue;
4420                 }
4421 
4422                 ftdm_log(FTDM_LOG_INFO, "Unloaded I/O interface %s\n", mod->name);
4423         }
4424 
4425         /* Now unload the actual shared object/dll */
4426         for (i = hashtable_first(globals.module_hash); i; i = hashtable_next(i)) {
4427                 ftdm_module_t *mod = NULL;
4428                 const void *key = NULL;
4429                 void *val = NULL;
4430 
4431                 hashtable_this(i, &key, NULL, &val);
4432 
4433                 if (!key || !val) {
4434                         continue;
4435                 }
4436 
4437                 mod = (ftdm_module_t *) val;
4438 
4439                 lib = mod->lib;
4440                 snprintf(modpath, sizeof(modpath), "%s", mod->path);
4441                 ftdm_log(FTDM_LOG_INFO, "Unloading module %s\n", modpath);
4442                 ftdm_dso_destroy(&lib);
4443                 ftdm_log(FTDM_LOG_INFO, "Unloaded module %s\n", modpath);
4444         }
4445 
4446         return FTDM_SUCCESS;
4447 }
4448 
4449 static ftdm_status_t post_configure_span_channels(ftdm_span_t *span)
4450 {
4451         unsigned i = 0;
4452         ftdm_status_t status = FTDM_SUCCESS;
4453         ftdm_signaling_status_t sigstatus = FTDM_SIG_STATE_DOWN;
4454         for (i = 1; i <= span->chan_count; i++) {
4455                 ftdm_channel_get_sig_status(span->channels[i], &sigstatus);
4456                 if (sigstatus == FTDM_SIG_STATE_UP) {
4457                         ftdm_set_flag(span->channels[i], FTDM_CHANNEL_SIG_UP);
4458                 }
4459         }
4460         if (ftdm_test_flag(span, FTDM_SPAN_USE_CHAN_QUEUE)) {
4461                 status = ftdm_queue_create(&span->pendingchans, SPAN_PENDING_CHANS_QUEUE_SIZE);
4462         }
4463         if (status == FTDM_SUCCESS && ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE)) {
4464                 status = ftdm_queue_create(&span->pendingsignals, SPAN_PENDING_SIGNALS_QUEUE_SIZE);
4465         }
4466         return status;
4467 }
4468 
4469 FT_DECLARE(ftdm_status_t) ftdm_configure_span(ftdm_span_t *span, const char *type, fio_signal_cb_t sig_cb, ...)
4470 {
4471         ftdm_module_t *mod = (ftdm_module_t *) hashtable_search(globals.module_hash, (void *)type);
4472         ftdm_status_t status = FTDM_FAIL;
4473 
4474         if (!span->chan_count) {
4475                 ftdm_log(FTDM_LOG_WARNING, "Cannot configure signaling on span with no channels\n");
4476                 return FTDM_FAIL;
4477         }
4478 
4479         if (!mod) {
4480                 ftdm_load_module_assume(type);
4481                 if ((mod = (ftdm_module_t *) hashtable_search(globals.module_hash, (void *)type))) {
4482                         ftdm_log(FTDM_LOG_INFO, "auto-loaded '%s'\n", type);
4483                 } else {
4484                         ftdm_log(FTDM_LOG_ERROR, "can't load '%s'\n", type);
4485                         return FTDM_FAIL;
4486                 }
4487         }
4488 
4489         if (mod->sig_configure) {
4490                 va_list ap;
4491                 va_start(ap, sig_cb);
4492                 status = mod->sig_configure(span, sig_cb, ap);
4493                 va_end(ap);
4494                 if (status == FTDM_SUCCESS) {
4495                         status = post_configure_span_channels(span);
4496                 }
4497         } else {
4498                 ftdm_log(FTDM_LOG_CRIT, "module '%s' did not implement the sig_configure method\n", type);
4499                 status = FTDM_FAIL;
4500         }
4501 
4502         return status;
4503 }
4504 
4505 FT_DECLARE(ftdm_status_t) ftdm_configure_span_signaling(ftdm_span_t *span, const char *type, fio_signal_cb_t sig_cb, ftdm_conf_parameter_t *parameters) 
4506 {
4507         ftdm_module_t *mod = (ftdm_module_t *) hashtable_search(globals.module_hash, (void *)type);
4508         ftdm_status_t status = FTDM_FAIL;
4509 
4510         ftdm_assert_return(type != NULL, FTDM_FAIL, "No signaling type");
4511         ftdm_assert_return(span != NULL, FTDM_FAIL, "No span");
4512         ftdm_assert_return(sig_cb != NULL, FTDM_FAIL, "No signaling callback");
4513         ftdm_assert_return(parameters != NULL, FTDM_FAIL, "No parameters");
4514 
4515         if (!span->chan_count) {
4516                 ftdm_log(FTDM_LOG_WARNING, "Cannot configure signaling on span with no channels\n");
4517                 return FTDM_FAIL;
4518         }
4519 
4520         if (!mod) {
4521                 ftdm_load_module_assume(type);
4522                 if ((mod = (ftdm_module_t *) hashtable_search(globals.module_hash, (void *)type))) {
4523                         ftdm_log(FTDM_LOG_INFO, "auto-loaded '%s'\n", type);
4524                 }
4525         }
4526 
4527         if (!mod) {
4528                 ftdm_log(FTDM_LOG_ERROR, "Failed to load module type: %s\n", type);
4529                 return FTDM_FAIL;
4530         }
4531 
4532         if (mod->configure_span_signaling) {
4533                 status = mod->configure_span_signaling(span, sig_cb, parameters);
4534                 if (status == FTDM_SUCCESS) {
4535                         status = post_configure_span_channels(span);
4536                 }
4537         } else {
4538                 ftdm_log(FTDM_LOG_ERROR, "Module %s did not implement the signaling configuration method\n", type);
4539         }
4540 
4541         return status;
4542 }
4543 
4544 FT_DECLARE(ftdm_status_t) ftdm_span_start(ftdm_span_t *span)
4545 {
4546         if (span->start) {
4547                 return span->start(span);
4548         }
4549 
4550         return FTDM_FAIL;
4551 }
4552 
4553 FT_DECLARE(ftdm_status_t) ftdm_channel_add_to_group(const char* name, ftdm_channel_t* ftdmchan)
4554 {
4555         unsigned int i;
4556         ftdm_group_t* group = NULL;
4557         
4558         ftdm_mutex_lock(globals.group_mutex);
4559 
4560         ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Cannot add a null channel to a group\n");
4561 
4562         if (ftdm_group_find_by_name(name, &group) != FTDM_SUCCESS) {
4563                 ftdm_log(FTDM_LOG_DEBUG, "Creating new group:%s\n", name);
4564                 ftdm_group_create(&group, name);
4565         }
4566 
4567         /*verify that group does not already include this channel first */
4568         for(i = 0; i < group->chan_count; i++) {
4569                 if (group->channels[i]->physical_span_id == ftdmchan->physical_span_id &&
4570                                 group->channels[i]->physical_chan_id == ftdmchan->physical_chan_id) {
4571 
4572                         ftdm_mutex_unlock(globals.group_mutex);
4573                         ftdm_log(FTDM_LOG_DEBUG, "Channel %d:%d is already added to group %s\n", 
4574                                         group->channels[i]->physical_span_id,
4575                                         group->channels[i]->physical_chan_id,
4576                                         name);
4577                         return FTDM_SUCCESS;
4578                 }
4579         }
4580 
4581         if (group->chan_count >= FTDM_MAX_CHANNELS_GROUP) {
4582                 ftdm_log(FTDM_LOG_ERROR, "Max number of channels exceeded (max:%d)\n", FTDM_MAX_CHANNELS_GROUP);
4583                 ftdm_mutex_unlock(globals.group_mutex);
4584                 return FTDM_FAIL;
4585         }
4586 
4587         group->channels[group->chan_count++] = ftdmchan;
4588         ftdm_mutex_unlock(globals.group_mutex);
4589         return FTDM_SUCCESS;
4590 }
4591 
4592 FT_DECLARE(ftdm_status_t) ftdm_channel_remove_from_group(ftdm_group_t* group, ftdm_channel_t* ftdmchan)
4593 {
4594         unsigned int i, j;
4595         //Need to test this function
4596         ftdm_mutex_lock(globals.group_mutex);
4597 
4598         for (i=0; i < group->chan_count; i++) {
4599                         if (group->channels[i]->physical_span_id == ftdmchan->physical_span_id &&
4600                                         group->channels[i]->physical_chan_id == ftdmchan->physical_chan_id) {
4601 
4602                                 j=i;
4603                                 while(j < group->chan_count-1) {
4604                                         group->channels[j] = group->channels[j+1];
4605                                         j++;
4606                                 }
4607                                 group->channels[group->chan_count--] = NULL;
4608                                 if (group->chan_count <=0) {
4609                                         /* Delete group if it is empty */
4610                                         hashtable_remove(globals.group_hash, (void *)group->name);
4611                                 }
4612                                 ftdm_mutex_unlock(globals.group_mutex);
4613                                 return FTDM_SUCCESS;
4614                         }
4615         }
4616 
4617         ftdm_mutex_unlock(globals.group_mutex);
4618         //Group does not contain this channel
4619         return FTDM_FAIL;
4620 }
4621 
4622 static ftdm_status_t ftdm_group_add_channels(ftdm_span_t* span, int currindex, const char* name)
4623 {
4624         unsigned chan_index = 0;
4625 
4626         ftdm_assert_return(strlen(name) > 0, FTDM_FAIL, "Invalid group name provided\n");
4627         ftdm_assert_return(currindex >= 0, FTDM_FAIL, "Invalid current channel index provided\n");
4628 
4629         if (!span->chan_count) {
4630                 return FTDM_SUCCESS;
4631         }
4632 
4633         for (chan_index = currindex+1; chan_index <= span->chan_count; chan_index++) {
4634                 if (!FTDM_IS_VOICE_CHANNEL(span->channels[chan_index])) {
4635                         continue;
4636                 }
4637                 if (ftdm_channel_add_to_group(name, span->channels[chan_index])) {
4638                         ftdm_log(FTDM_LOG_ERROR, "Failed to add chan:%d to group:%s\n", chan_index, name);
4639                 }
4640         }
4641         return FTDM_SUCCESS;
4642 }
4643 
4644 FT_DECLARE(ftdm_status_t) ftdm_group_find(uint32_t id, ftdm_group_t **group)
4645 {
4646         ftdm_group_t *fgroup = NULL, *grp;
4647 
4648         if (id > FTDM_MAX_GROUPS_INTERFACE) {
4649                 return FTDM_FAIL;
4650         }
4651 
4652         
4653         ftdm_mutex_lock(globals.group_mutex);
4654         for (grp = globals.groups; grp; grp = grp->next) {
4655                 if (grp->group_id == id) {
4656                         fgroup = grp;
4657                         break;
4658                 }
4659         }
4660         ftdm_mutex_unlock(globals.group_mutex);
4661 
4662         if (!fgroup) {
4663                 return FTDM_FAIL;
4664         }
4665 
4666         *group = fgroup;
4667 
4668         return FTDM_SUCCESS;
4669         
4670 }
4671 
4672 FT_DECLARE(ftdm_status_t) ftdm_group_find_by_name(const char *name, ftdm_group_t **group)
4673 {
4674         ftdm_status_t status = FTDM_FAIL;
4675         *group = NULL;
4676         ftdm_mutex_lock(globals.group_mutex);
4677         if (!ftdm_strlen_zero(name)) {
4678                 if ((*group = hashtable_search(globals.group_hash, (void *) name))) {
4679                         status = FTDM_SUCCESS;
4680                 }
4681         }
4682         ftdm_mutex_unlock(globals.group_mutex);
4683         return status;
4684 }
4685 
4686 static void ftdm_group_add(ftdm_group_t *group)
4687 {
4688         ftdm_group_t *grp;
4689         ftdm_mutex_lock(globals.group_mutex);
4690         
4691         for (grp = globals.groups; grp && grp->next; grp = grp->next);
4692 
4693         if (grp) {
4694                 grp->next = group;
4695         } else {
4696                 globals.groups = group;
4697         }
4698         hashtable_insert(globals.group_hash, (void *)group->name, group, HASHTABLE_FLAG_NONE);
4699 
4700         ftdm_mutex_unlock(globals.group_mutex);
4701 }
4702 
4703 
4704 FT_DECLARE(ftdm_status_t) ftdm_group_create(ftdm_group_t **group, const char *name)
4705 {
4706         ftdm_group_t *new_group = NULL;
4707         ftdm_status_t status = FTDM_FAIL;
4708 
4709         ftdm_mutex_lock(globals.mutex);
4710         if (globals.group_index < FTDM_MAX_GROUPS_INTERFACE) {
4711                 new_group = ftdm_calloc(1, sizeof(*new_group));
4712                 
4713                 ftdm_assert(new_group != NULL, "Failed to create new ftdm group, expect a crash\n");
4714 
4715                 status = ftdm_mutex_create(&new_group->mutex);
4716 
4717                 ftdm_assert(status == FTDM_SUCCESS, "Failed to create group mutex, expect a crash\n");
4718 
4719                 new_group->group_id = ++globals.group_index;
4720                 new_group->name = ftdm_strdup(name);
4721                 ftdm_group_add(new_group);
4722                 *group = new_group;
4723                 status = FTDM_SUCCESS;
4724         } else {
4725                 ftdm_log(FTDM_LOG_ERROR, "Group %s was not added, we exceeded the max number of groups\n", name);
4726         }
4727         ftdm_mutex_unlock(globals.mutex);
4728         return status;
4729 }
4730 
4731 static ftdm_status_t ftdm_span_trigger_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
4732 {
4733         return span->signal_cb(sigmsg);
4734 }
4735 
4736 static ftdm_status_t ftdm_span_queue_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
4737 {
4738         ftdm_sigmsg_t *new_sigmsg = NULL;
4739 
4740         ftdm_assert_return((sigmsg->raw_data == NULL), FTDM_FAIL, "No raw data should be used with asynchronous notification\n");
4741 
4742         new_sigmsg = ftdm_calloc(1, sizeof(*sigmsg));
4743         if (!new_sigmsg) {
4744                 return FTDM_FAIL;
4745         }
4746         memcpy(new_sigmsg, sigmsg, sizeof(*sigmsg));
4747 
4748         ftdm_queue_enqueue(span->pendingsignals, new_sigmsg);
4749         return FTDM_SUCCESS;
4750 }
4751 
4752 FT_DECLARE(ftdm_status_t) ftdm_span_trigger_signals(const ftdm_span_t *span)
4753 {
4754         ftdm_sigmsg_t *sigmsg = NULL;
4755         while ((sigmsg = ftdm_queue_dequeue(span->pendingsignals))) {
4756                 ftdm_span_trigger_signal(span, sigmsg);
4757                 ftdm_safe_free(sigmsg);
4758         }
4759         return FTDM_SUCCESS;
4760 }
4761 
4762 
4763 static void execute_safety_hangup(void *data)
4764 {
4765         ftdm_channel_t *fchan = data;
4766         ftdm_channel_lock(fchan);
4767         fchan->hangup_timer = 0;
4768         if (fchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
4769                 ftdm_log_chan(fchan, FTDM_LOG_CRIT, "Forcing hangup since the user did not confirmed our hangup after %dms\n", FORCE_HANGUP_TIMER);
4770                 call_hangup(fchan, __FILE__, __FUNCTION__, __LINE__);
4771         } else {
4772                 ftdm_log_chan(fchan, FTDM_LOG_CRIT, "Not performing safety hangup, channel state is %s\n", ftdm_channel_state2str(fchan->state));
4773         }
4774         ftdm_channel_unlock(fchan);
4775 }
4776 
4777 FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t *sigmsg)
4778 {
4779         if (sigmsg->channel) {
4780                 ftdm_mutex_lock(sigmsg->channel->mutex);
4781         }
4782 
4783         /* some core things to do on special events */
4784         switch (sigmsg->event_id) {
4785 
4786         case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
4787                 {
4788                         ftdm_signaling_status_t sigstatus = ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE) ? sigmsg->sigstatus : *((ftdm_signaling_status_t*)(sigmsg->raw_data));
4789                         if (sigstatus == FTDM_SIG_STATE_UP) {
4790                                 ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP);
4791                         } else {
4792                                 ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP);
4793                         }
4794                 }
4795                 break;
4796 
4797         case FTDM_SIGEVENT_START:
4798                 {
4799                         ftdm_set_echocancel_call_begin(sigmsg->channel);
4800 
4801                         /* when cleaning up the public API I added this because mod_freetdm.c on_fxs_signal was
4802                         * doing it during SIGEVENT_START, but now that flags are private they can't, wonder if
4803                         * is needed at all?
4804                         * */
4805                         ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_HOLD);
4806                 }
4807                 break;
4808 
4809         case FTDM_SIGEVENT_STOP:
4810                 if (ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_USER_HANGUP)) {
4811                         ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user already requested hangup\n");
4812                         goto done;
4813                 }
4814                 if (sigmsg->channel->state == FTDM_CHANNEL_STATE_TERMINATING) {
4815                         ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Scheduling safety hangup timer\n");
4816                         /* if the user does not move us to hangup in 2 seconds, we will do it ourselves */
4817                         ftdm_sched_timer(globals.timingsched, "safety-hangup", FORCE_HANGUP_TIMER, execute_safety_hangup, sigmsg->channel, &sigmsg->channel->hangup_timer);
4818                 }
4819                 break;
4820 
4821         default:
4822                 break;  
4823 
4824         }
4825         
4826         /* if the signaling module uses a queue for signaling notifications, then enqueue it */
4827         if (ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE)) {
4828                 ftdm_span_queue_signal(span, sigmsg);
4829         } else {
4830                 ftdm_span_trigger_signal(span, sigmsg);
4831         }
4832 
4833 done:
4834         if (sigmsg->channel) {
4835                 ftdm_mutex_unlock(sigmsg->channel->mutex);
4836         }
4837 
4838         return FTDM_SUCCESS;
4839 }
4840 
4841 static void *ftdm_cpu_monitor_run(ftdm_thread_t *me, void *obj)
4842 {
4843         cpu_monitor_t *monitor = (cpu_monitor_t *)obj;
4844         struct ftdm_cpu_monitor_stats *cpu_stats = ftdm_new_cpu_monitor();
4845         if (!cpu_stats) {
4846                 return NULL;
4847         }
4848         monitor->running = 1;
4849 
4850         while(ftdm_running()) {
4851                 double time;
4852                 if (ftdm_cpu_get_system_idle_time(cpu_stats, &time)) {
4853                         break;
4854                 }
4855 
4856                 if (monitor->alarm) {
4857                         if ((int)time >= (100 - monitor->set_alarm_threshold)) {
4858                                 ftdm_log(FTDM_LOG_DEBUG, "CPU alarm OFF (idle:%d)\n", (int) time);
4859                                 monitor->alarm = 0;
4860                         }
4861                         if (monitor->alarm_action_flags & FTDM_CPU_ALARM_ACTION_WARN) {
4862                         ftdm_log(FTDM_LOG_WARNING, "CPU alarm is ON (cpu usage:%d)\n", (int) (100-time));
4863                         }
4864                 } else {
4865                         if ((int)time <= (100-monitor->reset_alarm_threshold)) {
4866                                 ftdm_log(FTDM_LOG_DEBUG, "CPU alarm ON (idle:%d)\n", (int) time);
4867                                 monitor->alarm = 1;
4868                         }
4869                 }
4870                 ftdm_interrupt_wait(monitor->interrupt, monitor->interval);
4871         }
4872 
4873         ftdm_delete_cpu_monitor(cpu_stats);
4874         monitor->running = 0;
4875         return NULL;
4876 #ifdef __WINDOWS__
4877         UNREFERENCED_PARAMETER(me);
4878 #endif
4879 }
4880 
4881 static ftdm_status_t ftdm_cpu_monitor_start(void)
4882 {
4883         if (ftdm_interrupt_create(&globals.cpu_monitor.interrupt, FTDM_INVALID_SOCKET) != FTDM_SUCCESS) {
4884                 ftdm_log(FTDM_LOG_CRIT, "Failed to create CPU monitor interrupt\n");
4885                 return FTDM_FAIL;
4886         }
4887 
4888         if (ftdm_thread_create_detached(ftdm_cpu_monitor_run, &globals.cpu_monitor) != FTDM_SUCCESS) {
4889                 ftdm_log(FTDM_LOG_CRIT, "Failed to create cpu monitor thread!!\n");
4890                 return FTDM_FAIL;
4891         }
4892         return FTDM_SUCCESS;
4893 }
4894 
4895 static void ftdm_cpu_monitor_stop(void)
4896 {
4897         if (!globals.cpu_monitor.interrupt) {
4898                 return;
4899         }
4900 
4901         if (!globals.cpu_monitor.running) {
4902                 return;
4903         }
4904 
4905         if (ftdm_interrupt_signal(globals.cpu_monitor.interrupt) != FTDM_SUCCESS) {
4906                 ftdm_log(FTDM_LOG_CRIT, "Failed to interrupt the CPU monitor\n");
4907                 return;
4908         }
4909 
4910         while (globals.cpu_monitor.running) {
4911                 ftdm_sleep(10);
4912         }
4913 
4914         ftdm_interrupt_destroy(&globals.cpu_monitor.interrupt);
4915 }
4916 
4917 FT_DECLARE(ftdm_status_t) ftdm_global_init(void)
4918 {
4919         memset(&globals, 0, sizeof(globals));
4920 
4921         time_init();
4922         
4923         ftdm_thread_override_default_stacksize(FTDM_THREAD_STACKSIZE);
4924 
4925         memset(&interfaces, 0, sizeof(interfaces));
4926         globals.interface_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys);
4927         globals.module_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys);
4928         globals.span_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys);
4929         globals.group_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys);
4930         ftdm_mutex_create(&globals.mutex);
4931         ftdm_mutex_create(&globals.span_mutex);
4932         ftdm_mutex_create(&globals.group_mutex);
4933         ftdm_sched_global_init();
4934         if (ftdm_sched_create(&globals.timingsched, "freetdm-master") != FTDM_SUCCESS) {
4935                 ftdm_log(FTDM_LOG_CRIT, "Failed to create master timing schedule context\n");
4936                 return FTDM_FAIL;
4937         }
4938         if (ftdm_sched_free_run(globals.timingsched) != FTDM_SUCCESS) {
4939                 ftdm_log(FTDM_LOG_CRIT, "Failed to run master timing schedule context\n");
4940                 return FTDM_FAIL;
4941         }
4942         globals.running = 1;
4943         return FTDM_SUCCESS;
4944 }
4945 
4946 FT_DECLARE(ftdm_status_t) ftdm_global_configuration(void)
4947 {
4948         int modcount = 0;
4949 
4950         if (!globals.running) {
4951                 return FTDM_FAIL;
4952         }
4953         
4954         modcount = ftdm_load_modules();
4955 
4956         ftdm_log(FTDM_LOG_NOTICE, "Modules configured: %d \n", modcount);
4957 
4958         globals.cpu_monitor.enabled = 0;
4959         globals.cpu_monitor.interval = 1000;
4960         globals.cpu_monitor.alarm_action_flags = 0;
4961         globals.cpu_monitor.set_alarm_threshold = 80;
4962         globals.cpu_monitor.reset_alarm_threshold = 70;
4963 
4964         if (load_config() != FTDM_SUCCESS) {
4965                 globals.running = 0;
4966                 ftdm_log(FTDM_LOG_ERROR, "FreeTDM global configuration failed!\n");
4967                 return FTDM_FAIL;
4968         }
4969 
4970         if (globals.cpu_monitor.enabled) {
4971                 ftdm_log(FTDM_LOG_INFO, "CPU Monitor is running interval:%d lo-thres:%d hi-thres:%d\n", 
4972                                         globals.cpu_monitor.interval, 
4973                                         globals.cpu_monitor.set_alarm_threshold, 
4974                                         globals.cpu_monitor.reset_alarm_threshold);
4975 
4976                 if (ftdm_cpu_monitor_start() != FTDM_SUCCESS) {
4977                         return FTDM_FAIL;
4978                 }
4979         }
4980 
4981 
4982         return FTDM_SUCCESS;
4983 }
4984 
4985 FT_DECLARE(uint32_t) ftdm_running(void)
4986 {
4987         return globals.running;
4988 }
4989 
4990 
4991 FT_DECLARE(ftdm_status_t) ftdm_global_destroy(void)
4992 {
4993         ftdm_span_t *sp;
4994 
4995         time_end();
4996 
4997         /* many freetdm event loops rely on this variable to decide when to stop, do this first */
4998         globals.running = 0;    
4999 
5000         /* stop the scheduling thread */
5001         ftdm_free_sched_stop();
5002 
5003         /* stop the cpu monitor thread */
5004         ftdm_cpu_monitor_stop();
5005 
5006         /* now destroy channels and spans */
5007         globals.span_index = 0;
5008 
5009         ftdm_span_close_all();
5010         
5011         ftdm_mutex_lock(globals.span_mutex);
5012         for (sp = globals.spans; sp;) {
5013                 ftdm_span_t *cur_span = sp;
5014                 sp = sp->next;
5015 
5016                 if (cur_span) {
5017                         if (ftdm_test_flag(cur_span, FTDM_SPAN_CONFIGURED)) {
5018                                 ftdm_span_destroy(cur_span);
5019                         }
5020 
5021                         hashtable_remove(globals.span_hash, (void *)cur_span->name);
5022                         ftdm_safe_free(cur_span->type);
5023                         ftdm_safe_free(cur_span->name);
5024                         ftdm_safe_free(cur_span);
5025                         cur_span = NULL;
5026                 }
5027         }
5028         globals.spans = NULL;
5029         ftdm_mutex_unlock(globals.span_mutex);
5030 
5031         /* destroy signaling and io modules */
5032         ftdm_unload_modules();
5033 
5034         /* finally destroy the globals */
5035         ftdm_mutex_lock(globals.mutex);
5036         ftdm_sched_destroy(&globals.timingsched);
5037         hashtable_destroy(globals.interface_hash);
5038         hashtable_destroy(globals.module_hash); 
5039         hashtable_destroy(globals.span_hash);
5040         hashtable_destroy(globals.group_hash);
5041         ftdm_mutex_unlock(globals.mutex);
5042         ftdm_mutex_destroy(&globals.mutex);
5043         ftdm_mutex_destroy(&globals.span_mutex);
5044         ftdm_mutex_destroy(&globals.group_mutex);
5045 
5046         memset(&globals, 0, sizeof(globals));
5047         return FTDM_SUCCESS;
5048 }
5049 
5050 
5051 FT_DECLARE(uint32_t) ftdm_separate_string(char *buf, char delim, char **array, int arraylen)
5052 {
5053         int argc;
5054         char *ptr;
5055         int quot = 0;
5056         char qc = '\'';
5057         int x;
5058 
5059         if (!buf || !array || !arraylen) {
5060                 return 0;
5061         }
5062 
5063         memset(array, 0, arraylen * sizeof(*array));
5064 
5065         ptr = buf;
5066 
5067         for (argc = 0; *ptr && (argc < arraylen - 1); argc++) {
5068                 array[argc] = ptr;
5069                 for (; *ptr; ptr++) {
5070                         if (*ptr == qc) {
5071                                 if (quot) {
5072                                         quot--;
5073                                 } else {
5074                                         quot++;
5075                                 }
5076                         } else if ((*ptr == delim) && !quot) {
5077                                 *ptr++ = '\0';
5078                                 break;
5079                         }
5080                 }
5081         }
5082 
5083         if (*ptr) {
5084                 array[argc++] = ptr;
5085         }
5086 
5087         /* strip quotes and leading / trailing spaces */
5088         for (x = 0; x < argc; x++) {
5089                 char *p;
5090 
5091                 while(*(array[x]) == ' ') {
5092                         (array[x])++;
5093                 }
5094                 p = array[x];
5095                 while((p = strchr(array[x], qc))) {
5096                         memmove(p, p+1, strlen(p));
5097                         p++;
5098                 }
5099                 p = array[x] + (strlen(array[x]) - 1);
5100                 while(*p == ' ') {
5101                         *p-- = '\0';
5102                 }
5103         }
5104 
5105         return argc;
5106 }
5107 
5108 FT_DECLARE(void) ftdm_bitstream_init(ftdm_bitstream_t *bsp, uint8_t *data, uint32_t datalen, ftdm_endian_t endian, uint8_t ss)
5109 {
5110         memset(bsp, 0, sizeof(*bsp));
5111         bsp->data = data;
5112         bsp->datalen = datalen;
5113         bsp->endian = endian;
5114         bsp->ss = ss;
5115         
5116         if (endian < 0) {
5117                 bsp->top = bsp->bit_index = 7;
5118                 bsp->bot = 0;
5119         } else {
5120                 bsp->top = bsp->bit_index = 0;
5121                 bsp->bot = 7;
5122         }
5123 
5124 }
5125 
5126 FT_DECLARE(int8_t) ftdm_bitstream_get_bit(ftdm_bitstream_t *bsp)
5127 {
5128         int8_t bit = -1;
5129         
5130 
5131         if (bsp->byte_index >= bsp->datalen) {
5132                 goto done;
5133         }
5134 
5135         if (bsp->ss) {
5136                 if (!bsp->ssv) {
5137                         bsp->ssv = 1;
5138                         return 0;
5139                 } else if (bsp->ssv == 2) {
5140                         bsp->byte_index++;
5141                         bsp->ssv = 0;
5142                         return 1;
5143                 }
5144         }
5145 
5146 
5147 
5148 
5149         bit = (bsp->data[bsp->byte_index] >> (bsp->bit_index)) & 1;
5150         
5151         if (bsp->bit_index == bsp->bot) {
5152                 bsp->bit_index = bsp->top;
5153                 if (bsp->ss) {
5154                         bsp->ssv = 2;
5155                         goto done;
5156                 } 
5157 
5158                 if (++bsp->byte_index > bsp->datalen) {
5159                         bit = -1;
5160                         goto done;
5161                 }
5162                 
5163         } else {
5164                 bsp->bit_index = bsp->bit_index + bsp->endian;
5165         }
5166 
5167 
5168  done:
5169         return bit;
5170 }
5171 
5172 FT_DECLARE(void) print_hex_bytes(uint8_t *data, ftdm_size_t dlen, char *buf, ftdm_size_t blen)
5173 {
5174         char *bp = buf;
5175         uint8_t *byte = data;
5176         uint32_t i, j = 0;
5177 
5178         if (blen < (dlen * 3) + 2) {
5179         return;
5180     }
5181 
5182         *bp++ = '[';
5183         j++;
5184 
5185         for(i = 0; i < dlen; i++) {
5186                 snprintf(bp, blen-j, "%02x ", *byte++);
5187                 bp += 3;
5188                 j += 3;
5189         }
5190 
5191         *--bp = ']';
5192 
5193 }
5194 
5195 FT_DECLARE(void) print_bits(uint8_t *b, int bl, char *buf, int blen, ftdm_endian_t e, uint8_t ss)
5196 {
5197         ftdm_bitstream_t bs;
5198         int j = 0, c = 0;
5199         int8_t bit;
5200         uint32_t last;
5201 
5202         if (blen < (bl * 10) + 2) {
5203         return;
5204     }
5205 
5206         ftdm_bitstream_init(&bs, b, bl, e, ss);
5207         last = bs.byte_index;   
5208         while((bit = ftdm_bitstream_get_bit(&bs)) > -1) {
5209                 buf[j++] = bit ? '1' : '0';
5210                 if (bs.byte_index != last) {
5211                         buf[j++] = ' ';
5212                         last = bs.byte_index;
5213                         if (++c == 8) {
5214                                 buf[j++] = '\n';
5215                                 c = 0;
5216                         }
5217                 }
5218         }
5219 
5220 }
5221 
5222 
5223 
5224 FT_DECLARE_NONSTD(ftdm_status_t) ftdm_console_stream_raw_write(ftdm_stream_handle_t *handle, uint8_t *data, ftdm_size_t datalen)
5225 {
5226         ftdm_size_t need = handle->data_len + datalen;
5227         
5228         if (need >= handle->data_size) {
5229                 void *new_data;
5230                 need += handle->alloc_chunk;
5231 
5232                 if (!(new_data = realloc(handle->data, need))) {
5233                         return FTDM_MEMERR;
5234                 }
5235 
5236                 handle->data = new_data;
5237                 handle->data_size = need;
5238         }
5239 
5240         memcpy((uint8_t *) (handle->data) + handle->data_len, data, datalen);
5241         handle->data_len += datalen;
5242         handle->end = (uint8_t *) (handle->data) + handle->data_len;
5243         *(uint8_t *)handle->end = '\0';
5244 
5245         return FTDM_SUCCESS;
5246 }
5247 
5248 FT_DECLARE(int) ftdm_vasprintf(char **ret, const char *fmt, va_list ap) /* code from switch_apr.c */
5249 {
5250 #ifdef HAVE_VASPRINTF
5251         return vasprintf(ret, fmt, ap);
5252 #else
5253         char *buf;
5254         int len;
5255         size_t buflen;
5256         va_list ap2;
5257         char *tmp = NULL;
5258 
5259 #ifdef _MSC_VER
5260 #if _MSC_VER >= 1500
5261         /* hack for incorrect assumption in msvc header files for code analysis */
5262         __analysis_assume(tmp);
5263 #endif
5264         ap2 = ap;
5265 #else
5266         va_copy(ap2, ap);
5267 #endif
5268 
5269         len = vsnprintf(tmp, 0, fmt, ap2);
5270 
5271         if (len > 0 && (buf = ftdm_malloc((buflen = (size_t) (len + 1)))) != NULL) {
5272                 len = vsnprintf(buf, buflen, fmt, ap);
5273                 *ret = buf;
5274         } else {
5275                 *ret = NULL;
5276                 len = -1;
5277         }
5278 
5279         va_end(ap2);
5280         return len;
5281 #endif
5282 }
5283 
5284 FT_DECLARE_NONSTD(ftdm_status_t) ftdm_console_stream_write(ftdm_stream_handle_t *handle, const char *fmt, ...)
5285 {
5286         va_list ap;
5287         char *buf = handle->data;
5288         char *end = handle->end;
5289         int ret = 0;
5290         char *data = NULL;
5291 
5292         if (handle->data_len >= handle->data_size) {
5293                 return FTDM_FAIL;
5294         }
5295 
5296         va_start(ap, fmt);
5297         ret = ftdm_vasprintf(&data, fmt, ap);
5298         va_end(ap);
5299 
5300         if (data) {
5301                 ftdm_size_t remaining = handle->data_size - handle->data_len;
5302                 ftdm_size_t need = strlen(data) + 1;
5303 
5304                 if ((remaining < need) && handle->alloc_len) {
5305                         ftdm_size_t new_len;
5306                         void *new_data;
5307 
5308                         new_len = handle->data_size + need + handle->alloc_chunk;
5309                         if ((new_data = ftdm_realloc(handle->data, new_len))) {
5310                                 handle->data_size = handle->alloc_len = new_len;
5311                                 handle->data = new_data;
5312                                 buf = handle->data;
5313                                 remaining = handle->data_size - handle->data_len;
5314                                 handle->end = (uint8_t *) (handle->data) + handle->data_len;
5315                                 end = handle->end;
5316                         } else {
5317                                 ftdm_log(FTDM_LOG_CRIT, "Memory Error!\n");
5318                                 ftdm_safe_free(data);
5319                                 return FTDM_FAIL;
5320                         }
5321                 }
5322 
5323                 if (remaining < need) {
5324                         ret = -1;
5325                 } else {
5326                         ret = 0;
5327                         snprintf(end, remaining, "%s", data);
5328                         handle->data_len = strlen(buf);
5329                         handle->end = (uint8_t *) (handle->data) + handle->data_len;
5330                 }
5331                 ftdm_safe_free(data);
5332         }
5333 
5334         return ret ? FTDM_FAIL : FTDM_SUCCESS;
5335 }
5336 
5337 FT_DECLARE(char *) ftdm_strdup(const char *str)
5338 {
5339         ftdm_size_t len = strlen(str) + 1;
5340         void *new = ftdm_malloc(len);
5341 
5342         if (!new) {
5343                 return NULL;
5344         }
5345 
5346         return (char *)memcpy(new, str, len);
5347 }
5348 
5349 FT_DECLARE(char *) ftdm_strndup(const char *str, ftdm_size_t inlen)
5350 {
5351         char *new = NULL;
5352         ftdm_size_t len = strlen(str) + 1;
5353         if (len > (inlen+1)) {
5354                 len = inlen+1;
5355         }
5356         new = (char *)ftdm_malloc(len);
5357 
5358         if (!new) {
5359                 return NULL;
5360         }
5361         
5362         memcpy(new, str, len-1);
5363         new[len-1] = 0;
5364         return new;
5365 }
5366 
5367 FT_DECLARE(char *) ftdm_channel_get_history_str(const ftdm_channel_t *fchan)
5368 {
5369         char func[255];
5370         char line[255];
5371         char states[255];
5372         uint8_t i = 0;
5373 
5374         ftdm_stream_handle_t stream = { 0 };
5375         FTDM_STANDARD_STREAM(stream);
5376         if (!fchan->history[0].file) {
5377                 stream.write_function(&stream, "-- No state history --\n");
5378                 return stream.data;
5379         }
5380 
5381         stream.write_function(&stream, "%-30.30s %-30.30s %s", "-- States --", "-- Function --", "-- Location --\n");
5382 
5383         for (i = fchan->hindex; i < ftdm_array_len(fchan->history); i++) {
5384                 if (!fchan->history[i].file) {
5385                         break;
5386                 }
5387                 snprintf(states, sizeof(states), "%-5.15s => %-5.15s", ftdm_channel_state2str(fchan->history[i].last_state), ftdm_channel_state2str(fchan->history[i].state));
5388                 snprintf(func, sizeof(func), "[%s]", fchan->history[i].func);
5389                 snprintf(line, sizeof(func), "[%s:%d]", fchan->history[i].file, fchan->history[i].line);
5390                 stream.write_function(&stream, "%-30.30s %-30.30s %s\n", states, func, line);
5391         }
5392 
5393         for (i = 0; i < fchan->hindex; i++) {
5394                 snprintf(states, sizeof(states), "%-5.15s => %-5.15s", ftdm_channel_state2str(fchan->history[i].last_state), ftdm_channel_state2str(fchan->history[i].state));
5395                 snprintf(func, sizeof(func), "[%s]", fchan->history[i].func);
5396                 snprintf(line, sizeof(func), "[%s:%d]", fchan->history[i].file, fchan->history[i].line);
5397                 stream.write_function(&stream, "%-30.30s %-30.30s %s\n", states, func, line);
5398         }
5399 
5400         return stream.data;
5401 }
5402 
5403 
5404 /* For Emacs:
5405  * Local Variables:
5406  * mode:c
5407  * indent-tabs-mode:t
5408  * tab-width:4
5409  * c-basic-offset:4
5410  * End:
5411  * For VIM:
5412  * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
5413  */

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