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. write_chan_io_dump
  5. dump_chan_io_to_file
  6. stop_chan_io_dump
  7. start_chan_io_dump
  8. close_dtmf_debug_file
  9. disable_dtmf_debug
  10. FTDM_ENUM_NAMES
  11. null_logger
  12. default_logger
  13. ftdm_std_malloc
  14. ftdm_std_calloc
  15. ftdm_std_realloc
  16. ftdm_std_free
  17. ftdm_set_echocancel_call_begin
  18. ftdm_set_echocancel_call_end
  19. ftdm_set_caller_data
  20. FT_DECLARE
  21. FT_DECLARE
  22. FT_DECLARE
  23. FT_DECLARE
  24. FT_DECLARE
  25. FT_DECLARE_NONSTD
  26. FT_DECLARE_NONSTD
  27. ftdm_channel_destroy
  28. ftdm_span_destroy
  29. FT_DECLARE
  30. ftdm_span_add
  31. FT_DECLARE
  32. FT_DECLARE
  33. FT_DECLARE
  34. FT_DECLARE
  35. reset_gain_table
  36. FT_DECLARE
  37. FT_DECLARE
  38. FT_DECLARE
  39. FT_DECLARE
  40. ftdm_event_handle_oob
  41. FT_DECLARE
  42. FT_DECLARE
  43. ftdmchan_fsk_write_sample
  44. FT_DECLARE
  45. FT_DECLARE
  46. FT_DECLARE
  47. FT_DECLARE
  48. FT_DECLARE
  49. FT_DECLARE
  50. FT_DECLARE
  51. FT_DECLARE
  52. FT_DECLARE
  53. FT_DECLARE
  54. FT_DECLARE
  55. FT_DECLARE
  56. FT_DECLARE
  57. FT_DECLARE
  58. FT_DECLARE
  59. chan_is_avail
  60. chan_voice_is_avail
  61. request_voice_channel
  62. calculate_best_rate
  63. get_best_rated
  64. rr_next
  65. FT_DECLARE
  66. _ftdm_channel_open_by_group
  67. FT_DECLARE
  68. FT_DECLARE
  69. _ftdm_channel_open_by_span
  70. FT_DECLARE
  71. FT_DECLARE
  72. _ftdm_channel_open
  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. FT_DECLARE
  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. _ftdm_channel_call_answer_nl
  96. FT_DECLARE
  97. _ftdm_channel_call_hangup_nl
  98. FT_DECLARE
  99. FT_DECLARE
  100. FT_DECLARE
  101. FT_DECLARE
  102. FT_DECLARE
  103. FT_DECLARE
  104. FT_DECLARE
  105. FT_DECLARE
  106. FT_DECLARE
  107. FT_DECLARE
  108. FT_DECLARE
  109. _ftdm_channel_call_place_nl
  110. FT_DECLARE
  111. FT_DECLARE
  112. FT_DECLARE
  113. FT_DECLARE
  114. FT_DECLARE
  115. FT_DECLARE
  116. ftdm_channel_done
  117. FT_DECLARE
  118. FT_DECLARE
  119. ftdmchan_activate_dtmf_buffer
  120. FT_DECLARE
  121. FT_DECLARE
  122. FIO_CODEC_FUNCTION
  123. FIO_CODEC_FUNCTION
  124. FIO_CODEC_FUNCTION
  125. FIO_CODEC_FUNCTION
  126. FIO_CODEC_FUNCTION
  127. FIO_CODEC_FUNCTION
  128. FT_DECLARE
  129. FT_DECLARE
  130. FT_DECLARE
  131. FT_DECLARE
  132. FT_DECLARE
  133. FIO_WRITE_FUNCTION
  134. FIO_READ_FUNCTION
  135. handle_dtmf
  136. FT_DECLARE
  137. FT_DECLARE
  138. FT_DECLARE
  139. FT_DECLARE
  140. FT_DECLARE
  141. FT_DECLARE
  142. FT_DECLARE
  143. FT_DECLARE
  144. FT_DECLARE
  145. FT_DECLARE
  146. ftdm_channel_clear_vars
  147. FT_DECLARE
  148. FT_DECLARE
  149. get_iterator
  150. FT_DECLARE
  151. FT_DECLARE
  152. FT_DECLARE
  153. FT_DECLARE
  154. FT_DECLARE
  155. FT_DECLARE
  156. print_channels_by_flag
  157. print_channels_by_state
  158. print_core_usage
  159. handle_core_command
  160. FT_DECLARE
  161. ftdm_set_channels_gains
  162. ftdm_set_channels_alarms
  163. FT_DECLARE
  164. load_config
  165. process_module_config
  166. FT_DECLARE
  167. FT_DECLARE
  168. FT_DECLARE
  169. FT_DECLARE
  170. FT_DECLARE
  171. post_configure_span_channels
  172. FT_DECLARE
  173. FT_DECLARE
  174. FT_DECLARE
  175. FT_DECLARE
  176. FT_DECLARE
  177. ftdm_group_add_channels
  178. FT_DECLARE
  179. FT_DECLARE
  180. ftdm_group_add
  181. FT_DECLARE
  182. ftdm_span_trigger_signal
  183. ftdm_span_queue_signal
  184. FT_DECLARE
  185. execute_safety_hangup
  186. FT_DECLARE
  187. ftdm_cpu_monitor_run
  188. ftdm_cpu_monitor_start
  189. ftdm_cpu_monitor_stop
  190. FT_DECLARE
  191. FT_DECLARE
  192. FT_DECLARE
  193. FT_DECLARE
  194. FT_DECLARE
  195. FT_DECLARE
  196. FT_DECLARE
  197. FT_DECLARE
  198. FT_DECLARE
  199. FT_DECLARE_NONSTD
  200. FT_DECLARE
  201. FT_DECLARE_NONSTD
  202. FT_DECLARE
  203. FT_DECLARE
  204. ftdm_call_set_call_id
  205. ftdm_call_clear_call_id

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

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