Merge branch 'master' of homer:smg_freeswitch into davidy_test

This commit is contained in:
David Yat Sin 2010-09-03 12:34:25 -04:00
commit 09a8f6b19a
35 changed files with 984 additions and 255 deletions

View File

@ -1771,12 +1771,12 @@ Global
{834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.All|x64.ActiveCfg = Release|Any CPU {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.ActiveCfg = Debug|Any CPU
{834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|Win32.Build.0 = 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.ActiveCfg = Debug|x64
{834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Debug|x64.Build.0 = Debug|Any CPU {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.ActiveCfg = Release|Any CPU
{834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|Win32.Build.0 = 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.ActiveCfg = Release|x64
{834E2B2F-5483-4B80-8FE3-FE48FF76E5C0}.Release|x64.Build.0 = Release|Any CPU {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.ActiveCfg = Release|Win32
{E796E337-DE78-4303-8614-9A590862EE95}.All|Win32.Build.0 = Release|Win32 {E796E337-DE78-4303-8614-9A590862EE95}.All|Win32.Build.0 = Release|Win32
{E796E337-DE78-4303-8614-9A590862EE95}.All|x64.ActiveCfg = Release|Win32 {E796E337-DE78-4303-8614-9A590862EE95}.All|x64.ActiveCfg = Release|Win32

View File

@ -341,7 +341,7 @@ rm -rf autom4te*.cache
echo "Entering directory ${LIBDIR}/apr-util" echo "Entering directory ${LIBDIR}/apr-util"
cd ${LIBDIR}/apr-util cd ${LIBDIR}/apr-util
if [ "${BGJOB}" == "false" ] ; then if [ "${BGJOB}" = "false" ] ; then
./buildconf ./buildconf
else else
./buildconf & ./buildconf &
@ -350,14 +350,14 @@ fi
for i in ${SUBDIRS} for i in ${SUBDIRS}
do do
if [ "${BGJOB}" == "false" ] ; then if [ "${BGJOB}" = "false" ] ; then
libbootstrap ${i} libbootstrap ${i}
else else
libbootstrap ${i} & libbootstrap ${i} &
fi fi
done done
if [ "${BGJOB}" == "true" ] ; then if [ "${BGJOB}" = "true" ] ; then
wait wait
fi fi
cd ${BASEDIR} cd ${BASEDIR}

View File

@ -596,7 +596,7 @@
<extension name="ringback_183_uk_ring"> <extension name="ringback_183_uk_ring">
<condition field="destination_number" expression="^9181$"> <condition field="destination_number" expression="^9181$">
<action application="set" data="ringback=$${uk-ring}"/> <action application="set" data="ringback=$${uk-ring}"/>
<action application="bridge" data="loopback/wait"/> <action application="bridge" data="{ignore_early_media=true}loopback/wait"/>
</condition> </condition>
</extension> </extension>
@ -604,7 +604,7 @@
<extension name="ringback_183_music_ring"> <extension name="ringback_183_music_ring">
<condition field="destination_number" expression="^9182$"> <condition field="destination_number" expression="^9182$">
<action application="set" data="ringback=$${hold_music}"/> <action application="set" data="ringback=$${hold_music}"/>
<action application="bridge" data="loopback/wait"/> <action application="bridge" data="{ignore_early_media=true}loopback/wait"/>
</condition> </condition>
</extension> </extension>
@ -613,7 +613,7 @@
<condition field="destination_number" expression="^9183$"> <condition field="destination_number" expression="^9183$">
<action application="set" data="transfer_ringback=$${uk-ring}"/> <action application="set" data="transfer_ringback=$${uk-ring}"/>
<action application="answer"/> <action application="answer"/>
<action application="bridge" data="loopback/wait"/> <action application="bridge" data="{ignore_early_media=true}loopback/wait"/>
</condition> </condition>
</extension> </extension>
@ -622,7 +622,7 @@
<condition field="destination_number" expression="^9184$"> <condition field="destination_number" expression="^9184$">
<action application="set" data="transfer_ringback=$${hold_music}"/> <action application="set" data="transfer_ringback=$${hold_music}"/>
<action application="answer"/> <action application="answer"/>
<action application="bridge" data="loopback/wait"/> <action application="bridge" data="{ignore_early_media=true}loopback/wait"/>
</condition> </condition>
</extension> </extension>

View File

@ -11,6 +11,7 @@
<param name="date-format" value="D/M/Y"/> <param name="date-format" value="D/M/Y"/>
<param name="odbc-dsn" value=""/> <param name="odbc-dsn" value=""/>
<param name="debug" value="4"/> <param name="debug" value="4"/>
<param name="auto-restart" value="true"/>
</settings> </settings>
<device-types> <device-types>
<device-type id="Cisco ATA 186"> <device-type id="Cisco ATA 186">

View File

@ -373,6 +373,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_signal(ftdm_interrupt_t *interrupt)
if (!SetEvent(interrupt->event)) { if (!SetEvent(interrupt->event)) {
ftdm_log(FTDM_LOG_ERROR, "Failed to signal interrupt\n"); ftdm_log(FTDM_LOG_ERROR, "Failed to signal interrupt\n");
return FTDM_FAIL; return FTDM_FAIL;
} }
#else #else
int err; int err;
@ -404,6 +405,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_destroy(ftdm_interrupt_t **ininterrupt)
#else #else
close(interrupt->readfd); close(interrupt->readfd);
close(interrupt->writefd); close(interrupt->writefd);
interrupt->readfd = -1; interrupt->readfd = -1;
interrupt->writefd = -1; interrupt->writefd = -1;
#endif #endif
@ -416,6 +418,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru
{ {
int numdevices = 0; int numdevices = 0;
unsigned i; unsigned i;
#if defined(__WINDOWS__) #if defined(__WINDOWS__)
DWORD res = 0; DWORD res = 0;
HANDLE ints[20]; 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++) { for (i = 0; i < size; i++) {
ints[i] = interrupts[i]->event; ints[i] = interrupts[i]->event;
if (interrupts[i]->device != FTDM_INVALID_SOCKET) { if (interrupts[i]->device != FTDM_INVALID_SOCKET) {
ints[size+numdevices] = interrupts[i]->device; ints[size+numdevices] = interrupts[i]->device;
numdevices++; numdevices++;
} }
@ -454,7 +458,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru
struct pollfd ints[size*2]; struct pollfd ints[size*2];
memset(&ints, 0, sizeof(ints)); memset(&ints, 0, sizeof(ints));
pollagain:
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
ints[i].events = POLLIN; ints[i].events = POLLIN;
ints[i].revents = 0; 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].events = POLLIN;
ints[size+numdevices].revents = 0; ints[size+numdevices].revents = 0;
ints[size+numdevices].fd = interrupts[i]->device; ints[size+numdevices].fd = interrupts[i]->device;
numdevices++; numdevices++;
} }
} }
@ -470,6 +475,9 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru
res = poll(ints, size + numdevices, ms); res = poll(ints, size + numdevices, ms);
if (res == -1) { if (res == -1) {
if (errno == EINTR) {
goto pollagain;
}
ftdm_log(FTDM_LOG_CRIT, "interrupt poll failed (%s)\n", strerror(errno)); ftdm_log(FTDM_LOG_CRIT, "interrupt poll failed (%s)\n", strerror(errno));
return FTDM_FAIL; return FTDM_FAIL;
} }

View File

@ -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_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_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_link(ftdm_stream_handle_t *stream, char *name);
static ftdm_status_t handle_status_linkset(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 *mycmd = NULL;
char *argv[10] = { 0 }; char *argv[10] = { 0 };
int argc = 0; int argc = 0;
int span = 0; int span = 0;
int chan = 0; int chan = 0;
int trace = 0; int range = 0;
int trace_level = 7; int trace = 0;
int verbose = 1; int trace_level = 7;
int c = 0; int verbose = 1;
int c = 0;
if (data) { if (data) {
mycmd = ftdm_strdup(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 { } else {
/**************************************************************************/ /**************************************************************************/
goto handle_cli_error; 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, "Ftmod_sangoma_ss7 circuit control:\n");
stream->write_function(stream, "ftdm ss7 block span X chan Y\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 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"); stream->write_function(stream, "\n");
return FTDM_SUCCESS; return FTDM_SUCCESS;
@ -1090,6 +1151,125 @@ static ftdm_status_t handle_set_uninhibit(ftdm_stream_handle_t *stream, char *na
return FTDM_SUCCESS; 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) static ftdm_status_t extract_span_chan(char *argv[10], int pos, int *span, int *chan)
{ {

View File

@ -99,7 +99,11 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
SS7_ASSERT; 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 */ /* check if the circuit has a remote block */
if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || 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", " "); 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 */ /* 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); 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; 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 */ 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", SS7_ERROR_CHAN(ftdmchan, "Got IAM on channel in invalid state(%s)...reset!\n", ftdm_channel_state2str (ftdmchan->state));
ftdm_channel_state2str(ftdmchan->state),
ftdmchan->physical_span_id,
ftdmchan->physical_chan_id);
/* move the state of the channel to RESTART to force a reset */ /* move the state of the channel to RESTART to force a reset */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); 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: default:
/* fill in the channels SS7 Stack information */
sngss7_info->suInstId = get_unique_id();
sngss7_info->spInstId = spInstId;
/* throw the reset flag */ /* throw the reset flag */
sngss7_set_flag(sngss7_info, FLAG_RESET_RX); 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; SS7_ASSERT;
}; };
/* glare, throw the flag, go to down state*/ if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) {
sngss7_set_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 */ /* unlock the channel again before we exit */
ftdm_mutex_unlock(ftdmchan->mutex); 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__); SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_chan_data_t *sngss7_info = NULL; sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL; ftdm_channel_t *ftdmchan = NULL;
sngss7_span_data_t *span = NULL; sngss7_span_data_t *sngss7_span = NULL;
int range; int range;
int x; 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 */ /* fill in the span structure for this circuit */
span = ftdmchan->span->mod_data; sngss7_span = ftdmchan->span->mod_data;
span->grs.circuit = circuit; sngss7_span->rx_grs.circuit = circuit;
span->grs.range = range; 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,
(g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic + range)); (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_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,
(g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic + range)); (g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic + range));

View File

@ -303,24 +303,17 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
/* clean out all pending channel state changes */ /* clean out all pending channel state changes */
while ((ftdmchan = ftdm_queue_dequeue (ftdmspan->pendingchans))) { 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 */
/*first lock the channel */ ftdm_mutex_lock(ftdmchan->mutex);
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); 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))) */ }/* while ((ftdmchan = ftdm_queue_dequeue(ftdmspan->pendingchans))) */
/* clean out all pending stack events */ /* 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); ftdm_safe_free(sngss7_event);
}/* while ((sngss7_event = ftdm_queue_dequeue(ftdmspan->signal_data->event_queue))) */ }/* 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; break;
/**********************************************************************/ /**********************************************************************/
case FTDM_TIMEOUT: 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; sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data;
/* check if there is a GRS being processed on the span */ /* 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); 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);*/ /*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 */ /* 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 */ /* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { 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++) */ } /* for ( i = circuit; i < (circuit + range + 1); i++) */
SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n", SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n",
sngss7_span->grs.circuit, sngss7_span->rx_grs.circuit,
sngss7_span->grs.range); sngss7_span->rx_grs.range);
/* check all the circuits in the range to see if they are done resetting */ /* 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 */ /* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { 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++) */ } /* for ( i = circuit; i < (circuit + range + 1); i++) */
GRS_UNLOCK_ALL: 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 */ /* extract the channel in question */
if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); 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 */ /* now that we have the right channel...put a lock on it so no-one else can use it */
ftdm_mutex_lock(ftdmchan->mutex); 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 */ /* figure out the type of event and send it to the right handler */
switch (sngss7_event->event_id) { 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) static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
{ {
ftdm_sigmsg_t sigev; ftdm_sigmsg_t sigev;
ftdm_signaling_status_t status; sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; int i = 0;
int i = 0;
memset (&sigev, 0, sizeof (sigev)); 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 */ /* go to RESTART State until RSCa is received */
ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RESTART); ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RESTART);
} else { } 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 */ /* send out the release complete */
ft_to_sngss7_rlc (ftdmchan); 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 * we insure that this is the last circuit to have the state change queued
*/ */
sngss7_span_data_t *span = ftdmchan->span->mod_data; 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 */ /* send out the GRA */
ft_to_sngss7_gra(ftdmchan); ft_to_sngss7_gra(ftdmchan);
/* clean out the spans GRS structure */ /* clean out the spans GRS structure */
sngss7_span_data_t *span = ftdmchan->span->mod_data; sngss7_span_data_t *span = ftdmchan->span->mod_data;
span->grs.circuit = 0; span->rx_grs.circuit = 0;
span->grs.range = 0; span->rx_grs.range = 0;
} }
/* clear the grp reset flag */ /* 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)) { if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX_RSP)) {
/* clear the reset flag */ /* clear the reset flag */
sngss7_clear_flag(sngss7_info, FLAG_RESET_TX_RSP); 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); 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)) { if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
SS7_DEBUG_CHAN(ftdmchan,"All reset flags cleared %s\n", ""); SS7_DEBUG_CHAN(ftdmchan,"All reset flags cleared %s\n", "");
/* all flags are down so we can bring up the sig status */ /* 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.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.raw_data = &status; sigev.sigstatus = FTDM_SIG_STATE_UP;
ftdm_span_send_signal (ftdmchan->span, &sigev); ftdm_span_send_signal (ftdmchan->span, &sigev);
} }
} else { } else {
@ -879,7 +883,26 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
ftdm_channel_t *close_chan = ftdmchan; ftdm_channel_t *close_chan = ftdmchan;
/* close the channel */ /* close the channel */
ftdm_channel_close (&close_chan); 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; 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 the sig_status is up...bring it down */
if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) { if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
status = FTDM_SIG_STATE_DOWN;
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.raw_data = &status; sigev.sigstatus = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal (ftdmchan->span, &sigev); 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", ""); SS7_DEBUG_CHAN(ftdmchan, "Processing PAUSE flag %s\n", "");
/* bring the channel signaling status to down */ /* bring the channel signaling status to down */
status = FTDM_SIG_STATE_DOWN;
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.raw_data = &status; sigev.sigstatus = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal (ftdmchan->span, &sigev); ftdm_span_send_signal (ftdmchan->span, &sigev);
/* check the last state and return to it to allow the call to finish */ /* 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", ""); SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_UCIC_BLOCK flag %s\n", "");
/* bring the channel signaling status to down */ /* bring the channel signaling status to down */
status = FTDM_SIG_STATE_DOWN;
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.raw_data = &status; sigev.sigstatus = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal (ftdmchan->span, &sigev); ftdm_span_send_signal (ftdmchan->span, &sigev);
/* remove any reset flags */ /* remove any reset flags */
@ -1167,11 +1187,13 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call)
SS7_ASSERT; SS7_ASSERT;
}; };
/* check if the channel sig state is UP */
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
SS7_ERROR_CHAN(ftdmchan, "Requested channel sig state is down, cancelling call!%s\n", " "); SS7_ERROR_CHAN(ftdmchan, "Requested channel sig state is down, cancelling call!%s\n", " ");
goto outgoing_fail; goto outgoing_fail;
} }
/* check if there is a remote block */
if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || 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_HW_BLOCK_RX)) ||
(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_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; goto outgoing_break;
} }
/* check if there is a local block */
if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) || 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_HW_BLOCK_TX)) ||
(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_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 */ /* the channel is blocked...can't send any calls here */
SS7_ERROR_CHAN(ftdmchan, "Requested channel is locally blocked, re-hunt channel!%s\n", " "); SS7_ERROR_CHAN(ftdmchan, "Requested channel is locally blocked, re-hunt channel!%s\n", " ");
goto outgoing_break; goto outgoing_break;
} }
/* check the state of the channel */
switch (ftdmchan->state){ switch (ftdmchan->state){
/**************************************************************************/ /**************************************************************************/
case FTDM_CHANNEL_STATE_DOWN: 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_span_id,
ftdmchan->physical_chan_id); ftdmchan->physical_chan_id);
goto outgoing_fail; goto outgoing_break;
break; break;
/**************************************************************************/ /**************************************************************************/
} /* switch (ftdmchan->state) (original call) */ } /* 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; ftdm_channel_t *ftdmchan = NULL;
sngss7_chan_data_t *sngss7_info = NULL; sngss7_chan_data_t *sngss7_info = NULL;
sngss7_span_data_t *sngss7_span = NULL;
int x; 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 */ /* extract the channel structure and sngss7 channel data */
ftdmchan = span->channels[x]; ftdmchan = span->channels[x];
sngss7_info = ftdmchan->call_data; sngss7_info = ftdmchan->call_data;
sngss7_span = ftdmchan->span->mod_data;
/* lock the channel */ /* lock the channel */
ftdm_mutex_lock(ftdmchan->mutex); 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); sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX);
if (x == 1) { if (x == 1) {
sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_BASE); 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 */ /* 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->state_map = &sangoma_ss7_state_map;
span->mod_data = ss7_span_info; 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); 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 */ /* parse the configuration and apply to the global config structure */
if (ftmod_ss7_parse_xml(ftdm_parameters, span)) { if (ftmod_ss7_parse_xml(ftdm_parameters, span)) {

View File

@ -321,8 +321,7 @@ typedef struct sngss7_timer_data {
}sngss7_timer_data_t; }sngss7_timer_data_t;
typedef struct sngss7_glare_data { typedef struct sngss7_glare_data {
uint32_t suInstId; uint32_t spInstId;
uint32_t spInstId;
uint32_t circuit; uint32_t circuit;
SiConEvnt iam; SiConEvnt iam;
}sngss7_glare_data_t; }sngss7_glare_data_t;
@ -347,7 +346,8 @@ typedef struct sngss7_chan_data {
typedef struct sngss7_span_data { typedef struct sngss7_span_data {
ftdm_sched_t *sched; 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; ftdm_queue_t *event_queue;
}sngss7_span_data_t; }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) { \ #define SS7_MSG_TRACE(fchan, sngss7info ,msg) if (g_ftdm_sngss7_data.message_trace) { \
switch (g_ftdm_sngss7_data.message_trace_level) { \ switch (g_ftdm_sngss7_data.message_trace_level) { \
case 0: \ 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; \ break; \
case 1: \ 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; \ break; \
case 2: \ 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; \ break; \
case 3: \ 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; \ break; \
case 4: \ 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; \ break; \
case 5: \ 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; \ break; \
case 6: \ 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; \ break; \
case 7: \ 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; \ break; \
default: \ 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; \ break; \
} /* switch (g_ftdm_sngss7_data.message_trace_level) */ \ } /* switch (g_ftdm_sngss7_data.message_trace_level) */ \
} /* if(g_ftdm_sngss7_data.message_trace) */ } /* if(g_ftdm_sngss7_data.message_trace) */

View File

@ -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_gra (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan); void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan);
/******************************************************************************/
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
void void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
{ {
SS7_FUNC_TRACE_ENTER (__FUNCTION__); 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) void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
{ {
SS7_FUNC_TRACE_ENTER (__FUNCTION__); SS7_FUNC_TRACE_ENTER (__FUNCTION__);
@ -415,7 +415,7 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
{ {
SS7_FUNC_TRACE_ENTER (__FUNCTION__); 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; sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiStaEvnt gra; SiStaEvnt gra;
@ -426,11 +426,11 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
/* fill in the range */ /* fill in the range */
gra.rangStat.range.pres = PRSNT_NODEF; 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 */ /* fill in the status */
gra.rangStat.status.pres = PRSNT_NODEF; 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 /* the status field should be 1 if blocked for maintenace reasons
* and 0 is not blocked....since we memset the struct nothing to do * 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, sng_cc_sta_request (1,
0, 0,
0, 0,
span->grs.circuit, sngss7_span->rx_grs.circuit,
0, 0,
SIT_STA_GRSRSP, SIT_STA_GRSRSP,
&gra); &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__); SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return; return;
@ -454,31 +456,32 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
/******************************************************************************/ /******************************************************************************/
void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan) void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan)
{ {
SS7_FUNC_TRACE_ENTER (__FUNCTION__); SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data;
ftdm_span_t *span = ftdmchan->span; sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiStaEvnt grs; SiStaEvnt grs;
memset (&grs, 0x0, sizeof (grs)); memset (&grs, 0x0, sizeof (grs));
grs.rangStat.eh.pres = PRSNT_NODEF; grs.rangStat.eh.pres = PRSNT_NODEF;
grs.rangStat.range.pres = PRSNT_NODEF; grs.rangStat.range.pres = PRSNT_NODEF;
grs.rangStat.range.val = span->chan_count-1; grs.rangStat.range.val = sngss7_span->tx_grs.range;
sng_cc_sta_request (1, sng_cc_sta_request (1,
0, 0,
0, 0,
sngss7_info->circuit->id, sngss7_span->tx_grs.circuit,
0, 0,
SIT_STA_GRSREQ, SIT_STA_GRSREQ,
&grs); &grs);
SS7_INFO_CHAN(ftdmchan, "Tx GRS (%d:%d)\n",
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx GRS\n"); sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->tx_grs.range));
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return; return;
} }

View File

@ -163,6 +163,7 @@ struct ldl_session {
apr_hash_t *variables; apr_hash_t *variables;
apr_time_t created; apr_time_t created;
void *private_data; void *private_data;
ldl_user_flag_t flags;
}; };
static int on_disco_default(void *user_data, ikspak *pak); 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->created = apr_time_now();
session->state = LDL_STATE_NEW; session->state = LDL_STATE_NEW;
session->variables = apr_hash_make(session->pool); session->variables = apr_hash_make(session->pool);
session->flags = flags;
*session_p = session; *session_p = session;
@ -387,7 +389,24 @@ static ldl_status parse_session_code(ldl_handle_t *handle, char *id, char *from,
if (type) { 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; 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"))) { if ((key = iks_find_attrib(tag, "port"))) {
session->candidates[index].port = (uint16_t)atoi(key); 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) { if (globals.debug) {
globals.logger(DL_LOG_DEBUG, globals.logger(DL_LOG_DEBUG,
"New Candidate %d\n" "New Candidate %d\n"
@ -947,6 +972,18 @@ static void cancel_retry(ldl_handle_t *handle, char *id)
apr_thread_mutex_unlock(handle->lock); 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) static int on_commands(void *user_data, ikspak *pak)
{ {
ldl_handle_t *handle = user_data; 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"); char *type = iks_find_attrib(pak->x, "type");
uint8_t is_result = strcasecmp(type, "result") ? 0 : 1; uint8_t is_result = strcasecmp(type, "result") ? 0 : 1;
uint8_t is_error = strcasecmp(type, "error") ? 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) { if (is_result) {
iks *tag = iks_child (pak->x); 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) { if ((is_result || is_error) && iqid && from) {
cancel_retry(handle, iqid); cancel_retry(handle, iqid);
if (is_result) { if (is_result) {
if (handle->response_callback) { if (handle->response_callback) {
handle->response_callback(handle, iqid); handle->response_callback(handle, iqid);
@ -999,30 +1053,37 @@ static int on_commands(void *user_data, ikspak *pak)
return IKS_FILTER_EAT; return IKS_FILTER_EAT;
} else if (is_error) { } else if (is_error) {
return IKS_FILTER_EAT; return IKS_FILTER_EAT;
} }
} }
xml = iks_child (pak->x);
while (xml) { if ((xsession = working_find(xml, "ses:session")) || (xsession = working_find(xml, "session"))) {
char *name = iks_name_nons(xml); char *id;
if (!strcasecmp(name, "session")) {
char *id = iks_find_attrib(xml, "id"); id = iks_find_attrib(xsession, "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) { if (xredir) {
iks *reply; to = iks_cdata(iks_child(xredir));
if ((reply = iks_make_iq(IKS_TYPE_RESULT, NULL))) { type = "redirect";
iks_insert_attrib(reply, "to", from); }
iks_insert_attrib(reply, "from", to);
iks_insert_attrib(reply, "id", iqid); if (strcasecmp(type, "error") && strcasecmp(type, "redirect")) {
apr_queue_push(handle->queue, reply); type = NULL;
reply = 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; 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, unsigned int ldl_session_candidates(ldl_session_t *session,
ldl_candidate_t *candidates, ldl_candidate_t *candidates,
unsigned int clen) unsigned int clen)
@ -1981,6 +2105,8 @@ unsigned int ldl_session_candidates(ldl_session_t *session,
return id; return id;
} }
char *ldl_handle_probe(ldl_handle_t *handle, char *id, char *from, char *buf, unsigned int len) char *ldl_handle_probe(ldl_handle_t *handle, char *id, char *from, char *buf, unsigned int len)
{ {
iks *pres, *msg; 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; 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) int ldl_handle_connected(ldl_handle_t *handle)
{ {
return ldl_test_flag(handle, LDL_FLAG_CONNECTED) ? 1 : 0; return ldl_test_flag(handle, LDL_FLAG_CONNECTED) ? 1 : 0;

View File

@ -131,7 +131,8 @@ typedef enum {
LDL_FLAG_SASL_PLAIN = (1 << 11), LDL_FLAG_SASL_PLAIN = (1 << 11),
LDL_FLAG_SASL_MD5 = (1 << 12), LDL_FLAG_SASL_MD5 = (1 << 12),
LDL_FLAG_COMPONENT = (1 << 13), LDL_FLAG_COMPONENT = (1 << 13),
LDL_FLAG_OUTBOUND = (1 << 14) LDL_FLAG_OUTBOUND = (1 << 14),
LDL_FLAG_GATEWAY = (1 << 15)
} ldl_user_flag_t; } ldl_user_flag_t;
typedef enum { typedef enum {
@ -152,7 +153,8 @@ typedef enum {
LDL_SIGNAL_LOGIN_FAILURE, LDL_SIGNAL_LOGIN_FAILURE,
LDL_SIGNAL_CONNECTED, LDL_SIGNAL_CONNECTED,
LDL_SIGNAL_TRANSPORT_ACCEPT, LDL_SIGNAL_TRANSPORT_ACCEPT,
LDL_SIGNAL_REJECT LDL_SIGNAL_REJECT,
LDL_SIGNAL_REDIRECT
} ldl_signal_t; } ldl_signal_t;
typedef enum { typedef enum {
@ -494,6 +496,10 @@ unsigned int ldl_session_candidates(ldl_session_t *session,
ldl_candidate_t *candidates, ldl_candidate_t *candidates,
unsigned int clen); 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 \brief Initiate or Accept a new session and provide transport options
\param session the session to initiate or accept \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); void ldl_handle_run(ldl_handle_t *handle);
int ldl_session_gateway(ldl_session_t *handle);
/*! /*!
\brief Stop a libDingaLing handle \brief Stop a libDingaLing handle
\param handle the Dingaling handle to stop \param handle the Dingaling handle to stop

View File

@ -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); 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) \brief build a dynamic module object and register it (for use in double embeded modules)
\param filename the name of the modules source file \param filename the name of the modules source file

View File

@ -1731,6 +1731,8 @@ typedef struct switch_loadable_module_function_table {
switch_module_flag_t flags; switch_module_flag_t flags;
} switch_loadable_module_function_table_t; } 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) \ #define SWITCH_MODULE_DEFINITION_EX(name, load, shutdown, runtime, flags) \
static const char modname[] = #name ; \ static const char modname[] = #name ; \
SWITCH_MOD_DECLARE_DATA switch_loadable_module_function_table_t name##_module_interface = { \ SWITCH_MOD_DECLARE_DATA switch_loadable_module_function_table_t name##_module_interface = { \

View File

@ -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 flush_db_handles");
switch_console_set_complete("add fsctl min_idle_cpu"); switch_console_set_complete("add fsctl min_idle_cpu");
switch_console_set_complete("add fsctl send_sighup"); 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 reinit");
switch_console_set_complete("add nat_map republish"); switch_console_set_complete("add nat_map republish");
switch_console_set_complete("add nat_map status"); 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 reloadacl reloadxml");
switch_console_set_complete("add show aliases"); switch_console_set_complete("add show aliases");
switch_console_set_complete("add show api"); 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 show timer");
switch_console_set_complete("add shutdown"); switch_console_set_complete("add shutdown");
switch_console_set_complete("add sql_escape"); 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 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 read level");
switch_console_set_complete("add uuid_audio ::console::list_uuid start write mute"); switch_console_set_complete("add uuid_audio ::console::list_uuid start write mute");

1
src/mod/applications/mod_curl/mod_curl.c Executable file → Normal file
View File

@ -272,6 +272,7 @@ SWITCH_STANDARD_APP(curl_app_function)
} else if (!strcasecmp("get", argv[i]) || !strcasecmp("head", argv[i])) { } else if (!strcasecmp("get", argv[i]) || !strcasecmp("head", argv[i])) {
method = switch_core_strdup(pool, argv[i]); method = switch_core_strdup(pool, argv[i]);
} else if (!strcasecmp("post", argv[i])) { } else if (!strcasecmp("post", argv[i])) {
method = "post";
if (++i < argc) { if (++i < argc) {
postdata = switch_core_strdup(pool, argv[i]); postdata = switch_core_strdup(pool, argv[i]);
switch_url_decode(postdata); switch_url_decode(postdata);

View File

@ -1001,7 +1001,13 @@ static int do_candidates(struct private_object *tech_pvt, int force)
cand[0].protocol = "udp"; 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, 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); 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_TRANSPORT);
switch_set_flag_locked(tech_pvt, TFLAG_RTP_READY); 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(); now = switch_micro_time_now();
elapsed = (unsigned int) ((now - started) / 1000); elapsed = (unsigned int) ((now - started) / 1000);
if (switch_channel_down(channel) || switch_test_flag(tech_pvt, TFLAG_BYE)) { if (switch_channel_down(channel) || switch_test_flag(tech_pvt, TFLAG_BYE)) {
goto out; goto out;
} }
@ -1643,6 +1650,8 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
char workspace[1024] = ""; char workspace[1024] = "";
char *p, *u, ubuf[512] = "", *user = NULL, *f_cid_msg = NULL; char *p, *u, ubuf[512] = "", *user = NULL, *f_cid_msg = NULL;
const char *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)); switch_copy_string(workspace, outbound_profile->destination_number, sizeof(workspace));
profile_name = 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); terminate_session(new_session, __LINE__, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
return 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"); 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); terminate_session(new_session, __LINE__, SWITCH_CAUSE_NO_USER_RESPONSE);
return 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"); switch_stun_random_string(sess_id, 10, "0123456789");
tech_pvt->us = switch_core_session_strdup(*new_session, user); tech_pvt->us = switch_core_session_strdup(*new_session, user);
tech_pvt->them = switch_core_session_strdup(*new_session, full_id); 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) { if (session) {
switch_channel_t *calling_channel = switch_core_session_get_channel(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; cid_msg = f_cid_msg;
} }
if ((flags & LDL_FLAG_GATEWAY)) {
cid_msg = NULL;
}
if (cid_msg) { if (cid_msg) {
char *them; char *them;
them = strdup(tech_pvt->them); them = strdup(tech_pvt->them);
@ -3128,6 +3144,11 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
break; break;
case LDL_SIGNAL_TRANSPORT_ACCEPT: case LDL_SIGNAL_TRANSPORT_ACCEPT:
switch_set_flag_locked(tech_pvt, TFLAG_TRANSPORT_ACCEPT); switch_set_flag_locked(tech_pvt, TFLAG_TRANSPORT_ACCEPT);
if (ldl_session_gateway(dlsession)) {
do_candidates(tech_pvt, 1);
}
break; break;
case LDL_SIGNAL_INITIATE: case LDL_SIGNAL_INITIATE:
if (dl_signal) { if (dl_signal) {
@ -3243,7 +3264,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi
choice = x; choice = x;
ok = 1; ok = 1;
} }
if (ok) { if (ok) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "candidate %s:%d PASS ACL %s\n", 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]); 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; goto done;
} }
break; break;
case LDL_SIGNAL_REDIRECT:
do_describe(tech_pvt, 1);
break;
case LDL_SIGNAL_ERROR: case LDL_SIGNAL_ERROR:
case LDL_SIGNAL_TERMINATE: case LDL_SIGNAL_TERMINATE:
if (channel) { if (channel) {

View File

@ -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 move PTrace level set to FSH323EndPoint::Initialise
partially apply patch from from Peter Olsson, Remove UnLock() when TryLock() failed and DEBUG_RTP_PACKETS directive. 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. apply changes from mod_h323-patch.diff by Peter Olsson.

View File

@ -0,0 +1 @@
To compile this module use latest ptlib/h323plis combinations listed at http://www.gnugk.org/compiling-gnugk.html

View File

@ -614,7 +614,7 @@ H323Connection *FSH323EndPoint::CreateConnection(
} }
switch_core_session_t *fsSession = switch_core_session_request(GetSwitchInterface(), 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) if (fsSession == NULL)
return NULL; return NULL;

View File

@ -513,7 +513,7 @@ OpalLocalConnection *FSEndPoint::CreateConnection(OpalCall & call, void *userDat
{ {
FSManager & mgr = (FSManager &) GetManager(); FSManager & mgr = (FSManager &) GetManager();
switch_core_session_t *fsSession = switch_core_session_request(mgr.GetSwitchInterface(), 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) if (fsSession == NULL)
return NULL; return NULL;

View File

@ -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, "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, "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, "Debug \t%d\n", profile->debug);
stream->write_function(stream, "Auto-Restart \t%d\n", profile->auto_restart);
/* stats */ /* stats */
stream->write_function(stream, "CALLS-IN \t%d\n", profile->ib_calls); 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); 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
&& listener->sock && listener->sock
&& switch_test_flag(listener, LFLAG_RUNNING) && 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) 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); 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)) { 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); status = skinny_read_packet(listener, &request);
if (status != SWITCH_STATUS_SUCCESS) { 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); switch_clear_flag_locked(listener, LFLAG_RUNNING);
break; break;
} }
@ -1432,11 +1444,12 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
remove_listener(listener); remove_listener(listener);
if (listener->profile->debug > 0) { 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); switch_thread_rwlock_wrlock(listener->rwlock);
flush_listener(listener, SWITCH_TRUE, SWITCH_TRUE); flush_listener(listener);
if (listener->sock) { if (listener->sock) {
close_socket(&listener->sock, profile); 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); switch_thread_rwlock_unlock(listener->rwlock);
if (listener->profile->debug > 0) { 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) { if(destroy_pool == 0) {
goto no_destroy_pool; goto no_destroy_pool;
} }
@ -1502,6 +1506,7 @@ static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void
return NULL; return NULL;
} }
new_socket:
while(globals.running) { while(globals.running) {
rv = switch_sockaddr_info_get(&sa, profile->ip, SWITCH_INET, profile->port, 0, tmp_pool); rv = switch_sockaddr_info_get(&sa, profile->ip, SWITCH_INET, profile->port, 0, tmp_pool);
if (rv) if (rv)
@ -1526,7 +1531,7 @@ static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void
switch_yield(100000); switch_yield(100000);
} }
profile->listener_ready = 1; switch_set_flag_locked(profile, PFLAG_LISTENER_READY);
while(globals.running) { while(globals.running) {
@ -1539,6 +1544,10 @@ static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void
if (!globals.running) { if (!globals.running) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting Down\n"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting Down\n");
goto end; 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 { } else {
/* I wish we could use strerror_r here but its not defined everywhere =/ */ /* 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)); 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; 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 */ /* MODULE FUNCTIONS */
/*****************************************************************************/ /*****************************************************************************/
@ -1603,9 +1623,9 @@ switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, c
if (!var) if (!var)
return SWITCH_STATUS_FALSE; 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, 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; 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")) { } else if (!strcasecmp(var, "debug")) {
profile->debug = atoi(val); profile->debug = atoi(val);
} else if (!strcasecmp(var, "auto-restart")) {
profile->auto_restart = switch_true(val);
} else { } else {
return SWITCH_STATUS_FALSE; 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; 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 = switch_core_alloc(profile_pool, sizeof(skinny_profile_t));
profile->pool = profile_pool; profile->pool = profile_pool;
profile->name = switch_core_strdup(profile->pool, profile_name); 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->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->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) { for (param = switch_xml_child(xsettings, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name"); 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) 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_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool);
switch_core_hash_init(&globals.profile_hash, globals.pool); switch_core_hash_init(&globals.profile_hash, globals.pool);
globals.running = 1; globals.running = 1;
globals.auto_restart = SWITCH_TRUE;
load_skinny_config(); 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"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our message waiting handler!\n");
/* Not such severe to prevent loading */ /* 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 */ /* reserve events */
if (switch_event_reserve_subclass(SKINNY_EVENT_REGISTER) != SWITCH_STATUS_SUCCESS) { 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)) { for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
void *val; void *val;
skinny_profile_t *profile; skinny_profile_t *profile;
switch_thread_t *thread;
switch_threadattr_t *thd_attr = NULL;
switch_hash_this(hi, NULL, NULL, &val); switch_hash_this(hi, NULL, NULL, &val);
profile = (skinny_profile_t *) val; profile = (skinny_profile_t *) val;
switch_threadattr_create(&thd_attr, profile->pool); launch_skinny_profile_thread(profile);
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);
} }
switch_mutex_unlock(globals.mutex); 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.heartbeat_node);
switch_event_unbind(&globals.call_state_node); switch_event_unbind(&globals.call_state_node);
switch_event_unbind(&globals.message_waiting_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_REGISTER);
switch_event_free_subclass(SKINNY_EVENT_UNREGISTER); switch_event_free_subclass(SKINNY_EVENT_UNREGISTER);
switch_event_free_subclass(SKINNY_EVENT_EXPIRE); switch_event_free_subclass(SKINNY_EVENT_EXPIRE);

View File

@ -52,11 +52,18 @@ struct skinny_globals {
switch_event_node_t *heartbeat_node; switch_event_node_t *heartbeat_node;
switch_event_node_t *call_state_node; switch_event_node_t *call_state_node;
switch_event_node_t *message_waiting_node; switch_event_node_t *message_waiting_node;
switch_event_node_t *trap_node;
int auto_restart;
}; };
typedef struct skinny_globals skinny_globals_t; typedef struct skinny_globals skinny_globals_t;
extern skinny_globals_t globals; extern skinny_globals_t globals;
typedef enum {
PFLAG_LISTENER_READY = (1 << 0),
PFLAG_RESPAWN = (1 << 1),
} profile_flag_t;
struct skinny_profile { struct skinny_profile {
/* prefs */ /* prefs */
char *name; char *name;
@ -70,6 +77,7 @@ struct skinny_profile {
uint32_t keep_alive; uint32_t keep_alive;
char date_format[6]; char date_format[6];
int debug; int debug;
int auto_restart;
switch_hash_t *device_type_params_hash; switch_hash_t *device_type_params_hash;
/* db */ /* db */
char *dbname; char *dbname;
@ -89,7 +97,8 @@ struct skinny_profile {
switch_socket_t *sock; switch_socket_t *sock;
switch_mutex_t *sock_mutex; switch_mutex_t *sock_mutex;
struct listener *listeners; struct listener *listeners;
uint8_t listener_ready; int flags;
switch_mutex_t *flag_mutex;
/* call id */ /* call id */
uint32_t next_call_id; uint32_t next_call_id;
/* others */ /* others */
@ -114,7 +123,7 @@ typedef enum {
typedef enum { typedef enum {
LFLAG_RUNNING = (1 << 0), LFLAG_RUNNING = (1 << 0),
} event_flag_t; } listener_flag_t;
#define SKINNY_MAX_LINES 42 #define SKINNY_MAX_LINES 42
struct listener { struct listener {

View File

@ -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, "date-format");
switch_console_push_match(&my_matches, "odbc-dsn"); switch_console_push_match(&my_matches, "odbc-dsn");
switch_console_push_match(&my_matches, "debug"); switch_console_push_match(&my_matches, "debug");
switch_console_push_match(&my_matches, "auto-restart");
if (my_matches) { if (my_matches) {
*matches = my_matches; *matches = my_matches;

View File

@ -119,7 +119,7 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req)
} }
if (!listener_is_ready(listener)) { if (!listener_is_ready(listener)) {
return SWITCH_STATUS_FALSE; return SWITCH_STATUS_BREAK;
} }
ptr = mbuf; 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); 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"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Socket break.\n");
return SWITCH_STATUS_FALSE; 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) { if(bytes >= request->length + 2*SKINNY_MESSAGE_FIELD_SIZE) {
/* Message body */ /* 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; *req = request;
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
} }
} }
if (listener->expire_time && listener->expire_time < switch_epoch_time_now(NULL)) { 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"); return SWITCH_STATUS_TIMEOUT;
switch_clear_flag_locked(listener, LFLAG_RUNNING);
return SWITCH_STATUS_FALSE;
} }
if (do_sleep) { if (do_sleep) {
switch_cond_next(); switch_cond_next();

View File

@ -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); mwi_status = switch_stristr("Messages-Waiting: ", sip->sip_payload->pl_data);
if ( mwi_status ) { if ( mwi_status ) {
char *mwi_stat;
mwi_status += strlen( "Messages-Waiting: " ); 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) { 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_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_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_event_fire(&s_event);
} }
switch_safe_free(mwi_stat);
} }
} else { } 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 );
}; };
} }

View File

@ -565,34 +565,32 @@ static void actual_sofia_presence_event_handler(switch_event_t *event)
probe_euser = (p + 1); probe_euser = (p + 1);
} }
if (probe_euser && probe_host && (profile = sofia_glue_find_profile(probe_host))) { 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); 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); sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh);
switch_safe_free(sql); 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_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," "sip_dialogs.sip_to_user, sip_dialogs.sip_to_host, sip_presence.status,sip_presence.rpid,sip_presence.open_closed,"
"'%q','%q' " "'%q','%q' "
"from sip_registrations left join sip_dialogs on " "from sip_registrations left join sip_dialogs on "
"(sip_dialogs.sip_from_user = sip_registrations.sip_user " "(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 " "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) " "sip_registrations.profile_name=sip_presence.profile_name) "
"where sip_registrations.sip_user='%q' and " "where sip_registrations.sip_user='%q' and "
"(sip_registrations.sip_host='%q' or sip_registrations.presence_hosts like '%%%q%%')", "(sip_registrations.orig_server_host='%q' or sip_registrations.sip_host='%q' "
probe_host, dh.status, dh.rpid, probe_euser, probe_host, probe_host); "or sip_registrations.presence_hosts like '%%%q%%')",
dh.status, dh.rpid, probe_euser, probe_host, probe_host, probe_host);
switch_assert(sql); switch_assert(sql);
if (mod_sofia_globals.debug_presence > 0) { if (mod_sofia_globals.debug_presence > 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%s START_PRESENCE_PROBE_SQL\n", profile->name); 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); sofia_glue_release_profile(profile);
switch_safe_free(sql); switch_safe_free(sql);
} }
switch_safe_free(probe_user); 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; switch_event_header_t *hp;
if (argc > 5) { if (argc > 5) {
uuid = switch_str_nil(argv[5]); uuid = argv[5];
state = switch_str_nil(argv[6]); state = switch_str_nil(argv[6]);
direction = switch_str_nil(argv[7]); direction = switch_str_nil(argv[7]);
if (argc > 8) { if (argc > 8) {
@ -998,12 +997,13 @@ static int sofia_presence_resub_callback(void *pArg, int argc, char **argv, char
} }
if (zstr(state)) { 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, "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 { } else {
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "channel-state", "CS_ROUTING"); 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, "answer-state", state);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "astate", 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); 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) { if (is_dialog) {
char *version = switch_event_get_header(helper->event, "event_count");
if (!version) {
version = "0";
}
stream.write_function(&stream, stream.write_function(&stream,
"<?xml version=\"1.0\"?>\n" "<?xml version=\"1.0\"?>\n"
"<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" " "<dialog-info xmlns=\"urn:ietf:params:xml:ns:dialog-info\" "
"version=\"%s\" state=\"%s\" entity=\"%s\">\n", "version=\"%s\" state=\"%s\" entity=\"%s\">\n",
switch_str_nil(switch_event_get_header(helper->event, "event_count")), version,
!strcasecmp(answer_state, "resubscribe") ? "partial" : "full", clean_id); zstr(uuid) ? "partial" : "full", clean_id);
} }
if (strcasecmp(event_status, "Registered")) { //if (strcasecmp(event_status, "Registered")) {
if (!zstr(uuid)) {
if (!zstr(answer_state)) { if (!zstr(answer_state)) {
astate = 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) { 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, "proto", SOFIA_CHAT_PROTO);
switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "login", profile->url); 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, "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, "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, "proto-specific-event-name", event);
switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str); switch_event_add_header_string(pevent, SWITCH_STACK_BOTTOM, "expires", exp_delta_str);

View File

@ -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_user = NULL;
const char *from_host = NULL; const char *from_host = NULL;
const char *reg_host = profile->reg_db_domain; const char *reg_host = profile->reg_db_domain;
const char *sub_host = profile->sub_domain;
char contact_str[1024] = ""; char contact_str[1024] = "";
int nat_hack = 0; int nat_hack = 0;
uint8_t multi_reg = 0, multi_reg_contact = 0, avoid_multi_reg = 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) { if (!reg_host) {
reg_host = to_host; reg_host = to_host;
} }
if (!sub_host) {
sub_host = to_host;
}
if (contact->m_url) { if (contact->m_url) {
const char *port = contact->m_url->url_port; 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) { if (multi_reg) {
#ifdef DEL_SUBS
if (reg_count == 1) { if (reg_count == 1) {
sql = switch_mprintf("delete from sip_subscriptions where sip_user='%q' and sip_host='%q' and contact='%q'", 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); sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
} }
#endif
if (multi_reg_contact) { 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); sql = switch_mprintf("delete from sip_registrations where call_id='%q'", call_id);
} }
} else { } 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); 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); 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); switch_mutex_lock(profile->ireg_mutex);
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL, AF_INET); 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 " sql = switch_mprintf("insert into sip_registrations "
"(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires," "(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, "login", profile->url);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "user-agent", switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "user-agent",
(sip && sip->sip_user_agent) ? sip->sip_user_agent->g_string : "unknown"); (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, "status", "Registered");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_fire(&event); 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, "proto", "sip");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url); 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_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, "from", "%s@%s", to_user, sub_host);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "to", "%s@%s", to_user, reg_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, "status", "Registered");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_subtype", "probe"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_subtype", "probe");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); 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, "login", profile->url);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "user-agent", switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "user-agent",
(sip && sip->sip_user_agent) ? sip->sip_user_agent->g_string : "unknown"); (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, "status", "Unregistered");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event_type", "presence");
switch_event_fire(&event); 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) { 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, "proto", "sip");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url); 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, "status", "unavailable");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "rpid", rpid); 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, ':'))) { if ((p = strchr(icontact + 4, ':'))) {
*p = '\0'; *p = '\0';
} }
#ifdef DEL_SUBS
if (multi_reg_contact) { if (multi_reg_contact) {
sql = 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 { } else {
sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", call_id); sql = switch_mprintf("delete from sip_subscriptions where call_id='%q'", call_id);
} }
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
#endif
if (multi_reg_contact) { if (multi_reg_contact) {
sql = sql =
@ -1301,10 +1330,11 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand
switch_safe_free(icontact); switch_safe_free(icontact);
} else { } 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); 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))) { 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); 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) { 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, "proto", SOFIA_CHAT_PROTO);
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "login", profile->name); 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, "rpid", "unknown");
switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Registered"); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "status", "Registered");
switch_event_fire(&s_event); switch_event_fire(&s_event);
} }
#endif
} else { } else {
if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_UNREGISTER) == SWITCH_STATUS_SUCCESS) { 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); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name);

View File

@ -24,7 +24,7 @@
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>..\..\..\..\..\managed\debug\</OutputPath> <OutputPath>..\..\..\..\..\Win32\Debug\mod\</OutputPath>
<DefineConstants>TRACE;DEBUG;CLR_VERSION40</DefineConstants> <DefineConstants>TRACE;DEBUG;CLR_VERSION40</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
@ -32,11 +32,33 @@
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType> <DebugType>pdbonly</DebugType>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<OutputPath>..\..\..\..\..\managed\release\</OutputPath> <OutputPath>..\..\..\..\..\Win32\Release\mod\</OutputPath>
<DefineConstants>TRACE;CLR_VERSION40</DefineConstants> <DefineConstants>TRACE;CLR_VERSION40</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\..\..\..\x64\Debug\mod\</OutputPath>
<DefineConstants>TRACE;DEBUG;CLR_VERSION40</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
<CodeAnalysisFailOnMissingRules>true</CodeAnalysisFailOnMissingRules>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>..\..\..\..\..\x64\Release\mod\</OutputPath>
<DefineConstants>TRACE;CLR_VERSION40</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
<CodeAnalysisFailOnMissingRules>true</CodeAnalysisFailOnMissingRules>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core"> <Reference Include="System.Core">

View File

@ -319,11 +319,9 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2010.vcxproj"> <ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2010.vcxproj">
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project> <Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference> </ProjectReference>
<ProjectReference Include="managed\FreeSWITCH.Managed.csproj"> <ProjectReference Include="managed\FreeSWITCH.Managed.2010.csproj">
<Project>{834e2b2f-5483-4b80-8fe3-fe48ff76e5c0}</Project> <Project>{834e2b2f-5483-4b80-8fe3-fe48ff76e5c0}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -553,6 +553,46 @@ struct match_helper {
switch_console_callback_match_t *my_matches; 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) static int uuid_callback(void *pArg, int argc, char **argv, char **columnNames)
{ {
struct match_helper *h = (struct match_helper *) pArg; 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_mutex_init(&globals.func_mutex, SWITCH_MUTEX_NESTED, pool);
switch_core_hash_init(&globals.func_hash, 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); switch_console_add_complete_func("::console::list_uuid", (switch_console_complete_callback_t) switch_console_list_uuid);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }

View File

@ -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_thread_t *EVENT_QUEUE_THREADS[NUMBER_OF_QUEUES] = { 0 };
static switch_queue_t *EVENT_QUEUE[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 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 switch_queue_t *EVENT_DISPATCH_QUEUE[MAX_DISPATCH_VAL] = { 0 };
static int POOL_COUNT_MAX = SWITCH_CORE_QUEUE_LEN; static int POOL_COUNT_MAX = SWITCH_CORE_QUEUE_LEN;
static switch_mutex_t *EVENT_QUEUE_MUTEX = NULL; 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; switch_queue_t *queue = (switch_queue_t *) obj;
int my_id = 0; int my_id = 0;
switch_mutex_lock(EVENT_QUEUE_MUTEX); switch_mutex_lock(EVENT_QUEUE_MUTEX);
THREAD_COUNT++; THREAD_COUNT++;
switch_mutex_unlock(EVENT_QUEUE_MUTEX);
for (my_id = 0; my_id < NUMBER_OF_QUEUES; my_id++) { for (my_id = 0; my_id < NUMBER_OF_QUEUES; my_id++) {
if (EVENT_DISPATCH_QUEUE[my_id] == queue) { 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 (;;) { for (;;) {
void *pop = NULL; void *pop = NULL;
switch_event_t *event = 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); switch_mutex_lock(EVENT_QUEUE_MUTEX);
EVENT_DISPATCH_QUEUE_RUNNING[my_id] = 1;
THREAD_COUNT--; THREAD_COUNT--;
switch_mutex_unlock(EVENT_QUEUE_MUTEX); switch_mutex_unlock(EVENT_QUEUE_MUTEX);
@ -298,6 +303,7 @@ static void *SWITCH_THREAD_FUNC switch_event_thread(switch_thread_t *thread, voi
for (;;) { for (;;) {
void *pop = NULL; void *pop = NULL;
switch_event_t *event = NULL; switch_event_t *event = NULL;
int loops = 0;
if (switch_queue_pop(queue, &pop) != SWITCH_STATUS_SUCCESS) { if (switch_queue_pop(queue, &pop) != SWITCH_STATUS_SUCCESS) {
break; break;
@ -314,13 +320,13 @@ static void *SWITCH_THREAD_FUNC switch_event_thread(switch_thread_t *thread, voi
event = (switch_event_t *) pop; event = (switch_event_t *) pop;
while (event) { while (event) {
int max;
switch_mutex_lock(EVENT_QUEUE_MUTEX); if (++loops > 2) {
max = SOFT_MAX_DISPATCH; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Event system overloading\n");
switch_mutex_unlock(EVENT_QUEUE_MUTEX); 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) { if (switch_queue_trypush(EVENT_DISPATCH_QUEUE[index], event) == SWITCH_STATUS_SUCCESS) {
event = NULL; event = NULL;
break; break;
@ -328,19 +334,15 @@ static void *SWITCH_THREAD_FUNC switch_event_thread(switch_thread_t *thread, voi
} }
if (event) { if (event) {
switch_mutex_lock(EVENT_QUEUE_MUTEX);
if (SOFT_MAX_DISPATCH + 1 < MAX_DISPATCH) { 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); launch_dispatch_threads(SOFT_MAX_DISPATCH + 1, DISPATCH_QUEUE_LEN, RUNTIME_POOL);
switch_mutex_unlock(EVENT_QUEUE_MUTEX);
} else { } 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_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; switch_threadattr_t *thd_attr;
uint32_t index = 0; uint32_t index = 0;
int launched = 0;
uint32_t sanity = 200;
if (max > MAX_DISPATCH) { if (max > MAX_DISPATCH) {
return; 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_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
switch_threadattr_priority_increase(thd_attr); 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_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); while(--sanity && !EVENT_DISPATCH_QUEUE_RUNNING[index]) switch_yield(10000);
switch_yield(100000); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Create event dispatch thread %d\n", index);
launched++;
break;
} }
SOFT_MAX_DISPATCH = index; SOFT_MAX_DISPATCH = index;

View File

@ -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_DECLARE(switch_status_t) switch_loadable_module_build_dynamic(char *filename,
switch_module_load_t switch_module_load, switch_module_load_t switch_module_load,
switch_module_runtime_t switch_module_runtime, 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_api_interface_t *api;
switch_status_t status; switch_status_t status;
char *arg_no_spaces;
char *cmd_no_spaces;
switch_assert(stream != NULL); switch_assert(stream != NULL);
switch_assert(stream->data != NULL); switch_assert(stream->data != NULL);
switch_assert(stream->write_function != 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) { if (!stream->param_event) {
switch_event_create(&stream->param_event, SWITCH_EVENT_API); switch_event_create(&stream->param_event, SWITCH_EVENT_API);
} }
if (stream->param_event) { if (stream->param_event) {
if (cmd) { if (cmd_no_spaces) {
switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command", cmd); switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command", cmd_no_spaces);
} }
if (arg) { if (arg_no_spaces) {
switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command-Argument", arg); 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 (cmd_no_spaces && (api = switch_loadable_module_get_api_interface(cmd_no_spaces)) != 0) {
if ((status = api->function(arg, session, stream)) != SWITCH_STATUS_SUCCESS) { if ((status = api->function(arg_no_spaces, session, stream)) != SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "COMMAND RETURNED ERROR!\n"); stream->write_function(stream, "COMMAND RETURNED ERROR!\n");
} }
UNPROTECT_INTERFACE(api); 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_event_fire(&stream->param_event);
} }
switch_safe_free(cmd_no_spaces);
switch_safe_free(arg_no_spaces);
return status; return status;
} }

View File

@ -26,7 +26,7 @@
* Anthony Minessale II <anthm@freeswitch.org> * Anthony Minessale II <anthm@freeswitch.org>
* *
* *
* switch_caller.c -- Caller Identification * switch_resample.c -- Resampler
* *
*/ */

View File

@ -724,7 +724,7 @@ SWITCH_DECLARE(char *) switch_strip_whitespace(const char *str)
if (!sp) if (!sp)
return NULL; 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++; sp++;
} }
@ -735,7 +735,7 @@ SWITCH_DECLARE(char *) switch_strip_whitespace(const char *str)
p = s + (strlen(s) - 1); 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'; *p-- = '\0';
} }