diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 890d9d9d43..0117fcedf1 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -40,7 +40,7 @@ #define FREETDM_LIMIT_REALM "__freetdm" #define FREETDM_VAR_PREFIX "freetdm_" -#define FREETDM_VAR_PREFIX_LEN 8 +#define FREETDM_VAR_PREFIX_LEN (sizeof(FREETDM_VAR_PREFIX)-1) SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_freetdm_shutdown); @@ -1302,11 +1302,14 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi } } - ftdm_channel_clear_vars(ftdmchan); + span_id = ftdm_channel_get_span_id(ftdmchan); + chan_id = ftdm_channel_get_id(ftdmchan); + for (h = var_event->headers; h; h = h->next) { if (!strncasecmp(h->name, FREETDM_VAR_PREFIX, FREETDM_VAR_PREFIX_LEN)) { char *v = h->name + FREETDM_VAR_PREFIX_LEN; if (!zstr(v)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding outbound freetdm variable %s=%s to channel %d:%d\n", v, h->value, span_id, chan_id); ftdm_channel_add_var(ftdmchan, v, h->value); } } @@ -1317,9 +1320,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi switch_caller_profile_t *caller_profile; switch_channel_t *channel = switch_core_session_get_channel(*new_session); - span_id = ftdm_channel_get_span_id(ftdmchan); - chan_id = ftdm_channel_get_id(ftdmchan); - switch_core_session_add_stream(*new_session, NULL); if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) { tech_init(tech_pvt, *new_session, ftdmchan); @@ -1403,6 +1403,9 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session switch_core_session_t *session = NULL; private_t *tech_pvt = NULL; switch_channel_t *channel = NULL; + ftdm_iterator_t *iter = NULL; + const char *var_name = NULL; + const char *var_value = NULL; uint32_t spanid, chanid; char name[128]; ftdm_caller_data_t *channel_caller_data = ftdm_channel_get_caller_data(sigmsg->channel); @@ -1511,6 +1514,13 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session if (channel_caller_data->raw_data_len) { switch_channel_set_variable_printf(channel, "freetdm_custom_call_data", "%s", channel_caller_data->raw_data); } + /* Add any channel variable to the dial plan */ + iter = ftdm_channel_get_var_iterator(sigmsg->channel); + for ( ; iter; iter = ftdm_iterator_next(iter)) { + ftdm_channel_get_current_var(iter, &var_name, &var_value); + snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name); + switch_channel_set_variable_printf(channel, name, "%s", var_value); + } switch_channel_set_state(channel, CS_INIT); if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) { diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 238a9fc060..b087881e1d 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -400,8 +400,6 @@ static ftdm_status_t ftdm_channel_destroy(ftdm_channel_t *ftdmchan) ftdm_buffer_destroy(&ftdmchan->fsk_buffer); ftdmchan->pre_buffer_size = 0; - hashtable_destroy(ftdmchan->variable_hash); - ftdm_safe_free(ftdmchan->dtmf_hangup_buf); if (ftdmchan->tone_session.buffer) { @@ -812,7 +810,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_add_channel(ftdm_span_t *span, ftdm_socket_t ftdm_buffer_create(&new_chan->digit_buffer, 128, 128, 0); ftdm_buffer_create(&new_chan->gen_dtmf_buffer, 128, 128, 0); - new_chan->variable_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); new_chan->dtmf_hangup_buf = ftdm_calloc (span->dtmf_hangup_len + 1, sizeof (char)); @@ -2213,9 +2210,10 @@ static void close_dtmf_debug(ftdm_channel_t *ftdmchan) } #endif +static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan); FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan) { - assert(ftdmchan != NULL); + ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel can't be done!\n"); ftdm_mutex_lock(ftdmchan->mutex); @@ -2243,6 +2241,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan) #ifdef FTDM_DEBUG_DTMF close_dtmf_debug(ftdmchan); #endif + ftdm_channel_clear_vars(ftdmchan); ftdmchan->init_state = FTDM_CHANNEL_STATE_DOWN; ftdmchan->state = FTDM_CHANNEL_STATE_DOWN; @@ -3368,8 +3367,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat ftdm_size_t max = datasize; unsigned int i = 0; - assert(ftdmchan != NULL); - assert(ftdmchan->fio != NULL); + ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel on write!\n"); + ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "null I/O on write!\n"); if (!ftdmchan->buffer_delay && ((ftdmchan->dtmf_buffer && ftdm_buffer_inuse(ftdmchan->dtmf_buffer)) || @@ -3421,16 +3420,16 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat return status; } -FT_DECLARE(ftdm_status_t) ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan) +static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan) { - if(ftdmchan->variable_hash) { + ftdm_channel_lock(ftdmchan); + + if (ftdmchan->variable_hash) { hashtable_destroy(ftdmchan->variable_hash); } - ftdmchan->variable_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); + ftdmchan->variable_hash = NULL; - if(!ftdmchan->variable_hash) - return FTDM_FAIL; - + ftdm_channel_unlock(ftdmchan); return FTDM_SUCCESS; } @@ -3438,34 +3437,98 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_add_var(ftdm_channel_t *ftdmchan, const c { char *t_name = 0, *t_val = 0; - if(!ftdmchan->variable_hash || !var_name || !value) - { + ftdm_status_t status = FTDM_FAIL; + + if (!var_name || !value) { return FTDM_FAIL; } + ftdm_channel_lock(ftdmchan); + + if (!ftdmchan->variable_hash) { + /* initialize on first use */ + ftdmchan->variable_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); + if (!ftdmchan->variable_hash) { + goto done; + } + } + t_name = ftdm_strdup(var_name); t_val = ftdm_strdup(value); - if(hashtable_insert(ftdmchan->variable_hash, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE)) { - return FTDM_SUCCESS; - } - return FTDM_FAIL; + hashtable_insert(ftdmchan->variable_hash, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE); + + status = FTDM_SUCCESS; + +done: + ftdm_channel_unlock(ftdmchan); + + return status; } FT_DECLARE(const char *) ftdm_channel_get_var(ftdm_channel_t *ftdmchan, const char *var_name) { - if(!ftdmchan->variable_hash || !var_name) - { + const char *var = NULL; + + ftdm_channel_lock(ftdmchan); + + if (!ftdmchan->variable_hash || !var_name) { + goto done; + } + + var = (const char *)hashtable_search(ftdmchan->variable_hash, (void *)var_name); + +done: + ftdm_channel_unlock(ftdmchan); + + return var; +} + +FT_DECLARE(ftdm_iterator_t *) ftdm_channel_get_var_iterator(const ftdm_channel_t *ftdmchan) +{ + ftdm_hash_iterator_t *iter = NULL; + + ftdm_channel_lock(ftdmchan); + + iter = ftdmchan->variable_hash == NULL ? NULL : hashtable_first(ftdmchan->variable_hash); + + ftdm_channel_unlock(ftdmchan); + + return iter; +} + +FT_DECLARE(ftdm_status_t) ftdm_channel_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val) +{ + const void *key = NULL; + void *val = NULL; + + *var_name = NULL; + *var_val = NULL; + + if (!iter) { + return FTDM_FAIL; + } + + hashtable_this(iter, &key, NULL, &val); + + *var_name = key; + *var_val = val; + + return FTDM_SUCCESS; +} + +FT_DECLARE(ftdm_iterator_t *) ftdm_iterator_next(ftdm_iterator_t *iter) +{ + if (!iter) { return NULL; } - return (const char *) hashtable_search(ftdmchan->variable_hash, (void *)var_name); + return hashtable_next(iter); } static struct { ftdm_io_interface_t *pika_interface; } interfaces; - FT_DECLARE(char *) ftdm_api_execute(const char *cmd) { ftdm_io_interface_t *fio = NULL; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index b47660b076..a98429da73 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -35,7 +35,6 @@ #include "ftmod_sangoma_isdn.h" -#define FTDM_DEBUG_CHAN_MEMORY #ifdef FTDM_DEBUG_CHAN_MEMORY #include @@ -472,7 +471,10 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) case FTDM_CHANNEL_STATE_RING: /* incoming call request */ { ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending incoming call from %s to %s to FTDM core\n", ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.dnis.digits); - + ftdm_channel_add_var(ftdmchan, "isdn_specific_var", "1"); + ftdm_channel_add_var(ftdmchan, "isdn_crap", "morecrap"); + ftdm_channel_add_var(ftdmchan, "isdn_stuff", "s"); + ftdm_channel_add_var(ftdmchan, "isdn_d", "asdsadasdasdsad"); /* we have enough information to inform FTDM of the call*/ sigev.event_id = FTDM_SIGEVENT_START; ftdm_span_send_signal(ftdmchan->span, &sigev); diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 132fd303a2..61d37c8878 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -381,6 +381,9 @@ typedef struct ftdm_conf_parameter { void *ptr; } ftdm_conf_parameter_t; +/*! \brief Opaque general purpose iterator */ +typedef void ftdm_iterator_t; + /*! \brief Channel commands that can be executed through ftdm_channel_command() */ typedef enum { FTDM_COMMAND_NOOP, @@ -1014,14 +1017,25 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data */ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t datasize, ftdm_size_t *datalen); -/*! \brief Add a custom variable to the channel */ +/*! \brief Add a custom variable to the channel + * \note This variables may be used by signaling modules to override signaling parameters + * \todo Document which signaling variables are available + * */ FT_DECLARE(ftdm_status_t) ftdm_channel_add_var(ftdm_channel_t *ftdmchan, const char *var_name, const char *value); -/*! \brief Get a custom variable from the channel */ +/*! \brief Get a custom variable from the channel. + * \note The variable pointer returned is only valid while the channel is open and it'll be destroyed when the channel is closed. */ FT_DECLARE(const char *) ftdm_channel_get_var(ftdm_channel_t *ftdmchan, const char *var_name); -/*! \brief Clear custom channel variables from the channel */ -FT_DECLARE(ftdm_status_t) ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan); +/*! \brief Get an iterator to iterate over the channel variables + * \note The iterator pointer returned is only valid while the channel is open and it'll be destroyed when the channel is closed. */ +FT_DECLARE(ftdm_iterator_t *) ftdm_channel_get_var_iterator(const ftdm_channel_t *ftdmchan); + +/*! \brief Get variable name and value for the current iterator position */ +FT_DECLARE(ftdm_status_t) ftdm_channel_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val); + +/*! \brief Advance iterator */ +FT_DECLARE(ftdm_iterator_t *) ftdm_iterator_next(ftdm_iterator_t *iter); /*! \brief Get the span pointer associated to the channel */ FT_DECLARE(ftdm_span_t *) ftdm_channel_get_span(const ftdm_channel_t *ftdmchan); diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 95f34b4dd2..eb9a84a84a 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -579,7 +579,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t * */ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, const char *dtmf); - /*! \brief Assert condition */