]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
freetdm: fix call id generation
authorMoises Silva <moy@sangoma.com>
Wed, 22 Dec 2010 00:04:41 +0000 (19:04 -0500)
committerMoises Silva <moy@sangoma.com>
Wed, 22 Dec 2010 00:04:41 +0000 (19:04 -0500)
libs/freetdm/src/ftdm_io.c
libs/freetdm/src/include/freetdm.h

index 955729df363d7c07ff2ca7ad5dd72835c7057eaf..b8124147e9b77187fb94883070a51ed19940a1cd 100644 (file)
@@ -63,7 +63,7 @@ ftdm_time_t time_last_throttle_log = 0;
 ftdm_time_t time_current_throttle_log = 0;
 
 static ftdm_iterator_t *get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t *iter);
-static ftdm_status_t ftdm_call_set_call_id(ftdm_caller_data_t *caller_data);
+static ftdm_status_t ftdm_call_set_call_id(ftdm_channel_t *fchan, ftdm_caller_data_t *caller_data);
 static ftdm_status_t ftdm_call_clear_call_id(ftdm_caller_data_t *caller_data);
 static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan);
 static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan);
@@ -2522,7 +2522,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char
 
        if (status == FTDM_SUCCESS) {
                ftdm_set_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED);
-               ftdm_call_set_call_id(&ftdmchan->caller_data);
+               ftdm_call_set_call_id(ftdmchan, &ftdmchan->caller_data);
                ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 100);
        }
 
@@ -2606,10 +2606,11 @@ FT_DECLARE(ftdm_status_t) ftdm_span_get_sig_status(ftdm_span_t *span, ftdm_signa
        }
 }
 
+/* this function must be called with the channel lock */
 static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan)
 {
        ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel can't be done!\n");
-       ftdm_mutex_lock(ftdmchan->mutex);
+
        ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OPEN);
        ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
        ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
@@ -2694,7 +2695,6 @@ static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan)
                ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE);
        }
        ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "channel done\n");
-       ftdm_mutex_unlock(ftdmchan->mutex);
        return FTDM_SUCCESS;
 }
 
@@ -4397,6 +4397,16 @@ static void print_channels_by_state(ftdm_stream_handle_t *stream, ftdm_channel_s
        ftdm_mutex_unlock(globals.mutex);
 }
 
+static void print_core_usage(ftdm_stream_handle_t *stream)
+{
+       stream->write_function(stream, 
+       "--------------------------------------------------------------------------------\n"
+       "ftdm core state [!]<state_name> - List all channels in or not in the given state\n"
+       "ftdm core flag <flag-int-value> - List all channels with the fiven flag value set\n"
+       "ftdm core calls - List all known calls to the FreeTDM core\n"
+       "--------------------------------------------------------------------------------\n");
+}
+
 static char *handle_core_command(const char *cmd)
 {
        char *mycmd = NULL;
@@ -4407,22 +4417,31 @@ static char *handle_core_command(const char *cmd)
        char *state = NULL;
        char *flag = NULL;
        uint32_t flagval = 0;
+       uint32_t current_call_id = 0;
+       ftdm_caller_data_t *calldata = NULL;
+       ftdm_channel_t *fchan = NULL;
        ftdm_channel_state_t i = FTDM_CHANNEL_STATE_INVALID;
        ftdm_stream_handle_t stream = { 0 };
 
        FTDM_STANDARD_STREAM(stream);
 
-       if (cmd) {
+       if (cmd && strlen(cmd)) {
                mycmd = ftdm_strdup(cmd);
                argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
        } else {
-               stream.write_function(&stream, "invalid core command\n");
+               print_core_usage(&stream);
+               goto done;
+       }
+
+       if (!argc) {
+               print_core_usage(&stream);
                goto done;
        }
 
        if (!strcasecmp(argv[0], "state")) {
                if (argc < 2) {
                        stream.write_function(&stream, "core state command requires an argument\n");
+                       print_core_usage(&stream);
                        goto done;
                }
                state = argv[1];
@@ -4443,7 +4462,8 @@ static char *handle_core_command(const char *cmd)
                stream.write_function(&stream, "\nTotal channels %s %s: %d\n", not ? "not in state" : "in state", ftdm_channel_state2str(i), count);
        } else if (!strcasecmp(argv[0], "flag")) {
                if (argc < 2) {
-                       stream.write_function(&stream, "core state command requires an argument\n");
+                       stream.write_function(&stream, "core flag command requires an argument\n");
+                       print_core_usage(&stream);
                        goto done;
                }
                flag = argv[1];
@@ -4454,8 +4474,28 @@ static char *handle_core_command(const char *cmd)
                flagval = atoi(flag);
                print_channels_by_flag(&stream, flagval, not, &count);
                stream.write_function(&stream, "\nTotal channels %s %d: %d\n", not ? "without flag" : "with flag", flagval, count);
+       } else if (!strcasecmp(argv[0], "calls")) {
+               ftdm_mutex_lock(globals.call_id_mutex);
+               current_call_id = globals.last_call_id;
+               for (current_call_id = 0; current_call_id <= MAX_CALLIDS; current_call_id++) {
+                       if (!globals.call_ids[current_call_id]) {
+                               continue;
+                       }
+                       calldata = globals.call_ids[current_call_id];
+                       fchan = calldata->fchan;
+                       if (fchan) {
+                               stream.write_function(&stream, "Call %d on channel %d:%d\n", current_call_id, 
+                                               fchan->span_id, fchan->chan_id);
+                       } else {
+                               stream.write_function(&stream, "Call %d without a channel?\n", current_call_id);
+                       }
+                       count++;
+               }
+               ftdm_mutex_unlock(globals.call_id_mutex);
+               stream.write_function(&stream, "\nTotal calls: %d\n", count);
        } else {
                stream.write_function(&stream, "invalid core command %s\n", argv[0]);
+               print_core_usage(&stream);
        }
 
 done:
@@ -4475,6 +4515,8 @@ FT_DECLARE(char *) ftdm_api_execute(const char *cmd)
        if ((p = strchr(dup, ' '))) {
                *p++ = '\0';
                cmd = p;
+       } else {
+               cmd = "";
        }
 
        type = dup;
@@ -5447,7 +5489,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
        case FTDM_SIGEVENT_START:
                {
                        ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED);
-                       ftdm_call_set_call_id(&sigmsg->channel->caller_data);
+                       ftdm_call_set_call_id(sigmsg->channel, &sigmsg->channel->caller_data);
                        ftdm_set_echocancel_call_begin(sigmsg->channel);
                        if (sigmsg->channel->dtmfdbg.requested) {
                                ftdm_channel_command(sigmsg->channel, FTDM_COMMAND_ENABLE_DEBUG_DTMF, NULL);
@@ -6089,27 +6131,35 @@ FT_DECLARE(char *) ftdm_channel_get_history_str(const ftdm_channel_t *fchan)
        return stream.data;
 }
 
-static ftdm_status_t ftdm_call_set_call_id(ftdm_caller_data_t *caller_data)
+static ftdm_status_t ftdm_call_set_call_id(ftdm_channel_t *fchan, ftdm_caller_data_t *caller_data)
 {
        uint32_t current_call_id;
-       ftdm_assert_return(!caller_data->call_id, FTDM_FAIL, "Overwriting non-cleared call-id");
+       
+       ftdm_assert_return(!caller_data->call_id, FTDM_FAIL, "Overwriting non-cleared call-id\n");
 
        ftdm_mutex_lock(globals.call_id_mutex);
+
        current_call_id = globals.last_call_id;
 
-       do {
-               if (++current_call_id > MAX_CALLIDS) {
+       for (current_call_id = globals.last_call_id + 1; 
+            current_call_id != globals.last_call_id; 
+            current_call_id++ ) {
+               if (current_call_id > MAX_CALLIDS) {
                        current_call_id = 1;
                }
-               if (globals.call_ids[current_call_id] != NULL) {
-                       continue;
+               if (globals.call_ids[current_call_id] == NULL) {
+                       break;
                }
-       } while (0);
+       }
+
+       ftdm_assert_return(globals.call_ids[current_call_id] == NULL, FTDM_FAIL, "We ran out of call ids\n"); 
 
        globals.last_call_id = current_call_id;
        caller_data->call_id = current_call_id;
 
        globals.call_ids[current_call_id] = caller_data;
+       caller_data->fchan = fchan;
+
        ftdm_mutex_unlock(globals.call_id_mutex);
        return FTDM_SUCCESS;
 }
@@ -6126,8 +6176,8 @@ static ftdm_status_t ftdm_call_clear_call_id(ftdm_caller_data_t *caller_data)
        ftdm_mutex_lock(globals.call_id_mutex);
        if (globals.call_ids[caller_data->call_id]) {
                ftdm_log(FTDM_LOG_DEBUG, "Cleared call with id %u\n", caller_data->call_id);
-               caller_data->call_id = 0;
                globals.call_ids[caller_data->call_id] = NULL;
+               caller_data->call_id = 0;
        } else {
                ftdm_log(FTDM_LOG_CRIT, "call-id did not exist %u\n", caller_data->call_id);
        } 
index dfb3f1fc029145b8e828279ea9715b9a1777a640..d27353ddb0d413959ecc39c0ee316cefe22861f6 100644 (file)
@@ -320,6 +320,7 @@ typedef struct ftdm_caller_data {
         * that the user can use caller_data.call_id to obtain the call_id. The user
         * should use the call_id from sigmsg otherwise */
        uint32_t call_id; /*!< Unique call ID for this call */
+       ftdm_channel_t *fchan; /*!< FreeTDM channel associated (can be NULL) */
 } ftdm_caller_data_t;
 
 /*! \brief Tone type */