]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
freetdm: added channel variable iterator for signaling specific data
authorMoises Silva <moy@sangoma.com>
Wed, 1 Sep 2010 18:42:34 +0000 (14:42 -0400)
committerMoises Silva <moy@sangoma.com>
Thu, 2 Sep 2010 16:11:31 +0000 (12:11 -0400)
libs/freetdm/mod_freetdm/mod_freetdm.c
libs/freetdm/src/ftdm_io.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
libs/freetdm/src/include/freetdm.h
libs/freetdm/src/include/private/ftdm_core.h

index 890d9d9d4319a3a309885699644e8802b1f8fafc..0117fcedf15f9e11de4d30e84c886e6affe47827 100755 (executable)
@@ -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) {
index 238a9fc0609a6a8aef2689cdc1b389a706654145..b087881e1dbd9b627d7a9b2efbbdfe13dc7e184a 100644 (file)
@@ -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;
index b47660b0762a20d9fead1979ba42d7e3aaaa809a..a98429da738bf061f434e56ff56abcadccc57ff5 100644 (file)
@@ -35,7 +35,6 @@
 
 
 #include "ftmod_sangoma_isdn.h"
-#define FTDM_DEBUG_CHAN_MEMORY
 
 #ifdef FTDM_DEBUG_CHAN_MEMORY
 #include <sys/mman.h>
@@ -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);
index 132fd303a25c914b6b625b5659d4745aab607808..61d37c88781c6acdbfae9d3da73af408229eee81 100644 (file)
@@ -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);
index 95f34b4dd20be0d5da83ba6feaf8ae8d65f9f1d7..eb9a84a84ad85c66f3f94f5576837926ce86cddc 100644 (file)
@@ -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
 */