Merge branch 'master' into arnaldo.zt_chan_next_event

This commit is contained in:
Arnaldo Pereira 2010-12-22 19:09:53 -02:00
commit 818887f9d3
21 changed files with 466 additions and 108 deletions

View File

@ -204,6 +204,8 @@
<X-PRE-PROCESS cmd="set" data="fr-ring=%(1500,3500,440.0,0.0)"/> <X-PRE-PROCESS cmd="set" data="fr-ring=%(1500,3500,440.0,0.0)"/>
<X-PRE-PROCESS cmd="set" data="rs-ring=%(1000,4000,425.0,0.0)"/> <X-PRE-PROCESS cmd="set" data="rs-ring=%(1000,4000,425.0,0.0)"/>
<X-PRE-PROCESS cmd="set" data="ru-ring=%(800,3200,425,0)"/> <X-PRE-PROCESS cmd="set" data="ru-ring=%(800,3200,425,0)"/>
<X-PRE-PROCESS cmd="set" data="de-ring=%(1000,4000,425,0)"/>
<X-PRE-PROCESS cmd="set" data="dz-ring=%(1500,3500,425.0,0.0)"/>
<X-PRE-PROCESS cmd="set" data="bong-ring=v=-7;%(100,0,941.0,1477.0);v=-7;>=2;+=.1;%(1400,0,350,440)"/> <X-PRE-PROCESS cmd="set" data="bong-ring=v=-7;%(100,0,941.0,1477.0);v=-7;>=2;+=.1;%(1400,0,350,440)"/>
<X-PRE-PROCESS cmd="set" data="sit=%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)"/> <X-PRE-PROCESS cmd="set" data="sit=%(274,0,913.8);%(274,0,1370.6);%(380,0,1776.7)"/>
<!-- <!--

View File

@ -656,7 +656,7 @@ static int process_command(esl_handle_t *handle, const char *cmd)
"-----------------------------------------------\n" "-----------------------------------------------\n"
"/help \tHelp\n" "/help \tHelp\n"
"/exit, /quit, /bye, ... \tExit the program.\n" "/exit, /quit, /bye, ... \tExit the program.\n"
"/event, /noevent, /nixevent\tEvent commands.\n" "/event, /noevents, /nixevent\tEvent commands.\n"
"/log, /nolog \tLog commands.\n" "/log, /nolog \tLog commands.\n"
"/uuid \tFilter logs for a single call uuid\n" "/uuid \tFilter logs for a single call uuid\n"
"/filter \tFilter commands.\n" "/filter \tFilter commands.\n"
@ -692,7 +692,7 @@ static int process_command(esl_handle_t *handle, const char *cmd)
} else if ( } else if (
!strncasecmp(cmd, "event", 5) || !strncasecmp(cmd, "event", 5) ||
!strncasecmp(cmd, "noevent", 7) || !strncasecmp(cmd, "noevents", 8) ||
!strncasecmp(cmd, "nixevent", 8) || !strncasecmp(cmd, "nixevent", 8) ||
!strncasecmp(cmd, "log", 3) || !strncasecmp(cmd, "log", 3) ||
!strncasecmp(cmd, "nolog", 5) || !strncasecmp(cmd, "nolog", 5) ||

View File

@ -12,31 +12,81 @@ with the signaling protocols that you can run on top of your I/O interfaces.
<settings> <settings>
<param name="debug" value="0"/> <param name="debug" value="0"/>
<!--<param name="hold-music" value="$${moh_uri}"/>--> <!--<param name="hold-music" value="$${moh_uri}"/>-->
<!-- Analog global options (they apply to all spans)
Remember you can only choose between either call-swap
or 3-way, not both!
-->
<!--<param name="enable-analog-option" value="call-swap"/>--> <!--<param name="enable-analog-option" value="call-swap"/>-->
<!--<param name="enable-analog-option" value="3-way"/>--> <!--<param name="enable-analog-option" value="3-way"/>-->
</settings> </settings>
<!-- Sample analog configuration --> <!-- Sample analog configuration (The analog_spans tag is for ftmod_analog) -->
<analog_spans> <analog_spans>
<!-- The span name must match the name in your freetdm.conf --> <!-- The span name must match the name in your freetdm.conf -->
<span name="myAnalog"> <span name="myAnalog">
<!--<param name="hold-music" value="$${moh_uri}"/>--> <!--<param name="hold-music" value="$${moh_uri}"/>-->
<!--<param name="enable-analog-option" value="call-swap"/>--> <!--
<!--<param name="enable-analog-option" value="3-way"/>--> 3-way allows you to flash your FXS line and dial
another number and put all the parties in a conference
call-swap allows you to flash your FXS line and swap
between one call and another
Remember you can only choose between either call-swap
or 3-way, not both!
<param name="enable-analog-option" value="call-swap"/>
<param name="enable-analog-option" value="3-way"/>
-->
<!-- Tones are defined in tones.conf
This setting is very important for analog lines to
work properly
-->
<param name="tonegroup" value="us"/> <param name="tonegroup" value="us"/>
<!-- How much time to wait for digits (in FXS lines) -->
<param name="digit-timeout" value="2000"/> <param name="digit-timeout" value="2000"/>
<!-- Maximum number of digits to wait for (in FXS lines) -->
<param name="max-digits" value="11"/> <param name="max-digits" value="11"/>
<param name="dialplan" value="XML"/>
<param name="context" value="default"/> <!-- whether you want to wait for caller id -->
<param name="enable-callerid" value="true"/> <param name="enable-callerid" value="true"/>
<!-- whether you want to enable callwaiting feature -->
<!--<param name="callwaiting" value="true"/>-->
<!-- whether you want to answer/hangup on polarity reverse for outgoing calls in FXO devices
and send polarity reverse on answer/hangup for incoming calls in FXS devices -->
<!--<param name="answer-polarity-reverse" value="false"/>-->
<!--<param name="hangup-polarity-reverse" value="false"/>-->
<!--
Minimum delay (in milliseconds) required between an answer polarity reverse
and hangup polarity reverse in order to assume the second polarity reverse is a real hangup
<param name="polarity-delay" value="600"/>
-->
<!-- regex to stop dialing when it matches --> <!-- regex to stop dialing when it matches -->
<!--<param name="dial-regex" value="5555"/>--> <!--<param name="dial-regex" value="5555"/>-->
<!-- regex to stop dialing when it does not match --> <!-- regex to stop dialing when it does not match -->
<!--<param name="fail-dial-regex" value="^5"/>--> <!--<param name="fail-dial-regex" value="^5"/>-->
<!-- FreeSWITCH dialplan type and context to send the calls -->
<param name="dialplan" value="XML"/>
<param name="context" value="default"/>
</span> </span>
</analog_spans> </analog_spans>
<!-- openr2 (MFC-R2 signaling) spans <!--
openr2 (MFC-R2 signaling) spans (ftmod_r2)
In order to use this type of spans your FreeTDM must have been compiled with ftmod_r2 module.
The module is compiled if the openr2 library is present when running the ./configure script
in the FreeTDM source code
MFC-R2 signaling has lots of variants from country to country and even sometimes MFC-R2 signaling has lots of variants from country to country and even sometimes
minor variants inside the same country. The only mandatory parameters here are: minor variants inside the same country. The only mandatory parameters here are:
variant, but typically you also want to set max_ani and max_dnis. variant, but typically you also want to set max_ani and max_dnis.
@ -46,6 +96,7 @@ with the signaling protocols that you can run on top of your I/O interfaces.
best defaults for your country. If you want to contribute your configs for a particular best defaults for your country. If you want to contribute your configs for a particular
country send them to the e-mail of the primary OpenR2 developer that you can find in the country send them to the e-mail of the primary OpenR2 developer that you can find in the
AUTHORS file of the OpenR2 package, they will be added to the samples directory of openr2. AUTHORS file of the OpenR2 package, they will be added to the samples directory of openr2.
--> -->
<r2_spans> <r2_spans>
<span name="wp1" cfgprofile="testr2"> <span name="wp1" cfgprofile="testr2">

View File

@ -103,7 +103,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>FreeSwitch.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>FreeSwitchCore.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile> <ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
@ -127,7 +127,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>FreeSwitch.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>FreeSwitchCore.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile> <ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>

View File

@ -2717,6 +2717,9 @@ static switch_status_t load_config(void)
char *hold_music = NULL; char *hold_music = NULL;
char *fail_dial_regex = NULL; char *fail_dial_regex = NULL;
const char *enable_callerid = "true"; const char *enable_callerid = "true";
const char *answer_polarity = "false";
const char *hangup_polarity = "false";
int polarity_delay = 600;
int callwaiting = 1; int callwaiting = 1;
uint32_t span_id = 0, to = 0, max = 0; uint32_t span_id = 0, to = 0, max = 0;
@ -2788,6 +2791,12 @@ static switch_status_t load_config(void)
dial_regex = val; dial_regex = val;
} else if (!strcasecmp(var, "enable-callerid")) { } else if (!strcasecmp(var, "enable-callerid")) {
enable_callerid = val; enable_callerid = val;
} else if (!strcasecmp(var, "answer-polarity-reverse")) {
answer_polarity = val;
} else if (!strcasecmp(var, "hangup-polarity-reverse")) {
hangup_polarity = val;
} else if (!strcasecmp(var, "polarity-delay")) {
polarity_delay = atoi(val);
} else if (!strcasecmp(var, "fail-dial-regex")) { } else if (!strcasecmp(var, "fail-dial-regex")) {
fail_dial_regex = val; fail_dial_regex = val;
} else if (!strcasecmp(var, "hold-music")) { } else if (!strcasecmp(var, "hold-music")) {
@ -2848,6 +2857,9 @@ static switch_status_t load_config(void)
"max_dialstr", &max, "max_dialstr", &max,
"hotline", hotline ? hotline : "", "hotline", hotline ? hotline : "",
"enable_callerid", enable_callerid, "enable_callerid", enable_callerid,
"answer_polarity_reverse", answer_polarity,
"hangup_polarity_reverse", hangup_polarity,
"polarity_delay", &polarity_delay,
"callwaiting", &callwaiting, "callwaiting", &callwaiting,
FTDM_TAG_END) != FTDM_SUCCESS) { FTDM_TAG_END) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM analog span %s\n", ftdm_span_get_name(span)); ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM analog span %s\n", ftdm_span_get_name(span));

View File

@ -63,7 +63,7 @@ ftdm_time_t time_last_throttle_log = 0;
ftdm_time_t time_current_throttle_log = 0; ftdm_time_t time_current_throttle_log = 0;
static ftdm_iterator_t *get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t *iter); static ftdm_iterator_t *get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t *iter);
static ftdm_status_t ftdm_call_set_call_id(ftdm_caller_data_t *caller_data); static ftdm_status_t ftdm_call_set_call_id(ftdm_channel_t *fchan, ftdm_caller_data_t *caller_data);
static ftdm_status_t ftdm_call_clear_call_id(ftdm_caller_data_t *caller_data); static ftdm_status_t ftdm_call_clear_call_id(ftdm_caller_data_t *caller_data);
static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan); static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan);
static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan); static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan);
@ -1546,6 +1546,7 @@ end:
ftdm_mutex_unlock(ftdmchan->span->mutex); ftdm_mutex_unlock(ftdmchan->span->mutex);
} else { } else {
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "VETO state change from %s to %s\n", ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state)); ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "VETO state change from %s to %s\n", ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state));
goto done;
} }
/* there is an inherent race here between set and check of the change flag but we do not care because /* there is an inherent race here between set and check of the change flag but we do not care because
@ -1575,7 +1576,7 @@ end:
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "state change from %s to %s was most likely not processed after aprox %dms\n", ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "state change from %s to %s was most likely not processed after aprox %dms\n",
ftdm_channel_state2str(ftdmchan->last_state), ftdm_channel_state2str(state), DEFAULT_WAIT_TIME); ftdm_channel_state2str(ftdmchan->last_state), ftdm_channel_state2str(state), DEFAULT_WAIT_TIME);
} }
done:
return ok ? FTDM_SUCCESS : FTDM_FAIL; return ok ? FTDM_SUCCESS : FTDM_FAIL;
} }
@ -2294,8 +2295,15 @@ static ftdm_status_t call_hangup(ftdm_channel_t *chan, const char *file, const c
ftdm_channel_set_state(file, func, line, chan, FTDM_CHANNEL_STATE_HANGUP, 1); ftdm_channel_set_state(file, func, line, chan, FTDM_CHANNEL_STATE_HANGUP, 1);
} else { } else {
/* the signaling stack did not touch the state, /* the signaling stack did not touch the state,
* core is responsible from clearing flags and stuff */ * core is responsible from clearing flags and stuff, however, because ftmod_analog
ftdm_channel_close(&chan); * is a bitch in a serious need of refactoring, we also check whether the channel is open
* to avoid an spurious warning about the channel not being open. This is because ftmod_analog
* does not follow our convention of sending SIGEVENT_STOP and waiting for the user to move
* to HANGUP (implicitly through ftdm_channel_call_hangup(), as soon as ftmod_analog is fixed
* this check can be removed */
if (ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
ftdm_channel_close(&chan);
}
} }
return FTDM_SUCCESS; return FTDM_SUCCESS;
} }
@ -2519,7 +2527,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char
if (status == FTDM_SUCCESS) { if (status == FTDM_SUCCESS) {
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED); ftdm_set_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED);
ftdm_call_set_call_id(&ftdmchan->caller_data); ftdm_call_set_call_id(ftdmchan, &ftdmchan->caller_data);
ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 100); ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 100);
} }
@ -2603,10 +2611,11 @@ FT_DECLARE(ftdm_status_t) ftdm_span_get_sig_status(ftdm_span_t *span, ftdm_signa
} }
} }
/* this function must be called with the channel lock */
static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan) static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan)
{ {
ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel can't be done!\n"); ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel can't be done!\n");
ftdm_mutex_lock(ftdmchan->mutex);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OPEN); ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OPEN);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT); ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF); ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF);
@ -2691,7 +2700,6 @@ static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan)
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE); ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE);
} }
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "channel done\n"); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "channel done\n");
ftdm_mutex_unlock(ftdmchan->mutex);
return FTDM_SUCCESS; return FTDM_SUCCESS;
} }
@ -3938,7 +3946,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "cannot write in channel not open\n"); ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "cannot write in channel not open\n");
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "channel not open"); snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "channel not open");
status = FTDM_FAIL; status = FTDM_FAIL;
goto done; goto done;
@ -4394,6 +4402,16 @@ static void print_channels_by_state(ftdm_stream_handle_t *stream, ftdm_channel_s
ftdm_mutex_unlock(globals.mutex); ftdm_mutex_unlock(globals.mutex);
} }
static void print_core_usage(ftdm_stream_handle_t *stream)
{
stream->write_function(stream,
"--------------------------------------------------------------------------------\n"
"ftdm core state [!]<state_name> - List all channels in or not in the given state\n"
"ftdm core flag <flag-int-value> - List all channels with the fiven flag value set\n"
"ftdm core calls - List all known calls to the FreeTDM core\n"
"--------------------------------------------------------------------------------\n");
}
static char *handle_core_command(const char *cmd) static char *handle_core_command(const char *cmd)
{ {
char *mycmd = NULL; char *mycmd = NULL;
@ -4404,22 +4422,31 @@ static char *handle_core_command(const char *cmd)
char *state = NULL; char *state = NULL;
char *flag = NULL; char *flag = NULL;
uint32_t flagval = 0; uint32_t flagval = 0;
uint32_t current_call_id = 0;
ftdm_caller_data_t *calldata = NULL;
ftdm_channel_t *fchan = NULL;
ftdm_channel_state_t i = FTDM_CHANNEL_STATE_INVALID; ftdm_channel_state_t i = FTDM_CHANNEL_STATE_INVALID;
ftdm_stream_handle_t stream = { 0 }; ftdm_stream_handle_t stream = { 0 };
FTDM_STANDARD_STREAM(stream); FTDM_STANDARD_STREAM(stream);
if (cmd) { if (cmd && strlen(cmd)) {
mycmd = ftdm_strdup(cmd); mycmd = ftdm_strdup(cmd);
argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); argc = ftdm_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
} else { } else {
stream.write_function(&stream, "invalid core command\n"); print_core_usage(&stream);
goto done;
}
if (!argc) {
print_core_usage(&stream);
goto done; goto done;
} }
if (!strcasecmp(argv[0], "state")) { if (!strcasecmp(argv[0], "state")) {
if (argc < 2) { if (argc < 2) {
stream.write_function(&stream, "core state command requires an argument\n"); stream.write_function(&stream, "core state command requires an argument\n");
print_core_usage(&stream);
goto done; goto done;
} }
state = argv[1]; state = argv[1];
@ -4440,7 +4467,8 @@ static char *handle_core_command(const char *cmd)
stream.write_function(&stream, "\nTotal channels %s %s: %d\n", not ? "not in state" : "in state", ftdm_channel_state2str(i), count); stream.write_function(&stream, "\nTotal channels %s %s: %d\n", not ? "not in state" : "in state", ftdm_channel_state2str(i), count);
} else if (!strcasecmp(argv[0], "flag")) { } else if (!strcasecmp(argv[0], "flag")) {
if (argc < 2) { if (argc < 2) {
stream.write_function(&stream, "core state command requires an argument\n"); stream.write_function(&stream, "core flag command requires an argument\n");
print_core_usage(&stream);
goto done; goto done;
} }
flag = argv[1]; flag = argv[1];
@ -4451,8 +4479,28 @@ static char *handle_core_command(const char *cmd)
flagval = atoi(flag); flagval = atoi(flag);
print_channels_by_flag(&stream, flagval, not, &count); print_channels_by_flag(&stream, flagval, not, &count);
stream.write_function(&stream, "\nTotal channels %s %d: %d\n", not ? "without flag" : "with flag", flagval, count); stream.write_function(&stream, "\nTotal channels %s %d: %d\n", not ? "without flag" : "with flag", flagval, count);
} else if (!strcasecmp(argv[0], "calls")) {
ftdm_mutex_lock(globals.call_id_mutex);
current_call_id = globals.last_call_id;
for (current_call_id = 0; current_call_id <= MAX_CALLIDS; current_call_id++) {
if (!globals.call_ids[current_call_id]) {
continue;
}
calldata = globals.call_ids[current_call_id];
fchan = calldata->fchan;
if (fchan) {
stream.write_function(&stream, "Call %d on channel %d:%d\n", current_call_id,
fchan->span_id, fchan->chan_id);
} else {
stream.write_function(&stream, "Call %d without a channel?\n", current_call_id);
}
count++;
}
ftdm_mutex_unlock(globals.call_id_mutex);
stream.write_function(&stream, "\nTotal calls: %d\n", count);
} else { } else {
stream.write_function(&stream, "invalid core command %s\n", argv[0]); stream.write_function(&stream, "invalid core command %s\n", argv[0]);
print_core_usage(&stream);
} }
done: done:
@ -4472,6 +4520,8 @@ FT_DECLARE(char *) ftdm_api_execute(const char *cmd)
if ((p = strchr(dup, ' '))) { if ((p = strchr(dup, ' '))) {
*p++ = '\0'; *p++ = '\0';
cmd = p; cmd = p;
} else {
cmd = "";
} }
type = dup; type = dup;
@ -5444,7 +5494,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
case FTDM_SIGEVENT_START: case FTDM_SIGEVENT_START:
{ {
ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED); ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED);
ftdm_call_set_call_id(&sigmsg->channel->caller_data); ftdm_call_set_call_id(sigmsg->channel, &sigmsg->channel->caller_data);
ftdm_set_echocancel_call_begin(sigmsg->channel); ftdm_set_echocancel_call_begin(sigmsg->channel);
if (sigmsg->channel->dtmfdbg.requested) { if (sigmsg->channel->dtmfdbg.requested) {
ftdm_channel_command(sigmsg->channel, FTDM_COMMAND_ENABLE_DEBUG_DTMF, NULL); ftdm_channel_command(sigmsg->channel, FTDM_COMMAND_ENABLE_DEBUG_DTMF, NULL);
@ -6086,27 +6136,35 @@ FT_DECLARE(char *) ftdm_channel_get_history_str(const ftdm_channel_t *fchan)
return stream.data; return stream.data;
} }
static ftdm_status_t ftdm_call_set_call_id(ftdm_caller_data_t *caller_data) static ftdm_status_t ftdm_call_set_call_id(ftdm_channel_t *fchan, ftdm_caller_data_t *caller_data)
{ {
uint32_t current_call_id; uint32_t current_call_id;
ftdm_assert_return(!caller_data->call_id, FTDM_FAIL, "Overwriting non-cleared call-id");
ftdm_assert_return(!caller_data->call_id, FTDM_FAIL, "Overwriting non-cleared call-id\n");
ftdm_mutex_lock(globals.call_id_mutex); ftdm_mutex_lock(globals.call_id_mutex);
current_call_id = globals.last_call_id; current_call_id = globals.last_call_id;
do { for (current_call_id = globals.last_call_id + 1;
if (++current_call_id > MAX_CALLIDS) { current_call_id != globals.last_call_id;
current_call_id++ ) {
if (current_call_id > MAX_CALLIDS) {
current_call_id = 1; current_call_id = 1;
} }
if (globals.call_ids[current_call_id] != NULL) { if (globals.call_ids[current_call_id] == NULL) {
continue; break;
} }
} while (0); }
ftdm_assert_return(globals.call_ids[current_call_id] == NULL, FTDM_FAIL, "We ran out of call ids\n");
globals.last_call_id = current_call_id; globals.last_call_id = current_call_id;
caller_data->call_id = current_call_id; caller_data->call_id = current_call_id;
globals.call_ids[current_call_id] = caller_data; globals.call_ids[current_call_id] = caller_data;
caller_data->fchan = fchan;
ftdm_mutex_unlock(globals.call_id_mutex); ftdm_mutex_unlock(globals.call_id_mutex);
return FTDM_SUCCESS; return FTDM_SUCCESS;
} }
@ -6123,8 +6181,8 @@ static ftdm_status_t ftdm_call_clear_call_id(ftdm_caller_data_t *caller_data)
ftdm_mutex_lock(globals.call_id_mutex); ftdm_mutex_lock(globals.call_id_mutex);
if (globals.call_ids[caller_data->call_id]) { if (globals.call_ids[caller_data->call_id]) {
ftdm_log(FTDM_LOG_DEBUG, "Cleared call with id %u\n", caller_data->call_id); ftdm_log(FTDM_LOG_DEBUG, "Cleared call with id %u\n", caller_data->call_id);
caller_data->call_id = 0;
globals.call_ids[caller_data->call_id] = NULL; globals.call_ids[caller_data->call_id] = NULL;
caller_data->call_id = 0;
} else { } else {
ftdm_log(FTDM_LOG_CRIT, "call-id did not exist %u\n", caller_data->call_id); ftdm_log(FTDM_LOG_CRIT, "call-id did not exist %u\n", caller_data->call_id);
} }

View File

@ -37,7 +37,9 @@
typedef enum { typedef enum {
FTDM_ANALOG_RUNNING = (1 << 0), FTDM_ANALOG_RUNNING = (1 << 0),
FTDM_ANALOG_CALLERID = (1 << 1) FTDM_ANALOG_CALLERID = (1 << 1),
FTDM_ANALOG_ANSWER_POLARITY_REVERSE = (1 << 2),
FTDM_ANALOG_HANGUP_POLARITY_REVERSE = (1 << 3)
} ftdm_analog_flag_t; } ftdm_analog_flag_t;
#define FTDM_MAX_HOTLINE_STR 20 #define FTDM_MAX_HOTLINE_STR 20
@ -47,11 +49,13 @@ struct ftdm_analog_data {
uint32_t flags; uint32_t flags;
uint32_t max_dialstr; uint32_t max_dialstr;
uint32_t wait_dialtone_timeout; uint32_t wait_dialtone_timeout;
uint32_t polarity_delay;
uint32_t digit_timeout; uint32_t digit_timeout;
char hotline[FTDM_MAX_HOTLINE_STR]; char hotline[FTDM_MAX_HOTLINE_STR];
}; };
/* Analog flags to be set in the sflags (signaling flags) channel memeber */
#define AF_POLARITY_REVERSE (1 << 0)
static void *ftdm_analog_run(ftdm_thread_t *me, void *obj); static void *ftdm_analog_run(ftdm_thread_t *me, void *obj);
typedef struct ftdm_analog_data ftdm_analog_data_t; typedef struct ftdm_analog_data ftdm_analog_data_t;

View File

@ -184,6 +184,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
uint32_t digit_timeout = 10; uint32_t digit_timeout = 10;
uint32_t wait_dialtone_timeout = 30000; uint32_t wait_dialtone_timeout = 30000;
uint32_t max_dialstr = MAX_DTMF; uint32_t max_dialstr = MAX_DTMF;
uint32_t polarity_delay = 600;
const char *var, *val; const char *var, *val;
int *intval; int *intval;
uint32_t flags = FTDM_ANALOG_CALLERID; uint32_t flags = FTDM_ANALOG_CALLERID;
@ -236,6 +237,29 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
} else { } else {
flags &= ~FTDM_ANALOG_CALLERID; flags &= ~FTDM_ANALOG_CALLERID;
} }
} else if (!strcasecmp(var, "answer_polarity_reverse")) {
if (!(val = va_arg(ap, char *))) {
break;
}
if (ftdm_true(val)) {
flags |= FTDM_ANALOG_ANSWER_POLARITY_REVERSE;
} else {
flags &= ~FTDM_ANALOG_ANSWER_POLARITY_REVERSE;
}
} else if (!strcasecmp(var, "hangup_polarity_reverse")) {
if (!(val = va_arg(ap, char *))) {
break;
}
if (ftdm_true(val)) {
flags |= FTDM_ANALOG_HANGUP_POLARITY_REVERSE;
} else {
flags &= ~FTDM_ANALOG_HANGUP_POLARITY_REVERSE;
}
} else if (!strcasecmp(var, "polarity_delay")) {
if (!(intval = va_arg(ap, int *))) {
break;
}
polarity_delay = *intval;
} else if (!strcasecmp(var, "callwaiting")) { } else if (!strcasecmp(var, "callwaiting")) {
if (!(intval = va_arg(ap, int *))) { if (!(intval = va_arg(ap, int *))) {
break; break;
@ -276,6 +300,7 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
analog_data->flags = flags; analog_data->flags = flags;
analog_data->digit_timeout = digit_timeout; analog_data->digit_timeout = digit_timeout;
analog_data->wait_dialtone_timeout = wait_dialtone_timeout; analog_data->wait_dialtone_timeout = wait_dialtone_timeout;
analog_data->polarity_delay = polarity_delay;
analog_data->max_dialstr = max_dialstr; analog_data->max_dialstr = max_dialstr;
span->signal_cb = sig_cb; span->signal_cb = sig_cb;
strncpy(analog_data->hotline, hotline, sizeof(analog_data->hotline)); strncpy(analog_data->hotline, hotline, sizeof(analog_data->hotline));
@ -399,6 +424,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
ftdm_analog_data_t *analog_data = ftdmchan->span->signal_data; ftdm_analog_data_t *analog_data = ftdmchan->span->signal_data;
ftdm_channel_t *closed_chan; ftdm_channel_t *closed_chan;
uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = analog_data->wait_dialtone_timeout; uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = analog_data->wait_dialtone_timeout;
uint32_t answer_on_polarity_counter = 0;
ftdm_sigmsg_t sig; ftdm_sigmsg_t sig;
ftdm_status_t status; ftdm_status_t status;
@ -470,7 +496,12 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
if (ftdmchan->needed_tones[FTDM_TONEMAP_DIAL]) { if (ftdmchan->needed_tones[FTDM_TONEMAP_DIAL]) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY); ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
} else { } else {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); /* do not go up if we're waiting for polarity reversal */
if (ftdm_test_flag(analog_data, FTDM_ANALOG_ANSWER_POLARITY_REVERSE)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
} else {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
}
} }
} }
} }
@ -561,8 +592,30 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
} }
case FTDM_CHANNEL_STATE_UP: case FTDM_CHANNEL_STATE_UP:
case FTDM_CHANNEL_STATE_RING: case FTDM_CHANNEL_STATE_RING:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
{ {
ftdm_sleep(interval); if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) &&
ftdmchan->state == FTDM_CHANNEL_STATE_PROGRESS_MEDIA &&
ftdm_test_sflag(ftdmchan, AF_POLARITY_REVERSE)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Answering on polarity reverse\n");
ftdm_clear_sflag(ftdmchan, AF_POLARITY_REVERSE);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
answer_on_polarity_counter = state_counter;
} else if (ftdmchan->state == FTDM_CHANNEL_STATE_UP
&& ftdm_test_sflag(ftdmchan, AF_POLARITY_REVERSE)){
/* if this polarity reverse is close to the answer polarity reverse, ignore it */
if (answer_on_polarity_counter
&& (state_counter - answer_on_polarity_counter) > analog_data->polarity_delay) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Hanging up on polarity reverse\n");
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING,
"Not hanging up on polarity reverse, too close to Answer reverse\n");
}
ftdm_clear_sflag(ftdmchan, AF_POLARITY_REVERSE);
} else {
ftdm_sleep(interval);
}
continue; continue;
} }
break; break;
@ -615,6 +668,18 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
sig.event_id = FTDM_SIGEVENT_UP; sig.event_id = FTDM_SIGEVENT_UP;
} }
if (ftdmchan->type == FTDM_CHAN_TYPE_FXS &&
!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND) &&
ftdm_test_flag(analog_data, FTDM_ANALOG_ANSWER_POLARITY_REVERSE)) {
ftdm_polarity_t polarity = FTDM_POLARITY_REVERSE;
if (ftdmchan->polarity != FTDM_POLARITY_FORWARD) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Polarity is already reversed on answer??\n");
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Reversing polarity on answer\n");
ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_POLARITY, &polarity);
}
}
ftdm_span_send_signal(ftdmchan->span, &sig); ftdm_span_send_signal(ftdmchan->span, &sig);
continue; continue;
} }
@ -639,6 +704,22 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
continue; continue;
} }
break; break;
case FTDM_CHANNEL_STATE_HANGUP:
/* this state is only used when the user hangup, if the device hang up (onhook) we currently
* go straight to DOWN. If we ever change this (as other signaling modules do) by using this
* state for both user and device hangup, we should check here for the type of hangup since
* some actions (polarity reverse) do not make sense if the device hung up */
if (ftdmchan->type == FTDM_CHAN_TYPE_FXS &&
ftdmchan->last_state == FTDM_CHANNEL_STATE_UP &&
ftdm_test_flag(analog_data, FTDM_ANALOG_HANGUP_POLARITY_REVERSE)) {
ftdm_polarity_t polarity = ftdmchan->polarity == FTDM_POLARITY_REVERSE
? FTDM_POLARITY_FORWARD : FTDM_POLARITY_REVERSE;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Reversing polarity on hangup\n");
ftdm_channel_command(ftdmchan, FTDM_COMMAND_SET_POLARITY, &polarity);
}
break;
case FTDM_CHANNEL_STATE_DOWN: case FTDM_CHANNEL_STATE_DOWN:
{ {
sig.event_id = FTDM_SIGEVENT_STOP; sig.event_id = FTDM_SIGEVENT_STOP;
@ -847,6 +928,9 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
done: done:
closed_chan = ftdmchan;
ftdm_channel_lock(closed_chan);
if (ftdmchan->type == FTDM_CHAN_TYPE_FXO && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK)) { if (ftdmchan->type == FTDM_CHAN_TYPE_FXO && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK)) {
ftdm_channel_command(ftdmchan, FTDM_COMMAND_ONHOOK, NULL); ftdm_channel_command(ftdmchan, FTDM_COMMAND_ONHOOK, NULL);
@ -857,7 +941,8 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
} }
closed_chan = ftdmchan; ftdm_clear_sflag(ftdmchan, AF_POLARITY_REVERSE);
ftdm_channel_close(&ftdmchan); ftdm_channel_close(&ftdmchan);
ftdm_channel_command(closed_chan, FTDM_COMMAND_SET_NATIVE_CODEC, NULL); ftdm_channel_command(closed_chan, FTDM_COMMAND_SET_NATIVE_CODEC, NULL);
@ -875,8 +960,11 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
} }
ftdm_log_chan(closed_chan, FTDM_LOG_DEBUG, "ANALOG CHANNEL %d:%d thread ended.\n", closed_chan->span_id, closed_chan->chan_id); ftdm_log_chan(closed_chan, FTDM_LOG_DEBUG, "ANALOG CHANNEL %d:%d thread ended.\n", closed_chan->span_id, closed_chan->chan_id);
ftdm_clear_flag(closed_chan, FTDM_CHANNEL_INTHREAD); ftdm_clear_flag(closed_chan, FTDM_CHANNEL_INTHREAD);
ftdm_channel_unlock(closed_chan);
return NULL; return NULL;
} }
@ -903,6 +991,19 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
ftdm_mutex_lock(event->channel->mutex); ftdm_mutex_lock(event->channel->mutex);
locked++; locked++;
/* MAINTENANCE WARNING:
* 1. Be aware you are working on the locked channel
* 2. We should not be calling ftdm_span_send_signal or ftdm_set_state when there is already a channel thread running
* however, since this is old code I am not changing it now, but new code should adhere to that convention
* otherwise, we have possible races where we compete with the user for state changes, ie, the user requests
* a state change and then we process an event, the state change from the user is pending so our ftdm_set_state
* operation will fail. In cases where we win the race, our state change will be accepted but if a user requests
* a state change before the state change we requested here is processed by the channel thread, we'll end up
* rejecting the user request.
*
* See docs/locking.txt for further information about what guarantees should signaling modules provide when
* locking/unlocking a channel
* */
switch(event->enum_id) { switch(event->enum_id) {
case FTDM_OOB_RING_START: case FTDM_OOB_RING_START:
{ {
@ -940,7 +1041,11 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
} }
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN); ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN);
} }
if (event->channel->type == FTDM_CHAN_TYPE_FXS) {
/* we always return to forward when the device goes onhook */
ftdm_polarity_t forward_polarity = FTDM_POLARITY_FORWARD;
ftdm_channel_command(event->channel, FTDM_COMMAND_SET_POLARITY, &forward_polarity);
}
} }
break; break;
case FTDM_OOB_FLASH: case FTDM_OOB_FLASH:
@ -1004,6 +1109,35 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
ftdm_span_send_signal(span, &sig); ftdm_span_send_signal(span, &sig);
} }
break; break;
case FTDM_OOB_POLARITY_REVERSE:
{
if (event->channel->type != FTDM_CHAN_TYPE_FXO) {
ftdm_log_chan_msg(event->channel, FTDM_LOG_WARNING,
"Ignoring polarity reversal, this should not happen in non-FXO channels!\n");
break;
}
if (!ftdm_test_flag(event->channel, FTDM_CHANNEL_INTHREAD) &&
ftdm_test_flag(event->channel, FTDM_CHANNEL_OFFHOOK)) {
ftdm_log_chan_msg(event->channel, FTDM_LOG_WARNING,
"Forcing onhook in channel not in thread after polarity reversal\n");
ftdm_channel_command(event->channel, FTDM_COMMAND_ONHOOK, NULL);
break;
}
if (!ftdm_test_flag(analog_data, FTDM_ANALOG_ANSWER_POLARITY_REVERSE)
&& !ftdm_test_flag(analog_data, FTDM_ANALOG_HANGUP_POLARITY_REVERSE)) {
ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG,
"Ignoring polarity reversal because this channel is not configured for it\n");
break;
}
if (event->channel->state == FTDM_CHANNEL_STATE_DOWN) {
ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG,
"Ignoring polarity reversal because this channel is down\n");
break;
}
/* we have a good channel, set the polarity flag and let the channel thread deal with it */
ftdm_set_sflag(event->channel, AF_POLARITY_REVERSE);
}
break;
default: default:
{ {
ftdm_log_chan(event->channel, FTDM_LOG_DEBUG, "Ignoring event [%s] in state [%s]\n", ftdm_oob_event2str(event->enum_id), ftdm_channel_state2str(event->channel->state)); ftdm_log_chan(event->channel, FTDM_LOG_DEBUG, "Ignoring event [%s] in state [%s]\n", ftdm_oob_event2str(event->enum_id), ftdm_channel_state2str(event->channel->state));

View File

@ -40,11 +40,12 @@
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories="&quot;C:\Program Files\libsng_isdn\include&quot;;&quot;C:\Program Files\libsng_isdn\include\sng_isdn&quot;;../../include;&quot;C:\Program Files\Sangoma\include&quot;" AdditionalIncludeDirectories="&quot;C:\Program Files\sangoma\sng_isdn\include&quot;;../../include;&quot;C:\Program Files\Sangoma\include&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;" PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
MinimalRebuild="true" MinimalRebuild="true"
ExceptionHandling="0" ExceptionHandling="0"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0" UsePrecompiledHeader="0"
WarningLevel="3" WarningLevel="3"
Detect64BitPortabilityProblems="false" Detect64BitPortabilityProblems="false"
@ -63,7 +64,7 @@
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="freetdm.lib libsng_isdn.lib" AdditionalDependencies="freetdm.lib libsng_isdn.lib"
LinkIncremental="2" LinkIncremental="2"
AdditionalLibraryDirectories="&quot;$(OutDir)&quot;;&quot;C:\Program Files\libsng_isdn\lib&quot;;&quot;C:\Program Files\Sangoma\api\lib\x86&quot;" AdditionalLibraryDirectories="&quot;$(OutDir)&quot;;&quot;C:\Program Files\sangoma\sng_isdn\lib&quot;;&quot;C:\Program Files\Sangoma\api\lib\x86&quot;"
GenerateDebugInformation="true" GenerateDebugInformation="true"
SubSystem="1" SubSystem="1"
RandomizedBaseAddress="1" RandomizedBaseAddress="1"
@ -116,10 +117,11 @@
/> />
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
AdditionalIncludeDirectories="&quot;C:\Program Files\sangoma\sng_isdn\include&quot;;../../include;&quot;C:\Program Files\Sangoma\include&quot;"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;" PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
MinimalRebuild="true" MinimalRebuild="true"
BasicRuntimeChecks="3" BasicRuntimeChecks="3"
RuntimeLibrary="3" RuntimeLibrary="2"
UsePrecompiledHeader="0" UsePrecompiledHeader="0"
WarningLevel="3" WarningLevel="3"
Detect64BitPortabilityProblems="false" Detect64BitPortabilityProblems="false"
@ -136,7 +138,9 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalDependencies="freetdm.lib libsng_isdn.lib"
LinkIncremental="2" LinkIncremental="2"
AdditionalLibraryDirectories="&quot;$(OutDir)&quot;;&quot;C:\Program Files\sangoma\sng_isdn\lib&quot;;&quot;C:\Program Files\Sangoma\api\lib\x86&quot;"
GenerateDebugInformation="true" GenerateDebugInformation="true"
SubSystem="2" SubSystem="2"
OptimizeReferences="2" OptimizeReferences="2"

View File

@ -85,7 +85,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>C:\Program Files\libsng_isdn\include;C:\Program Files\libsng_isdn\include\sng_isdn;../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>C:\Program Files\sangoma\sng_isdn\include;../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>true</MinimalRebuild>
<ExceptionHandling> <ExceptionHandling>
@ -95,10 +95,11 @@
</PrecompiledHeader> </PrecompiledHeader>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat> <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>freetdm.lib;libsng_isdn.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>freetdm.lib;libsng_isdn.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);C:\Program Files\libsng_isdn\lib;C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>$(OutDir);C:\Program Files\sangoma\sng_isdn\lib;C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress> <RandomizedBaseAddress>false</RandomizedBaseAddress>
@ -110,7 +111,7 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile> <ClCompile>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>C:\Program Files\libsng_isdn\include;C:\Program Files\libsng_isdn\include\sng_isdn;../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>C:\Program Files\sangoma\sng_isdn\include;../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling> <ExceptionHandling>
</ExceptionHandling> </ExceptionHandling>
@ -119,6 +120,7 @@
</PrecompiledHeader> </PrecompiledHeader>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>freetdm.lib;libsng_isdn.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>freetdm.lib;libsng_isdn.lib;%(AdditionalDependencies)</AdditionalDependencies>
@ -135,11 +137,13 @@
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild> <MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader> <PrecompiledHeader>
</PrecompiledHeader> </PrecompiledHeader>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>C:\Program Files\sangoma\sng_isdn\include;../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<Optimization>Disabled</Optimization>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
@ -147,23 +151,27 @@
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine> <TargetMachine>MachineX86</TargetMachine>
<AdditionalDependencies>freetdm.lib;libsng_isdn.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);C:\Program Files\sangoma\sng_isdn\lib;C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile> <ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader> <PrecompiledHeader>
</PrecompiledHeader> </PrecompiledHeader>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<AdditionalIncludeDirectories>C:\Program Files\sangoma\sng_isdn\include;../../include;C:\Program Files\Sangoma\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<Link> <Link>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<AdditionalDependencies>freetdm.lib;libsng_isdn.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>

View File

@ -100,7 +100,7 @@
<DebugInformationFormat>EditAndContinue</DebugInformationFormat> <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>freetdm.lib;libsangoma.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>libsangoma.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>$(OutDir);C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -127,7 +127,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>freetdm.lib;libsangoma.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>libsangoma.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);C:\Program Files\Sangoma\api\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>$(OutDir);C:\Program Files\Sangoma\api\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -148,7 +148,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>freetdm.lib;libsangoma.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>libsangoma.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>$(OutDir);C:\Program Files\Sangoma\api\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
@ -174,7 +174,7 @@
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat> <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile> </ClCompile>
<Link> <Link>
<AdditionalDependencies>freetdm.lib;libsangoma.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>libsangoma.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir);C:\Program Files\Sangoma\api\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>$(OutDir);C:\Program Files\Sangoma\api\lib\x64;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>

View File

@ -784,17 +784,27 @@ static FIO_COMMAND_FUNCTION(wanpipe_command)
err = sangoma_set_tx_queue_sz(ftdmchan->sockfd, &tdm_api, queue_size); err = sangoma_set_tx_queue_sz(ftdmchan->sockfd, &tdm_api, queue_size);
} }
break; break;
case FTDM_COMMAND_SET_POLARITY:
{
ftdm_polarity_t polarity = FTDM_COMMAND_OBJ_INT;
err = sangoma_tdm_set_polarity(ftdmchan->sockfd, &tdm_api, polarity);
if (!err) {
ftdmchan->polarity = polarity;
}
}
break;
default: default:
err = FTDM_NOTIMPL; err = FTDM_NOTIMPL;
break; break;
}; };
if (err) { if (err) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno)); int myerrno = errno;
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Wanpipe failed to execute command %d: %s\n", command, strerror(myerrno));
errno = myerrno;
return err; return err;
} }
return FTDM_SUCCESS; return FTDM_SUCCESS;
} }
@ -1237,8 +1247,9 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event)
wanpipe_tdm_api_t tdm_api; wanpipe_tdm_api_t tdm_api;
ftdm_span_t *span = ftdmchan->span; ftdm_span_t *span = ftdmchan->span;
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) {
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_EVENT); ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_EVENT);
}
memset(&tdm_api, 0, sizeof(tdm_api)); memset(&tdm_api, 0, sizeof(tdm_api));
status = sangoma_tdm_read_event(ftdmchan->sockfd, &tdm_api); status = sangoma_tdm_read_event(ftdmchan->sockfd, &tdm_api);
@ -1251,7 +1262,7 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event)
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "read wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type); ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "read wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type);
switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type) { switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type) {
case WP_TDMAPI_EVENT_LINK_STATUS: case WP_API_EVENT_LINK_STATUS:
{ {
switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_link_status) { switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_link_status) {
case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED: case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED:
@ -1264,7 +1275,7 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event)
} }
break; break;
case WP_TDMAPI_EVENT_RXHOOK: case WP_API_EVENT_RXHOOK:
{ {
if (ftdmchan->type == FTDM_CHAN_TYPE_FXS) { if (ftdmchan->type == FTDM_CHAN_TYPE_FXS) {
event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_OFFHOOK : FTDM_OOB_ONHOOK; event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_OFFHOOK : FTDM_OOB_ONHOOK;
@ -1300,26 +1311,26 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event)
} }
} }
break; break;
case WP_TDMAPI_EVENT_RING_DETECT: case WP_API_EVENT_RING_DETECT:
{ {
event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_RING_START : FTDM_OOB_RING_STOP; event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_RING_START : FTDM_OOB_RING_STOP;
} }
break; break;
/* /*
disabled this ones when configuring, we don't need them, do we? disabled this ones when configuring, we don't need them, do we?
case WP_TDMAPI_EVENT_RING_TRIP_DETECT: case WP_API_EVENT_RING_TRIP_DETECT:
{ {
event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_ONHOOK : FTDM_OOB_OFFHOOK; event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_ONHOOK : FTDM_OOB_OFFHOOK;
} }
break; break;
*/ */
case WP_TDMAPI_EVENT_RBS: case WP_API_EVENT_RBS:
{ {
event_id = FTDM_OOB_CAS_BITS_CHANGE; event_id = FTDM_OOB_CAS_BITS_CHANGE;
ftdmchan->rx_cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits); ftdmchan->rx_cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits);
} }
break; break;
case WP_TDMAPI_EVENT_DTMF: case WP_API_EVENT_DTMF:
{ {
char tmp_dtmf[2] = { tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_digit, 0 }; char tmp_dtmf[2] = { tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_digit, 0 };
event_id = FTDM_OOB_NOOP; event_id = FTDM_OOB_NOOP;
@ -1342,12 +1353,18 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event)
} }
} }
break; break;
case WP_TDMAPI_EVENT_ALARM: case WP_API_EVENT_ALARM:
{ {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Got wanpipe alarms %d\n", tdm_api.wp_tdm_cmd.event.wp_api_event_alarm); ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Got wanpipe alarms %d\n", tdm_api.wp_tdm_cmd.event.wp_api_event_alarm);
event_id = FTDM_OOB_ALARM_TRAP; event_id = FTDM_OOB_ALARM_TRAP;
} }
break; break;
case WP_API_EVENT_POLARITY_REVERSE:
{
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Got polarity reverse\n");
event_id = FTDM_OOB_POLARITY_REVERSE;
}
break;
default: default:
{ {
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unhandled wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type); ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unhandled wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type);
@ -1423,7 +1440,7 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "read wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type); ftdm_log_chan(span->channels[i], FTDM_LOG_DEBUG, "read wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type);
switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type) { switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type) {
case WP_TDMAPI_EVENT_LINK_STATUS: case WP_API_EVENT_LINK_STATUS:
{ {
switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_link_status) { switch(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_link_status) {
case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED: case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED:
@ -1436,7 +1453,7 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
} }
break; break;
case WP_TDMAPI_EVENT_RXHOOK: case WP_API_EVENT_RXHOOK:
{ {
if (span->channels[i]->type == FTDM_CHAN_TYPE_FXS) { if (span->channels[i]->type == FTDM_CHAN_TYPE_FXS) {
event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_OFFHOOK : FTDM_OOB_ONHOOK; event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_hook_state & WP_TDMAPI_EVENT_RXHOOK_OFF ? FTDM_OOB_OFFHOOK : FTDM_OOB_ONHOOK;
@ -1472,26 +1489,26 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
} }
} }
break; break;
case WP_TDMAPI_EVENT_RING_DETECT: case WP_API_EVENT_RING_DETECT:
{ {
event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_RING_START : FTDM_OOB_RING_STOP; event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_RING_START : FTDM_OOB_RING_STOP;
} }
break; break;
/* /*
disabled this ones when configuring, we don't need them, do we? disabled this ones when configuring, we don't need them, do we?
case WP_TDMAPI_EVENT_RING_TRIP_DETECT: case WP_API_EVENT_RING_TRIP_DETECT:
{ {
event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_ONHOOK : FTDM_OOB_OFFHOOK; event_id = tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_ring_state == WP_TDMAPI_EVENT_RING_PRESENT ? FTDM_OOB_ONHOOK : FTDM_OOB_OFFHOOK;
} }
break; break;
*/ */
case WP_TDMAPI_EVENT_RBS: case WP_API_EVENT_RBS:
{ {
event_id = FTDM_OOB_CAS_BITS_CHANGE; event_id = FTDM_OOB_CAS_BITS_CHANGE;
span->channels[i]->rx_cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits); span->channels[i]->rx_cas_bits = wanpipe_swap_bits(tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_rbs_bits);
} }
break; break;
case WP_TDMAPI_EVENT_DTMF: case WP_API_EVENT_DTMF:
{ {
char tmp_dtmf[2] = { tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_digit, 0 }; char tmp_dtmf[2] = { tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_dtmf_digit, 0 };
event_id = FTDM_OOB_NOOP; event_id = FTDM_OOB_NOOP;
@ -1514,12 +1531,18 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
} }
} }
break; break;
case WP_TDMAPI_EVENT_ALARM: case WP_API_EVENT_ALARM:
{ {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Got wanpipe alarms %d\n", tdm_api.wp_tdm_cmd.event.wp_api_event_alarm); ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Got wanpipe alarms %d\n", tdm_api.wp_tdm_cmd.event.wp_api_event_alarm);
event_id = FTDM_OOB_ALARM_TRAP; event_id = FTDM_OOB_ALARM_TRAP;
} }
break; break;
case WP_API_EVENT_POLARITY_REVERSE:
{
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Got polarity reverse\n");
event_id = FTDM_OOB_POLARITY_REVERSE;
}
break;
default: default:
{ {
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unhandled wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type); ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unhandled wanpipe event %d\n", tdm_api.wp_tdm_cmd.event.wp_tdm_api_event_type);

View File

@ -320,6 +320,7 @@ typedef struct ftdm_caller_data {
* that the user can use caller_data.call_id to obtain the call_id. The user * that the user can use caller_data.call_id to obtain the call_id. The user
* should use the call_id from sigmsg otherwise */ * should use the call_id from sigmsg otherwise */
uint32_t call_id; /*!< Unique call ID for this call */ uint32_t call_id; /*!< Unique call ID for this call */
ftdm_channel_t *fchan; /*!< FreeTDM channel associated (can be NULL) */
} ftdm_caller_data_t; } ftdm_caller_data_t;
/*! \brief Tone type */ /*! \brief Tone type */
@ -557,8 +558,14 @@ typedef enum {
FTDM_COMMAND_COUNT, FTDM_COMMAND_COUNT,
FTDM_COMMAND_SET_RX_QUEUE_SIZE, FTDM_COMMAND_SET_RX_QUEUE_SIZE,
FTDM_COMMAND_SET_TX_QUEUE_SIZE, FTDM_COMMAND_SET_TX_QUEUE_SIZE,
FTDM_COMMAND_SET_POLARITY,
} ftdm_command_t; } ftdm_command_t;
typedef enum {
FTDM_POLARITY_FORWARD = 0,
FTDM_POLARITY_REVERSE = 1
} ftdm_polarity_t;
/*! \brief Custom memory handler hooks. Not recommended to use unless you need memory allocation customizations */ /*! \brief Custom memory handler hooks. Not recommended to use unless you need memory allocation customizations */
typedef void *(*ftdm_malloc_func_t)(void *pool, ftdm_size_t len); typedef void *(*ftdm_malloc_func_t)(void *pool, ftdm_size_t len);
typedef void *(*ftdm_calloc_func_t)(void *pool, ftdm_size_t elements, ftdm_size_t len); typedef void *(*ftdm_calloc_func_t)(void *pool, ftdm_size_t elements, ftdm_size_t len);

View File

@ -143,7 +143,9 @@ extern "C" {
\return true value if the object has the flags defined \return true value if the object has the flags defined
*/ */
#define ftdm_test_flag(obj, flag) ((obj)->flags & flag) #define ftdm_test_flag(obj, flag) ((obj)->flags & flag)
/*!< Physical (IO) module specific flags */
#define ftdm_test_pflag(obj, flag) ((obj)->pflags & flag) #define ftdm_test_pflag(obj, flag) ((obj)->pflags & flag)
/*!< signaling module specific flags */
#define ftdm_test_sflag(obj, flag) ((obj)->sflags & flag) #define ftdm_test_sflag(obj, flag) ((obj)->sflags & flag)
#define ftdm_set_alarm_flag(obj, flag) (obj)->alarm_flags |= (flag) #define ftdm_set_alarm_flag(obj, flag) (obj)->alarm_flags |= (flag)
@ -456,6 +458,7 @@ struct ftdm_channel {
ftdm_fsk_data_state_t fsk; ftdm_fsk_data_state_t fsk;
uint8_t fsk_buf[80]; uint8_t fsk_buf[80];
uint32_t ring_count; uint32_t ring_count;
ftdm_polarity_t polarity;
/* Private I/O data. Do not touch unless you are an I/O module */ /* Private I/O data. Do not touch unless you are an I/O module */
void *io_data; void *io_data;
/* Private signaling data. Do not touch unless you are a signaling module */ /* Private signaling data. Do not touch unless you are a signaling module */

View File

@ -123,6 +123,7 @@ typedef enum {
FTDM_STR2ENUM_P(ftdm_str2ftdm_analog_start_type, ftdm_analog_start_type2str, ftdm_analog_start_type_t) FTDM_STR2ENUM_P(ftdm_str2ftdm_analog_start_type, ftdm_analog_start_type2str, ftdm_analog_start_type_t)
typedef enum { typedef enum {
FTDM_OOB_NOOP,
FTDM_OOB_ONHOOK, FTDM_OOB_ONHOOK,
FTDM_OOB_OFFHOOK, FTDM_OOB_OFFHOOK,
FTDM_OOB_WINK, FTDM_OOB_WINK,
@ -131,11 +132,11 @@ typedef enum {
FTDM_OOB_RING_STOP, FTDM_OOB_RING_STOP,
FTDM_OOB_ALARM_TRAP, FTDM_OOB_ALARM_TRAP,
FTDM_OOB_ALARM_CLEAR, FTDM_OOB_ALARM_CLEAR,
FTDM_OOB_NOOP,
FTDM_OOB_CAS_BITS_CHANGE, FTDM_OOB_CAS_BITS_CHANGE,
FTDM_OOB_POLARITY_REVERSE,
FTDM_OOB_INVALID FTDM_OOB_INVALID
} ftdm_oob_event_t; } ftdm_oob_event_t;
#define OOB_STRINGS "ONHOOK", "OFFHOOK", "WINK", "FLASH", "RING_START", "RING_STOP", "ALARM_TRAP", "ALARM_CLEAR", "NOOP", "CAS_BITS_CHANGE", "INVALID" #define OOB_STRINGS "NOOP", "ONHOOK", "OFFHOOK", "WINK", "FLASH", "RING_START", "RING_STOP", "ALARM_TRAP", "ALARM_CLEAR", "CAS_BITS_CHANGE", "POLARITY_REVERSE", "INVALID"
FTDM_STR2ENUM_P(ftdm_str2ftdm_oob_event, ftdm_oob_event2str, ftdm_oob_event_t) FTDM_STR2ENUM_P(ftdm_str2ftdm_oob_event, ftdm_oob_event2str, ftdm_oob_event_t)
/*! \brief Event types */ /*! \brief Event types */

View File

@ -191,7 +191,8 @@ typedef enum {
EFLAG_TRANSFER = (1 << 23), EFLAG_TRANSFER = (1 << 23),
EFLAG_BGDIAL_RESULT = (1 << 24), EFLAG_BGDIAL_RESULT = (1 << 24),
EFLAG_FLOOR_CHANGE = (1 << 25), EFLAG_FLOOR_CHANGE = (1 << 25),
EFLAG_MUTE_DETECT = (1 << 26) EFLAG_MUTE_DETECT = (1 << 26),
EFLAG_RECORD = (1 << 27)
} event_type_t; } event_type_t;
typedef struct conference_file_node { typedef struct conference_file_node {
@ -270,6 +271,7 @@ typedef struct conference_obj {
uint32_t not_talking_buf_len; uint32_t not_talking_buf_len;
int comfort_noise_level; int comfort_noise_level;
int is_recording; int is_recording;
int record_count;
int video_running; int video_running;
uint32_t eflags; uint32_t eflags;
uint32_t verbose_events; uint32_t verbose_events;
@ -283,6 +285,7 @@ typedef struct conference_obj {
uint32_t avg_score; uint32_t avg_score;
uint32_t avg_itt; uint32_t avg_itt;
uint32_t avg_tally; uint32_t avg_tally;
switch_time_t run_time;
} conference_obj_t; } conference_obj_t;
/* Relationship with another member */ /* Relationship with another member */
@ -468,6 +471,7 @@ static switch_status_t conference_add_event_member_data(conference_member_t *mem
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Hear", "%s", switch_test_flag(member, MFLAG_CAN_HEAR) ? "true" : "false" ); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Hear", "%s", switch_test_flag(member, MFLAG_CAN_HEAR) ? "true" : "false" );
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Speak", "%s", switch_test_flag(member, MFLAG_CAN_SPEAK) ? "true" : "false" ); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Speak", "%s", switch_test_flag(member, MFLAG_CAN_SPEAK) ? "true" : "false" );
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Talking", "%s", switch_test_flag(member, MFLAG_TALKING) ? "true" : "false" ); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Talking", "%s", switch_test_flag(member, MFLAG_TALKING) ? "true" : "false" );
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Mute-Detect", "%s", switch_test_flag(member, MFLAG_MUTE_DETECT) ? "true" : "false" );
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-ID", "%u", member->id);
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-Type", "%s", switch_test_flag(member, MFLAG_MOD) ? "moderator" : "member"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Member-Type", "%s", switch_test_flag(member, MFLAG_MOD) ? "moderator" : "member");
@ -563,6 +567,7 @@ static switch_status_t conference_record_stop(conference_obj_t *conference, char
return count; return count;
} }
/* Add a custom relationship to a member */ /* Add a custom relationship to a member */
static conference_relationship_t *member_add_relationship(conference_member_t *member, uint32_t id) static conference_relationship_t *member_add_relationship(conference_member_t *member, uint32_t id)
{ {
@ -1035,6 +1040,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
switch_mutex_unlock(globals.hash_mutex); switch_mutex_unlock(globals.hash_mutex);
conference->is_recording = 0; conference->is_recording = 0;
conference->record_count = 0;
while (globals.running && !switch_test_flag(conference, CFLAG_DESTRUCT)) { while (globals.running && !switch_test_flag(conference, CFLAG_DESTRUCT)) {
switch_size_t file_sample_len = samples; switch_size_t file_sample_len = samples;
@ -1099,6 +1105,7 @@ static void *SWITCH_THREAD_FUNC conference_thread_run(switch_thread_t *thread, v
/* Start recording if there's more than one participant. */ /* Start recording if there's more than one participant. */
if (conference->auto_record && !conference->is_recording && conference->count > 1) { if (conference->auto_record && !conference->is_recording && conference->count > 1) {
conference->is_recording = 1; conference->is_recording = 1;
conference->record_count++;
imember = conference->members; imember = conference->members;
if (imember) { if (imember) {
switch_channel_t *channel = switch_core_session_get_channel(imember->session); switch_channel_t *channel = switch_core_session_get_channel(imember->session);
@ -2623,6 +2630,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
switch_timer_t timer = { 0 }; switch_timer_t timer = { 0 };
uint32_t rlen; uint32_t rlen;
switch_size_t data_buf_len; switch_size_t data_buf_len;
switch_event_t *event;
data_buf_len = samples * sizeof(int16_t); data_buf_len = samples * sizeof(int16_t);
@ -2701,6 +2709,15 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
switch_core_file_set_string(&fh, SWITCH_AUDIO_COL_STR_ARTIST, "FreeSWITCH mod_conference Software Conference Module"); switch_core_file_set_string(&fh, SWITCH_AUDIO_COL_STR_ARTIST, "FreeSWITCH mod_conference Software Conference Module");
if (test_eflag(conference, EFLAG_RECORD) &&
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
conference_add_event_data(conference, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "start-recording");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Path", rec->path);
switch_event_fire(&event);
}
while (switch_test_flag(member, MFLAG_RUNNING) && switch_test_flag(conference, CFLAG_RUNNING) && conference->count) { while (switch_test_flag(member, MFLAG_RUNNING) && switch_test_flag(conference, CFLAG_RUNNING) && conference->count) {
switch_size_t len = 0; switch_size_t len = 0;
mux_used = (uint32_t) switch_buffer_inuse(member->mux_buffer); mux_used = (uint32_t) switch_buffer_inuse(member->mux_buffer);
@ -3759,6 +3776,13 @@ static void conference_xlist(conference_obj_t *conference, switch_xml_t x_confer
switch_xml_set_attr_d(x_conference, "dynamic", "true"); switch_xml_set_attr_d(x_conference, "dynamic", "true");
} }
if (conference->record_count > 0) {
switch_xml_set_attr_d(x_conference, "recording", "true");
}
switch_snprintf(i, sizeof(i), "%d", switch_epoch_time_now(NULL) - conference->run_time);
switch_xml_set_attr_d(x_conference, "run_time", ival);
if (conference->agc_level) { if (conference->agc_level) {
char tmp[30] = ""; char tmp[30] = "";
switch_snprintf(tmp, sizeof(tmp), "%d", conference->agc_level); switch_snprintf(tmp, sizeof(tmp), "%d", conference->agc_level);
@ -3825,6 +3849,9 @@ static void conference_xlist(conference_obj_t *conference, switch_xml_t x_confer
x_tag = switch_xml_add_child_d(x_flags, "can_speak", count++); x_tag = switch_xml_add_child_d(x_flags, "can_speak", count++);
switch_xml_set_txt_d(x_tag, switch_test_flag(member, MFLAG_CAN_SPEAK) ? "true" : "false"); switch_xml_set_txt_d(x_tag, switch_test_flag(member, MFLAG_CAN_SPEAK) ? "true" : "false");
x_tag = switch_xml_add_child_d(x_flags, "mute_detect", count++);
switch_xml_set_txt_d(x_tag, switch_test_flag(member, MFLAG_MUTE_DETECT) ? "true" : "false");
x_tag = switch_xml_add_child_d(x_flags, "talking", count++); x_tag = switch_xml_add_child_d(x_flags, "talking", count++);
switch_xml_set_txt_d(x_tag, switch_test_flag(member, MFLAG_TALKING) ? "true" : "false"); switch_xml_set_txt_d(x_tag, switch_test_flag(member, MFLAG_TALKING) ? "true" : "false");
@ -4414,6 +4441,7 @@ static switch_status_t conf_api_sub_record(conference_obj_t *conference, switch_
return SWITCH_STATUS_GENERR; return SWITCH_STATUS_GENERR;
stream->write_function(stream, "Record file %s\n", argv[2]); stream->write_function(stream, "Record file %s\n", argv[2]);
conference->record_count++;
launch_conference_record_thread(conference, argv[2]); launch_conference_record_thread(conference, argv[2]);
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
} }
@ -4421,6 +4449,7 @@ static switch_status_t conf_api_sub_record(conference_obj_t *conference, switch_
static switch_status_t conf_api_sub_norecord(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv) static switch_status_t conf_api_sub_norecord(conference_obj_t *conference, switch_stream_handle_t *stream, int argc, char **argv)
{ {
int all; int all;
switch_event_t *event;
switch_assert(conference != NULL); switch_assert(conference != NULL);
switch_assert(stream != NULL); switch_assert(stream != NULL);
@ -4432,6 +4461,20 @@ static switch_status_t conf_api_sub_norecord(conference_obj_t *conference, switc
stream->write_function(stream, "Stop recording file %s\n", argv[2]); stream->write_function(stream, "Stop recording file %s\n", argv[2]);
if (!conference_record_stop(conference, all ? NULL : argv[2]) && !all) { if (!conference_record_stop(conference, all ? NULL : argv[2]) && !all) {
stream->write_function(stream, "non-existant recording '%s'\n", argv[2]); stream->write_function(stream, "non-existant recording '%s'\n", argv[2]);
} else {
if (all) {
conference->record_count = 0;
} else {
conference->record_count--;
}
if (test_eflag(conference, EFLAG_RECORD) &&
switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, CONF_EVENT_MAINT) == SWITCH_STATUS_SUCCESS) {
conference_add_event_data(conference, event);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "stop-recording");
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Path", all ? "all" : argv[2]);
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Other-Recordings", conference->record_count ? "true" : "false");
switch_event_fire(&event);
}
} }
return SWITCH_STATUS_SUCCESS; return SWITCH_STATUS_SUCCESS;
@ -5138,6 +5181,8 @@ static void clear_eflags(char *events, uint32_t *f)
*f &= ~EFLAG_BGDIAL_RESULT; *f &= ~EFLAG_BGDIAL_RESULT;
} else if (!strcmp(event, "floor-change")) { } else if (!strcmp(event, "floor-change")) {
*f &= ~EFLAG_FLOOR_CHANGE; *f &= ~EFLAG_FLOOR_CHANGE;
} else if (!strcmp(event, "record")) {
*f &= ~EFLAG_RECORD;
} }
event = next; event = next;
@ -6121,6 +6166,7 @@ static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_m
conference->caller_id_name = switch_core_strdup(conference->pool, caller_id_name); conference->caller_id_name = switch_core_strdup(conference->pool, caller_id_name);
conference->caller_id_number = switch_core_strdup(conference->pool, caller_id_number); conference->caller_id_number = switch_core_strdup(conference->pool, caller_id_number);
conference->caller_controls = switch_core_strdup(conference->pool, caller_controls); conference->caller_controls = switch_core_strdup(conference->pool, caller_controls);
conference->run_time = switch_epoch_time_now(NULL);
if (!zstr(perpetual_sound)) { if (!zstr(perpetual_sound)) {

View File

@ -1761,27 +1761,28 @@ static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *o
for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) { for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val); switch_hash_this(hi, &var, NULL, &val);
if ((node = (fifo_node_t *) val)) { if ((node = (fifo_node_t *) val)) {
int x = 0;
switch_event_t *pop;
if (node->ready == FIFO_DELAY_DESTROY) { if (node->ready == FIFO_DELAY_DESTROY) {
int doit = 0; if (switch_thread_rwlock_trywrlock(node->rwlock) == SWITCH_STATUS_SUCCESS) {
switch_mutex_lock(node->update_mutex);
doit = node->consumer_count == 0 && node_caller_count(node) == 0;
switch_mutex_unlock(node->update_mutex);
if (doit) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s removed.\n", node->name); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s removed.\n", node->name);
switch_core_hash_delete(globals.fifo_hash, node->name); switch_core_hash_delete(globals.fifo_hash, node->name);
for (x = 0; x < MAX_PRI; x++) {
while (fifo_queue_pop(node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) {
switch_event_destroy(&pop);
}
}
node->ready = 0; node->ready = 0;
switch_mutex_lock(node->mutex);
switch_core_hash_destroy(&node->consumer_hash); switch_core_hash_destroy(&node->consumer_hash);
switch_mutex_unlock(node->mutex); switch_mutex_unlock(node->mutex);
switch_mutex_unlock(node->update_mutex); switch_mutex_unlock(node->update_mutex);
switch_thread_rwlock_unlock(node->rwlock);
switch_core_destroy_memory_pool(&node->pool); switch_core_destroy_memory_pool(&node->pool);
goto restart; goto restart;
} }
} }
@ -2172,7 +2173,7 @@ SWITCH_STANDARD_APP(fifo_function)
char *mydata = NULL, *argv[5] = { 0 }; char *mydata = NULL, *argv[5] = { 0 };
fifo_node_t *node = NULL, *node_list[MAX_NODES_PER_CONSUMER + 1] = { 0 }; fifo_node_t *node = NULL, *node_list[MAX_NODES_PER_CONSUMER + 1] = { 0 };
switch_channel_t *channel = switch_core_session_get_channel(session); switch_channel_t *channel = switch_core_session_get_channel(session);
int do_wait = 1, node_count = 0, i = 0; int do_destroy = 0, do_wait = 1, node_count = 0, i = 0;
const char *moh = NULL; const char *moh = NULL;
const char *announce = NULL; const char *announce = NULL;
switch_event_t *event = NULL; switch_event_t *event = NULL;
@ -2247,13 +2248,10 @@ SWITCH_STANDARD_APP(fifo_function)
if (!(node = switch_core_hash_find(globals.fifo_hash, nlist[i]))) { if (!(node = switch_core_hash_find(globals.fifo_hash, nlist[i]))) {
node = create_node(nlist[i], importance, globals.sql_mutex); node = create_node(nlist[i], importance, globals.sql_mutex);
node->ready = 1; node->ready = 1;
switch_thread_rwlock_rdlock(node->rwlock);
} }
node_list[node_count++] = node;
}
if (switch_true(switch_channel_get_variable(channel, "fifo_destroy_after_use")) && node->ready == 1) { switch_thread_rwlock_rdlock(node->rwlock);
node->ready = FIFO_DELAY_DESTROY; node_list[node_count++] = node;
} }
switch_mutex_unlock(globals.mutex); switch_mutex_unlock(globals.mutex);
@ -3103,10 +3101,22 @@ SWITCH_STANDARD_APP(fifo_function)
done: done:
if (node) { if (switch_true(switch_channel_get_variable(channel, "fifo_destroy_after_use"))) {
switch_thread_rwlock_unlock(node->rwlock); do_destroy = 1;
} }
switch_mutex_lock(globals.mutex);
for (i = 0; i < node_count; i++) {
if (!(node = node_list[i])) {
continue;
}
switch_thread_rwlock_unlock(node->rwlock);
if (node->ready == 1 && do_destroy) {
node->ready = FIFO_DELAY_DESTROY;
}
}
switch_mutex_unlock(globals.mutex);
switch_channel_clear_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_BRIDGE_TAG); switch_channel_clear_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_BRIDGE_TAG);
switch_core_media_bug_resume(session); switch_core_media_bug_resume(session);

View File

@ -55,6 +55,7 @@ static void sync_sla(sofia_profile_t *profile, const char *to_user, const char *
struct dialog_helper { struct dialog_helper {
char status[512]; char status[512];
char rpid[512]; char rpid[512];
char presence_id[1024];
}; };
struct resub_helper { struct resub_helper {
@ -479,9 +480,10 @@ static int sofia_presence_dialog_callback(void *pArg, int argc, char **argv, cha
{ {
struct dialog_helper *helper = (struct dialog_helper *) pArg; struct dialog_helper *helper = (struct dialog_helper *) pArg;
if (argc == 2) { if (argc == 3) {
switch_set_string(helper->status, argv[0]); switch_set_string(helper->status, argv[0]);
switch_set_string(helper->rpid, argv[1]); switch_set_string(helper->rpid, argv[1]);
switch_set_string(helper->presence_id, argv[2]);
} }
return -1; return -1;
@ -638,7 +640,8 @@ static void actual_sofia_presence_event_handler(switch_event_t *event)
} }
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') or presence_id='%q@%q')", sql = switch_mprintf("select status,rpid,presence_id from sip_dialogs "
"where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')",
probe_euser, probe_host, probe_euser, probe_host); probe_euser, probe_host, 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);
@ -656,16 +659,16 @@ static void actual_sofia_presence_event_handler(switch_event_t *event)
"sip_dialogs.direction, " "sip_dialogs.direction, "
"sip_dialogs.sip_to_user, " "sip_dialogs.sip_to_user, "
"sip_dialogs.sip_to_host, " "sip_dialogs.sip_to_host, "
"sip_presence.status," "sip_presence.status,"
"sip_presence.rpid," "sip_presence.rpid,"
"sip_dialogs.presence_id, " "sip_dialogs.presence_id, "
"sip_presence.open_closed," "sip_presence.open_closed,"
"'%q','%q' " "'%q','%q' "
"from sip_registrations "
"from sip_registrations left join sip_dialogs on " "left join sip_dialogs on "
"sip_dialogs.presence_id = sip_registrations.sip_user || '@' || sip_registrations.sip_host " "sip_dialogs.presence_id = sip_registrations.sip_user || '@' || sip_registrations.sip_host "
"or (sip_dialogs.sip_from_user = sip_registrations.sip_user " "or (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.sip_host) "
@ -813,7 +816,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event)
sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE); sofia_glue_execute_sql_now(profile, &sql, SWITCH_TRUE);
} }
sql = switch_mprintf("select status,rpid from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')", sql = switch_mprintf("select status,rpid,presence_id from sip_dialogs where ((sip_from_user='%q' and sip_from_host='%q') or presence_id='%q@%q')",
euser, host, euser, host); euser, host, euser, 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);
@ -824,25 +827,19 @@ static void actual_sofia_presence_event_handler(switch_event_t *event)
"sip_subscriptions.full_via,sip_subscriptions.expires,sip_subscriptions.user_agent," "sip_subscriptions.full_via,sip_subscriptions.expires,sip_subscriptions.user_agent,"
"sip_subscriptions.accept,sip_subscriptions.profile_name" "sip_subscriptions.accept,sip_subscriptions.profile_name"
",'%q','%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed,'%q','%q'," ",'%q','%q','%q',sip_presence.status,sip_presence.rpid,sip_presence.open_closed,'%q','%q',"
"sip_subscriptions.version, sip_dialogs.presence_id " "sip_subscriptions.version, '%q' "
"from sip_subscriptions " "from sip_subscriptions "
"left join sip_presence on " "left join sip_presence on "
"(sip_subscriptions.sub_to_user=sip_presence.sip_user and sip_subscriptions.sub_to_host=sip_presence.sip_host and " "(sip_subscriptions.sub_to_user=sip_presence.sip_user and sip_subscriptions.sub_to_host=sip_presence.sip_host and "
"sip_subscriptions.profile_name=sip_presence.profile_name) " "sip_subscriptions.profile_name=sip_presence.profile_name) "
"left join sip_dialogs on "
"sip_dialogs.presence_id = sip_subscriptions.sub_to_user || '@' || sip_subscriptions.sub_to_host or "
"(sip_dialogs.sip_from_user = sip_subscriptions.sub_to_user "
"and sip_dialogs.sip_from_host = sip_subscriptions.sub_to_host) "
"where sip_subscriptions.expires > -1 and " "where sip_subscriptions.expires > -1 and "
"(event='%q' or event='%q') and sub_to_user='%q' " "(event='%q' or event='%q') and sub_to_user='%q' "
"and (sub_to_host='%q' or presence_hosts like '%%%q%%') " "and (sub_to_host='%q' or presence_hosts like '%%%q%%') "
"and (sip_subscriptions.profile_name = '%q' or sip_subscriptions.presence_hosts != sip_subscriptions.sub_to_host)", "and (sip_subscriptions.profile_name = '%q' or sip_subscriptions.presence_hosts != sip_subscriptions.sub_to_host) ",
switch_str_nil(status), switch_str_nil(rpid), host,
dh.status,dh.rpid, switch_str_nil(status), switch_str_nil(rpid), host,
dh.status,dh.rpid,dh.presence_id,
event_type, alt_event_type, euser, host, host, profile->name))) { event_type, alt_event_type, euser, host, host, profile->name))) {
struct presence_helper helper = { 0 }; struct presence_helper helper = { 0 };

View File

@ -1052,8 +1052,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_signal_bridge(switch_core_session_t *
switch_channel_set_variable(caller_channel, "signal_bridge", "true"); switch_channel_set_variable(caller_channel, "signal_bridge", "true");
switch_channel_set_variable(peer_channel, "signal_bridge", "true"); switch_channel_set_variable(peer_channel, "signal_bridge", "true");
switch_channel_sort_cid(peer_channel, SWITCH_FALSE);
/* fire events that will change the data table from "show channels" */ /* fire events that will change the data table from "show channels" */
if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE) == SWITCH_STATUS_SUCCESS) { if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_EXECUTE) == SWITCH_STATUS_SUCCESS) {
switch_channel_event_set_data(caller_channel, event); switch_channel_event_set_data(caller_channel, event);
@ -1119,8 +1117,6 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_multi_threaded_bridge(switch_core_ses
switch_channel_set_flag_recursive(caller_channel, CF_BRIDGE_ORIGINATOR); switch_channel_set_flag_recursive(caller_channel, CF_BRIDGE_ORIGINATOR);
switch_channel_clear_flag(peer_channel, CF_BRIDGE_ORIGINATOR); switch_channel_clear_flag(peer_channel, CF_BRIDGE_ORIGINATOR);
switch_channel_sort_cid(peer_channel, SWITCH_FALSE);
b_leg->session = peer_session; b_leg->session = peer_session;
switch_copy_string(b_leg->b_uuid, switch_core_session_get_uuid(session), sizeof(b_leg->b_uuid)); switch_copy_string(b_leg->b_uuid, switch_core_session_get_uuid(session), sizeof(b_leg->b_uuid));
b_leg->stream_id = stream_id; b_leg->stream_id = stream_id;

View File

@ -2410,6 +2410,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess
} }
} }
new_profile->callee_id_name = switch_core_strdup(new_profile->pool, "Outbound Call");
new_profile->callee_id_number = switch_core_strdup(new_profile->pool, new_profile->destination_number);
originate_status[i].caller_profile = NULL; originate_status[i].caller_profile = NULL;
originate_status[i].peer_channel = NULL; originate_status[i].peer_channel = NULL;
originate_status[i].peer_session = NULL; originate_status[i].peer_session = NULL;

View File

@ -120,8 +120,7 @@
<RandomizedBaseAddress>false</RandomizedBaseAddress> <RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention> <DataExecutionPrevention>
</DataExecutionPrevention> </DataExecutionPrevention>
<ImportLibrary> <ImportLibrary>$(OutDir)FreeSwitchCore.lib</ImportLibrary>
</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine> <TargetMachine>MachineX86</TargetMachine>
<ShowProgress> <ShowProgress>
</ShowProgress> </ShowProgress>