diff --git a/Freeswitch.2010.sln b/Freeswitch.2010.sln
index 7e0733ce70..c865b6861a 100644
--- a/Freeswitch.2010.sln
+++ b/Freeswitch.2010.sln
@@ -1771,12 +1771,12 @@ Global
{834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.All|x64.ActiveCfg = Release|Any CPU
{834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|Win32.ActiveCfg = Debug|Any CPU
{834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|Win32.Build.0 = Debug|Any CPU
- {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|x64.ActiveCfg = Debug|Any CPU
- {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|x64.Build.0 = Debug|Any CPU
+ {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|x64.ActiveCfg = Debug|x64
+ {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|x64.Build.0 = Debug|x64
{834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|Win32.ActiveCfg = Release|Any CPU
{834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|Win32.Build.0 = Release|Any CPU
- {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|x64.ActiveCfg = Release|Any CPU
- {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|x64.Build.0 = Release|Any CPU
+ {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|x64.ActiveCfg = Release|x64
+ {834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|x64.Build.0 = Release|x64
{E796E337-DE78-4303-8614-9A590862EE95}.All|Win32.ActiveCfg = Release|Win32
{E796E337-DE78-4303-8614-9A590862EE95}.All|Win32.Build.0 = Release|Win32
{E796E337-DE78-4303-8614-9A590862EE95}.All|x64.ActiveCfg = Release|Win32
diff --git a/bootstrap.sh b/bootstrap.sh
index 59a568769e..0ea5cd43d4 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -341,7 +341,7 @@ rm -rf autom4te*.cache
echo "Entering directory ${LIBDIR}/apr-util"
cd ${LIBDIR}/apr-util
-if [ "${BGJOB}" == "false" ] ; then
+if [ "${BGJOB}" = "false" ] ; then
./buildconf
else
./buildconf &
@@ -350,14 +350,14 @@ fi
for i in ${SUBDIRS}
do
- if [ "${BGJOB}" == "false" ] ; then
+ if [ "${BGJOB}" = "false" ] ; then
libbootstrap ${i}
else
libbootstrap ${i} &
fi
done
-if [ "${BGJOB}" == "true" ] ; then
+if [ "${BGJOB}" = "true" ] ; then
wait
fi
cd ${BASEDIR}
diff --git a/conf/dialplan/default.xml b/conf/dialplan/default.xml
index f7a82ea966..9862eed711 100644
--- a/conf/dialplan/default.xml
+++ b/conf/dialplan/default.xml
@@ -596,7 +596,7 @@
-
+
@@ -604,7 +604,7 @@
-
+
@@ -613,7 +613,7 @@
-
+
@@ -622,7 +622,7 @@
-
+
diff --git a/conf/skinny_profiles/internal.xml b/conf/skinny_profiles/internal.xml
index eaa493c047..e48557b234 100644
--- a/conf/skinny_profiles/internal.xml
+++ b/conf/skinny_profiles/internal.xml
@@ -11,6 +11,7 @@
+
diff --git a/libs/freetdm/src/ftdm_threadmutex.c b/libs/freetdm/src/ftdm_threadmutex.c
index 56bd49ca18..1271d80f4a 100644
--- a/libs/freetdm/src/ftdm_threadmutex.c
+++ b/libs/freetdm/src/ftdm_threadmutex.c
@@ -373,6 +373,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_signal(ftdm_interrupt_t *interrupt)
if (!SetEvent(interrupt->event)) {
ftdm_log(FTDM_LOG_ERROR, "Failed to signal interrupt\n");
return FTDM_FAIL;
+
}
#else
int err;
@@ -404,6 +405,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_destroy(ftdm_interrupt_t **ininterrupt)
#else
close(interrupt->readfd);
close(interrupt->writefd);
+
interrupt->readfd = -1;
interrupt->writefd = -1;
#endif
@@ -416,6 +418,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru
{
int numdevices = 0;
unsigned i;
+
#if defined(__WINDOWS__)
DWORD res = 0;
HANDLE ints[20];
@@ -428,6 +431,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru
for (i = 0; i < size; i++) {
ints[i] = interrupts[i]->event;
if (interrupts[i]->device != FTDM_INVALID_SOCKET) {
+
ints[size+numdevices] = interrupts[i]->device;
numdevices++;
}
@@ -454,7 +458,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru
struct pollfd ints[size*2];
memset(&ints, 0, sizeof(ints));
-
+pollagain:
for (i = 0; i < size; i++) {
ints[i].events = POLLIN;
ints[i].revents = 0;
@@ -463,6 +467,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru
ints[size+numdevices].events = POLLIN;
ints[size+numdevices].revents = 0;
ints[size+numdevices].fd = interrupts[i]->device;
+
numdevices++;
}
}
@@ -470,6 +475,9 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru
res = poll(ints, size + numdevices, ms);
if (res == -1) {
+ if (errno == EINTR) {
+ goto pollagain;
+ }
ftdm_log(FTDM_LOG_CRIT, "interrupt poll failed (%s)\n", strerror(errno));
return FTDM_FAIL;
}
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
index 7d0488ce7d..edb15604e5 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
@@ -60,6 +60,9 @@ static ftdm_status_t handle_show_flags(ftdm_stream_handle_t *stream, int span, i
static ftdm_status_t handle_show_blocks(ftdm_stream_handle_t *stream, int span, int chan, int verbose);
static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span, int chan, int verbose);
+static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int chan, int verbose);
+static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose);
+
static ftdm_status_t handle_status_link(ftdm_stream_handle_t *stream, char *name);
static ftdm_status_t handle_status_linkset(ftdm_stream_handle_t *stream, char *name);
@@ -72,13 +75,14 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
{
char *mycmd = NULL;
char *argv[10] = { 0 };
- int argc = 0;
- int span = 0;
- int chan = 0;
- int trace = 0;
- int trace_level = 7;
- int verbose = 1;
- int c = 0;
+ int argc = 0;
+ int span = 0;
+ int chan = 0;
+ int range = 0;
+ int trace = 0;
+ int trace_level = 7;
+ int verbose = 1;
+ int c = 0;
if (data) {
mycmd = ftdm_strdup(data);
@@ -332,6 +336,61 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
/**********************************************************************/
}
/**************************************************************************/
+ } else if (!strcasecmp(argv[c], "rsc")) {
+ /**************************************************************************/
+ if (check_arg_count(argc, 2)) goto handle_cli_error_argc;
+ c++;
+
+ if (!strcasecmp(argv[c], "span")) {
+ /**********************************************************************/
+ if (check_arg_count(argc, 5)) goto handle_cli_error_argc;
+
+ if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
+
+ handle_tx_rsc(stream, span, chan, verbose);
+ /**********************************************************************/
+ } else {
+ /**********************************************************************/
+ stream->write_function(stream, "Unknown \"rsc\" command\n");
+ goto handle_cli_error;
+ /**********************************************************************/
+ }
+ /**************************************************************************/
+ } else if (!strcasecmp(argv[c], "grs")) {
+ /**************************************************************************/
+ if (check_arg_count(argc, 2)) goto handle_cli_error_argc;
+ c++;
+
+ if (!strcasecmp(argv[c], "span")) {
+ /**********************************************************************/
+ if (check_arg_count(argc, 5)) goto handle_cli_error_argc;
+
+ if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan;
+ c = c + 4;
+
+ if (check_arg_count(argc, 7)) goto handle_cli_error_argc;
+
+ if (!strcasecmp(argv[c], "range")) {
+ /******************************************************************/
+ c++;
+ range = atoi(argv[c]);
+ /******************************************************************/
+ } else {
+ /******************************************************************/
+ stream->write_function(stream, "Unknown \"grs range\" command\n");
+ goto handle_cli_error;
+ /******************************************************************/
+ }
+
+ handle_tx_grs(stream, span, chan, range, verbose);
+ /**********************************************************************/
+ } else {
+ /**********************************************************************/
+ stream->write_function(stream, "Unknown \"grs\" command\n");
+ goto handle_cli_error;
+ /**********************************************************************/
+ }
+ /**************************************************************************/
} else {
/**************************************************************************/
goto handle_cli_error;
@@ -376,6 +435,8 @@ static ftdm_status_t handle_print_usuage(ftdm_stream_handle_t *stream)
stream->write_function(stream, "Ftmod_sangoma_ss7 circuit control:\n");
stream->write_function(stream, "ftdm ss7 block span X chan Y\n");
stream->write_function(stream, "ftdm ss7 unblk span X chan Y\n");
+ stream->write_function(stream, "ftdm ss7 rsc span X chan Y\n");
+ stream->write_function(stream, "ftdm ss7 grs span X chan Y range Z\n");
stream->write_function(stream, "\n");
return FTDM_SUCCESS;
@@ -1090,6 +1151,125 @@ static ftdm_status_t handle_set_uninhibit(ftdm_stream_handle_t *stream, char *na
return FTDM_SUCCESS;
}
+/******************************************************************************/
+static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int chan, int verbose)
+{
+ int x;
+ sngss7_chan_data_t *ss7_info;
+ ftdm_channel_t *ftdmchan;
+ int lspan;
+ int lchan;
+
+ x=1;
+ while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+ if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
+ ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
+ ftdmchan = ss7_info->ftdmchan;
+
+ /* if span == 0 then all spans should be printed */
+ if (span == 0) {
+ lspan = ftdmchan->physical_span_id;
+ } else {
+ lspan = span;
+ }
+
+ /* if chan == 0 then all chans should be printed */
+ if (chan == 0) {
+ lchan = ftdmchan->physical_chan_id;
+ } else {
+ lchan = chan;
+ }
+
+ if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
+ /* now that we have the right channel...put a lock on it so no-one else can use it */
+ ftdm_mutex_lock(ftdmchan->mutex);
+
+ /* check if there is a pending state change|give it a bit to clear */
+ if (check_for_state_change(ftdmchan)) {
+ SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", ss7_info->circuit->cic);
+ SS7_ASSERT;
+ } else {
+ /* throw the ckt block flag */
+ sngss7_set_flag(ss7_info, FLAG_RESET_TX);
+
+ /* set the channel to suspended state */
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+ }
+
+ /* unlock the channel again before we exit */
+ ftdm_mutex_unlock(ftdmchan->mutex);
+
+ } /* if ( span and chan) */
+
+ } /* if ( cic != 0) */
+
+ /* go the next circuit */
+ x++;
+ } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
+
+
+ return FTDM_SUCCESS;
+}
+
+/******************************************************************************/
+static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose)
+{
+ int x;
+ sngss7_chan_data_t *sngss7_info;
+ ftdm_channel_t *ftdmchan;
+ sngss7_span_data_t *sngss7_span;
+
+ if (range > 31) {
+ stream->write_function(stream, "Invalid range value %d", range);
+ return FTDM_SUCCESS;
+ }
+
+ x=1;
+ while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) {
+ if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) {
+
+ sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj;
+ ftdmchan = sngss7_info->ftdmchan;
+ sngss7_span = ftdmchan->span->mod_data;
+
+ if ((ftdmchan->physical_span_id == span) &&
+ ((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) {
+ /* now that we have the right channel...put a lock on it so no-one else can use it */
+ ftdm_mutex_lock(ftdmchan->mutex);
+
+ /* check if there is a pending state change|give it a bit to clear */
+ if (check_for_state_change(ftdmchan)) {
+ SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+ SS7_ASSERT;
+ } else {
+ /* throw the grp reset flag */
+ sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX);
+ if (ftdmchan->physical_chan_id == chan) {
+ sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_BASE);
+ sngss7_span->tx_grs.circuit = sngss7_info->circuit->id;
+ sngss7_span->tx_grs.range = range-1;
+ }
+
+ /* set the channel to suspended state */
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+
+ }
+
+ /* unlock the channel again before we exit */
+ ftdm_mutex_unlock(ftdmchan->mutex);
+
+ } /* if ( span and chan) */
+
+ } /* if ( cic != 0) */
+
+ /* go the next circuit */
+ x++;
+ } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
+
+
+ return FTDM_SUCCESS;
+}
+
/******************************************************************************/
static ftdm_status_t extract_span_chan(char *argv[10], int pos, int *span, int *chan)
{
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
index a0bf95b09c..7f70cb7566 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
@@ -99,7 +99,11 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
SS7_ASSERT;
};
- SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IAM\n");
+ if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) {
+ SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IAM (glare detected on circuit)\n");
+ } else {
+ SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IAM\n");
+ }
/* check if the circuit has a remote block */
if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
@@ -201,6 +205,9 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
SS7_DEBUG_CHAN(ftdmchan,"No TMR/Bearer Cap information in IAM!%s\n", " ");
}
+ /* add any special variables for the dialplan */
+ /*ftdm_channel_add_var(ftdmchan, "ss7_stuff", "s");*/
+
/* set the state of the channel to collecting...the rest is done by the chan monitor */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
@@ -208,11 +215,36 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
break;
/**************************************************************************/
+ case (FTDM_CHANNEL_STATE_DIALING):
+ case (FTDM_CHANNEL_STATE_TERMINATING):
+ case (FTDM_CHANNEL_STATE_HANGUP):
+ case (FTDM_CHANNEL_STATE_HANGUP_COMPLETE):
+
+ SS7_INFO_CHAN(ftdmchan, "Got IAM on channel in %s state...glare!\n", ftdm_channel_state2str (ftdmchan->state));
+
+ /* save the info so that we can use it later on */
+ sngss7_info->glare.spInstId = spInstId;
+ sngss7_info->glare.circuit = circuit;
+ memcpy(&sngss7_info->glare.iam, siConEvnt, sizeof(*siConEvnt));
+
+ if (!(sngss7_test_flag(sngss7_info, FLAG_GLARE))) {
+ /* glare, throw the flag */
+ sngss7_set_flag(sngss7_info, FLAG_GLARE);
+
+ /* setup the hangup cause */
+ ftdmchan->caller_data.hangup_cause = 34; /* Circuit Congrestion */
+
+ /* this is a remote hangup request */
+ sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL);
+
+ /* move the state of the channel to Terminating to end the call */
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+ }
+
+ break;
+ /**************************************************************************/
default: /* should not have gotten an IAM while in this state */
- SS7_ERROR("Got IAM in an invalid state (%s) on span=%d, chan=%d!\n",
- ftdm_channel_state2str(ftdmchan->state),
- ftdmchan->physical_span_id,
- ftdmchan->physical_chan_id);
+ SS7_ERROR_CHAN(ftdmchan, "Got IAM on channel in invalid state(%s)...reset!\n", ftdm_channel_state2str (ftdmchan->state));
/* move the state of the channel to RESTART to force a reset */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
@@ -540,10 +572,6 @@ ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/**************************************************************************/
default:
- /* fill in the channels SS7 Stack information */
- sngss7_info->suInstId = get_unique_id();
- sngss7_info->spInstId = spInstId;
-
/* throw the reset flag */
sngss7_set_flag(sngss7_info, FLAG_RESET_RX);
@@ -1028,10 +1056,26 @@ ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t ci
SS7_ASSERT;
};
- /* glare, throw the flag, go to down state*/
- sngss7_set_flag(sngss7_info, FLAG_GLARE);
+ if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) {
+ /* the glare flag is already up so it was caught ... do nothing */
+ SS7_DEBUG_CHAN(ftdmchan, "Glare flag is already up...nothing to do!%s\n", " ");
+ } else {
+ SS7_DEBUG_CHAN(ftdmchan, "Glare flag is not up yet...indicating glare from reattempt!%s\n", " ");
+ /* glare, throw the flag */
+ sngss7_set_flag(sngss7_info, FLAG_GLARE);
- ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
+ /* clear any existing glare data from the channel */
+ memset(&sngss7_info->glare, 0x0, sizeof(sngss7_glare_data_t));
+
+ /* setup the hangup cause */
+ ftdmchan->caller_data.hangup_cause = 34; /* Circuit Congrestion */
+
+ /* this is a remote hangup request */
+ sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL);
+
+ /* move the state of the channel to Terminating to end the call */
+ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+ }
/* unlock the channel again before we exit */
ftdm_mutex_unlock(ftdmchan->mutex);
@@ -1640,9 +1684,9 @@ ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
- sngss7_chan_data_t *sngss7_info = NULL;
- ftdm_channel_t *ftdmchan = NULL;
- sngss7_span_data_t *span = NULL;
+ sngss7_chan_data_t *sngss7_info = NULL;
+ ftdm_channel_t *ftdmchan = NULL;
+ sngss7_span_data_t *sngss7_span = NULL;
int range;
int x;
@@ -1680,11 +1724,11 @@ ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
};
/* fill in the span structure for this circuit */
- span = ftdmchan->span->mod_data;
- span->grs.circuit = circuit;
- span->grs.range = range;
+ sngss7_span = ftdmchan->span->mod_data;
+ sngss7_span->rx_grs.circuit = circuit;
+ sngss7_span->rx_grs.range = range;
- SS7_DEBUG_CHAN(ftdmchan, "Rx GRS (%d:%d)\n",
+ SS7_INFO_CHAN(ftdmchan, "Rx GRS (%d:%d)\n",
g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic,
(g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic + range));
@@ -1755,7 +1799,7 @@ ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
SS7_ASSERT;
};
- SS7_DEBUG_CHAN(ftdmchan, "Rx GRA (%d:%d)\n",
+ SS7_INFO_CHAN(ftdmchan, "Rx GRA (%d:%d)\n",
g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic,
(g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic + range));
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
index a9851bda3f..66efe1ab12 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
@@ -303,24 +303,17 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
/* clean out all pending channel state changes */
while ((ftdmchan = ftdm_queue_dequeue (ftdmspan->pendingchans))) {
- /* double check that this channel has a state change pending */
- if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
- /*first lock the channel */
- ftdm_mutex_lock(ftdmchan->mutex);
+
+ /*first lock the channel */
+ ftdm_mutex_lock(ftdmchan->mutex);
+ /* process state changes for this channel until they are all done */
+ while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
ftdm_sangoma_ss7_process_state_change (ftdmchan);
-
- /* unlock the channel */
- ftdm_mutex_unlock (ftdmchan->mutex);
- } else {
- /* since we handle state changes again after handling the trillium queue
- * this can occur since we'll clear the flag for the event but can't pop
- * the channel out of pendingchans
- */
-/* SS7_ERROR("ftdm_core reported state change, but state change flag not set on ft-span = %d, ft-chan = %d\n",
- ftdmchan->physical_span_id,
- ftdmchan->physical_chan_id);*/
}
+
+ /* unlock the channel */
+ ftdm_mutex_unlock (ftdmchan->mutex);
}/* while ((ftdmchan = ftdm_queue_dequeue(ftdmspan->pendingchans))) */
/* clean out all pending stack events */
@@ -329,6 +322,9 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
ftdm_safe_free(sngss7_event);
}/* while ((sngss7_event = ftdm_queue_dequeue(ftdmspan->signal_data->event_queue))) */
+ /* signal the core that sig events are queued for processing */
+ ftdm_span_trigger_signals(ftdmspan);
+
break;
/**********************************************************************/
case FTDM_TIMEOUT:
@@ -352,12 +348,12 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data;
/* check if there is a GRS being processed on the span */
- if (sngss7_span->grs.range > 0) {
+ if (sngss7_span->rx_grs.range > 0) {
ftdm_log(FTDM_LOG_DEBUG, "Found Rx GRS on span %d...checking circuits\n", ftdmspan->span_id);
/*SS7_DEBUG("Found Rx GRS on span %d...checking circuits\n", ftdmspan->span_id);*/
/* check all the circuits in the range to see if they are done resetting */
- for ( i = sngss7_span->grs.circuit; i < (sngss7_span->grs.circuit + sngss7_span->grs.range + 1); i++) {
+ for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
@@ -382,11 +378,11 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
} /* for ( i = circuit; i < (circuit + range + 1); i++) */
SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n",
- sngss7_span->grs.circuit,
- sngss7_span->grs.range);
+ sngss7_span->rx_grs.circuit,
+ sngss7_span->rx_grs.range);
/* check all the circuits in the range to see if they are done resetting */
- for ( i = sngss7_span->grs.circuit; i < (sngss7_span->grs.circuit + sngss7_span->grs.range + 1); i++) {
+ for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
@@ -403,7 +399,7 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
} /* for ( i = circuit; i < (circuit + range + 1); i++) */
GRS_UNLOCK_ALL:
- for ( i = sngss7_span->grs.circuit; i < (sngss7_span->grs.circuit + sngss7_span->grs.range + 1); i++) {
+ for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
/* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
@@ -451,6 +447,11 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
/* now that we have the right channel...put a lock on it so no-one else can use it */
ftdm_mutex_lock(ftdmchan->mutex);
+ /* while there's a state change present on this channel process it */
+ while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
+ ftdm_sangoma_ss7_process_state_change(ftdmchan);
+ }
+
/* figure out the type of event and send it to the right handler */
switch (sngss7_event->event_id) {
/**************************************************************************/
@@ -514,10 +515,9 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
/******************************************************************************/
static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
{
- ftdm_sigmsg_t sigev;
- ftdm_signaling_status_t status;
- sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
- int i = 0;
+ ftdm_sigmsg_t sigev;
+ sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+ int i = 0;
memset (&sigev, 0, sizeof (sigev));
@@ -748,7 +748,11 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* go to RESTART State until RSCa is received */
ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RESTART);
} else {
- if (!(sngss7_test_flag (sngss7_info, FLAG_RESET_RX))) {
+ /* if the hangup is from a rx RSC, rx GRS, or glare don't sent RLC */
+ if (!(sngss7_test_flag(sngss7_info, FLAG_RESET_RX)) &&
+ !(sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX)) &&
+ !(sngss7_test_flag(sngss7_info, FLAG_GLARE))) {
+
/* send out the release complete */
ft_to_sngss7_rlc (ftdmchan);
}
@@ -799,14 +803,14 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
* we insure that this is the last circuit to have the state change queued
*/
sngss7_span_data_t *span = ftdmchan->span->mod_data;
- if (span->grs.circuit == sngss7_info->circuit->id) {
+ if (span->rx_grs.circuit == sngss7_info->circuit->id) {
/* send out the GRA */
ft_to_sngss7_gra(ftdmchan);
/* clean out the spans GRS structure */
sngss7_span_data_t *span = ftdmchan->span->mod_data;
- span->grs.circuit = 0;
- span->grs.range = 0;
+ span->rx_grs.circuit = 0;
+ span->rx_grs.range = 0;
}
/* clear the grp reset flag */
@@ -820,6 +824,7 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX_RSP)) {
/* clear the reset flag */
sngss7_clear_flag(sngss7_info, FLAG_RESET_TX_RSP);
+ sngss7_clear_flag(sngss7_info, FLAG_RESET_SENT);
sngss7_clear_flag(sngss7_info, FLAG_RESET_TX);
}
@@ -845,9 +850,8 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
SS7_DEBUG_CHAN(ftdmchan,"All reset flags cleared %s\n", "");
/* all flags are down so we can bring up the sig status */
- status = FTDM_SIG_STATE_UP;
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sigev.raw_data = &status;
+ sigev.sigstatus = FTDM_SIG_STATE_UP;
ftdm_span_send_signal (ftdmchan->span, &sigev);
}
} else {
@@ -879,7 +883,26 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
ftdm_channel_t *close_chan = ftdmchan;
/* close the channel */
ftdm_channel_close (&close_chan);
- }
+ } /* if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OPEN)) */
+
+ /* check if there is a glared call that needs to be processed */
+ if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) {
+
+ /* clear the glare flag */
+ sngss7_clear_flag (sngss7_info, FLAG_GLARE);
+
+ /* check if we have an IAM stored...if we don't have one just exit */
+ if (sngss7_info->glare.circuit != 0) {
+ /* send the saved call back in to us */
+ handle_con_ind (0,
+ sngss7_info->glare.spInstId,
+ sngss7_info->glare.circuit,
+ &sngss7_info->glare.iam);
+
+ /* clear the glare info */
+ memset(&sngss7_info->glare, 0x0, sizeof(sngss7_glare_data_t));
+ } /* if (sngss7_info->glare.circuit != 0) */
+ } /* if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) */
break;
/**************************************************************************/
@@ -930,9 +953,8 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* if the sig_status is up...bring it down */
if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
- status = FTDM_SIG_STATE_DOWN;
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sigev.raw_data = &status;
+ sigev.sigstatus = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal (ftdmchan->span, &sigev);
}
@@ -994,9 +1016,8 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
SS7_DEBUG_CHAN(ftdmchan, "Processing PAUSE flag %s\n", "");
/* bring the channel signaling status to down */
- status = FTDM_SIG_STATE_DOWN;
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sigev.raw_data = &status;
+ sigev.sigstatus = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal (ftdmchan->span, &sigev);
/* check the last state and return to it to allow the call to finish */
@@ -1091,9 +1112,8 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_UCIC_BLOCK flag %s\n", "");
/* bring the channel signaling status to down */
- status = FTDM_SIG_STATE_DOWN;
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
- sigev.raw_data = &status;
+ sigev.sigstatus = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal (ftdmchan->span, &sigev);
/* remove any reset flags */
@@ -1167,11 +1187,13 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call)
SS7_ASSERT;
};
+ /* check if the channel sig state is UP */
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
SS7_ERROR_CHAN(ftdmchan, "Requested channel sig state is down, cancelling call!%s\n", " ");
goto outgoing_fail;
}
+ /* check if there is a remote block */
if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
(sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) ||
(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
@@ -1181,15 +1203,19 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call)
goto outgoing_break;
}
+ /* check if there is a local block */
if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) ||
(sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX)) ||
(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX))) {
+ /* KONRAD FIX ME : we should check if this is a TEST call and allow it */
+
/* the channel is blocked...can't send any calls here */
SS7_ERROR_CHAN(ftdmchan, "Requested channel is locally blocked, re-hunt channel!%s\n", " ");
goto outgoing_break;
}
+ /* check the state of the channel */
switch (ftdmchan->state){
/**************************************************************************/
case FTDM_CHANNEL_STATE_DOWN:
@@ -1208,7 +1234,7 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call)
ftdmchan->physical_span_id,
ftdmchan->physical_chan_id);
- goto outgoing_fail;
+ goto outgoing_break;
break;
/**************************************************************************/
} /* switch (ftdmchan->state) (original call) */
@@ -1268,6 +1294,7 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span)
{
ftdm_channel_t *ftdmchan = NULL;
sngss7_chan_data_t *sngss7_info = NULL;
+ sngss7_span_data_t *sngss7_span = NULL;
int x;
@@ -1278,6 +1305,7 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span)
/* extract the channel structure and sngss7 channel data */
ftdmchan = span->channels[x];
sngss7_info = ftdmchan->call_data;
+ sngss7_span = ftdmchan->span->mod_data;
/* lock the channel */
ftdm_mutex_lock(ftdmchan->mutex);
@@ -1289,6 +1317,8 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span)
sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX);
if (x == 1) {
sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_BASE);
+ sngss7_span->tx_grs.circuit = sngss7_info->circuit->id;
+ sngss7_span->tx_grs.range = span->chan_count -1;
}
/* throw the channel to suspend */
@@ -1388,7 +1418,10 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_ss7_span_config)
span->state_map = &sangoma_ss7_state_map;
span->mod_data = ss7_span_info;
+ /* set the flag to indicate that this span uses channel state change queues */
ftdm_set_flag (span, FTDM_SPAN_USE_CHAN_QUEUE);
+ /* set the flag to indicate that this span uses sig event queues */
+ ftdm_set_flag (span, FTDM_SPAN_USE_SIGNALS_QUEUE);
/* parse the configuration and apply to the global config structure */
if (ftmod_ss7_parse_xml(ftdm_parameters, span)) {
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
index 3bf12ae307..050f59e00e 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
@@ -321,8 +321,7 @@ typedef struct sngss7_timer_data {
}sngss7_timer_data_t;
typedef struct sngss7_glare_data {
- uint32_t suInstId;
- uint32_t spInstId;
+ uint32_t spInstId;
uint32_t circuit;
SiConEvnt iam;
}sngss7_glare_data_t;
@@ -347,7 +346,8 @@ typedef struct sngss7_chan_data {
typedef struct sngss7_span_data {
ftdm_sched_t *sched;
- sngss7_group_data_t grs;
+ sngss7_group_data_t rx_grs;
+ sngss7_group_data_t tx_grs;
ftdm_queue_t *event_queue;
}sngss7_span_data_t;
@@ -612,31 +612,40 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
#define SS7_MSG_TRACE(fchan, sngss7info ,msg) if (g_ftdm_sngss7_data.message_trace) { \
switch (g_ftdm_sngss7_data.message_trace_level) { \
case 0: \
- ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+ ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \
+ sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \
break; \
case 1: \
- ftdm_log_chan(fchan, FTDM_LOG_ALERT, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+ ftdm_log_chan(fchan, FTDM_LOG_ALERT, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \
+ sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \
break; \
case 2: \
- ftdm_log_chan(fchan, FTDM_LOG_CRIT, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+ ftdm_log_chan(fchan, FTDM_LOG_CRIT, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \
+ sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \
break; \
case 3: \
- ftdm_log_chan(fchan, FTDM_LOG_ERROR, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+ ftdm_log_chan(fchan, FTDM_LOG_ERROR, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \
+ sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \
break; \
case 4: \
- ftdm_log_chan(fchan, FTDM_LOG_WARNING, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+ ftdm_log_chan(fchan, FTDM_LOG_WARNING, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \
+ sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \
break; \
case 5: \
- ftdm_log_chan(fchan, FTDM_LOG_NOTICE, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+ ftdm_log_chan(fchan, FTDM_LOG_NOTICE, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \
+ sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \
break; \
case 6: \
- ftdm_log_chan(fchan, FTDM_LOG_INFO, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+ ftdm_log_chan(fchan, FTDM_LOG_INFO, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \
+ sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \
break; \
case 7: \
- ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+ ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \
+ sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \
break; \
default: \
- ftdm_log_chan(fchan, FTDM_LOG_INFO, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
+ ftdm_log_chan(fchan, FTDM_LOG_INFO, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \
+ sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \
break; \
} /* switch (g_ftdm_sngss7_data.message_trace_level) */ \
} /* if(g_ftdm_sngss7_data.message_trace) */
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c
index 600a52910c..4fac251c17 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c
@@ -60,9 +60,10 @@ void ft_to_sngss7_lpa (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan);
+/******************************************************************************/
+
/* FUNCTIONS ******************************************************************/
-void
-ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
+void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
@@ -133,7 +134,6 @@ ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
}
/******************************************************************************/
-
void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
@@ -415,7 +415,7 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
- sngss7_span_data_t *span = ftdmchan->span->mod_data;
+ sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiStaEvnt gra;
@@ -426,11 +426,11 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
/* fill in the range */
gra.rangStat.range.pres = PRSNT_NODEF;
- gra.rangStat.range.val = span->grs.range;
+ gra.rangStat.range.val = sngss7_span->rx_grs.range;
/* fill in the status */
gra.rangStat.status.pres = PRSNT_NODEF;
- gra.rangStat.status.len = ((span->grs.range + 1) >> 3) + (((span->grs.range + 1) & 0x07) ? 1 : 0);
+ gra.rangStat.status.len = ((sngss7_span->rx_grs.range + 1) >> 3) + (((sngss7_span->rx_grs.range + 1) & 0x07) ? 1 : 0);
/* the status field should be 1 if blocked for maintenace reasons
* and 0 is not blocked....since we memset the struct nothing to do
@@ -440,12 +440,14 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
sng_cc_sta_request (1,
0,
0,
- span->grs.circuit,
+ sngss7_span->rx_grs.circuit,
0,
SIT_STA_GRSRSP,
&gra);
- SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx GRA\n");
+ SS7_INFO_CHAN(ftdmchan, "Tx GRA (%d:%d)\n",
+ sngss7_info->circuit->cic,
+ (sngss7_info->circuit->cic + sngss7_span->rx_grs.range));
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
@@ -454,31 +456,32 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
/******************************************************************************/
void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan)
{
-SS7_FUNC_TRACE_ENTER (__FUNCTION__);
-
-sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
-ftdm_span_t *span = ftdmchan->span;
-
-SiStaEvnt grs;
-
-memset (&grs, 0x0, sizeof (grs));
-
-grs.rangStat.eh.pres = PRSNT_NODEF;
-grs.rangStat.range.pres = PRSNT_NODEF;
-grs.rangStat.range.val = span->chan_count-1;
-
-sng_cc_sta_request (1,
- 0,
- 0,
- sngss7_info->circuit->id,
- 0,
- SIT_STA_GRSREQ,
- &grs);
-
-
-SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx GRS\n");
-
-SS7_FUNC_TRACE_EXIT (__FUNCTION__);
+ SS7_FUNC_TRACE_ENTER (__FUNCTION__);
+
+ sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data;
+ sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
+
+ SiStaEvnt grs;
+
+ memset (&grs, 0x0, sizeof (grs));
+
+ grs.rangStat.eh.pres = PRSNT_NODEF;
+ grs.rangStat.range.pres = PRSNT_NODEF;
+ grs.rangStat.range.val = sngss7_span->tx_grs.range;
+
+ sng_cc_sta_request (1,
+ 0,
+ 0,
+ sngss7_span->tx_grs.circuit,
+ 0,
+ SIT_STA_GRSREQ,
+ &grs);
+
+ SS7_INFO_CHAN(ftdmchan, "Tx GRS (%d:%d)\n",
+ sngss7_info->circuit->cic,
+ (sngss7_info->circuit->cic + sngss7_span->tx_grs.range));
+
+ SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
diff --git a/libs/libdingaling/src/libdingaling.c b/libs/libdingaling/src/libdingaling.c
index 353dd139ab..ef6e7447a1 100644
--- a/libs/libdingaling/src/libdingaling.c
+++ b/libs/libdingaling/src/libdingaling.c
@@ -163,6 +163,7 @@ struct ldl_session {
apr_hash_t *variables;
apr_time_t created;
void *private_data;
+ ldl_user_flag_t flags;
};
static int on_disco_default(void *user_data, ikspak *pak);
@@ -346,6 +347,7 @@ ldl_status ldl_session_create(ldl_session_t **session_p, ldl_handle_t *handle, c
session->created = apr_time_now();
session->state = LDL_STATE_NEW;
session->variables = apr_hash_make(session->pool);
+ session->flags = flags;
*session_p = session;
@@ -387,7 +389,24 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
if (type) {
- if (!strcasecmp(type, "initiate") || !strcasecmp(type, "accept")) {
+ if (!strcasecmp(type, "redirect")) {
+ apr_hash_t *hash = session->handle->sessions;
+ char *p = to;
+ if ((p = strchr(to, ':'))) {
+ p++;
+ } else {
+ p = to;
+ }
+
+
+ apr_hash_set(hash, session->them, APR_HASH_KEY_STRING, NULL);
+ apr_hash_set(hash, session->id, APR_HASH_KEY_STRING, NULL);
+ session->them = apr_pstrdup(session->pool, p);
+ apr_hash_set(handle->sessions, session->them, APR_HASH_KEY_STRING, session);
+ apr_hash_set(handle->sessions, session->id, APR_HASH_KEY_STRING, session);
+
+ dl_signal = LDL_SIGNAL_REDIRECT;
+ } else if (!strcasecmp(type, "initiate") || !strcasecmp(type, "accept")) {
dl_signal = LDL_SIGNAL_INITIATE;
@@ -499,6 +518,12 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
if ((key = iks_find_attrib(tag, "port"))) {
session->candidates[index].port = (uint16_t)atoi(key);
}
+
+ if (!session->candidates[index].type) {
+ session->candidates[index].type = apr_pstrdup(session->pool, "stun");
+ }
+
+
if (globals.debug) {
globals.logger(DL_LOG_DEBUG,
"New Candidate %d\n"
@@ -947,6 +972,18 @@ static void cancel_retry(ldl_handle_t *handle, char *id)
apr_thread_mutex_unlock(handle->lock);
}
+static iks* working_find(iks *tag, const char *name)
+{
+ while(tag) {
+ if (!strcasecmp(iks_name(tag), name)) {
+ return tag;
+ }
+ tag = iks_next_tag(tag);
+ }
+
+ return NULL;
+}
+
static int on_commands(void *user_data, ikspak *pak)
{
ldl_handle_t *handle = user_data;
@@ -956,8 +993,22 @@ static int on_commands(void *user_data, ikspak *pak)
char *type = iks_find_attrib(pak->x, "type");
uint8_t is_result = strcasecmp(type, "result") ? 0 : 1;
uint8_t is_error = strcasecmp(type, "error") ? 0 : 1;
+ iks *xml, *xsession, *xerror = NULL, *xredir = NULL;
+
+ xml = iks_child (pak->x);
+
+ if (is_error) {
+ if ((xerror = working_find(xml, "error"))) {
+ char *code = iks_find_attrib(xerror, "code");
+ if (code && !strcmp(code, "302") &&
+ ((xredir = iks_find(xerror, "ses:redirect")) || (xredir = iks_find(xerror, "redirect")))) {
+ is_result = 0;
+ is_error = 0;
+ cancel_retry(handle, iqid);
+ }
+ }
+ }
- iks *xml;
if (is_result) {
iks *tag = iks_child (pak->x);
@@ -989,9 +1040,12 @@ static int on_commands(void *user_data, ikspak *pak)
}
}
+
+
if ((is_result || is_error) && iqid && from) {
cancel_retry(handle, iqid);
+
if (is_result) {
if (handle->response_callback) {
handle->response_callback(handle, iqid);
@@ -999,30 +1053,37 @@ static int on_commands(void *user_data, ikspak *pak)
return IKS_FILTER_EAT;
} else if (is_error) {
return IKS_FILTER_EAT;
+
}
}
- xml = iks_child (pak->x);
- while (xml) {
- char *name = iks_name_nons(xml);
- if (!strcasecmp(name, "session")) {
- char *id = iks_find_attrib(xml, "id");
- //printf("SESSION type=%s name=%s id=%s\n", type, name, id);
- if (parse_session_code(handle, id, from, to, xml, strcasecmp(type, "error") ? NULL : type) == LDL_STATUS_SUCCESS) {
- iks *reply;
- if ((reply = iks_make_iq(IKS_TYPE_RESULT, NULL))) {
- iks_insert_attrib(reply, "to", from);
- iks_insert_attrib(reply, "from", to);
- iks_insert_attrib(reply, "id", iqid);
- apr_queue_push(handle->queue, reply);
- reply = NULL;
- }
+
+ if ((xsession = working_find(xml, "ses:session")) || (xsession = working_find(xml, "session"))) {
+ char *id;
+
+ id = iks_find_attrib(xsession, "id");
+
+ if (xredir) {
+ to = iks_cdata(iks_child(xredir));
+ type = "redirect";
+ }
+
+ if (strcasecmp(type, "error") && strcasecmp(type, "redirect")) {
+ type = NULL;
+ }
+
+ if (parse_session_code(handle, id, from, to, xsession, type) == LDL_STATUS_SUCCESS) {
+ iks *reply;
+ if ((reply = iks_make_iq(IKS_TYPE_RESULT, NULL))) {
+ iks_insert_attrib(reply, "to", from);
+ iks_insert_attrib(reply, "from", to);
+ iks_insert_attrib(reply, "id", iqid);
+ apr_queue_push(handle->queue, reply);
+ reply = NULL;
}
}
- xml = iks_next_tag(xml);
}
-
return IKS_FILTER_EAT;
}
@@ -1922,6 +1983,69 @@ unsigned int ldl_session_terminate(ldl_session_t *session)
}
+
+unsigned int ldl_session_transport(ldl_session_t *session,
+ ldl_candidate_t *candidates,
+ unsigned int clen)
+
+{
+ iks *iq, *sess, *tag;
+ unsigned int x, id = 0;
+
+
+ for (x = 0; x < clen; x++) {
+ char buf[512];
+ iq = NULL;
+ sess = NULL;
+ id = 0;
+
+ new_session_iq(session, &iq, &sess, &id, "transport-info");
+ //tag = iks_insert(sess, "transport");
+ //iks_insert_attrib(tag, "xmlns", "http://www.google.com/transport/p2p");
+ tag = sess;
+
+ if (0) add_elements(session, tag);
+ tag = iks_insert(tag, "transport");
+ iks_insert_attrib(tag, "xmlns", "http://www.google.com/transport/p2p");
+
+ tag = iks_insert(tag, "candidate");
+
+ if (candidates[x].name) {
+ iks_insert_attrib(tag, "name", candidates[x].name);
+ }
+ if (candidates[x].address) {
+ iks_insert_attrib(tag, "address", candidates[x].address);
+ }
+ if (candidates[x].port) {
+ snprintf(buf, sizeof(buf), "%u", candidates[x].port);
+ iks_insert_attrib(tag, "port", buf);
+ }
+ if (candidates[x].username) {
+ iks_insert_attrib(tag, "username", candidates[x].username);
+ }
+ if (candidates[x].password) {
+ iks_insert_attrib(tag, "password", candidates[x].password);
+ }
+ if (candidates[x].pref) {
+ snprintf(buf, sizeof(buf), "%0.1f", candidates[x].pref);
+ iks_insert_attrib(tag, "preference", buf);
+ }
+ if (candidates[x].protocol) {
+ iks_insert_attrib(tag, "protocol", candidates[x].protocol);
+ }
+ if (candidates[x].type) {
+ iks_insert_attrib(tag, "type", candidates[x].type);
+ }
+
+ iks_insert_attrib(tag, "network", "0");
+ iks_insert_attrib(tag, "generation", "0");
+ schedule_packet(session->handle, id, iq, LDL_RETRY);
+ }
+
+
+ return id;
+}
+
unsigned int ldl_session_candidates(ldl_session_t *session,
ldl_candidate_t *candidates,
unsigned int clen)
@@ -1981,6 +2105,8 @@ unsigned int ldl_session_candidates(ldl_session_t *session,
return id;
}
+
+
char *ldl_handle_probe(ldl_handle_t *handle, char *id, char *from, char *buf, unsigned int len)
{
iks *pres, *msg;
@@ -2344,6 +2470,12 @@ int ldl_handle_running(ldl_handle_t *handle)
return ldl_test_flag(handle, LDL_FLAG_RUNNING) ? 1 : 0;
}
+
+int ldl_session_gateway(ldl_session_t *session)
+{
+ return ldl_test_flag(session, LDL_FLAG_GATEWAY) ? 1 : 0;
+}
+
int ldl_handle_connected(ldl_handle_t *handle)
{
return ldl_test_flag(handle, LDL_FLAG_CONNECTED) ? 1 : 0;
diff --git a/libs/libdingaling/src/libdingaling.h b/libs/libdingaling/src/libdingaling.h
index 07a71b3987..d78643810c 100644
--- a/libs/libdingaling/src/libdingaling.h
+++ b/libs/libdingaling/src/libdingaling.h
@@ -131,7 +131,8 @@ typedef enum {
LDL_FLAG_SASL_PLAIN = (1 << 11),
LDL_FLAG_SASL_MD5 = (1 << 12),
LDL_FLAG_COMPONENT = (1 << 13),
- LDL_FLAG_OUTBOUND = (1 << 14)
+ LDL_FLAG_OUTBOUND = (1 << 14),
+ LDL_FLAG_GATEWAY = (1 << 15)
} ldl_user_flag_t;
typedef enum {
@@ -152,7 +153,8 @@ typedef enum {
LDL_SIGNAL_LOGIN_FAILURE,
LDL_SIGNAL_CONNECTED,
LDL_SIGNAL_TRANSPORT_ACCEPT,
- LDL_SIGNAL_REJECT
+ LDL_SIGNAL_REJECT,
+ LDL_SIGNAL_REDIRECT
} ldl_signal_t;
typedef enum {
@@ -494,6 +496,10 @@ unsigned int ldl_session_candidates(ldl_session_t *session,
ldl_candidate_t *candidates,
unsigned int clen);
+unsigned int ldl_session_transport(ldl_session_t *session,
+ ldl_candidate_t *candidates,
+ unsigned int clen);
+
/*!
\brief Initiate or Accept a new session and provide transport options
\param session the session to initiate or accept
@@ -586,6 +592,8 @@ ldl_status ldl_handle_init(ldl_handle_t **handle,
*/
void ldl_handle_run(ldl_handle_t *handle);
+int ldl_session_gateway(ldl_session_t *handle);
+
/*!
\brief Stop a libDingaLing handle
\param handle the Dingaling handle to stop
diff --git a/src/include/switch_loadable_module.h b/src/include/switch_loadable_module.h
index 158de6ce63..68719062b7 100644
--- a/src/include/switch_loadable_module.h
+++ b/src/include/switch_loadable_module.h
@@ -120,6 +120,25 @@ SWITCH_DECLARE(switch_codec_interface_t *) switch_loadable_module_get_codec_inte
*/
SWITCH_DECLARE(switch_dialplan_interface_t *) switch_loadable_module_get_dialplan_interface(const char *name);
+/*!
+ \brief Enumerates a list of all modules discovered in a directory
+ \param the directory to look for modules in
+ \param memory pool
+ \param callback function to call for each module found
+ \param user data argument to pass to the callback function
+ \return the resulting status
+ */
+SWITCH_DECLARE(switch_status_t) switch_loadable_module_enumerate_available(const char *dir_path, switch_modulename_callback_func_t callback, void *user_data);
+
+
+/*!
+ \brief Enumerates a list of all currently loaded modules
+ \param callback function to call for each module found
+ \param user data argument to pass to the callback function
+ \return the resulting status
+ */
+SWITCH_DECLARE(switch_status_t) switch_loadable_module_enumerate_loaded(switch_modulename_callback_func_t callback, void *user_data);
+
/*!
\brief build a dynamic module object and register it (for use in double embeded modules)
\param filename the name of the modules source file
diff --git a/src/include/switch_types.h b/src/include/switch_types.h
index dacf2dddda..5a88cd5751 100644
--- a/src/include/switch_types.h
+++ b/src/include/switch_types.h
@@ -1731,6 +1731,8 @@ typedef struct switch_loadable_module_function_table {
switch_module_flag_t flags;
} switch_loadable_module_function_table_t;
+typedef int (*switch_modulename_callback_func_t) (void *user_data, const char *module_name);
+
#define SWITCH_MODULE_DEFINITION_EX(name, load, shutdown, runtime, flags) \
static const char modname[] = #name ; \
SWITCH_MOD_DECLARE_DATA switch_loadable_module_function_table_t name##_module_interface = { \
diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c
index cc864a266b..e1eb2a6b6a 100644
--- a/src/mod/applications/mod_commands/mod_commands.c
+++ b/src/mod/applications/mod_commands/mod_commands.c
@@ -4651,9 +4651,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
switch_console_set_complete("add fsctl flush_db_handles");
switch_console_set_complete("add fsctl min_idle_cpu");
switch_console_set_complete("add fsctl send_sighup");
+ switch_console_set_complete("add load ::console::list_available_modules");
switch_console_set_complete("add nat_map reinit");
switch_console_set_complete("add nat_map republish");
switch_console_set_complete("add nat_map status");
+ switch_console_set_complete("add reload ::console::list_loaded_modules");
switch_console_set_complete("add reloadacl reloadxml");
switch_console_set_complete("add show aliases");
switch_console_set_complete("add show api");
@@ -4678,6 +4680,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
switch_console_set_complete("add show timer");
switch_console_set_complete("add shutdown");
switch_console_set_complete("add sql_escape");
+ switch_console_set_complete("add unload ::console::list_loaded_modules");
switch_console_set_complete("add uuid_audio ::console::list_uuid start read mute");
switch_console_set_complete("add uuid_audio ::console::list_uuid start read level");
switch_console_set_complete("add uuid_audio ::console::list_uuid start write mute");
diff --git a/src/mod/applications/mod_curl/mod_curl.c b/src/mod/applications/mod_curl/mod_curl.c
old mode 100755
new mode 100644
index 9081ca6094..4f6aefd313
--- a/src/mod/applications/mod_curl/mod_curl.c
+++ b/src/mod/applications/mod_curl/mod_curl.c
@@ -272,6 +272,7 @@ SWITCH_STANDARD_APP(curl_app_function)
} else if (!strcasecmp("get", argv[i]) || !strcasecmp("head", argv[i])) {
method = switch_core_strdup(pool, argv[i]);
} else if (!strcasecmp("post", argv[i])) {
+ method = "post";
if (++i < argc) {
postdata = switch_core_strdup(pool, argv[i]);
switch_url_decode(postdata);
diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c
index bb88ac5b1a..69ce125d0f 100644
--- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c
+++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c
@@ -1001,7 +1001,13 @@ static int do_candidates(struct private_object *tech_pvt, int force)
cand[0].protocol = "udp";
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Send Candidate %s:%d [%s]\n", cand[0].address, cand[0].port,
cand[0].username);
- tech_pvt->cand_id = ldl_session_candidates(tech_pvt->dlsession, cand, 1);
+
+ if (ldl_session_gateway(tech_pvt->dlsession)) {
+ tech_pvt->cand_id = ldl_session_transport(tech_pvt->dlsession, cand, 1);
+ } else {
+ tech_pvt->cand_id = ldl_session_candidates(tech_pvt->dlsession, cand, 1);
+ }
+
switch_set_flag_locked(tech_pvt, TFLAG_TRANSPORT);
switch_set_flag_locked(tech_pvt, TFLAG_RTP_READY);
}
@@ -1112,6 +1118,7 @@ static switch_status_t negotiate_media(switch_core_session_t *session)
now = switch_micro_time_now();
elapsed = (unsigned int) ((now - started) / 1000);
+
if (switch_channel_down(channel) || switch_test_flag(tech_pvt, TFLAG_BYE)) {
goto out;
}
@@ -1643,6 +1650,8 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
char workspace[1024] = "";
char *p, *u, ubuf[512] = "", *user = NULL, *f_cid_msg = NULL;
const char *cid_msg = NULL;
+ ldl_user_flag_t flags = LDL_FLAG_OUTBOUND;
+
switch_copy_string(workspace, outbound_profile->destination_number, sizeof(workspace));
profile_name = workspace;
@@ -1711,7 +1720,10 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
terminate_session(new_session, __LINE__, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
}
- if (!(full_id = ldl_handle_probe(mdl_profile->handle, callto, user, idbuf, sizeof(idbuf)))) {
+ if (switch_stristr("voice.google.com", callto)) {
+ full_id = callto;
+ flags |= LDL_FLAG_GATEWAY;
+ } else if (!(full_id = ldl_handle_probe(mdl_profile->handle, callto, user, idbuf, sizeof(idbuf)))) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG, "Unknown Recipient!\n");
terminate_session(new_session, __LINE__, SWITCH_CAUSE_NO_USER_RESPONSE);
return SWITCH_CAUSE_NO_USER_RESPONSE;
@@ -1768,7 +1780,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
switch_stun_random_string(sess_id, 10, "0123456789");
tech_pvt->us = switch_core_session_strdup(*new_session, user);
tech_pvt->them = switch_core_session_strdup(*new_session, full_id);
- ldl_session_create(&dlsession, mdl_profile->handle, sess_id, full_id, user, LDL_FLAG_OUTBOUND);
+ ldl_session_create(&dlsession, mdl_profile->handle, sess_id, full_id, user, flags);
if (session) {
switch_channel_t *calling_channel = switch_core_session_get_channel(session);
@@ -1780,6 +1792,10 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
cid_msg = f_cid_msg;
}
+ if ((flags & LDL_FLAG_GATEWAY)) {
+ cid_msg = NULL;
+ }
+
if (cid_msg) {
char *them;
them = strdup(tech_pvt->them);
@@ -3128,6 +3144,11 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
break;
case LDL_SIGNAL_TRANSPORT_ACCEPT:
switch_set_flag_locked(tech_pvt, TFLAG_TRANSPORT_ACCEPT);
+
+ if (ldl_session_gateway(dlsession)) {
+ do_candidates(tech_pvt, 1);
+ }
+
break;
case LDL_SIGNAL_INITIATE:
if (dl_signal) {
@@ -3243,7 +3264,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
choice = x;
ok = 1;
}
-
+
if (ok) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "candidate %s:%d PASS ACL %s\n",
candidates[x].address, candidates[x].port, profile->acl[y]);
@@ -3348,6 +3369,10 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
goto done;
}
break;
+ case LDL_SIGNAL_REDIRECT:
+ do_describe(tech_pvt, 1);
+ break;
+
case LDL_SIGNAL_ERROR:
case LDL_SIGNAL_TERMINATE:
if (channel) {
diff --git a/src/mod/endpoints/mod_h323/changes.txt b/src/mod/endpoints/mod_h323/changes.txt
index 9dfda1e829..ff47780118 100644
--- a/src/mod/endpoints/mod_h323/changes.txt
+++ b/src/mod/endpoints/mod_h323/changes.txt
@@ -1,4 +1,3 @@
-set network_addr of caller profile to signaling ip address. (requested by Steven Ayre)
move PTrace level set to FSH323EndPoint::Initialise
partially apply patch from from Peter Olsson, Remove UnLock() when TryLock() failed and DEBUG_RTP_PACKETS directive.
apply changes from mod_h323-patch.diff by Peter Olsson.
diff --git a/src/mod/endpoints/mod_h323/compiling.txt b/src/mod/endpoints/mod_h323/compiling.txt
new file mode 100644
index 0000000000..91d547f13f
--- /dev/null
+++ b/src/mod/endpoints/mod_h323/compiling.txt
@@ -0,0 +1 @@
+To compile this module use latest ptlib/h323plis combinations listed at http://www.gnugk.org/compiling-gnugk.html
diff --git a/src/mod/endpoints/mod_h323/mod_h323.cpp b/src/mod/endpoints/mod_h323/mod_h323.cpp
index 45a9043d3f..aeee422ca5 100644
--- a/src/mod/endpoints/mod_h323/mod_h323.cpp
+++ b/src/mod/endpoints/mod_h323/mod_h323.cpp
@@ -614,7 +614,7 @@ H323Connection *FSH323EndPoint::CreateConnection(
}
switch_core_session_t *fsSession = switch_core_session_request(GetSwitchInterface(),
- (switch_caller_profile_t *)userData ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND, NULL);
+ (switch_caller_profile_t *)userData ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL);
if (fsSession == NULL)
return NULL;
diff --git a/src/mod/endpoints/mod_opal/mod_opal.cpp b/src/mod/endpoints/mod_opal/mod_opal.cpp
index e38e113196..8935bbb06d 100644
--- a/src/mod/endpoints/mod_opal/mod_opal.cpp
+++ b/src/mod/endpoints/mod_opal/mod_opal.cpp
@@ -513,7 +513,7 @@ OpalLocalConnection *FSEndPoint::CreateConnection(OpalCall & call, void *userDat
{
FSManager & mgr = (FSManager &) GetManager();
switch_core_session_t *fsSession = switch_core_session_request(mgr.GetSwitchInterface(),
- (switch_caller_profile_t *)userData ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND, NULL);
+ (switch_caller_profile_t *)userData ? SWITCH_CALL_DIRECTION_OUTBOUND : SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL);
if (fsSession == NULL)
return NULL;
diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c
index 9ee9e1e45d..5da1367a35 100644
--- a/src/mod/endpoints/mod_skinny/mod_skinny.c
+++ b/src/mod/endpoints/mod_skinny/mod_skinny.c
@@ -121,6 +121,7 @@ switch_status_t skinny_profile_dump(const skinny_profile_t *profile, switch_stre
stream->write_function(stream, "Date-Format \t%s\n", profile->date_format);
stream->write_function(stream, "DBName \t%s\n", profile->dbname ? profile->dbname : switch_str_nil(profile->odbc_dsn));
stream->write_function(stream, "Debug \t%d\n", profile->debug);
+ stream->write_function(stream, "Auto-Restart \t%d\n", profile->auto_restart);
/* stats */
stream->write_function(stream, "CALLS-IN \t%d\n", profile->ib_calls);
stream->write_function(stream, "FAILED-CALLS-IN \t%d\n", profile->ib_failed_calls);
@@ -1187,7 +1188,8 @@ uint8_t listener_is_ready(listener_t *listener)
&& listener
&& listener->sock
&& switch_test_flag(listener, LFLAG_RUNNING)
- && listener->profile->listener_ready;
+ && switch_test_flag(listener->profile, PFLAG_LISTENER_READY)
+ && !switch_test_flag(listener->profile, PFLAG_RESPAWN);
}
static void add_listener(listener_t *listener)
@@ -1248,7 +1250,7 @@ static void walk_listeners(skinny_listener_callback_func_t callback, void *pvt)
switch_mutex_unlock(globals.mutex);
}
-static void flush_listener(listener_t *listener, switch_bool_t flush_log, switch_bool_t flush_events)
+static void flush_listener(listener_t *listener)
{
if(!zstr(listener->device_name)) {
@@ -1410,7 +1412,17 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
status = skinny_read_packet(listener, &request);
if (status != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Socket Error!\n");
+ switch(status) {
+ case SWITCH_STATUS_BREAK:
+ break;
+ case SWITCH_STATUS_TIMEOUT:
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Communication Time Out with %s:%d.\n",
+ listener->remote_ip, listener->remote_port);
+ break;
+ default:
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Communication Error with %s:%d.\n",
+ listener->remote_ip, listener->remote_port);
+ }
switch_clear_flag_locked(listener, LFLAG_RUNNING);
break;
}
@@ -1432,11 +1444,12 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
remove_listener(listener);
if (listener->profile->debug > 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Session complete, waiting for children\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Communication Complete with %s:%d.\n",
+ listener->remote_ip, listener->remote_port);
}
switch_thread_rwlock_wrlock(listener->rwlock);
- flush_listener(listener, SWITCH_TRUE, SWITCH_TRUE);
+ flush_listener(listener);
if (listener->sock) {
close_socket(&listener->sock, profile);
@@ -1445,19 +1458,10 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
switch_thread_rwlock_unlock(listener->rwlock);
if (listener->profile->debug > 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connection Closed\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Communication Closed with %s:%d.\n",
+ listener->remote_ip, listener->remote_port);
}
- /* TODO
- for(int line = 0 ; line < SKINNY_MAX_BUTTON_COUNT ; line++) {
- if(listener->session[line]) {
- switch_channel_clear_flag(switch_core_session_get_channel(listener->session[line]), CF_CONTROLLED);
- //TODO switch_clear_flag_locked(listener, LFLAG_SESSION);
- switch_core_session_rwunlock(listener->session[line]);
- destroy_pool = 0;
- }
- }
- */
if(destroy_pool == 0) {
goto no_destroy_pool;
}
@@ -1502,6 +1506,7 @@ static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void
return NULL;
}
+new_socket:
while(globals.running) {
rv = switch_sockaddr_info_get(&sa, profile->ip, SWITCH_INET, profile->port, 0, tmp_pool);
if (rv)
@@ -1526,7 +1531,7 @@ static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void
switch_yield(100000);
}
- profile->listener_ready = 1;
+ switch_set_flag_locked(profile, PFLAG_LISTENER_READY);
while(globals.running) {
@@ -1539,6 +1544,10 @@ static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void
if (!globals.running) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting Down\n");
goto end;
+ } else if (switch_test_flag(profile, PFLAG_RESPAWN)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Creating a new socket\n");
+ switch_clear_flag_locked(profile, PFLAG_RESPAWN);
+ goto new_socket;
} else {
/* I wish we could use strerror_r here but its not defined everywhere =/ */
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error [%s]\n", strerror(errno));
@@ -1590,6 +1599,17 @@ static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void
return NULL;
}
+
+void launch_skinny_profile_thread(skinny_profile_t *profile) {
+ switch_thread_t *thread;
+ switch_threadattr_t *thd_attr = NULL;
+
+ switch_threadattr_create(&thd_attr, profile->pool);
+ switch_threadattr_detach_set(thd_attr, 1);
+ switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+ switch_thread_create(&thread, thd_attr, skinny_profile_run, profile, profile->pool);
+}
+
/*****************************************************************************/
/* MODULE FUNCTIONS */
/*****************************************************************************/
@@ -1603,9 +1623,9 @@ switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, c
if (!var)
return SWITCH_STATUS_FALSE;
- if (profile->sock && (!strcasecmp(var, "ip") || !strcasecmp(var, "port") || !strcasecmp(var, "odbc-dsn"))) {
+ if (profile->sock && !strcasecmp(var, "odbc-dsn")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
- "Skinny profile settings 'ip', 'port' and 'odbc-dsn' can't be changed while running\n");
+ "Skinny profile setting 'odbc-dsn' can't be changed while running\n");
return SWITCH_STATUS_FALSE;
}
@@ -1643,9 +1663,17 @@ switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, c
}
} else if (!strcasecmp(var, "debug")) {
profile->debug = atoi(val);
+ } else if (!strcasecmp(var, "auto-restart")) {
+ profile->auto_restart = switch_true(val);
} else {
return SWITCH_STATUS_FALSE;
}
+ if (profile->sock && (!strcasecmp(var, "ip") || !strcasecmp(var, "port"))) {
+ switch_set_flag_locked(profile, PFLAG_RESPAWN);
+ switch_clear_flag_locked(profile, PFLAG_LISTENER_READY);
+ close_socket(&profile->sock, profile);
+ }
+
return SWITCH_STATUS_SUCCESS;
}
@@ -1684,9 +1712,11 @@ static switch_status_t load_skinny_config(void)
profile = switch_core_alloc(profile_pool, sizeof(skinny_profile_t));
profile->pool = profile_pool;
profile->name = switch_core_strdup(profile->pool, profile_name);
- switch_mutex_init(&profile->listener_mutex, SWITCH_MUTEX_NESTED, profile->pool);
+ profile->auto_restart = SWITCH_TRUE;
switch_mutex_init(&profile->sql_mutex, SWITCH_MUTEX_NESTED, profile->pool);
+ switch_mutex_init(&profile->listener_mutex, SWITCH_MUTEX_NESTED, profile->pool);
switch_mutex_init(&profile->sock_mutex, SWITCH_MUTEX_NESTED, profile->pool);
+ switch_mutex_init(&profile->flag_mutex, SWITCH_MUTEX_NESTED, profile->pool);
for (param = switch_xml_child(xsettings, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
@@ -1950,6 +1980,41 @@ static void skinny_message_waiting_event_handler(switch_event_t *event)
}
+static void skinny_trap_event_handler(switch_event_t *event)
+{
+ const char *cond = switch_event_get_header(event, "condition");
+
+
+ if (cond && !strcmp(cond, "network-address-change") && globals.auto_restart) {
+ const char *old_ip4 = switch_event_get_header_nil(event, "network-address-previous-v4");
+ const char *new_ip4 = switch_event_get_header_nil(event, "network-address-change-v4");
+ const char *old_ip6 = switch_event_get_header_nil(event, "network-address-previous-v6");
+ const char *new_ip6 = switch_event_get_header_nil(event, "network-address-change-v6");
+ switch_hash_index_t *hi;
+ const void *var;
+ void *val;
+ skinny_profile_t *profile;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "EVENT_TRAP: IP change detected\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "IP change detected [%s]->[%s] [%s]->[%s]\n", old_ip4, new_ip4, old_ip6, new_ip6);
+
+ switch_mutex_lock(globals.mutex);
+ if (globals.profile_hash) {
+ for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, &var, NULL, &val);
+ if ((profile = (skinny_profile_t *) val) && profile->auto_restart) {
+ if (!strcmp(profile->ip, old_ip4)) {
+ skinny_profile_set(profile, "ip", new_ip4);
+ } else if (!strcmp(profile->ip, old_ip6)) {
+ skinny_profile_set(profile, "ip", new_ip6);
+ }
+ }
+ }
+ }
+ switch_mutex_unlock(globals.mutex);
+ }
+
+}
/*****************************************************************************/
SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)
{
@@ -1964,6 +2029,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)
switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool);
switch_core_hash_init(&globals.profile_hash, globals.pool);
globals.running = 1;
+ globals.auto_restart = SWITCH_TRUE;
load_skinny_config();
@@ -1980,6 +2046,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our message waiting handler!\n");
/* Not such severe to prevent loading */
}
+ if ((switch_event_bind_removable(modname, SWITCH_EVENT_TRAP, NULL, skinny_trap_event_handler, NULL, &globals.trap_node) != SWITCH_STATUS_SUCCESS)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our trap handler!\n");
+ /* Not such severe to prevent loading */
+ }
/* reserve events */
if (switch_event_reserve_subclass(SKINNY_EVENT_REGISTER) != SWITCH_STATUS_SUCCESS) {
@@ -2017,16 +2087,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)
for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
void *val;
skinny_profile_t *profile;
- switch_thread_t *thread;
- switch_threadattr_t *thd_attr = NULL;
switch_hash_this(hi, NULL, NULL, &val);
profile = (skinny_profile_t *) val;
-
- switch_threadattr_create(&thd_attr, profile->pool);
- switch_threadattr_detach_set(thd_attr, 1);
- switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
- switch_thread_create(&thread, thd_attr, skinny_profile_run, profile, profile->pool);
+
+ launch_skinny_profile_thread(profile);
}
switch_mutex_unlock(globals.mutex);
@@ -2048,6 +2113,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skinny_shutdown)
switch_event_unbind(&globals.heartbeat_node);
switch_event_unbind(&globals.call_state_node);
switch_event_unbind(&globals.message_waiting_node);
+ switch_event_unbind(&globals.trap_node);
switch_event_free_subclass(SKINNY_EVENT_REGISTER);
switch_event_free_subclass(SKINNY_EVENT_UNREGISTER);
switch_event_free_subclass(SKINNY_EVENT_EXPIRE);
diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.h b/src/mod/endpoints/mod_skinny/mod_skinny.h
index 41b9b72a6e..f52f171fdc 100644
--- a/src/mod/endpoints/mod_skinny/mod_skinny.h
+++ b/src/mod/endpoints/mod_skinny/mod_skinny.h
@@ -52,11 +52,18 @@ struct skinny_globals {
switch_event_node_t *heartbeat_node;
switch_event_node_t *call_state_node;
switch_event_node_t *message_waiting_node;
+ switch_event_node_t *trap_node;
+ int auto_restart;
};
typedef struct skinny_globals skinny_globals_t;
extern skinny_globals_t globals;
+typedef enum {
+ PFLAG_LISTENER_READY = (1 << 0),
+ PFLAG_RESPAWN = (1 << 1),
+} profile_flag_t;
+
struct skinny_profile {
/* prefs */
char *name;
@@ -70,6 +77,7 @@ struct skinny_profile {
uint32_t keep_alive;
char date_format[6];
int debug;
+ int auto_restart;
switch_hash_t *device_type_params_hash;
/* db */
char *dbname;
@@ -89,7 +97,8 @@ struct skinny_profile {
switch_socket_t *sock;
switch_mutex_t *sock_mutex;
struct listener *listeners;
- uint8_t listener_ready;
+ int flags;
+ switch_mutex_t *flag_mutex;
/* call id */
uint32_t next_call_id;
/* others */
@@ -114,7 +123,7 @@ typedef enum {
typedef enum {
LFLAG_RUNNING = (1 << 0),
-} event_flag_t;
+} listener_flag_t;
#define SKINNY_MAX_LINES 42
struct listener {
diff --git a/src/mod/endpoints/mod_skinny/skinny_api.c b/src/mod/endpoints/mod_skinny/skinny_api.c
index 0ef0beb2d5..86eea74fc8 100644
--- a/src/mod/endpoints/mod_skinny/skinny_api.c
+++ b/src/mod/endpoints/mod_skinny/skinny_api.c
@@ -230,6 +230,7 @@ static switch_status_t skinny_api_list_settings(const char *line, const char *cu
switch_console_push_match(&my_matches, "date-format");
switch_console_push_match(&my_matches, "odbc-dsn");
switch_console_push_match(&my_matches, "debug");
+ switch_console_push_match(&my_matches, "auto-restart");
if (my_matches) {
*matches = my_matches;
diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.c b/src/mod/endpoints/mod_skinny/skinny_protocol.c
index ba4cba70db..28699b9c03 100644
--- a/src/mod/endpoints/mod_skinny/skinny_protocol.c
+++ b/src/mod/endpoints/mod_skinny/skinny_protocol.c
@@ -119,7 +119,7 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
}
if (!listener_is_ready(listener)) {
- return SWITCH_STATUS_FALSE;
+ return SWITCH_STATUS_BREAK;
}
ptr = mbuf;
@@ -136,7 +136,10 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
status = switch_socket_recv(listener->sock, ptr, &mlen);
- if (!listener_is_ready(listener) || (!SWITCH_STATUS_IS_BREAK(status) && status != SWITCH_STATUS_SUCCESS)) {
+ if (!listener_is_ready(listener)) {
+ return SWITCH_STATUS_BREAK;
+ }
+ if (!SWITCH_STATUS_IS_BREAK(status) && status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Socket break.\n");
return SWITCH_STATUS_FALSE;
}
@@ -167,20 +170,13 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
}
if(bytes >= request->length + 2*SKINNY_MESSAGE_FIELD_SIZE) {
/* Message body */
-#ifdef SKINNY_MEGA_DEBUG
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
- "Got complete request: length=%d,reserved=%x,type=%x,data=%d\n",
- request->length,request->reserved,request->type,request->data.as_char);
-#endif
*req = request;
return SWITCH_STATUS_SUCCESS;
}
}
}
if (listener->expire_time && listener->expire_time < switch_epoch_time_now(NULL)) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Listener timed out.\n");
- switch_clear_flag_locked(listener, LFLAG_RUNNING);
- return SWITCH_STATUS_FALSE;
+ return SWITCH_STATUS_TIMEOUT;
}
if (do_sleep) {
switch_cond_next();
diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c
index 16b928bb47..14d05fd977 100644
--- a/src/mod/endpoints/mod_sofia/sofia.c
+++ b/src/mod/endpoints/mod_sofia/sofia.c
@@ -436,18 +436,24 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status,
mwi_status = switch_stristr("Messages-Waiting: ", sip->sip_payload->pl_data);
if ( mwi_status ) {
+ char *mwi_stat;
mwi_status += strlen( "Messages-Waiting: " );
- mwi_status = switch_strip_whitespace( mwi_status );
+ mwi_stat = switch_strip_whitespace( mwi_status );
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Forwarding unsolicited MWI ( %s : %s@%s )\n", mwi_status, sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host );
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG,
+ "Forwarding unsolicited MWI ( %s : %s@%s )\n",
+ mwi_stat, sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host );
if (switch_event_create(&s_event, SWITCH_EVENT_MESSAGE_WAITING) == SWITCH_STATUS_SUCCESS) {
- switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "MWI-Messages-Waiting", mwi_status );
- switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "MWI-Message-Account", "%s@%s", sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host );
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "MWI-Messages-Waiting", mwi_stat );
+ switch_event_add_header(s_event, SWITCH_STACK_BOTTOM,
+ "MWI-Message-Account", "%s@%s", sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host );
switch_event_fire(&s_event);
}
+ switch_safe_free(mwi_stat);
}
} else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Dropping unsolicited MWI ( %s@%s ) because of ACL\n", sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host );
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Dropping unsolicited MWI ( %s@%s ) because of ACL\n",
+ sip->sip_to->a_url->url_user, sip->sip_to->a_url->url_host );
};
}
diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c
index 39b495d392..73d930314b 100644
--- a/src/mod/endpoints/mod_sofia/sofia_presence.c
+++ b/src/mod/endpoints/mod_sofia/sofia_presence.c
@@ -565,34 +565,32 @@ static void actual_sofia_presence_event_handler(switch_event_t *event)
probe_euser = (p + 1);
}
-
-
-
if (probe_euser && probe_host && (profile = sofia_glue_find_profile(probe_host))) {
sql = switch_mprintf("select status,rpid from sip_dialogs where sip_from_user='%q' and sip_from_host='%q'", probe_euser, probe_host);
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh);
switch_safe_free(sql);
- sql = switch_mprintf("select sip_registrations.sip_user, '%q', sip_registrations.status, "
+ sql = switch_mprintf("select sip_registrations.sip_user, sip_registrations.orig_server_host, sip_registrations.status, "
"sip_registrations.rpid,'', sip_dialogs.uuid, sip_dialogs.state, sip_dialogs.direction, "
"sip_dialogs.sip_to_user, sip_dialogs.sip_to_host, sip_presence.status,sip_presence.rpid,sip_presence.open_closed,"
"'%q','%q' "
"from sip_registrations left join sip_dialogs on "
"(sip_dialogs.sip_from_user = sip_registrations.sip_user "
- "and sip_dialogs.sip_from_host = sip_registrations.sip_host) "
+ "and (sip_dialogs.sip_from_host = sip_registrations.orig_server_host or "
+ "sip_dialogs.sip_from_host = sip_registrations.sip_host) ) "
"left join sip_presence on "
- "(sip_registrations.sip_user=sip_presence.sip_user and sip_registrations.sip_host=sip_presence.sip_host and "
+ "(sip_registrations.sip_user=sip_presence.sip_user and sip_registrations.orig_server_host=sip_presence.sip_host and "
"sip_registrations.profile_name=sip_presence.profile_name) "
"where sip_registrations.sip_user='%q' and "
- "(sip_registrations.sip_host='%q' or sip_registrations.presence_hosts like '%%%q%%')",
- probe_host, dh.status, dh.rpid, probe_euser, probe_host, probe_host);
+ "(sip_registrations.orig_server_host='%q' or sip_registrations.sip_host='%q' "
+ "or sip_registrations.presence_hosts like '%%%q%%')",
+ dh.status, dh.rpid, probe_euser, probe_host, probe_host, probe_host);
switch_assert(sql);
-
if (mod_sofia_globals.debug_presence > 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s START_PRESENCE_PROBE_SQL\n", profile->name);
}
@@ -622,6 +620,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event)
sofia_glue_release_profile(profile);
switch_safe_free(sql);
}
+
switch_safe_free(probe_user);
}
@@ -961,7 +960,7 @@ static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char
switch_event_header_t *hp;
if (argc > 5) {
- uuid = switch_str_nil(argv[5]);
+ uuid = argv[5];
state = switch_str_nil(argv[6]);
direction = switch_str_nil(argv[7]);
if (argc > 8) {
@@ -998,12 +997,13 @@ static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char
}
if (zstr(state)) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", SOFIA_CHAT_PROTO);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_HANGUP");
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "resubscribe");
+ //switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", "resubscribe");
} else {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING");
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", uuid);
+ if (uuid) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "unique-id", uuid);
+ }
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "answer-state", state);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "astate", state);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "presence-call-direction", direction);
@@ -1317,15 +1317,21 @@ static int sofia_presence_sub_callback(void *pArg, int argc, char **argv, char *
}
if (is_dialog) {
+ char *version = switch_event_get_header(helper->event, "event_count");
+ if (!version) {
+ version = "0";
+ }
+
stream.write_function(&stream,
"\n"
"\n",
- switch_str_nil(switch_event_get_header(helper->event, "event_count")),
- !strcasecmp(answer_state, "resubscribe") ? "partial" : "full", clean_id);
+ version,
+ zstr(uuid) ? "partial" : "full", clean_id);
}
- if (strcasecmp(event_status, "Registered")) {
+ //if (strcasecmp(event_status, "Registered")) {
+ if (!zstr(uuid)) {
if (!zstr(answer_state)) {
astate = answer_state;
}
@@ -2232,8 +2238,11 @@ void sofia_presence_handle_sip_i_subscribe(int status,
if (switch_event_create(&pevent, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "login", profile->url);
- switch_event_add_header(pevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, to_host);
+ //switch_event_add_header(pevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, to_host);
+ switch_event_add_header(pevent, SWITCH_STACK_BOTTOM, "from", "%s@%s", from_user, from_host);
+ switch_event_add_header(pevent, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, to_host);
switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "event_type", "presence");
+ switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "event_subtype", "probe");
switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "proto-specific-event-name", event);
switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str);
diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c
index 18df1c4398..6b90b775fc 100644
--- a/src/mod/endpoints/mod_sofia/sofia_reg.c
+++ b/src/mod/endpoints/mod_sofia/sofia_reg.c
@@ -787,6 +787,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
const char *from_user = NULL;
const char *from_host = NULL;
const char *reg_host = profile->reg_db_domain;
+ const char *sub_host = profile->sub_domain;
char contact_str[1024] = "";
int nat_hack = 0;
uint8_t multi_reg = 0, multi_reg_contact = 0, avoid_multi_reg = 0;
@@ -851,6 +852,9 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
if (!reg_host) {
reg_host = to_host;
}
+ if (!sub_host) {
+ sub_host = to_host;
+ }
if (contact->m_url) {
const char *port = contact->m_url->url_port;
@@ -1146,11 +1150,14 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
}
if (multi_reg) {
+
+#ifdef DEL_SUBS
if (reg_count == 1) {
sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'",
- to_user, reg_host, contact_str);
+ to_user, sub_host, contact_str);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
+#endif
if (multi_reg_contact) {
@@ -1160,14 +1167,35 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
sql = switch_mprintf("delete from sip_registrations where call_id='%q'", call_id);
}
} else {
- sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, reg_host);
+#ifdef DEL_SUBS
+ sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
+#endif
sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host);
}
switch_mutex_lock(profile->ireg_mutex);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL, AF_INET);
+
+ if (profile->reg_db_domain) {
+ sofia_profile_t *xprofile;
+
+ if ((xprofile = sofia_glue_find_profile(to_host))) {
+ sofia_glue_release_profile(xprofile);
+ } else {
+
+ if (sofia_glue_add_profile(switch_core_strdup(profile->pool, to_host), profile) == SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Auto-Adding Alias [%s] for profile [%s]\n", to_host, profile->name);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Alias [%s] for profile [%s] (already exists)\n",
+ to_host, profile->name);
+ }
+
+
+ }
+ }
+
sql = switch_mprintf("insert into sip_registrations "
"(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires,"
@@ -1220,7 +1248,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "user-agent",
(sip && sip->sip_user_agent) ? sip->sip_user_agent->g_string : "unknown");
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, reg_host);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "Registered");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_fire(&event);
@@ -1234,8 +1262,8 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", "sip");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, reg_host);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, reg_host);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, sub_host);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "Registered");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_subtype", "probe");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
@@ -1253,7 +1281,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "user-agent",
(sip && sip->sip_user_agent) ? sip->sip_user_agent->g_string : "unknown");
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, reg_host);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "Unregistered");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_fire(&event);
@@ -1262,7 +1290,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
if (switch_event_create(&event, SWITCH_EVENT_PRESENCE_OUT) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", "sip");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s+%s@%s", SOFIA_CHAT_PROTO, to_user, reg_host);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from", "%s+%s@%s", SOFIA_CHAT_PROTO, to_user, sub_host);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "status", "unavailable");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid);
@@ -1280,15 +1308,16 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
if ((p = strchr(icontact + 4, ':'))) {
*p = '\0';
}
-
+#ifdef DEL_SUBS
if (multi_reg_contact) {
sql =
- switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, reg_host, contact_str);
+ switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'", to_user, sub_host, contact_str);
} else {
sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", call_id);
}
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
+#endif
if (multi_reg_contact) {
sql =
@@ -1301,10 +1330,11 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_safe_free(icontact);
} else {
- if ((sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, reg_host))) {
+#ifdef DEL_SUBS
+ if ((sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q'", to_user, sub_host))) {
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
-
+#endif
if ((sql = switch_mprintf("delete from sip_registrations where sip_user='%q' and sip_host='%q'", to_user, reg_host))) {
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
}
@@ -1333,15 +1363,26 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
}
+#if 0
+ if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_PROBE) == SWITCH_STATUS_SUCCESS) {
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name);
+ switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
+ switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, sub_host);
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "event_type", "presence");
+ switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "alt_event_type", "dialog");
+ switch_event_fire(&s_event);
+ }
+#else
if (switch_event_create(&s_event, SWITCH_EVENT_PRESENCE_IN) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name);
- switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, reg_host);
+ switch_event_add_header(s_event, SWITCH_STACK_BOTTOM, "from", "%s@%s", to_user, sub_host);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "rpid", "unknown");
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Registered");
switch_event_fire(&s_event);
- }
-
+ }
+#endif
} else {
if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_UNREGISTER) == SWITCH_STATUS_SUCCESS) {
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);
diff --git a/src/mod/languages/mod_managed/managed/FreeSWITCH.Managed.2010.csproj b/src/mod/languages/mod_managed/managed/FreeSWITCH.Managed.2010.csproj
index 740ae04cff..4c1382b9a6 100644
--- a/src/mod/languages/mod_managed/managed/FreeSWITCH.Managed.2010.csproj
+++ b/src/mod/languages/mod_managed/managed/FreeSWITCH.Managed.2010.csproj
@@ -24,7 +24,7 @@
true
full
false
- ..\..\..\..\..\managed\debug\
+ ..\..\..\..\..\Win32\Debug\mod\
TRACE;DEBUG;CLR_VERSION40
prompt
4
@@ -32,11 +32,33 @@
pdbonly
true
- ..\..\..\..\..\managed\release\
+ ..\..\..\..\..\Win32\Release\mod\
TRACE;CLR_VERSION40
prompt
4
+
+ true
+ ..\..\..\..\..\x64\Debug\mod\
+ TRACE;DEBUG;CLR_VERSION40
+ full
+ x64
+ prompt
+ true
+ true
+ true
+
+
+ ..\..\..\..\..\x64\Release\mod\
+ TRACE;CLR_VERSION40
+ true
+ pdbonly
+ x64
+ prompt
+ true
+ true
+ true
+
diff --git a/src/mod/languages/mod_managed/mod_managed.2010.vcxproj b/src/mod/languages/mod_managed/mod_managed.2010.vcxproj
index 76ce260a91..ee1f7d7e96 100644
--- a/src/mod/languages/mod_managed/mod_managed.2010.vcxproj
+++ b/src/mod/languages/mod_managed/mod_managed.2010.vcxproj
@@ -319,11 +319,9 @@
{202d7a4e-760d-4d0e-afa1-d7459ced30ff}
- false
-
+
{834e2b2f-5483-4b80-8fe3-fe48ff76e5c0}
- false
diff --git a/src/switch_console.c b/src/switch_console.c
index e82290bce7..30d1d97fed 100644
--- a/src/switch_console.c
+++ b/src/switch_console.c
@@ -553,6 +553,46 @@ struct match_helper {
switch_console_callback_match_t *my_matches;
};
+static int modulename_callback(void *pArg, const char *module_name)
+{
+ struct match_helper *h = (struct match_helper *) pArg;
+
+ switch_console_push_match(&h->my_matches, module_name);
+ return 0;
+}
+
+SWITCH_DECLARE_NONSTD(switch_status_t) switch_console_list_available_modules(const char *line, const char *cursor, switch_console_callback_match_t **matches)
+{
+ struct match_helper h = { 0 };
+
+ if (switch_loadable_module_enumerate_available(SWITCH_GLOBAL_dirs.mod_dir, modulename_callback, &h) != SWITCH_STATUS_SUCCESS) {
+ return SWITCH_STATUS_GENERR;
+ }
+
+ if (h.my_matches) {
+ *matches = h.my_matches;
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ return SWITCH_STATUS_FALSE;
+}
+
+SWITCH_DECLARE_NONSTD(switch_status_t) switch_console_list_loaded_modules(const char *line, const char *cursor, switch_console_callback_match_t **matches)
+{
+ struct match_helper h = { 0 };
+
+ if (switch_loadable_module_enumerate_loaded(modulename_callback, &h) != SWITCH_STATUS_SUCCESS) {
+ return SWITCH_STATUS_GENERR;
+ }
+
+ if (h.my_matches) {
+ *matches = h.my_matches;
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ return SWITCH_STATUS_FALSE;
+}
+
static int uuid_callback(void *pArg, int argc, char **argv, char **columnNames)
{
struct match_helper *h = (struct match_helper *) pArg;
@@ -1542,6 +1582,8 @@ SWITCH_DECLARE(switch_status_t) switch_console_init(switch_memory_pool_t *pool)
{
switch_mutex_init(&globals.func_mutex, SWITCH_MUTEX_NESTED, pool);
switch_core_hash_init(&globals.func_hash, pool);
+ switch_console_add_complete_func("::console::list_available_modules", (switch_console_complete_callback_t) switch_console_list_available_modules);
+ switch_console_add_complete_func("::console::list_loaded_modules", (switch_console_complete_callback_t) switch_console_list_loaded_modules);
switch_console_add_complete_func("::console::list_uuid", (switch_console_complete_callback_t) switch_console_list_uuid);
return SWITCH_STATUS_SUCCESS;
}
diff --git a/src/switch_event.c b/src/switch_event.c
index 1301d92477..cfd6a7a139 100644
--- a/src/switch_event.c
+++ b/src/switch_event.c
@@ -79,6 +79,7 @@ static switch_memory_pool_t *THRUNTIME_POOL = NULL;
static switch_thread_t *EVENT_QUEUE_THREADS[NUMBER_OF_QUEUES] = { 0 };
static switch_queue_t *EVENT_QUEUE[NUMBER_OF_QUEUES] = { 0 };
static switch_thread_t *EVENT_DISPATCH_QUEUE_THREADS[MAX_DISPATCH_VAL] = { 0 };
+static uint8_t EVENT_DISPATCH_QUEUE_RUNNING[MAX_DISPATCH_VAL] = { 0 };
static switch_queue_t *EVENT_DISPATCH_QUEUE[MAX_DISPATCH_VAL] = { 0 };
static int POOL_COUNT_MAX = SWITCH_CORE_QUEUE_LEN;
static switch_mutex_t *EVENT_QUEUE_MUTEX = NULL;
@@ -238,9 +239,9 @@ static void *SWITCH_THREAD_FUNC switch_event_dispatch_thread(switch_thread_t *th
{
switch_queue_t *queue = (switch_queue_t *) obj;
int my_id = 0;
+
switch_mutex_lock(EVENT_QUEUE_MUTEX);
THREAD_COUNT++;
- switch_mutex_unlock(EVENT_QUEUE_MUTEX);
for (my_id = 0; my_id < NUMBER_OF_QUEUES; my_id++) {
if (EVENT_DISPATCH_QUEUE[my_id] == queue) {
@@ -248,6 +249,9 @@ static void *SWITCH_THREAD_FUNC switch_event_dispatch_thread(switch_thread_t *th
}
}
+ EVENT_DISPATCH_QUEUE_RUNNING[my_id] = 1;
+ switch_mutex_unlock(EVENT_QUEUE_MUTEX);
+
for (;;) {
void *pop = NULL;
switch_event_t *event = NULL;
@@ -270,6 +274,7 @@ static void *SWITCH_THREAD_FUNC switch_event_dispatch_thread(switch_thread_t *th
switch_mutex_lock(EVENT_QUEUE_MUTEX);
+ EVENT_DISPATCH_QUEUE_RUNNING[my_id] = 1;
THREAD_COUNT--;
switch_mutex_unlock(EVENT_QUEUE_MUTEX);
@@ -298,6 +303,7 @@ static void *SWITCH_THREAD_FUNC switch_event_thread(switch_thread_t *thread, voi
for (;;) {
void *pop = NULL;
switch_event_t *event = NULL;
+ int loops = 0;
if (switch_queue_pop(queue, &pop) != SWITCH_STATUS_SUCCESS) {
break;
@@ -314,13 +320,13 @@ static void *SWITCH_THREAD_FUNC switch_event_thread(switch_thread_t *thread, voi
event = (switch_event_t *) pop;
while (event) {
- int max;
- switch_mutex_lock(EVENT_QUEUE_MUTEX);
- max = SOFT_MAX_DISPATCH;
- switch_mutex_unlock(EVENT_QUEUE_MUTEX);
+ if (++loops > 2) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Event system overloading\n");
+ switch_yield(1000000);
+ }
- for (index = 0; (int)index < max; index++) {
+ for (index = 0; index < SOFT_MAX_DISPATCH; index++) {
if (switch_queue_trypush(EVENT_DISPATCH_QUEUE[index], event) == SWITCH_STATUS_SUCCESS) {
event = NULL;
break;
@@ -328,19 +334,15 @@ static void *SWITCH_THREAD_FUNC switch_event_thread(switch_thread_t *thread, voi
}
if (event) {
- switch_mutex_lock(EVENT_QUEUE_MUTEX);
if (SOFT_MAX_DISPATCH + 1 < MAX_DISPATCH) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Adding a new event thread #%d\n", SOFT_MAX_DISPATCH + 1);
+ switch_mutex_lock(EVENT_QUEUE_MUTEX);
launch_dispatch_threads(SOFT_MAX_DISPATCH + 1, DISPATCH_QUEUE_LEN, RUNTIME_POOL);
+ switch_mutex_unlock(EVENT_QUEUE_MUTEX);
} else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Event threads maxed out at %d.\n", SOFT_MAX_DISPATCH);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Out of threads!\n");
switch_yield(1000000);
}
- switch_mutex_unlock(EVENT_QUEUE_MUTEX);
}
-
-
- switch_cond_next();
}
}
@@ -566,6 +568,8 @@ static void launch_dispatch_threads(uint32_t max, int len, switch_memory_pool_t
{
switch_threadattr_t *thd_attr;
uint32_t index = 0;
+ int launched = 0;
+ uint32_t sanity = 200;
if (max > MAX_DISPATCH) {
return;
@@ -584,8 +588,10 @@ static void launch_dispatch_threads(uint32_t max, int len, switch_memory_pool_t
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
switch_threadattr_priority_increase(thd_attr);
switch_thread_create(&EVENT_DISPATCH_QUEUE_THREADS[index], thd_attr, switch_event_dispatch_thread, EVENT_DISPATCH_QUEUE[index], pool);
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Create event dispatch thread %d\n", index);
- switch_yield(100000);
+ while(--sanity && !EVENT_DISPATCH_QUEUE_RUNNING[index]) switch_yield(10000);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Create event dispatch thread %d\n", index);
+ launched++;
+ break;
}
SOFT_MAX_DISPATCH = index;
diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c
index 97cb5e8d70..0ef3624326 100644
--- a/src/switch_loadable_module.c
+++ b/src/switch_loadable_module.c
@@ -1068,6 +1068,62 @@ SWITCH_DECLARE(switch_status_t) switch_loadable_module_unload_module(char *dir,
}
+SWITCH_DECLARE(switch_status_t) switch_loadable_module_enumerate_available(const char *dir_path, switch_modulename_callback_func_t callback, void *user_data)
+{
+ switch_dir_t *dir = NULL;
+ switch_status_t status;
+ char buffer[256];
+ const char *fname;
+ const char *fname_ext;
+ char *fname_base;
+
+#ifdef WIN32
+ const char *ext = ".dll";
+#else
+ const char *ext = ".so";
+#endif
+
+ if ((status = switch_dir_open(&dir, dir_path, loadable_modules.pool)) != SWITCH_STATUS_SUCCESS) {
+ return status;
+ }
+
+ while((fname = switch_dir_next_file(dir, buffer, sizeof(buffer)))) {
+ if ((fname_ext = strrchr(fname, '.'))) {
+ if (!strcmp(fname_ext, ext)) {
+ if (!(fname_base = switch_mprintf("%.*s", (int)(fname_ext-fname), fname))) {
+ status = SWITCH_STATUS_GENERR;
+ goto end;
+ }
+ callback(user_data, fname_base);
+ switch_safe_free(fname_base)
+ }
+ }
+ }
+
+
+ end:
+ switch_dir_close(dir);
+ return status;
+}
+
+SWITCH_DECLARE(switch_status_t) switch_loadable_module_enumerate_loaded(switch_modulename_callback_func_t callback, void *user_data)
+{
+ switch_hash_index_t *hi;
+ void *val;
+ switch_loadable_module_t *module;
+
+ switch_mutex_lock(loadable_modules.mutex);
+ for (hi = switch_hash_first(NULL, loadable_modules.module_hash); hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, NULL, NULL, &val);
+ module = (switch_loadable_module_t *) val;
+
+ callback(user_data, module->module_interface->module_name);
+ }
+ switch_mutex_unlock(loadable_modules.mutex);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
SWITCH_DECLARE(switch_status_t) switch_loadable_module_build_dynamic(char *filename,
switch_module_load_t switch_module_load,
switch_module_runtime_t switch_module_runtime,
@@ -1627,27 +1683,34 @@ SWITCH_DECLARE(switch_status_t) switch_api_execute(const char *cmd, const char *
{
switch_api_interface_t *api;
switch_status_t status;
+ char *arg_no_spaces;
+ char *cmd_no_spaces;
switch_assert(stream != NULL);
switch_assert(stream->data != NULL);
switch_assert(stream->write_function != NULL);
+
+ cmd_no_spaces = switch_strip_whitespace(cmd);
+ arg_no_spaces = switch_strip_whitespace(arg);
+
+
if (!stream->param_event) {
switch_event_create(&stream->param_event, SWITCH_EVENT_API);
}
if (stream->param_event) {
- if (cmd) {
- switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command", cmd);
+ if (cmd_no_spaces) {
+ switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command", cmd_no_spaces);
}
- if (arg) {
- switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command-Argument", arg);
+ if (arg_no_spaces) {
+ switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command-Argument", arg_no_spaces);
}
}
- if (cmd && (api = switch_loadable_module_get_api_interface(cmd)) != 0) {
- if ((status = api->function(arg, session, stream)) != SWITCH_STATUS_SUCCESS) {
+ if (cmd_no_spaces && (api = switch_loadable_module_get_api_interface(cmd_no_spaces)) != 0) {
+ if ((status = api->function(arg_no_spaces, session, stream)) != SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "COMMAND RETURNED ERROR!\n");
}
UNPROTECT_INTERFACE(api);
@@ -1660,6 +1723,8 @@ SWITCH_DECLARE(switch_status_t) switch_api_execute(const char *cmd, const char *
switch_event_fire(&stream->param_event);
}
+ switch_safe_free(cmd_no_spaces);
+ switch_safe_free(arg_no_spaces);
return status;
}
diff --git a/src/switch_resample.c b/src/switch_resample.c
index 3264b9ed99..65ebe3c32f 100644
--- a/src/switch_resample.c
+++ b/src/switch_resample.c
@@ -26,7 +26,7 @@
* Anthony Minessale II
*
*
- * switch_caller.c -- Caller Identification
+ * switch_resample.c -- Resampler
*
*/
diff --git a/src/switch_utils.c b/src/switch_utils.c
index d7c5d6b6d4..91b78f7bbb 100644
--- a/src/switch_utils.c
+++ b/src/switch_utils.c
@@ -724,7 +724,7 @@ SWITCH_DECLARE(char *) switch_strip_whitespace(const char *str)
if (!sp)
return NULL;
- while ((*sp == 13 ) || (*sp == 10 ) || (*sp == 9 ) || (*sp == 20) || (*sp == 11) ) {
+ while ((*sp == 13 ) || (*sp == 10 ) || (*sp == 9 ) || (*sp == 32) || (*sp == 11) ) {
sp++;
}
@@ -735,7 +735,7 @@ SWITCH_DECLARE(char *) switch_strip_whitespace(const char *str)
p = s + (strlen(s) - 1);
- while ((*p == 13 ) || (*p == 10 ) || (*p == 9 ) || (*p == 20) || (*p == 11) ) {
+ while ((*p == 13 ) || (*p == 10 ) || (*p == 9 ) || (*p == 32) || (*p == 11) ) {
*p-- = '\0';
}