From b44bcd57637020397483b655aa35af26a3581d95 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Wed, 20 Jun 2012 16:28:00 -0400 Subject: [PATCH] Added core spanflag CLI command --- libs/freetdm/mod_freetdm/mod_freetdm.c | 3 +- libs/freetdm/src/ftdm_io.c | 271 +++++++++++++----- libs/freetdm/src/include/private/ftdm_types.h | 2 + 3 files changed, 205 insertions(+), 71 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 63abc9f284..12cb7e5ef7 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -5069,7 +5069,8 @@ static ftdm_cli_entry_t ftdm_cli_options[] = /* Fake handlers as they are handled within freetdm library, * we should provide a way inside freetdm to query for completions from signaling modules */ { "core state", "[!]", "", NULL }, - { "core flag", "[!]", "", NULL }, + { "core flag", "[!] [] []", "", NULL }, + { "core spanflag", "[!] []", "", NULL }, { "core calls", "", "", NULL }, }; diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index a9cb0b4f2a..6052971274 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -63,12 +63,78 @@ struct tm *localtime_r(const time_t *clock, struct tm *result); ftdm_time_t time_last_throttle_log = 0; ftdm_time_t time_current_throttle_log = 0; +typedef struct val_str { + const char *str; + unsigned long long val; +} val_str_t; + +static val_str_t channel_flag_strs[] = { + { "configured" , FTDM_CHANNEL_CONFIGURED}, + { "ready", FTDM_CHANNEL_READY}, + { "open", FTDM_CHANNEL_OPEN}, + { "dtmf-detect", FTDM_CHANNEL_DTMF_DETECT}, + { "suppress-dtmf", FTDM_CHANNEL_SUPRESS_DTMF}, + { "transcode", FTDM_CHANNEL_TRANSCODE}, + { "buffer", FTDM_CHANNEL_BUFFER}, + { "in-thread", FTDM_CHANNEL_INTHREAD}, + { "wink", FTDM_CHANNEL_WINK}, + { "flash", FTDM_CHANNEL_FLASH}, + { "state-change", FTDM_CHANNEL_STATE_CHANGE}, + { "hold", FTDM_CHANNEL_HOLD}, + { "in-use", FTDM_CHANNEL_INUSE}, + { "off-hook", FTDM_CHANNEL_OFFHOOK}, + { "ringing", FTDM_CHANNEL_RINGING}, + { "progress-detect", FTDM_CHANNEL_PROGRESS_DETECT}, + { "callerid-detect", FTDM_CHANNEL_CALLERID_DETECT}, + { "outbound", FTDM_CHANNEL_OUTBOUND}, + { "suspended", FTDM_CHANNEL_SUSPENDED}, + { "3-way", FTDM_CHANNEL_3WAY}, + { "progress", FTDM_CHANNEL_PROGRESS}, + { "media", FTDM_CHANNEL_MEDIA}, + { "answered", FTDM_CHANNEL_ANSWERED}, + { "mute", FTDM_CHANNEL_MUTE}, + { "use-rx-gain", FTDM_CHANNEL_USE_RX_GAIN}, + { "use-tx-gain", FTDM_CHANNEL_USE_TX_GAIN}, + { "in-alarm", FTDM_CHANNEL_IN_ALARM}, + { "sig-up", FTDM_CHANNEL_SIG_UP}, + { "user-hangup", FTDM_CHANNEL_USER_HANGUP}, + { "rx-disabled", FTDM_CHANNEL_RX_DISABLED}, + { "tx-disabled", FTDM_CHANNEL_TX_DISABLED}, + { "call-started", FTDM_CHANNEL_CALL_STARTED}, + { "non-block", FTDM_CHANNEL_NONBLOCK}, + { "ind-ack-pending", FTDM_CHANNEL_IND_ACK_PENDING}, + { "blocking", FTDM_CHANNEL_BLOCKING}, + { "media", FTDM_CHANNEL_DIGITAL_MEDIA}, + { "native-sigbridge", FTDM_CHANNEL_NATIVE_SIGBRIDGE}, + { "invalid", FTDM_CHANNEL_MAX_FLAG}, +}; + +static val_str_t span_flag_strs[] = { + { "configured", FTDM_SPAN_CONFIGURED}, + { "started", FTDM_SPAN_STARTED}, + { "state-change", FTDM_SPAN_STATE_CHANGE}, + { "suspended", FTDM_SPAN_SUSPENDED}, + { "in-thread", FTDM_SPAN_IN_THREAD}, + { "stop-thread", FTDM_SPAN_STOP_THREAD}, + { "use-chan-queue", FTDM_SPAN_USE_CHAN_QUEUE}, + { "suggest-chan-id", FTDM_SPAN_SUGGEST_CHAN_ID}, + { "use-av-rate", FTDM_SPAN_USE_AV_RATE}, + { "power-saving", FTDM_SPAN_PWR_SAVING}, + { "signals-queue", FTDM_SPAN_USE_SIGNALS_QUEUE}, + { "proceed-state", FTDM_SPAN_USE_PROCEED_STATE}, + { "skip-state", FTDM_SPAN_USE_SKIP_STATES}, + { "non-stoppable", FTDM_SPAN_NON_STOPPABLE}, + { "use-transfer", FTDM_SPAN_USE_TRANSFER}, +}; + 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_done(ftdm_channel_t *ftdmchan); static ftdm_status_t ftdm_channel_sig_indicate(ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication, ftdm_usrmsg_t *usrmsg); -static const char *channel_val2str(unsigned long long flag); -static unsigned long long channel_str2val(const char *flag_name); + +static const char *ftdm_val2str(unsigned long long val, val_str_t *val_str_table, ftdm_size_t array_size, const char *default_str); +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); + static int time_is_init = 0; @@ -1051,7 +1117,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_add_channel(ftdm_span_t *span, ftdm_socket_t i++; } - ftdm_set_flag(new_chan, FTDM_CHANNEL_CONFIGURED | FTDM_CHANNEL_READY); + ftdm_set_flag(new_chan, FTDM_CHANNEL_CONFIGURED | FTDM_CHANNEL_READY); new_chan->state = FTDM_CHANNEL_STATE_DOWN; new_chan->state_status = FTDM_STATE_STATUS_COMPLETED; *chan = new_chan; @@ -4370,28 +4436,28 @@ static void print_channels_by_flag(ftdm_stream_handle_t *stream, ftdm_span_t *in stream->write_function(stream, "[s%dc%d][%d:%d] flag !%d(!%s) ON \n", fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, - flagval, channel_val2str(flagval)); + flagval, ftdm_val2str(flag, channel_flag_strs, ftdm_array_len(channel_flag_strs), "invalid")); mycount++; } else { stream->write_function(stream, "[s%dc%d][%d:%d] flag !%d(!%s) OFF \n", fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, - flagval, channel_val2str(flagval)); + flagval, ftdm_val2str(flag, channel_flag_strs, ftdm_array_len(channel_flag_strs), "invalid")); } - } else if (!not) { + } else { if (ftdm_test_flag(fchan, flag)) { - stream->write_function(stream, "[s%dc%d][%d:%d] flag %d(%s) ON\n", + stream->write_function(stream, "[s%dc%d][%d:%d] flag %d(%s) ON\n", fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, - flagval, channel_val2str(flagval)); + flagval, ftdm_val2str(flag, channel_flag_strs, ftdm_array_len(channel_flag_strs), "invalid")); mycount++; } else { stream->write_function(stream, "[s%dc%d][%d:%d] flag %d(%s) OFF \n", fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, - flagval, channel_val2str(flagval)); + flagval, ftdm_val2str(flag, channel_flag_strs, ftdm_array_len(channel_flag_strs), "invalid")); } } } @@ -4412,16 +4478,16 @@ static void print_channels_by_flag(ftdm_stream_handle_t *stream, ftdm_span_t *in for (curr = citer ; curr; curr = ftdm_iterator_next(curr)) { fchan = ftdm_iterator_current(curr); if (not && !ftdm_test_flag(fchan, flag)) { - stream->write_function(stream, "[s%dc%d][%d:%d] has not flag %d\n", + stream->write_function(stream, "[s%dc%d][%d:%d] flag !%d(!%s)\n", fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, - flagval); + flagval, ftdm_val2str(flag, channel_flag_strs, ftdm_array_len(channel_flag_strs), "invalid")); mycount++; } else if (!not && ftdm_test_flag(fchan, flag)) { - stream->write_function(stream, "[s%dc%d][%d:%d] has flag %d\n", + stream->write_function(stream, "[s%dc%d][%d:%d] flag %d(%s)\n", fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, - flagval); + flagval, ftdm_val2str(flag, channel_flag_strs, ftdm_array_len(channel_flag_strs), "invalid")); mycount++; } } @@ -4433,6 +4499,68 @@ end: ftdm_mutex_unlock(globals.mutex); } +static void print_spans_by_flag(ftdm_stream_handle_t *stream, ftdm_span_t *inspan, int32_t flagval, int not, int *count) +{ + ftdm_hash_iterator_t *i = NULL; + ftdm_span_t *span; + const void *key = NULL; + void *val = NULL; + uint32_t flag = (1 << flagval); + int mycount = 0; + + *count = 0; + + ftdm_mutex_lock(globals.mutex); + + if (inspan) { + if (not) { + if (!ftdm_test_flag(inspan, flag)) { + stream->write_function(stream, "[s%d] flag !%d(!%s) ON \n", + inspan->span_id, + flagval, ftdm_val2str(flag, span_flag_strs, ftdm_array_len(span_flag_strs), "invalid")); + + mycount++; + } else { + stream->write_function(stream, "[s%d] flag !%d(!%s) OFF \n", + inspan->span_id, + flagval, ftdm_val2str(flag, span_flag_strs, ftdm_array_len(span_flag_strs), "invalid")); + } + } else { + if (ftdm_test_flag(inspan, flag)) { + stream->write_function(stream, "[s%d] flag %d(%s) ON \n", + inspan->span_id, + flagval, ftdm_val2str(flag, span_flag_strs, ftdm_array_len(span_flag_strs), "invalid")); + mycount++; + } else { + stream->write_function(stream, "[s%d] flag %d(%s) OFF \n", + inspan->span_id, + flagval, ftdm_val2str(flag, span_flag_strs, ftdm_array_len(span_flag_strs), "invalid")); + } + } + } else { + for (i = hashtable_first(globals.span_hash); i; i = hashtable_next(i)) { + hashtable_this(i, &key, NULL, &val); + if (!key || !val) { + break; + } + span = val; + if (not && !ftdm_test_flag(span, flag)) { + stream->write_function(stream, "[s%d] flag !%d(!%s)\n", + span->span_id, + flagval, ftdm_val2str(flag, span_flag_strs, ftdm_array_len(span_flag_strs), "invalid")); + mycount++; + } else if (!not && ftdm_test_flag(span, flag)) { + stream->write_function(stream, "[s%d] flag %d(%s)\n", + span->span_id, + flagval, ftdm_val2str(flag, span_flag_strs, ftdm_array_len(span_flag_strs), "invalid")); + mycount++; + } + } + } + *count = mycount; + ftdm_mutex_unlock(globals.mutex); +} + static void print_channels_by_state(ftdm_stream_handle_t *stream, ftdm_channel_state_t state, int not, int *count) { ftdm_hash_iterator_t *i = NULL; @@ -4483,83 +4611,47 @@ static void print_core_usage(ftdm_stream_handle_t *stream) "--------------------------------------------------------------------------------\n" "ftdm core state [!] - List all channels in or not in the given state\n" "ftdm core flag [!] [] [] - List all channels with the given flag value set\n" + "ftdm core spanflag [!] [] - List all spans with the given span flag value set\n" "ftdm core calls - List all known calls to the FreeTDM core\n" "--------------------------------------------------------------------------------\n"); } -typedef struct channel_flags_str { - const char *name; - unsigned long long channel_flag; -} channel_flag_str_t; -static channel_flag_str_t channel_flag_strs[] = { - { "configured" , FTDM_CHANNEL_CONFIGURED}, - { "ready", FTDM_CHANNEL_READY}, - { "open", FTDM_CHANNEL_OPEN}, - { "dtmf-detect", FTDM_CHANNEL_DTMF_DETECT}, - { "suppress-dtmf", FTDM_CHANNEL_SUPRESS_DTMF}, - { "transcode", FTDM_CHANNEL_TRANSCODE}, - { "buffer", FTDM_CHANNEL_BUFFER}, - { "in-thread", FTDM_CHANNEL_INTHREAD}, - { "wink", FTDM_CHANNEL_WINK}, - { "flash", FTDM_CHANNEL_FLASH}, - { "state-change", FTDM_CHANNEL_STATE_CHANGE}, - { "hold", FTDM_CHANNEL_HOLD}, - { "in-use", FTDM_CHANNEL_INUSE}, - { "off-hook", FTDM_CHANNEL_OFFHOOK}, - { "ringing", FTDM_CHANNEL_RINGING}, - { "progress-detect", FTDM_CHANNEL_PROGRESS_DETECT}, - { "callerid-detect", FTDM_CHANNEL_CALLERID_DETECT}, - { "outbound", FTDM_CHANNEL_OUTBOUND}, - { "suspended", FTDM_CHANNEL_SUSPENDED}, - { "3-way", FTDM_CHANNEL_3WAY}, - { "progress", FTDM_CHANNEL_PROGRESS}, - { "media", FTDM_CHANNEL_MEDIA}, - { "answered", FTDM_CHANNEL_ANSWERED}, - { "mute", FTDM_CHANNEL_MUTE}, - { "use-rx-gain", FTDM_CHANNEL_USE_RX_GAIN}, - { "use-tx-gain", FTDM_CHANNEL_USE_TX_GAIN}, - { "in-alarm", FTDM_CHANNEL_IN_ALARM}, - { "sig-up", FTDM_CHANNEL_SIG_UP}, - { "user-hangup", FTDM_CHANNEL_USER_HANGUP}, - { "rx-disabled", FTDM_CHANNEL_RX_DISABLED}, - { "tx-disabled", FTDM_CHANNEL_TX_DISABLED}, - { "call-started", FTDM_CHANNEL_CALL_STARTED}, - { "non-block", FTDM_CHANNEL_NONBLOCK}, - { "ind-ack-pending", FTDM_CHANNEL_IND_ACK_PENDING}, - { "blocking", FTDM_CHANNEL_BLOCKING}, - { "media", FTDM_CHANNEL_DIGITAL_MEDIA}, - { "native-sigbridge", FTDM_CHANNEL_NATIVE_SIGBRIDGE}, - { "invalid", FTDM_CHANNEL_MAX_FLAG}, -}; - -static unsigned long long channel_str2val(const char *flag_name) +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) { int i; - for (i = 0; i < ftdm_array_len(channel_flag_strs); i++) { - if (!strcasecmp(channel_flag_strs[i].name, flag_name)) { - return channel_flag_strs[i].channel_flag; + for (i = 0; i < array_size; i++) { + if (!strcasecmp(val_str_table[i].str, str)) { + return val_str_table[i].val; } } - return FTDM_CHANNEL_MAX_FLAG; + return default_val; } -static const char *channel_val2str(unsigned long long flag) +static const char *ftdm_val2str(unsigned long long val, val_str_t *val_str_table, ftdm_size_t array_size, const char *default_str) { int i; - for (i = 0; i < ftdm_array_len(channel_flag_strs); i++) { - if (channel_flag_strs[i].channel_flag == flag) { - return channel_flag_strs[i].name; + for (i = 0; i < array_size; i++) { + if (val_str_table[i].val == val) { + return val_str_table[i].str; } } - return "invalid"; + return default_str; } static void print_channel_flag_values(ftdm_stream_handle_t *stream) { int i; for (i = 0; i < ftdm_array_len(channel_flag_strs); i++) { - stream->write_function(stream, "%s\n", channel_flag_strs[i].name); + stream->write_function(stream, "%s\n", channel_flag_strs[i].str); + } +} + +static void print_span_flag_values(ftdm_stream_handle_t *stream) +{ + int i; + for (i = 0; i < ftdm_array_len(span_flag_strs); i++) { + stream->write_function(stream, "%s\n", span_flag_strs[i].str); } } @@ -4631,12 +4723,13 @@ static char *handle_core_command(const char *cmd) } if (isalpha(flag[0])) { - flagval = channel_str2val(flag); + flagval = ftdm_str2val(flag, channel_flag_strs, ftdm_array_len(channel_flag_strs), FTDM_CHANNEL_MAX_FLAG); if (flagval == FTDM_CHANNEL_MAX_FLAG) { stream.write_function(&stream, "\nInvalid channel flag value. Possible channel flags\n"); print_channel_flag_values(&stream); goto done; } + flagval = flagval >> 1; } else { flagval = atoi(flag); } @@ -4661,6 +4754,44 @@ static char *handle_core_command(const char *cmd) print_channels_by_flag(&stream, fspan, chan_id, 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], "spanflag")) { + if (argc < 2) { + stream.write_function(&stream, "core spanflag command requires an argument\n"); + print_core_usage(&stream); + goto done; + } + + flag = argv[1]; + if (argv[1][0] == '!') { + not = 1; + flag++; + } + + if (isalpha(flag[0])) { + flagval = ftdm_str2val(flag, span_flag_strs, ftdm_array_len(span_flag_strs), FTDM_SPAN_MAX_FLAG); + if (flagval == FTDM_SPAN_MAX_FLAG) { + stream.write_function(&stream, "\nInvalid span flag value. Possible span flags\n"); + print_span_flag_values(&stream); + goto done; + } + flagval = flagval >> 1; + } else { + flagval = atoi(flag); + } + + /* Specific span specified */ + if (argv[2]) { + ftdm_span_find_by_name(argv[2], &fspan); + if (!fspan) { + stream.write_function(&stream, "-ERR span:%s not found\n", argv[2]); + goto done; + } + } + + print_spans_by_flag(&stream, fspan, flagval, not, &count); + if (!fspan) { + stream.write_function(&stream, "\nTotal spans %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; diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index 7df764e52f..19d496bea4 100755 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -197,6 +197,8 @@ typedef enum { FTDM_SPAN_NON_STOPPABLE = (1 << 13), /* If this flag is set, then this span supports TRANSFER state */ FTDM_SPAN_USE_TRANSFER = (1 << 14), + /* This is the last flag, no more flags bigger than this */ + FTDM_SPAN_MAX_FLAG = (1 << 15), } ftdm_span_flag_t; /*! \brief Channel supported features */