OPENZAP-238: [freetdm] Several core and gsm improvements
* Add error handing in mod_freetdm for ftdm trace failures * Allow freetdm signaling modules to specify a destroy function * Added conditional forwarding to the freetdm gsm module Just specify the conditional-forwarding-number gsm parameter in freetdm.conf.xml * Added new 'gsm call' freetdm command for raw GSM calls which can be used to enable/disabling network features (e.g call *93) without having to resort to use a full originate that requires routing the call somewhere when answered * Miscelaneous cleanup of piggy coding style left over by one of the previous authors -_-
This commit is contained in:
parent
ff283f60de
commit
f5894db211
|
@ -4936,6 +4936,7 @@ FTDM_CLI_DECLARE(ftdm_cmd_trace)
|
||||||
uint32_t chan_id = 0;
|
uint32_t chan_id = 0;
|
||||||
uint32_t span_id = 0;
|
uint32_t span_id = 0;
|
||||||
uint32_t chan_count = 0;
|
uint32_t chan_count = 0;
|
||||||
|
ftdm_status_t status;
|
||||||
ftdm_span_t *span = NULL;
|
ftdm_span_t *span = NULL;
|
||||||
ftdm_channel_t *chan = NULL;
|
ftdm_channel_t *chan = NULL;
|
||||||
|
|
||||||
|
@ -4964,17 +4965,39 @@ FTDM_CLI_DECLARE(ftdm_cmd_trace)
|
||||||
|
|
||||||
if (chan_id) {
|
if (chan_id) {
|
||||||
chan = ftdm_span_get_channel(span, chan_id);
|
chan = ftdm_span_get_channel(span, chan_id);
|
||||||
|
|
||||||
snprintf(tracepath, sizeof(tracepath), "%s-in-s%dc%d", argv[1], span_id, chan_id);
|
snprintf(tracepath, sizeof(tracepath), "%s-in-s%dc%d", argv[1], span_id, chan_id);
|
||||||
ftdm_channel_command(chan, FTDM_COMMAND_TRACE_INPUT, tracepath);
|
status = ftdm_channel_command(chan, FTDM_COMMAND_TRACE_INPUT, tracepath);
|
||||||
|
if (status != FTDM_SUCCESS) {
|
||||||
|
stream->write_function(stream, "-ERR failed to enable input trace at path %s\n", tracepath);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(tracepath, sizeof(tracepath), "%s-out-s%dc%d", argv[1], span_id, chan_id);
|
snprintf(tracepath, sizeof(tracepath), "%s-out-s%dc%d", argv[1], span_id, chan_id);
|
||||||
ftdm_channel_command(chan, FTDM_COMMAND_TRACE_OUTPUT, tracepath);
|
status = ftdm_channel_command(chan, FTDM_COMMAND_TRACE_OUTPUT, tracepath);
|
||||||
|
if (status != FTDM_SUCCESS) {
|
||||||
|
stream->write_function(stream, "-ERR failed to enable output trace at path %s\n", tracepath);
|
||||||
|
ftdm_channel_command(chan, FTDM_COMMAND_TRACE_END_ALL, NULL);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = 1; i <= chan_count; i++) {
|
for (i = 1; i <= chan_count; i++) {
|
||||||
chan = ftdm_span_get_channel(span, i);
|
chan = ftdm_span_get_channel(span, i);
|
||||||
|
|
||||||
snprintf(tracepath, sizeof(tracepath), "%s-in-s%dc%d", argv[1], span_id, i);
|
snprintf(tracepath, sizeof(tracepath), "%s-in-s%dc%d", argv[1], span_id, i);
|
||||||
ftdm_channel_command(chan, FTDM_COMMAND_TRACE_INPUT, tracepath);
|
status = ftdm_channel_command(chan, FTDM_COMMAND_TRACE_INPUT, tracepath);
|
||||||
|
if (status != FTDM_SUCCESS) {
|
||||||
|
stream->write_function(stream, "-ERR failed to enable input trace at path %s\n", tracepath);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(tracepath, sizeof(tracepath), "%s-out-s%dc%d", argv[1], span_id, i);
|
snprintf(tracepath, sizeof(tracepath), "%s-out-s%dc%d", argv[1], span_id, i);
|
||||||
ftdm_channel_command(chan, FTDM_COMMAND_TRACE_OUTPUT, tracepath);
|
status = ftdm_channel_command(chan, FTDM_COMMAND_TRACE_OUTPUT, tracepath);
|
||||||
|
if (status != FTDM_SUCCESS) {
|
||||||
|
stream->write_function(stream, "-ERR failed to enable output trace at path %s\n", tracepath);
|
||||||
|
ftdm_channel_command(chan, FTDM_COMMAND_TRACE_END_ALL, NULL);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stream->write_function(stream, "+OK trace enabled with prefix path %s\n", argv[1]);
|
stream->write_function(stream, "+OK trace enabled with prefix path %s\n", argv[1]);
|
||||||
|
|
|
@ -728,7 +728,14 @@ static ftdm_status_t ftdm_span_destroy(ftdm_span_t *span)
|
||||||
}
|
}
|
||||||
ftdm_mutex_unlock(span->mutex);
|
ftdm_mutex_unlock(span->mutex);
|
||||||
ftdm_mutex_destroy(&span->mutex);
|
ftdm_mutex_destroy(&span->mutex);
|
||||||
ftdm_safe_free(span->signal_data);
|
|
||||||
|
/* Give the span a chance to destroy its own signaling data */
|
||||||
|
if (span->destroy) {
|
||||||
|
span->destroy(span);
|
||||||
|
} else if (span->signal_data) {
|
||||||
|
/* We take care of their dirty business ... */
|
||||||
|
ftdm_free(span->signal_data);
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -5520,7 +5527,8 @@ FT_DECLARE(ftdm_io_interface_t *) ftdm_global_get_io_interface(const char *iotyp
|
||||||
FT_DECLARE(int) ftdm_load_module(const char *name)
|
FT_DECLARE(int) ftdm_load_module(const char *name)
|
||||||
{
|
{
|
||||||
ftdm_dso_lib_t lib;
|
ftdm_dso_lib_t lib;
|
||||||
int count = 0, x = 0;
|
int count = 0;
|
||||||
|
ftdm_bool_t load_proceed = FTDM_TRUE;
|
||||||
char path[512] = "";
|
char path[512] = "";
|
||||||
char *err;
|
char *err;
|
||||||
ftdm_module_t *mod;
|
ftdm_module_t *mod;
|
||||||
|
@ -5544,11 +5552,11 @@ FT_DECLARE(int) ftdm_load_module(const char *name)
|
||||||
|
|
||||||
if (mod->io_load(&interface1) != FTDM_SUCCESS || !interface1 || !interface1->name) {
|
if (mod->io_load(&interface1) != FTDM_SUCCESS || !interface1 || !interface1->name) {
|
||||||
ftdm_log(FTDM_LOG_ERROR, "Error loading %s\n", path);
|
ftdm_log(FTDM_LOG_ERROR, "Error loading %s\n", path);
|
||||||
|
load_proceed = FTDM_FALSE;
|
||||||
} else {
|
} else {
|
||||||
ftdm_log(FTDM_LOG_INFO, "Loading IO from %s [%s]\n", path, interface1->name);
|
ftdm_log(FTDM_LOG_INFO, "Loading IO from %s [%s]\n", path, interface1->name);
|
||||||
if (ftdm_global_add_io_interface(interface1) == FTDM_SUCCESS) {
|
if (ftdm_global_add_io_interface(interface1) == FTDM_SUCCESS) {
|
||||||
process_module_config(interface1);
|
process_module_config(interface1);
|
||||||
x++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5556,13 +5564,13 @@ FT_DECLARE(int) ftdm_load_module(const char *name)
|
||||||
if (mod->sig_load) {
|
if (mod->sig_load) {
|
||||||
if (mod->sig_load() != FTDM_SUCCESS) {
|
if (mod->sig_load() != FTDM_SUCCESS) {
|
||||||
ftdm_log(FTDM_LOG_ERROR, "Error loading %s\n", path);
|
ftdm_log(FTDM_LOG_ERROR, "Error loading %s\n", path);
|
||||||
|
load_proceed = FTDM_FALSE;
|
||||||
} else {
|
} else {
|
||||||
ftdm_log(FTDM_LOG_INFO, "Loading SIG from %s\n", path);
|
ftdm_log(FTDM_LOG_INFO, "Loading SIG from %s\n", path);
|
||||||
x++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x) {
|
if (load_proceed) {
|
||||||
char *p;
|
char *p;
|
||||||
mod->lib = lib;
|
mod->lib = lib;
|
||||||
ftdm_set_string(mod->path, path);
|
ftdm_set_string(mod->path, path);
|
||||||
|
@ -5583,7 +5591,7 @@ FT_DECLARE(int) ftdm_load_module(const char *name)
|
||||||
}
|
}
|
||||||
ftdm_mutex_unlock(globals.mutex);
|
ftdm_mutex_unlock(globals.mutex);
|
||||||
} else {
|
} else {
|
||||||
ftdm_log(FTDM_LOG_ERROR, "Unloading %s\n", path);
|
ftdm_log(FTDM_LOG_ERROR, "Errors during module load. Unloading %s\n", path);
|
||||||
ftdm_dso_destroy(&lib);
|
ftdm_dso_destroy(&lib);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@
|
||||||
"ftdm gsm status <span_id|span_name>\n" \
|
"ftdm gsm status <span_id|span_name>\n" \
|
||||||
"ftdm gsm sms <span_id|span_name> <destination> <text>\n" \
|
"ftdm gsm sms <span_id|span_name> <destination> <text>\n" \
|
||||||
"ftdm gsm exec <span_id|span_name> <command string>\n" \
|
"ftdm gsm exec <span_id|span_name> <command string>\n" \
|
||||||
|
"ftdm gsm call <span_id|span_name> [number]\n" \
|
||||||
"--------------------------------------------------------------------------------\n"
|
"--------------------------------------------------------------------------------\n"
|
||||||
|
|
||||||
// Used to declare command handler
|
// Used to declare command handler
|
||||||
|
@ -105,6 +106,9 @@ typedef struct ftdm_gsm_span_data_s {
|
||||||
ftdm_channel_t *bchan;
|
ftdm_channel_t *bchan;
|
||||||
int32_t call_id;
|
int32_t call_id;
|
||||||
uint32_t sms_id;
|
uint32_t sms_id;
|
||||||
|
char conditional_forward_number[255];
|
||||||
|
ftdm_sched_t *sched;
|
||||||
|
ftdm_timer_id_t conditional_forwarding_timer;
|
||||||
} ftdm_gsm_span_data_t;
|
} ftdm_gsm_span_data_t;
|
||||||
|
|
||||||
// command handler function type.
|
// command handler function type.
|
||||||
|
@ -200,8 +204,46 @@ int on_wat_span_write(unsigned char span_id, void *buffer, unsigned len)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ftdm_gsm_make_raw_call(ftdm_gsm_span_data_t *gsm_data, const char *number)
|
||||||
|
{
|
||||||
|
wat_con_event_t con_event;
|
||||||
|
|
||||||
|
ftdm_channel_lock(gsm_data->bchan);
|
||||||
|
|
||||||
|
if (ftdm_test_flag(gsm_data->bchan, FTDM_CHANNEL_INUSE)) {
|
||||||
|
ftdm_log_chan(gsm_data->bchan, FTDM_LOG_ERROR, "Failed to place raw call to %s: channel busy\n", number);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
ftdm_log_chan(gsm_data->bchan, FTDM_LOG_INFO, "Placing raw call to %s\n", number);
|
||||||
|
ftdm_set_flag(gsm_data->bchan, FTDM_CHANNEL_INUSE);
|
||||||
|
|
||||||
|
gsm_data->call_id = g_outbound_call_id++;
|
||||||
|
memset(&con_event, 0, sizeof(con_event));
|
||||||
|
ftdm_set_string(con_event.called_num.digits, number);
|
||||||
|
wat_con_req(gsm_data->span->span_id, gsm_data->call_id , &con_event);
|
||||||
|
|
||||||
|
done:
|
||||||
|
ftdm_channel_unlock(gsm_data->bchan);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ftdm_gsm_enable_conditional_forwarding(void *data)
|
||||||
|
{
|
||||||
|
ftdm_gsm_span_data_t *gsm_data = data;
|
||||||
|
ftdm_log_chan(gsm_data->bchan, FTDM_LOG_NOTICE, "Enabling conditional forwarding to %s\n", gsm_data->conditional_forward_number);
|
||||||
|
ftdm_gsm_make_raw_call(data, gsm_data->conditional_forward_number);
|
||||||
|
}
|
||||||
|
|
||||||
static void on_wat_span_status(unsigned char span_id, wat_span_status_t *status)
|
static void on_wat_span_status(unsigned char span_id, wat_span_status_t *status)
|
||||||
{
|
{
|
||||||
|
ftdm_span_t *span = NULL;
|
||||||
|
ftdm_gsm_span_data_t *gsm_data = NULL;
|
||||||
|
if (!(span = GetSpanByID(span_id, &gsm_data))) {
|
||||||
|
ftdm_log(FTDM_LOG_ERROR, "Failed to get span from id %d\n", span_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gsm_data = span->signal_data;
|
||||||
|
|
||||||
switch (status->type) {
|
switch (status->type) {
|
||||||
case WAT_SPAN_STS_READY:
|
case WAT_SPAN_STS_READY:
|
||||||
{
|
{
|
||||||
|
@ -211,9 +253,15 @@ static void on_wat_span_status(unsigned char span_id, wat_span_status_t *status)
|
||||||
case WAT_SPAN_STS_SIGSTATUS:
|
case WAT_SPAN_STS_SIGSTATUS:
|
||||||
{
|
{
|
||||||
if (status->sts.sigstatus == WAT_SIGSTATUS_UP) {
|
if (status->sts.sigstatus == WAT_SIGSTATUS_UP) {
|
||||||
ftdm_log(FTDM_LOG_INFO, "span %d: Signaling is now up\n", span_id);
|
ftdm_log_chan_msg(gsm_data->bchan, FTDM_LOG_INFO, "Signaling is now up\n");
|
||||||
} else {
|
} else {
|
||||||
ftdm_log(FTDM_LOG_INFO, "span %d: Signaling is now down\n", span_id);
|
ftdm_log_chan_msg(gsm_data->bchan, FTDM_LOG_INFO, "Signaling is now down\n");
|
||||||
|
}
|
||||||
|
if (!ftdm_strlen_zero_buf(gsm_data->conditional_forward_number)) {
|
||||||
|
ftdm_sched_timer(gsm_data->sched, "conditional_forwarding_delay", 500,
|
||||||
|
ftdm_gsm_enable_conditional_forwarding,
|
||||||
|
gsm_data,
|
||||||
|
&gsm_data->conditional_forwarding_timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -309,33 +357,34 @@ void on_wat_con_sts(unsigned char span_id, uint8_t call_id, wat_con_status_t *st
|
||||||
{
|
{
|
||||||
|
|
||||||
ftdm_span_t *span = NULL;
|
ftdm_span_t *span = NULL;
|
||||||
|
ftdm_channel_state_t state = FTDM_CHANNEL_STATE_END;
|
||||||
//ftdm_status_t ftdm_status = FTDM_FAIL;
|
//ftdm_status_t ftdm_status = FTDM_FAIL;
|
||||||
ftdm_gsm_span_data_t *gsm_data = NULL;
|
ftdm_gsm_span_data_t *gsm_data = NULL;
|
||||||
|
|
||||||
if(!(span = GetSpanByID(span_id, &gsm_data))) {
|
if (!(span = GetSpanByID(span_id, &gsm_data))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (status->type) {
|
||||||
|
|
||||||
switch(status->type) {
|
|
||||||
|
|
||||||
case WAT_CON_STATUS_TYPE_RINGING:
|
case WAT_CON_STATUS_TYPE_RINGING:
|
||||||
ftdm_log(FTDM_LOG_INFO, "on_wat_con_sts - WAT_CON_STATUS_TYPE_RINGING\r\n");
|
ftdm_log_chan_msg(gsm_data->bchan, FTDM_LOG_INFO, "Received ringing indication\n");
|
||||||
ftdm_set_state(gsm_data->bchan, FTDM_CHANNEL_STATE_RINGING);
|
state = FTDM_CHANNEL_STATE_RINGING;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WAT_CON_STATUS_TYPE_ANSWER:
|
case WAT_CON_STATUS_TYPE_ANSWER:
|
||||||
ftdm_log(FTDM_LOG_INFO, "on_wat_con_sts - WAT_CON_STATUS_TYPE_ANSWER\r\n");
|
ftdm_log_chan_msg(gsm_data->bchan, FTDM_LOG_INFO, "Received answer indication\n");
|
||||||
ftdm_set_state(gsm_data->bchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
|
state = FTDM_CHANNEL_STATE_PROGRESS_MEDIA;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ftdm_log(FTDM_LOG_INFO, "on_wat_con_sts - Unhandled state %d\n", span_id);
|
ftdm_log_chan(gsm_data->bchan, FTDM_LOG_WARNING, "Unhandled indication status %d\n", status->type);
|
||||||
|
break;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (state != FTDM_CHANNEL_STATE_END && gsm_data->bchan->state != FTDM_CHANNEL_STATE_DOWN) {
|
||||||
return;
|
ftdm_set_state(gsm_data->bchan, state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_wat_rel_ind(unsigned char span_id, uint8_t call_id, wat_rel_event_t *rel_event)
|
void on_wat_rel_ind(unsigned char span_id, uint8_t call_id, wat_rel_event_t *rel_event)
|
||||||
|
@ -352,6 +401,8 @@ void on_wat_rel_ind(unsigned char span_id, uint8_t call_id, wat_rel_event_t *rel
|
||||||
|
|
||||||
if (gsm_data->bchan->state == FTDM_CHANNEL_STATE_HANGUP ||
|
if (gsm_data->bchan->state == FTDM_CHANNEL_STATE_HANGUP ||
|
||||||
gsm_data->bchan->state == FTDM_CHANNEL_STATE_DOWN) {
|
gsm_data->bchan->state == FTDM_CHANNEL_STATE_DOWN) {
|
||||||
|
/* this might be due to a call to enable call forwarding,
|
||||||
|
* which does not run the state machine */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,7 +417,13 @@ void on_wat_rel_cfm(unsigned char span_id, uint8_t call_id)
|
||||||
|
|
||||||
ftdm_log(FTDM_LOG_INFO, "s%d: Call hangup complete (id:%d)\n", span_id, call_id);
|
ftdm_log(FTDM_LOG_INFO, "s%d: Call hangup complete (id:%d)\n", span_id, call_id);
|
||||||
|
|
||||||
if(!(span = GetSpanByID(span_id, &gsm_data))) {
|
if (!(span = GetSpanByID(span_id, &gsm_data))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gsm_data->bchan->state == FTDM_CHANNEL_STATE_DOWN) {
|
||||||
|
/* this is most likely a call forwarding enable call, which do not run the state machine */
|
||||||
|
ftdm_clear_flag(gsm_data->bchan, FTDM_CHANNEL_INUSE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,7 +435,6 @@ void on_wat_rel_cfm(unsigned char span_id, uint8_t call_id)
|
||||||
ftdm_set_state(gsm_data->bchan, FTDM_CHANNEL_STATE_DOWN);
|
ftdm_set_state(gsm_data->bchan, FTDM_CHANNEL_STATE_DOWN);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_wat_sms_ind(unsigned char span_id, wat_sms_event_t *sms_event)
|
void on_wat_sms_ind(unsigned char span_id, wat_sms_event_t *sms_event)
|
||||||
|
@ -528,7 +584,6 @@ static ftdm_status_t ftdm_gsm_start(ftdm_span_t *span)
|
||||||
ftdm_log(FTDM_LOG_ERROR, "Failed to start span %s!\n", span->name);
|
ftdm_log(FTDM_LOG_ERROR, "Failed to start span %s!\n", span->name);
|
||||||
return FTDM_FAIL;
|
return FTDM_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ftdm_thread_create_detached(ftdm_gsm_run, span);
|
return ftdm_thread_create_detached(ftdm_gsm_run, span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,6 +596,17 @@ static ftdm_status_t ftdm_gsm_stop(ftdm_span_t *span)
|
||||||
return FTDM_SUCCESS;
|
return FTDM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ftdm_status_t ftdm_gsm_destroy(ftdm_span_t *span)
|
||||||
|
{
|
||||||
|
ftdm_gsm_span_data_t *gsm_data = span->signal_data;
|
||||||
|
ftdm_assert_return(gsm_data != NULL, FTDM_FAIL, "Span does not have GSM data!\n");
|
||||||
|
if (gsm_data->sched) {
|
||||||
|
ftdm_sched_destroy(&gsm_data->sched);
|
||||||
|
}
|
||||||
|
ftdm_free(gsm_data);
|
||||||
|
return FTDM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_gsm_get_channel_sig_status)
|
static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_gsm_get_channel_sig_status)
|
||||||
{
|
{
|
||||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
|
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
|
||||||
|
@ -898,6 +964,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling)
|
||||||
unsigned paramindex = 0;
|
unsigned paramindex = 0;
|
||||||
const char *var = NULL;
|
const char *var = NULL;
|
||||||
const char *val = NULL;
|
const char *val = NULL;
|
||||||
|
char schedname[255];
|
||||||
|
|
||||||
int codec = FTDM_CODEC_SLIN;
|
int codec = FTDM_CODEC_SLIN;
|
||||||
int interval = 20;
|
int interval = 20;
|
||||||
|
@ -993,6 +1060,8 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling)
|
||||||
span_config.hardware_dtmf = WAT_FALSE;
|
span_config.hardware_dtmf = WAT_FALSE;
|
||||||
}
|
}
|
||||||
ftdm_log(FTDM_LOG_DEBUG, "Configuring GSM span %s with hardware dtmf %s\n", span->name, val);
|
ftdm_log(FTDM_LOG_DEBUG, "Configuring GSM span %s with hardware dtmf %s\n", span->name, val);
|
||||||
|
} else if (!strcasecmp(var, "conditional-forwarding-number")) {
|
||||||
|
ftdm_set_string(gsm_data->conditional_forward_number, val);
|
||||||
} else {
|
} else {
|
||||||
ftdm_log(FTDM_LOG_ERROR, "Ignoring unknown GSM parameter '%s'", var);
|
ftdm_log(FTDM_LOG_ERROR, "Ignoring unknown GSM parameter '%s'", var);
|
||||||
}
|
}
|
||||||
|
@ -1001,6 +1070,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling)
|
||||||
/* Bind function pointers for control operations */
|
/* Bind function pointers for control operations */
|
||||||
span->start = ftdm_gsm_start;
|
span->start = ftdm_gsm_start;
|
||||||
span->stop = ftdm_gsm_stop;
|
span->stop = ftdm_gsm_stop;
|
||||||
|
span->destroy = ftdm_gsm_destroy;
|
||||||
span->sig_read = NULL;
|
span->sig_read = NULL;
|
||||||
span->sig_write = NULL;
|
span->sig_write = NULL;
|
||||||
if (hwdtmf_detect || hwdtmf_generate) {
|
if (hwdtmf_detect || hwdtmf_generate) {
|
||||||
|
@ -1033,8 +1103,18 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_gsm_configure_span_signaling)
|
||||||
|
|
||||||
gsm_data->span = span;
|
gsm_data->span = span;
|
||||||
|
|
||||||
|
/* Setup the scheduler */
|
||||||
|
snprintf(schedname, sizeof(schedname), "ftmod_gsm_%s", span->name);
|
||||||
|
if (ftdm_sched_create(&gsm_data->sched, schedname) != FTDM_SUCCESS) {
|
||||||
|
ftdm_log(FTDM_LOG_ERROR, "Failed to setup scheduler for span %s!\n", span->name);
|
||||||
|
ftdm_gsm_destroy(span);
|
||||||
|
return FTDM_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start the signaling stack */
|
||||||
if (wat_span_config(span->span_id, &span_config)) {
|
if (wat_span_config(span->span_id, &span_config)) {
|
||||||
ftdm_log(FTDM_LOG_ERROR, "Failed to configure span %s for GSM signaling!!\n", span->name);
|
ftdm_log(FTDM_LOG_ERROR, "Failed to configure span %s for GSM signaling!!\n", span->name);
|
||||||
|
ftdm_gsm_destroy(span);
|
||||||
return FTDM_FAIL;
|
return FTDM_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1057,11 +1137,10 @@ static void *ftdm_gsm_run(ftdm_thread_t *me, void *obj)
|
||||||
ftdm_status_t status = FTDM_SUCCESS;
|
ftdm_status_t status = FTDM_SUCCESS;
|
||||||
char buffer[1025] = { 0 };
|
char buffer[1025] = { 0 };
|
||||||
int waitms = 0;
|
int waitms = 0;
|
||||||
|
ftdm_wait_flag_t flags = 0;
|
||||||
|
ftdm_status_t status;
|
||||||
|
|
||||||
ftdm_log(FTDM_LOG_INFO,"ftdm_gsm_run\r\n");
|
|
||||||
|
|
||||||
gsm_data = span->signal_data;
|
gsm_data = span->signal_data;
|
||||||
|
|
||||||
ftdm_assert_return(gsm_data != NULL, NULL, "No gsm data attached to span\n");
|
ftdm_assert_return(gsm_data != NULL, NULL, "No gsm data attached to span\n");
|
||||||
|
|
||||||
ftdm_log(FTDM_LOG_DEBUG, "GSM monitor thread for span %s started\n", span->name);
|
ftdm_log(FTDM_LOG_DEBUG, "GSM monitor thread for span %s started\n", span->name);
|
||||||
|
@ -1073,6 +1152,7 @@ static void *ftdm_gsm_run(ftdm_thread_t *me, void *obj)
|
||||||
|
|
||||||
while (ftdm_running()) {
|
while (ftdm_running()) {
|
||||||
wat_span_run(span->span_id);
|
wat_span_run(span->span_id);
|
||||||
|
ftdm_sched_run(gsm_data->sched);
|
||||||
|
|
||||||
waitms = wat_span_schedule_next(span->span_id);
|
waitms = wat_span_schedule_next(span->span_id);
|
||||||
if (waitms > GSM_POLL_INTERVAL_MS) {
|
if (waitms > GSM_POLL_INTERVAL_MS) {
|
||||||
|
@ -1123,25 +1203,14 @@ static FIO_IO_LOAD_FUNCTION(ftdm_gsm_io_init)
|
||||||
|
|
||||||
return (FTDM_SUCCESS);
|
return (FTDM_SUCCESS);
|
||||||
}
|
}
|
||||||
static FIO_SIG_LOAD_FUNCTION(ftdm_gsm_init)
|
|
||||||
{
|
|
||||||
/* this is called on module load */
|
|
||||||
return FTDM_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FIO_SIG_UNLOAD_FUNCTION(ftdm_gsm_destroy)
|
|
||||||
{
|
|
||||||
/* this is called on module unload */
|
|
||||||
return FTDM_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
EX_DECLARE_DATA ftdm_module_t ftdm_module = {
|
EX_DECLARE_DATA ftdm_module_t ftdm_module = {
|
||||||
/* .name */ "gsm",
|
/* .name */ "gsm",
|
||||||
/* .io_load */ ftdm_gsm_io_init,
|
/* .io_load */ ftdm_gsm_io_init,
|
||||||
/* .io_unload */ NULL,
|
/* .io_unload */ NULL,
|
||||||
/* .sig_load */ ftdm_gsm_init,
|
/* .sig_load */ NULL,
|
||||||
/* .sig_configure */ NULL,
|
/* .sig_configure */ NULL,
|
||||||
/* .sig_unload */ ftdm_gsm_destroy,
|
/* .sig_unload */ NULL,
|
||||||
/* .configure_span_signaling */ ftdm_gsm_configure_span_signaling
|
/* .configure_span_signaling */ ftdm_gsm_configure_span_signaling
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1317,12 +1386,12 @@ COMMAND_HANDLER(exec)
|
||||||
|
|
||||||
span_id = atoi(argv[0]);
|
span_id = atoi(argv[0]);
|
||||||
if (ftdm_span_find_by_name(argv[0], &span) != FTDM_SUCCESS && ftdm_span_find(span_id, &span) != FTDM_SUCCESS) {
|
if (ftdm_span_find_by_name(argv[0], &span) != FTDM_SUCCESS && ftdm_span_find(span_id, &span) != FTDM_SUCCESS) {
|
||||||
stream->write_function(stream, "-ERR Failed to find GSM span '%s'\n", argv[1]);
|
stream->write_function(stream, "-ERR Failed to find GSM span '%s'\n", argv[0]);
|
||||||
return FTDM_FAIL;
|
return FTDM_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!span || !span->signal_data || (span->start != ftdm_gsm_start)) {
|
if (!span || !span->signal_data || (span->start != ftdm_gsm_start)) {
|
||||||
stream->write_function(stream, "-ERR '%s' is not a valid GSM span\n", argv[1]);
|
stream->write_function(stream, "-ERR '%s' is not a valid GSM span\n", argv[0]);
|
||||||
return FTDM_FAIL;
|
return FTDM_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1345,6 +1414,28 @@ COMMAND_HANDLER(exec)
|
||||||
return FTDM_SUCCESS;
|
return FTDM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AT Command Handler
|
||||||
|
COMMAND_HANDLER(call)
|
||||||
|
{
|
||||||
|
int span_id = 0;
|
||||||
|
ftdm_span_t *span = NULL;
|
||||||
|
|
||||||
|
span_id = atoi(argv[0]);
|
||||||
|
if (ftdm_span_find_by_name(argv[0], &span) != FTDM_SUCCESS && ftdm_span_find(span_id, &span) != FTDM_SUCCESS) {
|
||||||
|
stream->write_function(stream, "-ERR Failed to find GSM span '%s'\n", argv[0]);
|
||||||
|
return FTDM_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!span || !span->signal_data || (span->start != ftdm_gsm_start)) {
|
||||||
|
stream->write_function(stream, "-ERR '%s' is not a valid GSM span\n", argv[0]);
|
||||||
|
return FTDM_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ftdm_gsm_make_raw_call(span->signal_data, argv[1]);
|
||||||
|
stream->write_function(stream, "+OK\n");
|
||||||
|
return FTDM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
// command map
|
// command map
|
||||||
struct {
|
struct {
|
||||||
const char*CMD; // command
|
const char*CMD; // command
|
||||||
|
@ -1355,7 +1446,8 @@ struct {
|
||||||
COMMAND(version, 0),
|
COMMAND(version, 0),
|
||||||
COMMAND(status, 1),
|
COMMAND(status, 1),
|
||||||
COMMAND(sms, 3),
|
COMMAND(sms, 3),
|
||||||
COMMAND(exec, 2)
|
COMMAND(exec, 2),
|
||||||
|
COMMAND(call, 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Commnand API entry point
|
// Commnand API entry point
|
||||||
|
|
|
@ -512,6 +512,7 @@ struct ftdm_span {
|
||||||
fio_channel_request_t channel_request;
|
fio_channel_request_t channel_request;
|
||||||
ftdm_span_start_t start;
|
ftdm_span_start_t start;
|
||||||
ftdm_span_stop_t stop;
|
ftdm_span_stop_t stop;
|
||||||
|
ftdm_span_destroy_t destroy;
|
||||||
ftdm_channel_sig_read_t sig_read;
|
ftdm_channel_sig_read_t sig_read;
|
||||||
ftdm_channel_sig_write_t sig_write;
|
ftdm_channel_sig_write_t sig_write;
|
||||||
ftdm_channel_sig_dtmf_t sig_queue_dtmf;
|
ftdm_channel_sig_dtmf_t sig_queue_dtmf;
|
||||||
|
|
|
@ -348,6 +348,7 @@ typedef struct ftdm_bitstream ftdm_bitstream_t;
|
||||||
typedef struct ftdm_fsk_modulator ftdm_fsk_modulator_t;
|
typedef struct ftdm_fsk_modulator ftdm_fsk_modulator_t;
|
||||||
typedef ftdm_status_t (*ftdm_span_start_t)(ftdm_span_t *span);
|
typedef ftdm_status_t (*ftdm_span_start_t)(ftdm_span_t *span);
|
||||||
typedef ftdm_status_t (*ftdm_span_stop_t)(ftdm_span_t *span);
|
typedef ftdm_status_t (*ftdm_span_stop_t)(ftdm_span_t *span);
|
||||||
|
typedef ftdm_status_t (*ftdm_span_destroy_t)(ftdm_span_t *span);
|
||||||
typedef ftdm_status_t (*ftdm_channel_sig_read_t)(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t size);
|
typedef ftdm_status_t (*ftdm_channel_sig_read_t)(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t size);
|
||||||
typedef ftdm_status_t (*ftdm_channel_sig_write_t)(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t size);
|
typedef ftdm_status_t (*ftdm_channel_sig_write_t)(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t size);
|
||||||
typedef ftdm_status_t (*ftdm_channel_sig_dtmf_t)(ftdm_channel_t *ftdmchan, const char *dtmf);
|
typedef ftdm_status_t (*ftdm_channel_sig_dtmf_t)(ftdm_channel_t *ftdmchan, const char *dtmf);
|
||||||
|
|
Loading…
Reference in New Issue