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