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