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