From a082c9e913bb3d777d29e4692a8a6e8afcd552e2 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 16 Dec 2010 17:01:06 -0200 Subject: [PATCH 1/4] freetdm: ftmod_r2 - implemented ftdm_r2_get_span_sig_status() and ftdm_r2_set_span_sig_status() mod_freetdm - created sigstatus api command --- libs/freetdm/mod_freetdm/mod_freetdm.c | 78 +++++++++++++++++++++- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 71 +++++++++++++++++++- 2 files changed, 147 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 38197bb2f0..daddc9abc1 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -3542,7 +3542,83 @@ SWITCH_STANDARD_API(ft_function) goto end; } - if (!strcasecmp(argv[0], "dump")) { + if (!strcasecmp(argv[0], "sigstatus")) { + ftdm_span_t *span = NULL; + ftdm_signaling_status_t sigstatus; + + if (argc < 3) { + stream->write_function(stream, "-ERR Usage: ftdm sigstatus get|set [] [] []\n"); + goto end; + } + if (!strcasecmp(argv[1], "get") && argc < 3) { + stream->write_function(stream, "-ERR sigstatus get usage: get \n"); + goto end; + } + if (!strcasecmp(argv[1], "set") && argc != 5) { + stream->write_function(stream, "-ERR sigstatus set usage: set |all \n"); + goto end; + } + + ftdm_span_find_by_name(argv[2], &span); + if (!span) { + stream->write_function(stream, "-ERR invalid span\n"); + goto end; + } + + if (!strcasecmp(argv[1], "get")) { + if (argc == 4) { + uint32_t chan_id = atol(argv[3]); + ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id); + if (!fchan) { + stream->write_function(stream, "-ERR failed to get channel id '%d'\n", chan_id); + goto end; + } + + if ((FTDM_SUCCESS == ftdm_channel_get_sig_status(fchan, &sigstatus))) { + stream->write_function(stream, "channel %d signaling status: %s\n", chan_id, ftdm_signaling_status2str(sigstatus)); + } else { + stream->write_function(stream, "-ERR failed to get channel sigstatus\n"); + } + goto end; + } else { + if ((FTDM_SUCCESS == ftdm_span_get_sig_status(span, &sigstatus))) { + stream->write_function(stream, "signaling_status: %s\n", ftdm_signaling_status2str(sigstatus)); + } else { + stream->write_function(stream, "-ERR failed to read span status: %s\n", ftdm_span_get_last_error(span)); + } + } + goto end; + } + if (!strcasecmp(argv[1], "set")) { + sigstatus = ftdm_str2ftdm_signaling_status(argv[4]); + + if (!strcasecmp(argv[3], "all")) { + if ((FTDM_SUCCESS == ftdm_span_set_sig_status(span, sigstatus))) { + stream->write_function(stream, "Signaling status of all channels from span %s set to %s\n", + ftdm_span_get_name(span), ftdm_signaling_status2str(sigstatus)); + } else { + stream->write_function(stream, "-ERR failed to set span sigstatus to '%s'\n", ftdm_signaling_status2str(sigstatus)); + } + goto end; + } else { + uint32_t chan_id = atol(argv[3]); + ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id); + if (!fchan) { + stream->write_function(stream, "-ERR failed to get channel id '%d'\n", chan_id); + goto end; + } + + if ((FTDM_SUCCESS == ftdm_channel_set_sig_status(fchan, sigstatus))) { + stream->write_function(stream, "Signaling status of channel %d set to %s\n", chan_id, + ftdm_signaling_status2str(sigstatus)); + } else { + stream->write_function(stream, "-ERR failed to set span sigstatus to '%s'\n", ftdm_signaling_status2str(sigstatus)); + } + goto end; + } + } + + } else if (!strcasecmp(argv[0], "dump")) { if (argc < 2) { stream->write_function(stream, "-ERR Usage: ftdm dump []\n"); goto end; diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index ef9201bbe6..b4e9e138cc 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -461,12 +461,79 @@ static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_channel_sig_status) openr2_chan_set_idle(r2chan); break; default: - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%s'\n", status); + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status); return FTDM_FAIL; } return FTDM_SUCCESS; } +static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_span_sig_status) +{ + ftdm_iterator_t *chaniter = NULL; + ftdm_iterator_t *citer = NULL; + uint32_t i; + + chaniter = ftdm_span_get_chan_iterator(span, NULL); + if (!chaniter) { + ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); + return FTDM_FAIL; + } + /* if ALL channels are non-idle, report SUSPENDED. UP otherwise. */ + *status = FTDM_SIG_STATE_SUSPENDED; + for (i = 1, citer = chaniter; citer; citer = ftdm_iterator_next(citer), i++) { + ftdm_channel_t *fchan = ftdm_iterator_current(citer); + + if (ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP)) { + *status = FTDM_SIG_STATE_UP; + break; + } + } + ftdm_iterator_free(chaniter); + return FTDM_SUCCESS; +} + +static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_span_sig_status) +{ + ftdm_iterator_t *chaniter = NULL; + ftdm_iterator_t *citer = NULL; + uint32_t span_opr = -1; + uint32_t i; + + /* we either set the channels to BLOCK or IDLE */ + switch(status) { + case FTDM_SIG_STATE_DOWN: + case FTDM_SIG_STATE_SUSPENDED: + span_opr = 0; + break; + case FTDM_SIG_STATE_UP: + span_opr = 1; + break; + default: + ftdm_log(FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status); + return FTDM_FAIL; + } + + chaniter = ftdm_span_get_chan_iterator(span, NULL); + if (!chaniter) { + ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); + return FTDM_FAIL; + } + /* iterate over all channels, setting them to the requested state */ + for (i = 1, citer = chaniter; citer; citer = ftdm_iterator_next(citer), i++) { + ftdm_channel_t *fchan = ftdm_iterator_current(citer); + openr2_chan_t *r2chan = R2CALL(fchan)->r2chan; + if (span_opr == 0) { + openr2_chan_set_blocked(r2chan); + ftdm_log_chan_msg(fchan, FTDM_LOG_NOTICE, "Channel blocked\n"); + } else { + openr2_chan_set_idle(r2chan); + ftdm_log_chan_msg(fchan, FTDM_LOG_NOTICE, "Channel idle\n"); + } + } + ftdm_iterator_free(chaniter); + return FTDM_SUCCESS; +} + /* always called from the monitor thread */ static void ftdm_r2_on_call_init(openr2_chan_t *r2chan) { @@ -1441,6 +1508,8 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling) span->signal_type = FTDM_SIGTYPE_R2; span->signal_data = r2data; span->outgoing_call = r2_outgoing_call; + span->get_span_sig_status = ftdm_r2_get_span_sig_status; + span->set_span_sig_status = ftdm_r2_set_span_sig_status; span->get_channel_sig_status = ftdm_r2_get_channel_sig_status; span->set_channel_sig_status = ftdm_r2_set_channel_sig_status; From 6b66a0516bcc4d7bd9461366ea7bf958b4ef9aeb Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 16 Dec 2010 18:19:50 -0200 Subject: [PATCH 2/4] freetdm: ftmod_r2 - fixed infinite loop on span stop --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index d1b24da1b8..952b94b63f 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -55,10 +55,13 @@ static int32_t g_thread_count = 0; typedef int openr2_call_status_t; -/* when the users kills a span we clear this flag to kill the signaling thread */ +/* when the user stops a span, we clear FTDM_R2_SPAN_STARTED, so that the signaling thread + * knows it must stop, and we wait for FTDM_R2_RUNNING to be clear, which tells us the + * signaling thread is done. */ /* FIXME: what about the calls that are already up-and-running? */ typedef enum { FTDM_R2_RUNNING = (1 << 0), + FTDM_R2_SPAN_STARTED = (1 << 1), } ftdm_r2_flag_t; /* private call information stored in ftdmchan->call_data void* ptr, @@ -424,13 +427,14 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call) static ftdm_status_t ftdm_r2_start(ftdm_span_t *span) { ftdm_r2_data_t *r2_data = span->signal_data; - ftdm_set_flag(r2_data, FTDM_R2_RUNNING); + ftdm_set_flag(r2_data, FTDM_R2_SPAN_STARTED); return ftdm_thread_create_detached(ftdm_r2_run, span); } static ftdm_status_t ftdm_r2_stop(ftdm_span_t *span) { ftdm_r2_data_t *r2_data = span->signal_data; + ftdm_clear_flag(r2_data, FTDM_R2_SPAN_STARTED); while (ftdm_test_flag(r2_data, FTDM_R2_RUNNING)) { ftdm_log(FTDM_LOG_DEBUG, "Waiting for R2 span %s\n", span->name); ftdm_sleep(100); @@ -1759,6 +1763,9 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) uint32_t txqueue_size = 4; short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count); + /* as long as this thread is running, this flag is set */ + ftdm_set_flag(r2data, FTDM_R2_RUNNING); + #ifdef __linux__ r2data->monitor_thread_id = syscall(SYS_gettid); #endif @@ -1781,7 +1788,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj) memset(&start, 0, sizeof(start)); memset(&end, 0, sizeof(end)); - while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_RUNNING)) { + while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_SPAN_STARTED)) { res = gettimeofday(&end, NULL); if (res) { ftdm_log(FTDM_LOG_CRIT, "Failure gettimeofday [%s]\n", strerror(errno)); From 43dd86fb96f8a20b405df6f6fda932ad6cc2e017 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 16 Dec 2010 18:47:40 -0200 Subject: [PATCH 3/4] freetdm: ftmod_r2 - small code clean --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 952b94b63f..9f35971abb 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -473,20 +473,16 @@ static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_channel_sig_status) static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_span_sig_status) { - ftdm_iterator_t *chaniter = NULL; ftdm_iterator_t *citer = NULL; - uint32_t i; - - chaniter = ftdm_span_get_chan_iterator(span, NULL); + ftdm_iterator_t *chaniter = ftdm_span_get_chan_iterator(span, NULL); if (!chaniter) { ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name); return FTDM_FAIL; } /* if ALL channels are non-idle, report SUSPENDED. UP otherwise. */ *status = FTDM_SIG_STATE_SUSPENDED; - for (i = 1, citer = chaniter; citer; citer = ftdm_iterator_next(citer), i++) { + for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) { ftdm_channel_t *fchan = ftdm_iterator_current(citer); - if (ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP)) { *status = FTDM_SIG_STATE_UP; break; @@ -501,7 +497,6 @@ static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_span_sig_status) ftdm_iterator_t *chaniter = NULL; ftdm_iterator_t *citer = NULL; uint32_t span_opr = -1; - uint32_t i; /* we either set the channels to BLOCK or IDLE */ switch(status) { @@ -523,7 +518,7 @@ static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_span_sig_status) return FTDM_FAIL; } /* iterate over all channels, setting them to the requested state */ - for (i = 1, citer = chaniter; citer; citer = ftdm_iterator_next(citer), i++) { + for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) { ftdm_channel_t *fchan = ftdm_iterator_current(citer); openr2_chan_t *r2chan = R2CALL(fchan)->r2chan; if (span_opr == 0) { From a134136ee715f6b392ec8bf3c5b3e31af7953c18 Mon Sep 17 00:00:00 2001 From: Arnaldo Pereira Date: Thu, 16 Dec 2010 19:44:32 -0200 Subject: [PATCH 4/4] freetdm: ftmod_r2 - notify the core when we change the signaling status of a channel or span through the api --- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 9f35971abb..14eca429e8 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -468,6 +468,7 @@ static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_channel_sig_status) ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status); return FTDM_FAIL; } + ftdm_r2_set_chan_sig_status(ftdmchan, status); return FTDM_SUCCESS; } @@ -528,6 +529,7 @@ static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_span_sig_status) openr2_chan_set_idle(r2chan); ftdm_log_chan_msg(fchan, FTDM_LOG_NOTICE, "Channel idle\n"); } + ftdm_r2_set_chan_sig_status(fchan, status); } ftdm_iterator_free(chaniter); return FTDM_SUCCESS;