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