Merge branch 'master' of ssh://git.freeswitch.org/freeswitch

This commit is contained in:
Georgiewskiy Yuriy 2010-12-02 17:30:27 +03:00
commit de66ad246f
170 changed files with 11658 additions and 9210 deletions

View File

@ -6,8 +6,13 @@ all:
@echo " + Install by running: +"
@echo " + +"
@echo " + $(MK) install +"
@echo " + +"
@echo " + While you're waiting, register for ClueCon! +"
@echo " + http://www.cluecon.com +"
@echo " + +"
@echo " +-----------------------------------------------+"
install:
@echo " +---------- FreeSWITCH install Complete ----------+"
@echo " + FreeSWITCH has been successfully installed. +"

View File

@ -62,6 +62,7 @@ endpoints/mod_loopback
#endpoints/mod_skinny
#endpoints/mod_skypopen
#endpoints/mod_h323
#endpoints/mod_khomp
#../../libs/openzap/mod_openzap
#../../libs/freetdm/mod_freetdm
#asr_tts/mod_unimrcp
@ -105,5 +106,4 @@ say/mod_say_ru
#say/mod_say_th
## Experimental Modules (don't cry if they're broken)
#endpoints/mod_khomp
#../../contrib/mod/xml_int/mod_xml_odbc

View File

@ -38,6 +38,7 @@
<!-- <load module="mod_openzap"/> -->
<!-- <load module="mod_unicall"/> -->
<!-- <load module="mod_skinny"/> -->
<!-- <load module="mod_khomp"/> -->
<!-- Applications -->
<load module="mod_commands"/>

View File

@ -1005,7 +1005,7 @@ int main(int argc, char *argv[])
int temp_log = -1;
int argv_error = 0;
int argv_exec = 0;
char argv_command[256] = "";
char argv_command[1024] = "";
char argv_loglevel[128] = "";
int argv_quiet = 0;
int loops = 2, reconnect = 0;

View File

@ -5,8 +5,9 @@ fsdir=../..
set -x
cp Debug/mod/*.dll $fsdir/Debug/mod/
cp mod_freetdm/Debug/*.pdb $fsdir/Debug/mod/
cp Debug/*.dll $fsdir/Debug/
cp Debug/*.pdb $fsdir/Debug/
cp Debug/freetdm.dll $fsdir/Debug/
cp Debug/ftmod_*.dll $fsdir/Debug/mod/
cp Debug/*.pdb $fsdir/Debug/mod/
#cp Debug/testsangomaboost.exe $fsdir/Debug/
echo "FRIENDLY REMINDER: RECOMPILE ftmod_wanpipe WHENEVER YOU INSTALL NEW DRIVERS"
set +x

View File

@ -161,10 +161,8 @@ Global
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.Build.0 = Release|Win32
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|x64.ActiveCfg = Release|Win32
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.ActiveCfg = Debug|Win32
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.Build.0 = Debug|Win32
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|x64.ActiveCfg = Debug|Win32
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.ActiveCfg = Release|Win32
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.Build.0 = Release|Win32
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|x64.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution

View File

@ -120,16 +120,14 @@ Global
{0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.Build.0 = Release|x64
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.ActiveCfg = Debug|Win32
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.Build.0 = Debug|Win32
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|x64.ActiveCfg = Debug|Win32
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|x64.ActiveCfg = Debug|x64
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.ActiveCfg = Release|Win32
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.Build.0 = Release|Win32
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|x64.ActiveCfg = Release|Win32
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|x64.ActiveCfg = Release|x64
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.ActiveCfg = Debug|Win32
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.Build.0 = Debug|Win32
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|x64.ActiveCfg = Debug|Win32
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|x64.ActiveCfg = Debug|x64
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.ActiveCfg = Release|Win32
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|Win32.Build.0 = Release|Win32
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|x64.ActiveCfg = Release|Win32
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Release|x64.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -149,6 +149,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
static const char* channel_get_variable(switch_core_session_t *session, switch_event_t *var_event, const char *variable_name);
ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session_t **sp);
void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream);
void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stream);
@ -425,8 +426,11 @@ static switch_status_t channel_on_routing(switch_core_session_t *session)
tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel));
assert(tech_pvt->ftdmchan != NULL);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel));
ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROCEED);
return SWITCH_STATUS_SUCCESS;
}
@ -837,9 +841,9 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
assert(tech_pvt != NULL);
if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE);
return SWITCH_STATUS_FALSE;
}
switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE);
return SWITCH_STATUS_FALSE;
}
if (ftdm_channel_call_check_hangup(tech_pvt->ftdmchan)) {
return SWITCH_STATUS_SUCCESS;
@ -852,7 +856,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_RINGING:
{
ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROGRESS);
ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RINGING);
}
break;
case SWITCH_MESSAGE_INDICATE_PROGRESS:
@ -884,9 +888,9 @@ static switch_status_t channel_receive_message_fxo(switch_core_session_t *sessio
assert(tech_pvt != NULL);
if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE);
return SWITCH_STATUS_FALSE;
}
switch_channel_hangup(channel, SWITCH_CAUSE_LOSE_RACE);
return SWITCH_STATUS_FALSE;
}
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
return SWITCH_STATUS_SUCCESS;
@ -935,7 +939,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio
!switch_channel_test_flag(channel, CF_EARLY_MEDIA) &&
!switch_channel_test_flag(channel, CF_RING_READY)
) {
ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RING);
ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_RINGING);
switch_channel_mark_ring_ready(channel);
}
break;
@ -1046,6 +1050,27 @@ switch_io_routines_t freetdm_io_routines = {
/*.receive_message*/ channel_receive_message
};
static const char* channel_get_variable(switch_core_session_t *session, switch_event_t *var_event, const char *variable_name)
{
const char *variable = NULL;
if (var_event) {
if ((variable = switch_event_get_header(var_event, variable_name))) {
return variable;
}
}
if (session) {
switch_channel_t *channel = switch_core_session_get_channel(session);
if ((variable = switch_channel_get_variable(channel, variable_name))) {
return variable;
}
}
if ((variable = switch_core_get_variable(variable_name))) {
return variable;
}
return NULL;
}
/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines
that allocate memory or you will have 1 channel with memory allocated from another channel's pool!
*/
@ -1223,20 +1248,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
}
}
if (session) {
/* take out some other values from the session if they're present */
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *freetdmvar;
freetdmvar = switch_channel_get_variable(channel, "freetdm_bearer_capability");
if (freetdmvar) {
caller_data.bearer_capability = (uint8_t)atoi(freetdmvar);
}
freetdmvar = switch_channel_get_variable(channel, "freetdm_bearer_layer1");
if (freetdmvar) {
caller_data.bearer_layer1 = (uint8_t)atoi(freetdmvar);
}
}
if (switch_test_flag(outbound_profile, SWITCH_CPF_SCREEN)) {
caller_data.screen = 1;
}
@ -1245,29 +1256,37 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
caller_data.pres = 1;
}
if (!zstr(dest)) {
ftdm_set_string(caller_data.dnis.digits, dest);
if ((var = channel_get_variable(session, var_event, "freetdm_bearer_capability"))) {
caller_data.bearer_capability = (uint8_t)atoi(var);
}
if ((var = switch_event_get_header(var_event, "freetdm_outbound_ton")) || (var = switch_core_get_variable("freetdm_outbound_ton"))) {
if (!strcasecmp(var, "national")) {
caller_data.dnis.type = FTDM_TON_NATIONAL;
} else if (!strcasecmp(var, "international")) {
caller_data.dnis.type = FTDM_TON_INTERNATIONAL;
} else if (!strcasecmp(var, "local")) {
caller_data.dnis.type = FTDM_TON_SUBSCRIBER_NUMBER;
} else if (!strcasecmp(var, "unknown")) {
caller_data.dnis.type = FTDM_TON_UNKNOWN;
}
if ((var = channel_get_variable(session, var_event, "freetdm_bearer_layer1"))) {
caller_data.bearer_layer1 = (uint8_t)atoi(var);
}
if ((var = channel_get_variable(session, var_event, "freetdm_screening_ind"))) {
ftdm_set_screening_ind(var, &caller_data.screen);
}
if ((var = channel_get_variable(session, var_event, "freetdm_presentation_ind"))) {
ftdm_set_presentation_ind(var, &caller_data.pres);
}
if ((var = channel_get_variable(session, var_event, "freetdm_outbound_ton"))) {
ftdm_set_ton(var, &caller_data.dnis.type);
} else {
caller_data.dnis.type = outbound_profile->destination_number_ton;
}
if ((var = switch_event_get_header(var_event, "freetdm_custom_call_data")) || (var = switch_core_get_variable("freetdm_custom_call_data"))) {
if ((var = channel_get_variable(session, var_event, "freetdm_custom_call_data"))) {
ftdm_set_string(caller_data.raw_data, var);
caller_data.raw_data_len = (uint32_t)strlen(var);
}
if (!zstr(dest)) {
ftdm_set_string(caller_data.dnis.digits, dest);
}
caller_data.dnis.plan = outbound_profile->destination_number_numplan;
/* blindly copy data from outbound_profile. They will be overwritten
@ -1690,6 +1709,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
}
}
break;
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
default:
{
@ -1744,6 +1764,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxs_signal)
}
}
break;
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
case FTDM_SIGEVENT_STOP:
{
private_t *tech_pvt = NULL;
@ -1966,6 +1987,8 @@ static FIO_SIGNAL_CB_FUNCTION(on_r2_signal)
status = ftdm_channel_from_event(sigmsg, &session);
}
break;
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
/* on DNIS received from the R2 forward side, return status == FTDM_BREAK to stop requesting DNIS */
case FTDM_SIGEVENT_COLLECTED_DIGIT:
@ -2028,6 +2051,14 @@ static FIO_SIGNAL_CB_FUNCTION(on_r2_signal)
}
break;
case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
{
ftdm_signaling_status_t sigstatus = sigmsg->raw_data ? *((ftdm_signaling_status_t*)(sigmsg->raw_data)) : sigmsg->sigstatus;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d:%d signalling changed to: %s\n",
spanid, chanid, ftdm_signaling_status2str(sigstatus));
}
break;
default:
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled event %d from R2 for channel %d:%d\n",
@ -2059,10 +2090,16 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
switch(sigmsg->event_id) {
case FTDM_SIGEVENT_START:
{
ftdm_channel_add_var(sigmsg->channel, "screening_ind", ftdm_screening2str(caller_data->screen));
ftdm_channel_add_var(sigmsg->channel, "presentation_ind", ftdm_presentation2str(caller_data->pres));
ftdm_enable_channel_dtmf(sigmsg->channel, NULL);
return ftdm_channel_from_event(sigmsg, &session);
}
break;
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
case FTDM_SIGEVENT_STOP:
case FTDM_SIGEVENT_RESTART:
{
@ -2118,7 +2155,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
spanid, chanid, (uuid) ? uuid : "N/A");
}
}
break;
break;
case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
{
ftdm_signaling_status_t sigstatus = sigmsg->raw_data ? *((ftdm_signaling_status_t*)(sigmsg->raw_data)) : sigmsg->sigstatus;
@ -2126,6 +2163,10 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
spanid, chanid, ftdm_signaling_status2str(sigstatus));
}
break;
case FTDM_SIGEVENT_PROCEED:
case FTDM_SIGEVENT_MSG:
/* FS does not have handlers for these messages, so ignore them for now */
break;
default:
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled msg type %d for channel %d:%d\n",

View File

@ -22,7 +22,7 @@
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
IntermediateDirectory="testboost\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
BuildLogFile="$(IntDir)\BuildLog-testboost.htm"
@ -97,87 +97,10 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
BuildLogFile="$(IntDir)\BuildLog-testboost.htm"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../src/include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\testboost\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
BuildLogFile="$(IntDir)\BuildLog-testboost.htm"
@ -253,10 +176,87 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="testboost\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
BuildLogFile="$(IntDir)\BuildLog-testboost.htm"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../src/include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\testboost\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"

View File

@ -97,83 +97,6 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
BuildLogFile="$(IntDir)\BuildLog-testsangomaboost.htm"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../src/include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
@ -253,6 +176,83 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
BuildLogFile="$(IntDir)\BuildLog-testsangomaboost.htm"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../src/include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
@ -285,7 +285,7 @@
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
WarnAsError="false"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>

View File

@ -186,7 +186,7 @@
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
<TreatWarningAsError>false</TreatWarningAsError>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4100;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>

View File

@ -1,82 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openzap", "msvc\openzap.2005.vcproj", "{93B8812C-3EC4-4F78-8970-FFBFC99E167D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testanalog", "msvc\testanalog\testanalog.2005.vcproj", "{BB833648-BAFF-4BE2-94DB-F8BB043C588C}"
ProjectSection(ProjectDependencies) = postProject
{93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testisdn", "msvc\testisdn\testisdn.2005.vcproj", "{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}"
ProjectSection(ProjectDependencies) = postProject
{93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_openzap", "mod_openzap\mod_openzap.2005.vcproj", "{FE3540C5-3303-46E0-A69E-D92F775687F1}"
ProjectSection(ProjectDependencies) = postProject
{93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_analog", "src\ozmod\ozmod_analog\ozmod_analog.2005.vcproj", "{37C94798-6E33-4B4F-8EE0-C72A7DC91157}"
ProjectSection(ProjectDependencies) = postProject
{93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_analog_em", "src\ozmod\ozmod_analog_em\ozmod_analog_em.2005.vcproj", "{C539D7C8-26A8-4A94-B938-77672165C130}"
ProjectSection(ProjectDependencies) = postProject
{93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_isdn", "src\ozmod\ozmod_isdn\ozmod_isdn.2005.vcproj", "{729344A5-D5E9-434D-8EE8-AF8C6C795D15}"
ProjectSection(ProjectDependencies) = postProject
{93B8812C-3EC4-4F78-8970-FFBFC99E167D} = {93B8812C-3EC4-4F78-8970-FFBFC99E167D}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_wanpipe", "src\ozmod\ozmod_wanpipe\ozmod_wanpipe.2005.vcproj", "{1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ozmod_pika", "src\ozmod\ozmod_pika\ozmod_pika.2005.vcproj", "{E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.ActiveCfg = Debug|Win32
{93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Debug|Win32.Build.0 = Debug|Win32
{93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.ActiveCfg = Release|Win32
{93B8812C-3EC4-4F78-8970-FFBFC99E167D}.Release|Win32.Build.0 = Release|Win32
{BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.ActiveCfg = Debug|Win32
{BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Debug|Win32.Build.0 = Debug|Win32
{BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.ActiveCfg = Release|Win32
{BB833648-BAFF-4BE2-94DB-F8BB043C588C}.Release|Win32.Build.0 = Release|Win32
{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|Win32.ActiveCfg = Debug|Win32
{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Debug|Win32.Build.0 = Debug|Win32
{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|Win32.ActiveCfg = Release|Win32
{6DA6FD42-641D-4147-92F5-3BC4AAA6589B}.Release|Win32.Build.0 = Release|Win32
{FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.ActiveCfg = Debug|Win32
{FE3540C5-3303-46E0-A69E-D92F775687F1}.Debug|Win32.Build.0 = Debug|Win32
{FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.ActiveCfg = Release|Win32
{FE3540C5-3303-46E0-A69E-D92F775687F1}.Release|Win32.Build.0 = Release|Win32
{37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.ActiveCfg = Debug|Win32
{37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Debug|Win32.Build.0 = Debug|Win32
{37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.ActiveCfg = Release|Win32
{37C94798-6E33-4B4F-8EE0-C72A7DC91157}.Release|Win32.Build.0 = Release|Win32
{C539D7C8-26A8-4A94-B938-77672165C130}.Debug|Win32.ActiveCfg = Debug|Win32
{C539D7C8-26A8-4A94-B938-77672165C130}.Debug|Win32.Build.0 = Debug|Win32
{C539D7C8-26A8-4A94-B938-77672165C130}.Release|Win32.ActiveCfg = Release|Win32
{C539D7C8-26A8-4A94-B938-77672165C130}.Release|Win32.Build.0 = Release|Win32
{729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|Win32.ActiveCfg = Debug|Win32
{729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Debug|Win32.Build.0 = Debug|Win32
{729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|Win32.ActiveCfg = Release|Win32
{729344A5-D5E9-434D-8EE8-AF8C6C795D15}.Release|Win32.Build.0 = Release|Win32
{1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Debug|Win32.ActiveCfg = Debug|Win32
{1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}.Release|Win32.ActiveCfg = Release|Win32
{E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Debug|Win32.ActiveCfg = Debug|Win32
{E886B4D5-AB4F-4092-B8F4-3B06E1E462EF}.Release|Win32.ActiveCfg = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -36,80 +36,101 @@
#include <ctype.h>
FT_DECLARE(ftdm_status_t) ftdm_span_set_npi(const char *npi_string, uint8_t *target)
FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *string, uint8_t *target)
{
if (!strcasecmp(npi_string, "isdn") || !strcasecmp(npi_string, "e164")) {
*target = FTDM_NPI_ISDN;
} else if (!strcasecmp(npi_string, "data")) {
*target = FTDM_NPI_DATA;
} else if (!strcasecmp(npi_string, "telex")) {
*target = FTDM_NPI_TELEX;
} else if (!strcasecmp(npi_string, "national")) {
*target = FTDM_NPI_NATIONAL;
} else if (!strcasecmp(npi_string, "private")) {
*target = FTDM_NPI_PRIVATE;
} else if (!strcasecmp(npi_string, "reserved")) {
*target = FTDM_NPI_RESERVED;
} else if (!strcasecmp(npi_string, "unknown")) {
*target = FTDM_NPI_UNKNOWN;
} else {
ftdm_log(FTDM_LOG_WARNING, "Invalid NPI value (%s)\n", npi_string);
*target = FTDM_NPI_UNKNOWN;
return FTDM_FAIL;
uint8_t val;
ftdm_status_t status = FTDM_SUCCESS;
val = ftdm_str2ftdm_npi(string);
if (val == FTDM_NPI_INVALID) {
ftdm_log(FTDM_LOG_WARNING, "Invalid NPI string (%s)\n", string);
status = FTDM_FAIL;
val = FTDM_NPI_UNKNOWN;
}
return FTDM_SUCCESS;
*target = val;
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_span_set_ton(const char *ton_string, uint8_t *target)
FT_DECLARE(ftdm_status_t) ftdm_set_ton(const char *string, uint8_t *target)
{
if (!strcasecmp(ton_string, "national")) {
*target = FTDM_TON_NATIONAL;
} else if (!strcasecmp(ton_string, "international")) {
*target = FTDM_TON_INTERNATIONAL;
} else if (!strcasecmp(ton_string, "local")) {
*target = FTDM_TON_SUBSCRIBER_NUMBER;
} else if (!strcasecmp(ton_string, "unknown")) {
*target = FTDM_TON_UNKNOWN;
} else {
ftdm_log(FTDM_LOG_WARNING, "Invalid TON value (%s)\n", ton_string);
*target = FTDM_TON_UNKNOWN;
return FTDM_FAIL;
uint8_t val;
ftdm_status_t status = FTDM_SUCCESS;
val = ftdm_str2ftdm_ton(string);
if (val == FTDM_TON_INVALID) {
ftdm_log(FTDM_LOG_WARNING, "Invalid TON string (%s)\n", string);
status = FTDM_FAIL;
val = FTDM_TON_UNKNOWN;
}
return FTDM_SUCCESS;
*target = val;
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_capability(const char *bc_string, ftdm_bearer_cap_t *target)
FT_DECLARE(ftdm_status_t) ftdm_set_bearer_capability(const char *string, uint8_t *target)
{
if (!strcasecmp(bc_string, "speech")) {
*target = FTDM_BEARER_CAP_SPEECH;
} else if (!strcasecmp(bc_string, "unrestricted-digital")) {
*target = FTDM_BEARER_CAP_64K_UNRESTRICTED;
} else if (!strcasecmp(bc_string, "3.1Khz")) {
*target = FTDM_BEARER_CAP_3_1KHZ_AUDIO;
} else {
ftdm_log(FTDM_LOG_WARNING, "Unsupported Bearer Capability value (%s)\n", bc_string);
return FTDM_FAIL;
uint8_t val;
ftdm_status_t status = FTDM_SUCCESS;
val = ftdm_str2ftdm_bearer_cap(string);
if (val == FTDM_NPI_INVALID) {
ftdm_log(FTDM_LOG_WARNING, "Invalid Bearer-Capability string (%s)\n", string);
status = FTDM_FAIL;
val = FTDM_BEARER_CAP_SPEECH;
}
return FTDM_SUCCESS;
*target = val;
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_layer1(const char *bc_string, ftdm_user_layer1_prot_t *target)
FT_DECLARE(ftdm_status_t) ftdm_set_bearer_layer1(const char *string, uint8_t *target)
{
if (!strcasecmp(bc_string, "v110")) {
*target = FTDM_USER_LAYER1_PROT_V110;
} else if (!strcasecmp(bc_string, "ulaw")) {
*target = FTDM_USER_LAYER1_PROT_ULAW;
} else if (!strcasecmp(bc_string, "alaw")) {
*target =FTDM_USER_LAYER1_PROT_ALAW ;
} else {
ftdm_log(FTDM_LOG_WARNING, "Unsupported Bearer Layer1 Prot value (%s)\n", bc_string);
return FTDM_FAIL;
uint8_t val;
ftdm_status_t status = FTDM_SUCCESS;
val = ftdm_str2ftdm_usr_layer1_prot(string);
if (val == FTDM_USER_LAYER1_PROT_INVALID) {
ftdm_log(FTDM_LOG_WARNING, "Invalid Bearer Layer 1 Protocol string (%s)\n", string);
status = FTDM_FAIL;
val = FTDM_USER_LAYER1_PROT_ULAW;
}
return FTDM_SUCCESS;
*target = val;
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_set_screening_ind(const char *string, uint8_t *target)
{
uint8_t val;
ftdm_status_t status = FTDM_SUCCESS;
FT_DECLARE(ftdm_status_t) ftdm_is_number(char *number)
val = ftdm_str2ftdm_screening(string);
if (val == FTDM_SCREENING_INVALID) {
ftdm_log(FTDM_LOG_WARNING, "Invalid screening indicator string (%s)\n", string);
status = FTDM_FAIL;
val = FTDM_SCREENING_NOT_SCREENED;
}
*target = val;
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_set_presentation_ind(const char *string, uint8_t *target)
{
uint8_t val;
ftdm_status_t status = FTDM_SUCCESS;
val = ftdm_str2ftdm_presentation(string);
if (val == FTDM_PRES_INVALID) {
ftdm_log(FTDM_LOG_WARNING, "Invalid presentation string (%s)\n", string);
status = FTDM_FAIL;
val = FTDM_PRES_ALLOWED;
}
*target = val;
return status;
}
FT_DECLARE(ftdm_status_t) ftdm_is_number(const char *number)
{
if (!number) {
return FTDM_FAIL;

View File

@ -38,8 +38,6 @@
*/
#define _GNU_SOURCE
#ifndef WIN32
#endif
#include "private/ftdm_core.h"
#include <stdarg.h>
#ifdef WIN32
@ -56,6 +54,9 @@
#define FTDM_READ_TRACE_INDEX 0
#define FTDM_WRITE_TRACE_INDEX 1
ftdm_time_t time_last_throttle_log = 0;
ftdm_time_t time_current_throttle_log = 0;
static int time_is_init = 0;
static void time_init(void)
@ -147,6 +148,24 @@ FTDM_STR2ENUM(ftdm_str2ftdm_chan_type, ftdm_chan_type2str, ftdm_chan_type_t, CHA
FTDM_ENUM_NAMES(SIGNALING_STATUS_NAMES, SIGSTATUS_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_signaling_status, ftdm_signaling_status2str, ftdm_signaling_status_t, SIGNALING_STATUS_NAMES, FTDM_SIG_STATE_INVALID)
FTDM_ENUM_NAMES(TON_NAMES, TON_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_ton, ftdm_ton2str, ftdm_ton_t, TON_NAMES, FTDM_TON_INVALID)
FTDM_ENUM_NAMES(NPI_NAMES, NPI_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_npi, ftdm_npi2str, ftdm_npi_t, NPI_NAMES, FTDM_NPI_INVALID)
FTDM_ENUM_NAMES(PRESENTATION_NAMES, PRESENTATION_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_presentation, ftdm_presentation2str, ftdm_presentation_t, PRESENTATION_NAMES, FTDM_PRES_INVALID)
FTDM_ENUM_NAMES(SCREENING_NAMES, SCREENING_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_screening, ftdm_screening2str, ftdm_screening_t, SCREENING_NAMES, FTDM_SCREENING_INVALID)
FTDM_ENUM_NAMES(BEARER_CAP_NAMES, BEARER_CAP_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_bearer_cap, ftdm_bearer_cap2str, ftdm_bearer_cap_t, BEARER_CAP_NAMES, FTDM_BEARER_CAP_INVALID)
FTDM_ENUM_NAMES(USER_LAYER1_PROT_NAMES, USER_LAYER1_PROT_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_usr_layer1_prot, ftdm_user_layer1_prot2str, ftdm_user_layer1_prot_t, USER_LAYER1_PROT_NAMES, FTDM_USER_LAYER1_PROT_INVALID)
static ftdm_status_t ftdm_group_add_channels(ftdm_span_t* span, int currindex, const char* name);
static const char *cut_path(const char *in)
@ -1745,16 +1764,26 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan)
ftdm_mutex_lock(ftdmchan->mutex);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is suspended\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is suspended\n");
goto done;
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM) && !ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is alarmed\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is alarmed\n");
goto done;
if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is suspended\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is suspended\n");
goto done;
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM) && !ftdm_test_flag(ftdmchan->span, FTDM_SPAN_PWR_SAVING)) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "Channel is alarmed\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Cannot open channel when is alarmed\n");
goto done;
}
if (globals.cpu_monitor.alarm &&
globals.cpu_monitor.alarm_action_flags & FTDM_CPU_ALARM_ACTION_REJECT) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "CPU usage alarm is on - refusing to open channel\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "CPU usage alarm is on - refusing to open channel\n");
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_SWITCH_CONGESTION;
goto done;
}
}
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_READY)) {
@ -1763,15 +1792,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan)
goto done;
}
if (globals.cpu_monitor.alarm &&
globals.cpu_monitor.alarm_action_flags & FTDM_CPU_ALARM_ACTION_REJECT) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", "CPU usage alarm is on - refusing to open channel\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "CPU usage alarm is on - refusing to open channel\n");
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_SWITCH_CONGESTION;
goto done;
}
status = ftdmchan->fio->open(ftdmchan);
if (status == FTDM_SUCCESS) {
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_OPEN | FTDM_CHANNEL_INUSE);
@ -2030,6 +2050,10 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char
goto done;
}
#ifndef FREETDM_SKIP_SIG_STATES
/* We will fail RFC's if we not skip states, but some modules apart from ftmod_sangoma_isdn
* expect the call to always to go PROGRESS and PROGRESS MEDIA state before going to UP, so
* remove this only in netborder branch for now while we update the sig modules */
if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) {
ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1);
@ -2050,7 +2074,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to UP\n");
goto done;
}
#endif
ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_UP, 1);
done:
@ -2199,14 +2223,19 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
switch (indication) {
/* FIXME: ring and busy cannot be used with all signaling stacks
* (particularly isdn stacks I think, we should emulate or just move to hangup with busy cause) */
case FTDM_CHANNEL_INDICATE_RING:
ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RING, 1);
case FTDM_CHANNEL_INDICATE_RINGING:
ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_RINGING, 1);
break;
case FTDM_CHANNEL_INDICATE_BUSY:
ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_BUSY, 1);
break;
case FTDM_CHANNEL_INDICATE_PROCEED:
if (ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_PROCEED_STATE)) {
if (ftdmchan->state == FTDM_CHANNEL_STATE_RING) {
ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROCEED, 1);
}
}
break;
case FTDM_CHANNEL_INDICATE_PROGRESS:
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS);
@ -2214,7 +2243,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1);
}
break;
case FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA:
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_PROGRESS);
@ -2233,7 +2261,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1);
}
break;
default:
ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "Do not know how to indicate %d\n", indication);
status = FTDM_FAIL;
@ -2386,6 +2413,16 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan)
ftdm_log(FTDM_LOG_DEBUG, "channel done %u:%u\n", ftdmchan->span_id, ftdmchan->chan_id);
if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
ftdm_sigmsg_t sigmsg;
memset(&sigmsg, 0, sizeof(sigmsg));
sigmsg.span_id = ftdmchan->span_id;
sigmsg.chan_id = ftdmchan->chan_id;
sigmsg.channel = ftdmchan;
sigmsg.event_id = FTDM_SIGEVENT_RELEASED;
ftdm_span_send_signal(ftdmchan->span, &sigmsg);
}
ftdm_mutex_unlock(ftdmchan->mutex);
return FTDM_SUCCESS;
@ -2810,21 +2847,17 @@ done:
FT_DECLARE(ftdm_status_t) ftdm_channel_wait(ftdm_channel_t *ftdmchan, ftdm_wait_flag_t *flags, int32_t to)
{
assert(ftdmchan != NULL);
assert(ftdmchan->fio != NULL);
ftdm_status_t status = FTDM_FAIL;
ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel\n");
ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "Null io interface\n");
ftdm_assert_return(ftdmchan->fio->wait != NULL, FTDM_NOTIMPL, "wait method not implemented\n");
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "channel not open");
return FTDM_FAIL;
}
if (!ftdmchan->fio->wait) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "method not implemented");
return FTDM_FAIL;
status = ftdmchan->fio->wait(ftdmchan, flags, to);
if (status == FTDM_TIMEOUT) {
/* make sure the flags are cleared on timeout */
*flags = 0;
}
return ftdmchan->fio->wait(ftdmchan, flags, to);
return status;
}
/*******************************/
@ -4809,7 +4842,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
if (sigmsg->channel) {
ftdm_mutex_lock(sigmsg->channel->mutex);
}
/* some core things to do on special events */
switch (sigmsg->event_id) {

View File

@ -1,353 +1,353 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="ftmod_analog"
ProjectGUID="{37C94798-6E33-4B4F-8EE0-C72A7DC91157}"
RootNamespace="ftmod_analog"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="4"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="false"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="ftmod_analog.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="ftdm_analog.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="ftmod_analog"
ProjectGUID="{37C94798-6E33-4B4F-8EE0-C72A7DC91157}"
RootNamespace="ftmod_analog"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="4"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="false"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="false"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="ftmod_analog.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="ftdm_analog.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -168,7 +168,7 @@
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
<TreatWarningAsError>false</TreatWarningAsError>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4100;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>

View File

@ -438,7 +438,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
{
if (state_counter > 5000 || !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT)) {
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_CALLERID_DETECT, NULL);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
}
}
break;
@ -492,8 +492,8 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) &&
(ftdmchan->last_state == FTDM_CHANNEL_STATE_RING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE
|| ftdmchan->last_state >= FTDM_CHANNEL_STATE_IDLE)) {
(ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE
|| ftdmchan->last_state >= FTDM_CHANNEL_STATE_RING)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
} else {
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING;
@ -535,7 +535,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
}
}
case FTDM_CHANNEL_STATE_UP:
case FTDM_CHANNEL_STATE_IDLE:
case FTDM_CHANNEL_STATE_RING:
{
ftdm_sleep(interval);
continue;
@ -599,7 +599,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
ftdm_channel_use(ftdmchan);
}
break;
case FTDM_CHANNEL_STATE_IDLE:
case FTDM_CHANNEL_STATE_RING:
{
ftdm_channel_use(ftdmchan);
sig.event_id = FTDM_SIGEVENT_START;
@ -669,7 +669,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
continue;
}
break;
case FTDM_CHANNEL_STATE_RING:
case FTDM_CHANNEL_STATE_RINGING:
{
ftdm_buffer_zero(dt_buffer);
teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_RING]);
@ -732,7 +732,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
if (last_digit && (!collecting || ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) >= analog_data->max_dialstr))) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
last_digit = 0;
collecting = 0;
}
@ -890,7 +890,7 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
if (ftdm_test_flag(analog_data, FTDM_ANALOG_CALLERID)) {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_GET_CALLERID);
} else {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_IDLE);
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RING);
}
event->channel->ring_count = 1;
ftdm_mutex_unlock(event->channel->mutex);

View File

@ -1,202 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="ftmod_analog"
ProjectGUID="{37C94798-6E33-4B4F-8EE0-C72A7DC91157}"
RootNamespace="ftmod_analog"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="4"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="ftmod_analog.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="ftdm_analog.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -1,353 +1,353 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="ftmod_analog_em"
ProjectGUID="{B3F49375-2834-4937-9D8C-4AC2EC911010}"
RootNamespace="ftmod_analog_em"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="4"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="false"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="ftmod_analog_em.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="ftdm_analog_em.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="ftmod_analog_em"
ProjectGUID="{B3F49375-2834-4937-9D8C-4AC2EC911010}"
RootNamespace="ftmod_analog_em"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="4"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="false"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="false"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="ftmod_analog_em.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="ftdm_analog_em.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -168,7 +168,7 @@
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
<TreatWarningAsError>false</TreatWarningAsError>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4100;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>

View File

@ -1,202 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="ftmod_analog_em"
ProjectGUID="{C539D7C8-26A8-4A94-B938-77672165C130}"
RootNamespace="ftmod_analog_em"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="4"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\..\include;..\..\isdn\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_ANALOG_EM_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="ftmod_analog_em.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="ftdm_analog_em.h"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -462,7 +462,7 @@ static ftdm_state_map_t isdn_state_map = {
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_RING, FTDM_END},
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END}
},
{
ZSD_INBOUND,
@ -479,7 +479,7 @@ static ftdm_state_map_t isdn_state_map = {
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
{FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
@ -537,6 +537,8 @@ static __inline__ void state_advance(ftdm_channel_t *chan)
break;
case FTDM_CHANNEL_STATE_PROGRESS:
/* RINGING is an alias for PROGRESS state in inbound calls ATM */
case FTDM_CHANNEL_STATE_RINGING:
{
if (ftdm_test_flag(chan, FTDM_CHANNEL_OUTBOUND)) {
sig.event_id = FTDM_SIGEVENT_PROGRESS;

View File

@ -60,9 +60,9 @@
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="freetdm.lib openr2.lib"
AdditionalDependencies="freetdm.lib libopenr2.lib"
LinkIncremental="2"
AdditionalLibraryDirectories="&quot;C:\Program Files\openr2\lib&quot;;&quot;$(OutDir)&quot;"
AdditionalLibraryDirectories="&quot;$(OutDir)&quot;;&quot;C:\Program Files\openr2\lib&quot;"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"

View File

@ -5,10 +5,18 @@
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>ftmod_r2</ProjectName>
@ -19,33 +27,53 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</LinkIncremental>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@ -68,6 +96,25 @@
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\include;c:\Program Files\openr2\include\openr2;C:\Program Files\openr2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;FTMOD_R2_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>freetdm.lib;openr2.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>C:\Program Files\openr2\lib;$(OutDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\include;C:\Program Files\openr2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@ -86,6 +133,23 @@
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\..\include;C:\Program Files\openr2\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_R2_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="ftmod_r2.c" />
</ItemGroup>

View File

@ -220,6 +220,23 @@ static char *strsep(char **stringp, const char *delim)
}
#endif /* WIN32 */
static void ftdm_r2_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status)
{
ftdm_sigmsg_t sig;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Signalling link status changed to %s\n", ftdm_signaling_status2str(status));
memset(&sig, 0, sizeof(sig));
sig.chan_id = ftdmchan->chan_id;
sig.span_id = ftdmchan->span_id;
sig.channel = ftdmchan;
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sig.sigstatus = status;
if (ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to change channel status to %s\n", ftdm_signaling_status2str(status));
}
return;
}
static ftdm_call_cause_t ftdm_r2_cause_to_ftdm_cause(ftdm_channel_t *fchan, openr2_call_disconnect_cause_t cause)
{
switch (cause) {
@ -593,17 +610,14 @@ static void ftdm_r2_on_line_blocked(openr2_chan_t *r2chan)
{
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Far end blocked in state %s\n", ftdm_channel_state2str(ftdmchan->state));
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED);
ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED);
}
static void ftdm_r2_on_line_idle(openr2_chan_t *r2chan)
{
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Far end unblocked in state %s\n", ftdm_channel_state2str(ftdmchan->state));
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED);
/* XXX when should we set/unset this flag? XXX */
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SIG_UP);
ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
}
static void ftdm_r2_write_log(openr2_log_level_t level, const char *file, const char *function, int line, const char *message)
@ -1130,6 +1144,9 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_r2_configure_span)
span->signal_data = r2data;
span->outgoing_call = r2_outgoing_call;
/* use signals queue */
ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE);
return FTDM_SUCCESS;
fail:
@ -1439,6 +1456,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
} else if (status != FTDM_TIMEOUT) {
ftdm_log(FTDM_LOG_ERROR, "ftdm_span_poll_event returned %d.\n", status);
}
ftdm_span_trigger_signals(span);
ftdm_sleep(20);
}

View File

@ -58,7 +58,7 @@ typedef struct ftdm_sangoma_boost_trunkgroup {
ftdm_size_t size; /* Number of b-channels in group */
unsigned int last_used_index; /* index of last b-channel used */
ftdm_channel_t* ftdmchans[MAX_CHANS_PER_TRUNKGROUP];
//DAVIDY need to merge congestion timeouts to this struct
//TODO need to merge congestion timeouts to this struct
} ftdm_sangoma_boost_trunkgroup_t;
#endif

View File

@ -95,83 +95,6 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\..\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
@ -249,6 +172,83 @@
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories="..\..\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;FTMOD_SANGOMA_BOOST_EXPORTS"
RuntimeLibrary="2"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
@ -283,7 +283,7 @@
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="4"
WarnAsError="true"
WarnAsError="false"
DebugInformationFormat="3"
DisableSpecificWarnings="4100"
/>

View File

@ -172,7 +172,7 @@
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
<TreatWarningAsError>false</TreatWarningAsError>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<DisableSpecificWarnings>4100;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>

View File

@ -55,7 +55,7 @@ ftdm_mutex_t *g_boost_modules_mutex = NULL;
ftdm_hash_t *g_boost_modules_hash = NULL;
#define MAX_TRUNK_GROUPS 64
//DAVIDY need to merge congestion_timeouts with ftdm_sangoma_boost_trunkgroups
//TODO need to merge congestion_timeouts with ftdm_sangoma_boost_trunkgroups
static time_t congestion_timeouts[MAX_TRUNK_GROUPS];
static ftdm_sangoma_boost_trunkgroup_t *g_trunkgroups[MAX_TRUNK_GROUPS];
@ -1557,11 +1557,11 @@ static __inline__ ftdm_status_t state_advance(ftdm_channel_t *ftdmchan)
ftdm_set_string(event.calling_name, ftdmchan->caller_data.cid_name);
ftdm_set_string(event.rdnis.digits, ftdmchan->caller_data.rdnis.digits);
if (strlen(ftdmchan->caller_data.rdnis.digits)) {
event.rdnis.digits_count = (uint8_t)strlen(ftdmchan->caller_data.rdnis.digits)+1;
event.rdnis.ton = ftdmchan->caller_data.rdnis.type;
event.rdnis.npi = ftdmchan->caller_data.rdnis.plan;
event.rdnis.digits_count = (uint8_t)strlen(ftdmchan->caller_data.rdnis.digits)+1;
event.rdnis.ton = ftdmchan->caller_data.rdnis.type;
event.rdnis.npi = ftdmchan->caller_data.rdnis.plan;
}
event.calling.screening_ind = ftdmchan->caller_data.screen;
event.calling.presentation_ind = ftdmchan->caller_data.pres;
@ -2582,17 +2582,17 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_boost_configure_span)
} else if (!strcasecmp(var, "remote_port")) {
remote_port = atoi(val);
} else if (!strcasecmp(var, "outbound-called-ton")) {
ftdm_span_set_ton(val, &span->default_caller_data.dnis.type);
ftdm_set_ton(val, &span->default_caller_data.dnis.type);
} else if (!strcasecmp(var, "outbound-called-npi")) {
ftdm_span_set_npi(val, &span->default_caller_data.dnis.plan);
ftdm_set_npi(val, &span->default_caller_data.dnis.plan);
} else if (!strcasecmp(var, "outbound-calling-ton")) {
ftdm_span_set_ton(val, &span->default_caller_data.cid_num.type);
ftdm_set_ton(val, &span->default_caller_data.cid_num.type);
} else if (!strcasecmp(var, "outbound-calling-npi")) {
ftdm_span_set_npi(val, &span->default_caller_data.cid_num.plan);
ftdm_set_npi(val, &span->default_caller_data.cid_num.plan);
} else if (!strcasecmp(var, "outbound-rdnis-ton")) {
ftdm_span_set_ton(val, &span->default_caller_data.rdnis.type);
ftdm_set_ton(val, &span->default_caller_data.rdnis.type);
} else if (!strcasecmp(var, "outbound-rdnis-npi")) {
ftdm_span_set_npi(val, &span->default_caller_data.rdnis.plan);
ftdm_set_npi(val, &span->default_caller_data.rdnis.plan);
} else if (!sigmod) {
snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var);
FAIL_CONFIG_RETURN(FTDM_FAIL);

View File

@ -5,10 +5,18 @@
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectName>ftmod_sangoma_isdn</ProjectName>
@ -21,33 +29,58 @@
<ConfigurationType>DynamicLibrary</ConfigurationType>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</IntDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</LinkIncremental>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@ -74,6 +107,29 @@
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<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>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ExceptionHandling>
</ExceptionHandling>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<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>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Console</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
@ -93,6 +149,23 @@
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="ftmod_sangoma_isdn.h" />
<ClInclude Include="ftmod_sangoma_isdn_trace.h" />

View File

@ -40,22 +40,24 @@
#include <sys/mman.h>
#endif
static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj);
static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj);
static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span);
static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span);
ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event);
static void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftdmchan);
static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span);
static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event);
static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan);
static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event);
static void ftdm_sangoma_isdn_wakeup_phy(ftdm_channel_t *dchan);
static void ftdm_sangoma_isdn_dchan_set_queue_size(ftdm_channel_t *ftdmchan);
static ftdm_io_interface_t g_sngisdn_io_interface;
static sng_isdn_event_interface_t g_sngisdn_event_interface;
static ftdm_io_interface_t g_sngisdn_io_interface;
static sng_isdn_event_interface_t g_sngisdn_event_interface;
ftdm_sngisdn_data_t g_sngisdn_data;
ftdm_sngisdn_data_t g_sngisdn_data;
ftdm_state_map_t sangoma_isdn_state_map = {
{
@ -113,7 +115,20 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_RING, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}
},
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_PROCEED, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
FTDM_CHANNEL_STATE_UP, FTDM_END}
},
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_RINGING, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
{
ZSD_INBOUND,
@ -187,9 +202,17 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_DIALING, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS,
FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_DOWN, FTDM_END}
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
FTDM_CHANNEL_STATE_DOWN, FTDM_END}
},
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_PROCEED, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
@ -236,39 +259,51 @@ static __inline__ void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftd
}
}
static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
sngisdn_snd_event(signal_data->dchan, event);
switch (event) {
/* Check if the span woke up from power-saving mode */
case FTDM_OOB_ALARM_CLEAR:
if (FTDM_SPAN_IS_BRI(span)) {
ftdm_channel_t *ftdmchan;
sngisdn_chan_data_t *sngisdn_info;
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data;
if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)) {
ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING);
ftdm_sched_timer(signal_data->sched, "delayed_setup", 1000, sngisdn_delayed_setup, (void*) ftdmchan->call_data, NULL);
}
}
ftdm_iterator_free(chaniter);
}
break;
default:
/* Ignore other events for now */
break;
}
}
static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span)
{
ftdm_status_t ret_status;
ftdm_channel_t *ftdmchan;
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
ftdm_status_t ret_status;
ret_status = ftdm_span_poll_event(span, 0, NULL);
switch(ret_status) {
case FTDM_SUCCESS:
{
ftdm_event_t *event;
while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) {
if (FTDM_SPAN_IS_BRI(span)) {
switch (event->enum_id) {
/* Check if the span woke up from power-saving mode */
case FTDM_OOB_ALARM_CLEAR:
{
chaniter = ftdm_span_get_chan_iterator(span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
if (ftdm_test_flag(sngisdn_info, FLAG_ACTIVATING)) {
ftdm_clear_flag(sngisdn_info, FLAG_ACTIVATING);
sngisdn_snd_setup((ftdm_channel_t*)ftdmchan);
}
}
ftdm_iterator_free(chaniter);
}
}
}
ftdm_sangoma_isdn_process_phy_events(span, event->enum_id);
}
}
break;
@ -280,9 +315,83 @@ static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span)
}
}
static void ftdm_sangoma_isdn_dchan_set_queue_size(ftdm_channel_t *dchan)
{
ftdm_status_t ret_status;
uint32_t queue_size;
queue_size = SNGISDN_DCHAN_QUEUE_LEN;
ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_RX_QUEUE_SIZE, &queue_size);
ftdm_assert(ret_status == FTDM_SUCCESS, "Failed to set Rx Queue size");
queue_size = SNGISDN_DCHAN_QUEUE_LEN;
ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_TX_QUEUE_SIZE, &queue_size);
ftdm_assert(ret_status == FTDM_SUCCESS, "Failed to set Tx Queue size");
RETVOID;
}
static void ftdm_sangoma_isdn_wakeup_phy(ftdm_channel_t *dchan)
{
ftdm_status_t ret_status;
ftdm_channel_hw_link_status_t status = FTDM_HW_LINK_CONNECTED;
ret_status = ftdm_channel_command(dchan, FTDM_COMMAND_SET_LINK_STATUS, &status);
if (ret_status != FTDM_SUCCESS) {
ftdm_log_chan_msg(dchan, FTDM_LOG_WARNING, "Failed to wake-up link\n");
}
return;
}
static void *ftdm_sangoma_isdn_dchan_run(ftdm_thread_t *me, void *obj)
{
uint8_t data[1000];
ftdm_status_t status = FTDM_SUCCESS;
ftdm_wait_flag_t wflags = FTDM_READ;
ftdm_span_t *span = (ftdm_span_t*) obj;
ftdm_channel_t *dchan = ((sngisdn_span_data_t*)span->signal_data)->dchan;
ftdm_size_t len = 0;
ftdm_channel_set_feature(dchan, FTDM_CHANNEL_FEATURE_IO_STATS);
ftdm_sangoma_isdn_dchan_set_queue_size(dchan);
ftdm_assert(dchan, "Span does not have a dchannel");
ftdm_channel_open_chan(dchan);
while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) {
wflags = FTDM_READ;
status = ftdm_channel_wait(dchan, &wflags, 10000);
switch(status) {
case FTDM_FAIL:
ftdm_log_chan_msg(dchan, FTDM_LOG_CRIT, "Failed to wait for d-channel\n");
break;
case FTDM_TIMEOUT:
break;
case FTDM_SUCCESS:
if ((wflags & FTDM_READ)) {
len = 1000;
status = ftdm_channel_read(dchan, data, &len);
if (status == FTDM_SUCCESS) {
sngisdn_snd_data(dchan, data, len);
} else {
ftdm_log_chan_msg(dchan, FTDM_LOG_WARNING, "Failed to read from channel \n");
}
#ifndef WIN32 /* It is valid on WIN32 for poll to return without errors, but no flags set */
} else {
ftdm_log_chan_msg(dchan, FTDM_LOG_CRIT, "Failed to poll for d-channel\n");
#endif
}
break;
default:
ftdm_log_chan_msg(dchan, FTDM_LOG_CRIT, "Unhandled IO event\n");
}
}
ftdm_channel_close(&dchan);
return NULL;
}
static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
{
ftdm_interrupt_t *ftdm_sangoma_isdn_int[2];
ftdm_interrupt_t *ftdm_sangoma_isdn_int[3];
ftdm_status_t ret_status;
ftdm_span_t *span = (ftdm_span_t *) obj;
ftdm_channel_t *ftdmchan = NULL;
@ -300,8 +409,13 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a ftdm_interrupt for span = %s!\n", span->name);
goto ftdm_sangoma_isdn_run_exit;
}
if (ftdm_queue_get_interrupt(span->pendingsignals, &ftdm_sangoma_isdn_int[1]) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a signal interrupt for span = %s!\n", span->name);
goto ftdm_sangoma_isdn_run_exit;
}
if (ftdm_queue_get_interrupt(signal_data->event_queue, &ftdm_sangoma_isdn_int[1]) != FTDM_SUCCESS) {
if (ftdm_queue_get_interrupt(signal_data->event_queue, &ftdm_sangoma_isdn_int[2]) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a event interrupt for span = %s!\n", span->name);
goto ftdm_sangoma_isdn_run_exit;
}
@ -310,8 +424,14 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
/* Check if there are any timers to process */
ftdm_sched_run(signal_data->sched);
ftdm_span_trigger_signals(span);
ret_status = ftdm_interrupt_multiple_wait(ftdm_sangoma_isdn_int, 2, sleep);
if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) {
if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) {
sleep = SNGISDN_EVENT_POLL_RATE;
}
}
ret_status = ftdm_interrupt_multiple_wait(ftdm_sangoma_isdn_int, 3, sleep);
/* find out why we returned from the interrupt queue */
switch (ret_status) {
case FTDM_SUCCESS: /* there was a state change on the span */
@ -327,7 +447,6 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
ftdm_sangoma_isdn_process_stack_event(span, sngisdn_event);
ftdm_safe_free(sngisdn_event);
}
ftdm_span_trigger_signals(span);
break;
case FTDM_TIMEOUT:
/* twiddle */
@ -343,12 +462,6 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
/* Poll for events, e.g HW DTMF */
ftdm_sangoma_isdn_poll_events(span);
if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) {
if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) {
sleep = SNGISDN_EVENT_POLL_RATE;
}
}
}
/* clear the IN_THREAD flag so that we know the thread is done */
@ -512,13 +625,15 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
break;
case FTDM_CHANNEL_STATE_GET_CALLERID:
{
sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
sngisdn_snd_proceed(ftdmchan);
if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
sngisdn_snd_proceed(ftdmchan);
}
/* Wait in this state until we get FACILITY msg */
}
break;
case FTDM_CHANNEL_STATE_RING: /* incoming call request */
{
{
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending incoming call from %s to %s to FTDM core\n", ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.dnis.digits);
/* we have enough information to inform FTDM of the call*/
@ -535,14 +650,34 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Requesting Line activation\n");
sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING);
sng_isdn_wake_up_phy(ftdmchan->span);
sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING);
ftdm_sangoma_isdn_wakeup_phy(ftdmchan);
ftdm_sched_timer(signal_data->sched, "timer_t3", signal_data->timer_t3*1000, sngisdn_t3_timeout, (void*) sngisdn_info, NULL);
} else {
sngisdn_snd_setup(ftdmchan);
}
}
break;
case FTDM_CHANNEL_STATE_PROCEED:
{
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
/*OUTBOUND...so we were told by the line of this so noifiy the user*/
sigev.event_id = FTDM_SIGEVENT_PROCEED;
ftdm_span_send_signal(ftdmchan->span, &sigev);
} else {
if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
sngisdn_snd_proceed(ftdmchan);
}
}
}
break;
case FTDM_CHANNEL_STATE_RINGING:
{
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
sngisdn_snd_alert(ftdmchan, prog_ind);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS:
{
/*check if the channel is inbound or outbound*/
@ -550,9 +685,13 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
/*OUTBOUND...so we were told by the line of this so noifiy the user*/
sigev.event_id = FTDM_SIGEVENT_PROGRESS;
ftdm_span_send_signal(ftdmchan->span, &sigev);
} else if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
sngisdn_snd_proceed(ftdmchan);
} else {
/* If we already sent a PROCEED before, do not send a PROGRESS as there is nothing to indicate to the remote switch */
if (ftdmchan->last_state != FTDM_CHANNEL_STATE_PROCEED) {
/* Send a progress message, indicating: Call is not end-to-end ISDN, further call progress may be available */
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
sngisdn_snd_progress(ftdmchan, prog_ind);
}
}
}
break;
@ -562,7 +701,9 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
sigev.event_id = FTDM_SIGEVENT_PROGRESS_MEDIA;
ftdm_span_send_signal(ftdmchan->span, &sigev);
} else {
sngisdn_snd_progress(ftdmchan);
/* Send a progress message, indicating: In-band information/pattern available */
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_IB_AVAIL};
sngisdn_snd_progress(ftdmchan, prog_ind);
}
}
break;
@ -633,7 +774,7 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
sngisdn_snd_release(ftdmchan, 0);
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
sng_isdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
sngisdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
}
} else {
sngisdn_snd_disconnect(ftdmchan);
@ -658,9 +799,7 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
break;
case FTDM_CHANNEL_STATE_DOWN: /* the call is finished and removed */
{
uint8_t glare = 0;
glare = sngisdn_test_flag(sngisdn_info, FLAG_GLARE);
uint8_t glare = sngisdn_test_flag(sngisdn_info, FLAG_GLARE);
/* clear all of the call specific data store in the channel structure */
clear_call_data(sngisdn_info);
@ -788,7 +927,7 @@ static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_span_sig_status)
static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
{
ftdm_log(FTDM_LOG_INFO,"Starting span %s:%u.\n",span->name,span->span_id);
if (sng_isdn_stack_start(span) != FTDM_SUCCESS) {
if (sngisdn_stack_start(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name);
return FTDM_FAIL;
}
@ -802,6 +941,12 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
return FTDM_FAIL;
}
/*start the dchan monitor thread*/
if (ftdm_thread_create_detached(ftdm_sangoma_isdn_dchan_run, span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT,"Failed to start Sangoma ISDN d-channel Monitor Thread!\n");
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG,"Finished starting span %s\n", span->name);
return FTDM_SUCCESS;
}
@ -823,7 +968,7 @@ static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span)
ftdm_sleep(10);
}
if (sng_isdn_stack_stop(span) != FTDM_SUCCESS) {
if (sngisdn_stack_stop(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to stop span %s\n", span->name);
}
@ -875,7 +1020,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
return FTDM_FAIL;
}
if (sng_isdn_stack_cfg(span) != FTDM_SUCCESS) {
if (sngisdn_stack_cfg(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Sangoma ISDN Stack configuration failed\n");
return FTDM_FAIL;
}
@ -894,11 +1039,12 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
span->state_map = &sangoma_isdn_state_map;
ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE);
ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE);
ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE);
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
span->trunk_type == FTDM_TRUNK_BRI) {
sng_isdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
sngisdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
}
/* Initialize scheduling context */
@ -917,7 +1063,7 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init)
ftdm_log(FTDM_LOG_INFO, "Loading ftmod_sangoma_isdn...\n");
memset(&g_sngisdn_data, 0, sizeof(g_sngisdn_data));
memset(&g_sngisdn_event_interface, 0, sizeof(g_sngisdn_event_interface));
/* set callbacks */
g_sngisdn_event_interface.cc.sng_con_ind = sngisdn_rcv_con_ind;
g_sngisdn_event_interface.cc.sng_con_cfm = sngisdn_rcv_con_cfm;
@ -946,8 +1092,11 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init)
g_sngisdn_event_interface.sta.sng_q921_trc_ind = sngisdn_rcv_q921_trace;
g_sngisdn_event_interface.sta.sng_q931_sta_ind = sngisdn_rcv_q931_ind;
g_sngisdn_event_interface.sta.sng_q931_trc_ind = sngisdn_rcv_q931_trace;
g_sngisdn_event_interface.sta.sng_cc_sta_ind = sngisdn_rcv_cc_ind;
g_sngisdn_event_interface.sta.sng_cc_sta_ind = sngisdn_rcv_cc_ind;
g_sngisdn_event_interface.io.sng_l1_data_req = sngisdn_rcv_l1_data_req;
g_sngisdn_event_interface.io.sng_l1_cmd_req = sngisdn_rcv_l1_cmd_req;
for(i=1;i<=MAX_VARIANTS;i++) {
ftdm_mutex_create(&g_sngisdn_data.ccs[i].mutex);
}
@ -1008,11 +1157,11 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
goto done;
}
if (!strcasecmp(trace_opt, "q921")) {
sng_isdn_activate_trace(span, SNGISDN_TRACE_Q921);
sngisdn_activate_trace(span, SNGISDN_TRACE_Q921);
} else if (!strcasecmp(trace_opt, "q931")) {
sng_isdn_activate_trace(span, SNGISDN_TRACE_Q931);
sngisdn_activate_trace(span, SNGISDN_TRACE_Q931);
} else if (!strcasecmp(trace_opt, "disable")) {
sng_isdn_activate_trace(span, SNGISDN_TRACE_DISABLE);
sngisdn_activate_trace(span, SNGISDN_TRACE_DISABLE);
} else {
stream->write_function(stream, "-ERR invalid trace option <q921|q931> <span name>\n");
}

View File

@ -60,9 +60,37 @@
#define SNGISDN_EVENT_QUEUE_SIZE 100
#define SNGISDN_EVENT_POLL_RATE 100
#define SNGISDN_NUM_LOCAL_NUMBERS 8
#define SNGISDN_DCHAN_QUEUE_LEN 200
/* TODO: rename all *_cc_* to *_an_* */
#define SNGISDN_ENUM_NAMES(_NAME, _STRINGS) static const char * _NAME [] = { _STRINGS , NULL };
#define SNGISDN_STR2ENUM_P(_FUNC1, _FUNC2, _TYPE) _TYPE _FUNC1 (const char *name); const char * _FUNC2 (_TYPE type);
#define SNGISDN_STR2ENUM(_FUNC1, _FUNC2, _TYPE, _STRINGS, _MAX) \
_TYPE _FUNC1 (const char *name) \
{ \
int i; \
_TYPE t = _MAX ; \
\
for (i = 0; i < _MAX ; i++) { \
if (!strcasecmp(name, _STRINGS[i])) { \
t = (_TYPE) i; \
break; \
} \
} \
\
return t; \
} \
const char * _FUNC2 (_TYPE type) \
{ \
if (type > _MAX) { \
type = _MAX; \
} \
return _STRINGS[(int)type]; \
} \
typedef enum {
FLAG_RESET_RX = (1 << 0),
FLAG_RESET_TX = (1 << 1),
@ -74,7 +102,8 @@ typedef enum {
FLAG_DELAYED_REL = (1 << 7),
FLAG_SENT_PROCEED = (1 << 8),
FLAG_SEND_DISC = (1 << 9),
FLAG_ACTIVATING = (1 << 10), /* Used for BRI only, flag is set after we request line CONNECTED */
/* Used for BRI only, flag is set after we request line CONNECTED */
FLAG_ACTIVATING = (1 << 10),
} sngisdn_flag_t;
@ -134,6 +163,51 @@ typedef enum {
SNGISDN_EVENT_RST_IND,
} ftdm_sngisdn_event_id_t;
typedef enum {
/* Call is not end-to-end ISDN */
SNGISDN_PROGIND_DESCR_NETE_ISDN,
/* Destination address is non-ISDN */
SNGISDN_PROGIND_DESCR_DEST_NISDN,
/* Origination address is non-ISDN */
SNGISDN_PROGIND_DESCR_ORIG_NISDN,
/* Call has returned to the ISDN */
SNGISDN_PROGIND_DESCR_RET_ISDN,
/* Interworking as occured and has resulted in a telecommunication service change */
SNGISDN_PROGIND_DESCR_SERV_CHANGE,
/* In-band information or an appropriate pattern is now available */
SNGISDN_PROGIND_DESCR_IB_AVAIL,
/* Invalid */
SNGISDN_PROGIND_DESCR_INVALID,
} ftdm_sngisdn_progind_descr_t;
#define SNGISDN_PROGIND_DESCR_STRINGS "not-end-to-end-isdn", "destination-is-non-isdn", "origination-is-non-isdn", "call-returned-to-isdn", "service-change", "inband-info-available", "invalid"
SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t);
typedef enum {
/* User */
SNGISDN_PROGIND_LOC_USER,
/* Private network serving the local user */
SNGISDN_PROGIND_LOC_PRIV_NET_LOCAL_USR,
/* Public network serving the local user */
SNGISDN_PROGIND_LOC_PUB_NET_LOCAL_USR,
/* Transit network */
SNGISDN_PROGIND_LOC_TRANSIT_NET,
/* Public network serving remote user */
SNGISDN_PROGIND_LOC_PUB_NET_REMOTE_USR,
/* Private network serving remote user */
SNGISDN_PROGIND_LOC_PRIV_NET_REMOTE_USR,
/* Network beyond the interworking point */
SNGISDN_PROGIND_LOC_NET_BEYOND_INTRW,
/* Invalid */
SNGISDN_PROGIND_LOC_INVALID,
} ftdm_sngisdn_progind_loc_t;
#define SNGISDN_PROGIND_LOC_STRINGS "user", "private-net-local-user", "public-net-local-user", "transit-network", "public-net-remote-user", "private-net-remote-user", "beyond-interworking", "invalid"
SNGISDN_STR2ENUM_P(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t);
typedef struct ftdm_sngisdn_prog_ind {
ftdm_sngisdn_progind_loc_t loc; /* location */
ftdm_sngisdn_progind_descr_t descr; /* description */
} ftdm_sngisdn_progind_t;
/* Only timers that can be cancelled are listed here */
#define SNGISDN_NUM_TIMERS 1
/* Increase NUM_TIMERS as number of ftdm_sngisdn_timer_t increases */
@ -168,6 +242,7 @@ typedef struct sngisdn_chan_data {
/* Span specific data */
typedef struct sngisdn_span_data {
ftdm_span_t *ftdm_span;
ftdm_channel_t *dchan;
uint8_t link_id;
uint8_t switchtype;
uint8_t signalling; /* SNGISDN_SIGNALING_CPE or SNGISDN_SIGNALING_NET */
@ -179,9 +254,11 @@ typedef struct sngisdn_span_data {
uint8_t trace_flags; /* TODO: change to flags, so we can use ftdm_test_flag etc.. */
uint8_t overlap_dial;
uint8_t setup_arb;
uint8_t facility_ie_decode;
uint8_t facility;
int8_t facility_timeout;
uint8_t num_local_numbers;
uint8_t ignore_cause_value;
uint8_t timer_t3;
uint8_t restart_opt;
char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS];
@ -269,60 +346,58 @@ extern ftdm_sngisdn_data_t g_sngisdn_data;
ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span);
/* Support functions */
FT_DECLARE(uint32_t) get_unique_suInstId(int16_t cc_id);
FT_DECLARE(void) clear_call_data(sngisdn_chan_data_t *sngisdn_info);
FT_DECLARE(void) clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info);
uint32_t get_unique_suInstId(int16_t cc_id);
void clear_call_data(sngisdn_chan_data_t *sngisdn_info);
void clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info);
ftdm_status_t get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data);
ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data);
ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail);
ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
void stack_hdr_init(Header *hdr);
void stack_pst_init(Pst *pst);
FT_DECLARE(ftdm_status_t) get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data);
FT_DECLARE(ftdm_status_t) get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data);
FT_DECLARE(ftdm_status_t) sng_isdn_set_avail_rate(ftdm_span_t *ftdmspan, sngisdn_avail_t avail);
FT_DECLARE(ftdm_status_t) cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
FT_DECLARE(ftdm_status_t) cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb);
FT_DECLARE(ftdm_status_t) cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb);
FT_DECLARE(ftdm_status_t) cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display);
FT_DECLARE(ftdm_status_t) cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm);
FT_DECLARE(ftdm_status_t) cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm);
FT_DECLARE(ftdm_status_t) cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm);
FT_DECLARE(ftdm_status_t) cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan);
/* Outbound Call Control functions */
void sngisdn_snd_setup(ftdm_channel_t *ftdmchan);
void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan);
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan);
void sngisdn_snd_progress(ftdm_channel_t *ftdmchan);
void sngisdn_snd_alert(ftdm_channel_t *ftdmchan);
void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
void sngisdn_snd_connect(ftdm_channel_t *ftdmchan);
void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan);
void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare);
void sngisdn_snd_reset(ftdm_channel_t *ftdmchan);
void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan);
void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan);
void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan);
void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan);
void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len);
void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event);
/* Inbound Call Control functions */
void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces);
void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces);
void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces);
void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt);
void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt);
void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt);
void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, int16_t dChan, uint8_t ces);
void sngisdn_rcv_sta_cfm ( int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
void sngisdn_rcv_srv_ind ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces);
void sngisdn_rcv_srv_cfm ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces);
void sngisdn_rcv_rst_cfm ( int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType);
void sngisdn_rcv_rst_ind ( int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType);
void sngisdn_rcv_con_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces);
void sngisdn_rcv_con_cfm(int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces);
void sngisdn_rcv_cnst_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces);
void sngisdn_rcv_disc_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt);
void sngisdn_rcv_rel_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt);
void sngisdn_rcv_dat_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt);
void sngisdn_rcv_sshl_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
void sngisdn_rcv_sshl_cfm(int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
void sngisdn_rcv_rmrt_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
void sngisdn_rcv_rmrt_cfm(int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
void sngisdn_rcv_flc_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
void sngisdn_rcv_fac_ind(int16_t suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, int16_t dChan, uint8_t ces);
void sngisdn_rcv_sta_cfm(int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
void sngisdn_rcv_srv_ind(int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces);
void sngisdn_rcv_srv_cfm(int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces);
void sngisdn_rcv_rst_cfm(int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType);
void sngisdn_rcv_rst_ind(int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType);
int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame);
int16_t sngisdn_rcv_l1_cmd_req(uint16_t spId, sng_l1_cmd_t *l1_cmd);
void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event);
@ -360,6 +435,26 @@ void sngisdn_rcv_cc_ind(CcMngmt *status);
void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...);
void sngisdn_rcv_sng_assert(char *message);
ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb);
ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb);
ftdm_status_t get_calling_name_from_display(ftdm_channel_t *ftdmchan, Display *display);
ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr);
ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad);
ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd);
ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);
ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t data_len);
ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb);
ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb);
ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt);
ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad);
ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind);
ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);
ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t *data_len);
uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability);
uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_prot);
ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_user(uint8_t bearer_capability);
@ -386,6 +481,7 @@ static __inline__ void sngisdn_set_flag(sngisdn_chan_data_t *sngisdn_info, sngis
void handle_sng_log(uint8_t level, char *fmt,...);
void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status);
void sngisdn_delayed_setup(void* p_sngisdn_info);
void sngisdn_delayed_release(void* p_sngisdn_info);
void sngisdn_delayed_connect(void* p_sngisdn_info);
void sngisdn_delayed_disconnect(void* p_sngisdn_info);
@ -393,10 +489,10 @@ void sngisdn_facility_timeout(void* p_sngisdn_info);
void sngisdn_t3_timeout(void* p_sngisdn_info);
/* Stack management functions */
ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span);
ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span);
ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span);
ftdm_status_t sng_isdn_wake_up_phy(ftdm_span_t *span);
ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span);
ftdm_status_t sngisdn_stack_start(ftdm_span_t *span);
ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span);
ftdm_status_t sngisdn_wake_up_phy(ftdm_span_t *span);
void sngisdn_print_phy_stats(ftdm_stream_handle_t *stream, ftdm_span_t *span);
void sngisdn_print_spans(ftdm_stream_handle_t *stream);

View File

@ -34,13 +34,24 @@
#include "ftmod_sangoma_isdn.h"
ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span);
ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span);
ftdm_status_t add_local_number(const char* val, ftdm_span_t *span);
static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span);
static ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span);
static ftdm_status_t add_local_number(const char* val, ftdm_span_t *span);
static ftdm_status_t parse_yesno(const char* var, const char* val, uint8_t *target);
extern ftdm_sngisdn_data_t g_sngisdn_data;
ftdm_status_t add_local_number(const char* val, ftdm_span_t *span)
static ftdm_status_t parse_yesno(const char* var, const char* val, uint8_t *target)
{
if (ftdm_true(val)) {
*target = SNGISDN_OPT_TRUE;
} else {
*target = SNGISDN_OPT_FALSE;
}
return FTDM_SUCCESS;
}
static ftdm_status_t add_local_number(const char* val, ftdm_span_t *span)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
@ -53,12 +64,14 @@ ftdm_status_t add_local_number(const char* val, ftdm_span_t *span)
return FTDM_SUCCESS;
}
ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
static ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
{
unsigned i;
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
sngisdn_dchan_data_t *dchan_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
switch(span->trunk_type) {
case FTDM_TRUNK_T1:
if (!strcasecmp(switch_name, "ni2") ||
@ -124,9 +137,9 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
/* add this span to its ent_cc */
signal_data->cc_id = i;
/* create a new dchan */ /* for NFAS - no-dchan on b-channels only links */
/* create a new dchan */ /* for NFAS - no-dchan on b-channels-only links */
g_sngisdn_data.num_dchan++;
signal_data->dchan_id = g_sngisdn_data.num_dchan;
signal_data->dchan_id = g_sngisdn_data.num_dchan;
dchan_data = &g_sngisdn_data.dchans[signal_data->dchan_id];
dchan_data->num_spans++;
@ -138,20 +151,27 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
ftdm_log(FTDM_LOG_DEBUG, "%s: cc_id:%d dchan_id:%d span_id:%d\n", span->name, signal_data->cc_id, signal_data->dchan_id, signal_data->span_id);
/* Add the channels to the span */
for (i=1;i<=span->chan_count;i++) {
unsigned chan_id;
ftdm_channel_t *ftdmchan = span->channels[i];
/* NFAS is not supported on E1, so span_id will always be 1 for E1 so this will work for E1 as well */
chan_id = ((signal_data->span_id-1)*NUM_T1_CHANNELS_PER_SPAN)+ftdmchan->physical_chan_id;
dchan_data->channels[chan_id] = (sngisdn_chan_data_t*)ftdmchan->call_data;
dchan_data->num_chans++;
chaniter = ftdm_span_get_chan_iterator(span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
int32_t chan_id;
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) {
/* set the d-channel */
signal_data->dchan = ftdmchan;
} else {
/* Add the channels to the span */
/* NFAS is not supported on E1, so span_id will always be 1 for E1 so this will work for E1 as well */
chan_id = ((signal_data->span_id-1)*NUM_T1_CHANNELS_PER_SPAN)+ftdmchan->physical_chan_id;
dchan_data->channels[chan_id] = (sngisdn_chan_data_t*)ftdmchan->call_data;
dchan_data->num_chans++;
}
}
ftdm_iterator_free(chaniter);
return FTDM_SUCCESS;
}
ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span)
static ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
if (!strcasecmp(signalling, "net") ||
@ -181,6 +201,8 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
signal_data->min_digits = 8;
signal_data->overlap_dial = SNGISDN_OPT_DEFAULT;
signal_data->setup_arb = SNGISDN_OPT_DEFAULT;
signal_data->facility_ie_decode = SNGISDN_OPT_DEFAULT;
signal_data->ignore_cause_value = SNGISDN_OPT_DEFAULT;
signal_data->timer_t3 = 8;
signal_data->restart_opt = SNGISDN_OPT_DEFAULT;
@ -193,20 +215,19 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
if (span->trunk_type == FTDM_TRUNK_BRI ||
span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
ftdm_span_set_npi("unknown", &span->default_caller_data.dnis.plan);
ftdm_span_set_ton("unknown", &span->default_caller_data.dnis.type);
ftdm_span_set_npi("unknown", &span->default_caller_data.cid_num.plan);
ftdm_span_set_ton("unknown", &span->default_caller_data.cid_num.type);
ftdm_span_set_npi("unknown", &span->default_caller_data.rdnis.plan);
ftdm_span_set_ton("unknown", &span->default_caller_data.rdnis.type);
ftdm_set_npi("unknown", &span->default_caller_data.dnis.plan);
ftdm_set_ton("unknown", &span->default_caller_data.dnis.type);
ftdm_set_npi("unknown", &span->default_caller_data.cid_num.plan);
ftdm_set_ton("unknown", &span->default_caller_data.cid_num.type);
ftdm_set_npi("unknown", &span->default_caller_data.rdnis.plan);
ftdm_set_ton("unknown", &span->default_caller_data.rdnis.type);
} else {
ftdm_span_set_npi("e164", &span->default_caller_data.dnis.plan);
ftdm_span_set_ton("national", &span->default_caller_data.dnis.type);
ftdm_span_set_npi("e164", &span->default_caller_data.cid_num.plan);
ftdm_span_set_ton("national", &span->default_caller_data.cid_num.type);
ftdm_span_set_npi("e164", &span->default_caller_data.rdnis.plan);
ftdm_span_set_ton("national", &span->default_caller_data.rdnis.type);
ftdm_set_npi("isdn", &span->default_caller_data.dnis.plan);
ftdm_set_ton("national", &span->default_caller_data.dnis.type);
ftdm_set_npi("isdn", &span->default_caller_data.cid_num.plan);
ftdm_set_ton("national", &span->default_caller_data.cid_num.type);
ftdm_set_npi("isdn", &span->default_caller_data.rdnis.plan);
ftdm_set_ton("national", &span->default_caller_data.rdnis.type);
}
for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) {
@ -238,49 +259,30 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
} else {
ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val);
}
} else if (!strcasecmp(var, "setup arbitration")) {
if (!strcasecmp(val, "yes")) {
signal_data->setup_arb = SNGISDN_OPT_TRUE;
} else if (!strcasecmp(val, "no")) {
signal_data->setup_arb = SNGISDN_OPT_FALSE;
} else {
ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val);
}
} else if (!strcasecmp(var, "setup-arbitration")) {
parse_yesno(var, val, &signal_data->setup_arb);
} else if (!strcasecmp(var, "facility")) {
if (!strcasecmp(val, "yes")) {
signal_data->facility = SNGISDN_OPT_TRUE;
} else if (!strcasecmp(val, "no")) {
signal_data->facility = SNGISDN_OPT_FALSE;
} else {
ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val);
}
parse_yesno(var, val, &signal_data->facility);
} else if (!strcasecmp(var, "min_digits")) {
signal_data->min_digits = atoi(val);
} else if (!strcasecmp(var, "outbound-called-ton")) {
ftdm_span_set_ton(val, &span->default_caller_data.dnis.type);
ftdm_set_ton(val, &span->default_caller_data.dnis.type);
} else if (!strcasecmp(var, "outbound-called-npi")) {
ftdm_span_set_npi(val, &span->default_caller_data.dnis.plan);
ftdm_set_npi(val, &span->default_caller_data.dnis.plan);
} else if (!strcasecmp(var, "outbound-calling-ton")) {
ftdm_span_set_ton(val, &span->default_caller_data.cid_num.type);
ftdm_set_ton(val, &span->default_caller_data.cid_num.type);
} else if (!strcasecmp(var, "outbound-calling-npi")) {
ftdm_span_set_npi(val, &span->default_caller_data.cid_num.plan);
ftdm_set_npi(val, &span->default_caller_data.cid_num.plan);
} else if (!strcasecmp(var, "outbound-rdnis-ton")) {
ftdm_span_set_ton(val, &span->default_caller_data.rdnis.type);
ftdm_set_ton(val, &span->default_caller_data.rdnis.type);
} else if (!strcasecmp(var, "outbound-rdnis-npi")) {
ftdm_span_set_npi(val, &span->default_caller_data.rdnis.plan);
ftdm_set_npi(val, &span->default_caller_data.rdnis.plan);
} else if (!strcasecmp(var, "outbound-bearer_cap")) {
ftdm_span_set_bearer_capability(val, &span->default_caller_data.bearer_capability);
ftdm_set_bearer_capability(val, (uint8_t*)&span->default_caller_data.bearer_capability);
} else if (!strcasecmp(var, "outbound-bearer_layer1")) {
ftdm_span_set_bearer_layer1(val, &span->default_caller_data.bearer_layer1);
ftdm_set_bearer_layer1(val, (uint8_t*)&span->default_caller_data.bearer_layer1);
} else if (!strcasecmp(var, "channel-restart-on-link-up")) {
if (!strcasecmp(val, "yes")) {
signal_data->restart_opt = SNGISDN_OPT_TRUE;
} else if (!strcasecmp(val, "no")) {
signal_data->restart_opt = SNGISDN_OPT_FALSE;
} else {
ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val);
}
parse_yesno(var, val, &signal_data->restart_opt);
} else if (!strcasecmp(var, "local-number")) {
if (add_local_number(val, span) != FTDM_SUCCESS) {
return FTDM_FAIL;
@ -290,6 +292,10 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
if (signal_data->facility_timeout < 0) {
signal_data->facility_timeout = 0;
}
} else if (!strcasecmp(var, "facility-ie-decode")) {
parse_yesno(var, val, &signal_data->facility_ie_decode);
} else if (!strcasecmp(var, "ignore-cause-value")) {
parse_yesno(var, val, &signal_data->ignore_cause_value);
} else {
ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
}

View File

@ -38,52 +38,52 @@ extern ftdm_sngisdn_data_t g_sngisdn_data;
uint8_t sng_isdn_stack_switchtype(sngisdn_switchtype_t switchtype);
ftdm_status_t sng_isdn_cfg_phy(ftdm_span_t *span);
ftdm_status_t sng_isdn_cfg_q921(ftdm_span_t *span);
ftdm_status_t sng_isdn_cfg_q931(ftdm_span_t *span);
ftdm_status_t sng_isdn_cfg_cc(ftdm_span_t *span);
ftdm_status_t sngisdn_cfg_phy(ftdm_span_t *span);
ftdm_status_t sngisdn_cfg_q921(ftdm_span_t *span);
ftdm_status_t sngisdn_cfg_q931(ftdm_span_t *span);
ftdm_status_t sngisdn_cfg_cc(ftdm_span_t *span);
ftdm_status_t sng_isdn_stack_cfg_phy_gen(void);
ftdm_status_t sng_isdn_stack_cfg_q921_gen(void);
ftdm_status_t sng_isdn_stack_cfg_q931_gen(void);
ftdm_status_t sng_isdn_stack_cfg_cc_gen(void);
ftdm_status_t sngisdn_stack_cfg_phy_gen(void);
ftdm_status_t sngisdn_stack_cfg_q921_gen(void);
ftdm_status_t sngisdn_stack_cfg_q931_gen(void);
ftdm_status_t sngisdn_stack_cfg_cc_gen(void);
ftdm_status_t sng_isdn_stack_cfg_phy_psap(ftdm_span_t *span);
ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span);
ftdm_status_t sng_isdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management);
ftdm_status_t sng_isdn_stack_cfg_q931_tsap(ftdm_span_t *span);
ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span);
ftdm_status_t sng_isdn_stack_cfg_q931_lce(ftdm_span_t *span);
ftdm_status_t sngisdn_stack_cfg_phy_psap(ftdm_span_t *span);
ftdm_status_t sngisdn_stack_cfg_q921_msap(ftdm_span_t *span);
ftdm_status_t sngisdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management);
ftdm_status_t sngisdn_stack_cfg_q931_tsap(ftdm_span_t *span);
ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span);
ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span);
ftdm_status_t sng_isdn_stack_cfg_cc_sap(ftdm_span_t *span);
ftdm_status_t sngisdn_stack_cfg_cc_sap(ftdm_span_t *span);
ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span)
ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
if (!g_sngisdn_data.gen_config_done) {
g_sngisdn_data.gen_config_done = 1;
ftdm_log(FTDM_LOG_DEBUG, "Starting general stack configuration\n");
if(sng_isdn_stack_cfg_phy_gen()!= FTDM_SUCCESS) {
if(sngisdn_stack_cfg_phy_gen()!= FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed general physical configuration\n");
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "General stack physical done\n");
if(sng_isdn_stack_cfg_q921_gen()!= FTDM_SUCCESS) {
if(sngisdn_stack_cfg_q921_gen()!= FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed general q921 configuration\n");
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "General stack q921 done\n");
if(sng_isdn_stack_cfg_q931_gen()!= FTDM_SUCCESS) {
if(sngisdn_stack_cfg_q931_gen()!= FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed general q921 configuration\n");
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "General stack q931 done\n");
if(sng_isdn_stack_cfg_cc_gen()!= FTDM_SUCCESS) {
if(sngisdn_stack_cfg_cc_gen()!= FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed general CC configuration\n");
return FTDM_FAIL;
}
@ -92,26 +92,26 @@ ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span)
}
/* TODO: for NFAS, should only call these function for spans with d-chans */
if (sng_isdn_stack_cfg_phy_psap(span) != FTDM_SUCCESS) {
if (sngisdn_stack_cfg_phy_psap(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%s:phy_psap configuration failed\n", span->name);
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "%s:phy_psap configuration done\n", span->name);
if (sng_isdn_stack_cfg_q921_msap(span) != FTDM_SUCCESS) {
if (sngisdn_stack_cfg_q921_msap(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%s:q921_msap configuration failed\n", span->name);
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "%s:q921_msap configuration done\n", span->name);
if (sng_isdn_stack_cfg_q921_dlsap(span, 0) != FTDM_SUCCESS) {
if (sngisdn_stack_cfg_q921_dlsap(span, 0) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%s:q921_dlsap configuration failed\n", span->name);
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "%s:q921_dlsap configuration done\n", span->name);
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
if (sng_isdn_stack_cfg_q921_dlsap(span, 1) != FTDM_SUCCESS) {
if (sngisdn_stack_cfg_q921_dlsap(span, 1) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%s:q921_dlsap management configuration failed\n", span->name);
return FTDM_FAIL;
}
@ -119,13 +119,13 @@ ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span)
}
if (sng_isdn_stack_cfg_q931_dlsap(span) != FTDM_SUCCESS) {
if (sngisdn_stack_cfg_q931_dlsap(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%s:q931_dlsap configuration failed\n", span->name);
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "%s:q931_dlsap configuration done\n", span->name);
if (sng_isdn_stack_cfg_q931_lce(span) != FTDM_SUCCESS) {
if (sngisdn_stack_cfg_q931_lce(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%s:q931_lce configuration failed\n", span->name);
return FTDM_FAIL;
}
@ -134,13 +134,13 @@ ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span)
if (!g_sngisdn_data.ccs[signal_data->cc_id].config_done) {
g_sngisdn_data.ccs[signal_data->cc_id].config_done = 1;
/* if BRI, need to configure dlsap_mgmt */
if (sng_isdn_stack_cfg_q931_tsap(span) != FTDM_SUCCESS) {
if (sngisdn_stack_cfg_q931_tsap(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%s:q931_tsap configuration failed\n", span->name);
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_DEBUG, "%s:q931_tsap configuration done\n", span->name);
if (sng_isdn_stack_cfg_cc_sap(span) != FTDM_SUCCESS) {
if (sngisdn_stack_cfg_cc_sap(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "%s:cc_sap configuration failed\n", span->name);
return FTDM_FAIL;
}
@ -153,37 +153,37 @@ ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span)
ftdm_status_t sng_isdn_stack_cfg_phy_gen(void)
ftdm_status_t sngisdn_stack_cfg_phy_gen(void)
{
/*local variables*/
L1Mngmt cfg; /*configuration structure*/
Pst pst; /*post structure*/
L1Mngmt cfg; /*configuration structure*/
Pst pst; /*post structure*/
/* initalize the post structure */
stack_pst_init(&pst);
/* initalize the post structure */
stack_pst_init(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTL1;
/* insert the destination Entity */
pst.dstEnt = ENTL1;
/*clear the configuration structure*/
/*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
/*fill in some general sections of the header*/
stack_hdr_init(&cfg.hdr);
/*fill in some general sections of the header*/
stack_hdr_init(&cfg.hdr);
/*fill in the specific fields of the header*/
cfg.hdr.msgType = TCFG;
cfg.hdr.entId.ent = ENTL1;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STGEN;
/*fill in the specific fields of the header*/
cfg.hdr.msgType = TCFG;
cfg.hdr.entId.ent = ENTL1;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STGEN;
stack_pst_init(&cfg.t.cfg.s.l1Gen.sm );
cfg.t.cfg.s.l1Gen.sm.srcEnt = ENTL1;
cfg.t.cfg.s.l1Gen.sm.dstEnt = ENTSM;
stack_pst_init(&cfg.t.cfg.s.l1Gen.sm );
cfg.t.cfg.s.l1Gen.sm.srcEnt = ENTL1;
cfg.t.cfg.s.l1Gen.sm.dstEnt = ENTSM;
cfg.t.cfg.s.l1Gen.nmbLnks = MAX_L1_LINKS+1;
cfg.t.cfg.s.l1Gen.poolTrUpper = POOL_UP_TR; /* upper pool threshold */
cfg.t.cfg.s.l1Gen.poolTrLower = POOL_LW_TR; /* lower pool threshold */
cfg.t.cfg.s.l1Gen.nmbLnks = MAX_L1_LINKS;
cfg.t.cfg.s.l1Gen.poolTrUpper = POOL_UP_TR; /* upper pool threshold */
cfg.t.cfg.s.l1Gen.poolTrLower = POOL_LW_TR; /* lower pool threshold */
if (sng_isdn_phy_config(&pst, &cfg)) {
return FTDM_FAIL;
@ -191,55 +191,40 @@ ftdm_status_t sng_isdn_stack_cfg_phy_gen(void)
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_stack_cfg_phy_psap(ftdm_span_t *span)
{
ftdm_iterator_t *chaniter;
ftdm_iterator_t *curr;
L1Mngmt cfg;
Pst pst;
ftdm_status_t sngisdn_stack_cfg_phy_psap(ftdm_span_t *span)
{
L1Mngmt cfg;
Pst pst;
int32_t d_channel_fd = -1;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
/* initalize the post structure */
stack_pst_init(&pst);
/* initalize the post structure */
stack_pst_init(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTL1;
/* insert the destination Entity */
pst.dstEnt = ENTL1;
/*clear the configuration structure*/
/*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
/*fill in some general sections of the header*/
stack_hdr_init(&cfg.hdr);
/*fill in some general sections of the header*/
stack_hdr_init(&cfg.hdr);
/*fill in the specific fields of the header*/
cfg.hdr.msgType = TCFG;
cfg.hdr.entId.ent = ENTL1;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STPSAP;
/*fill in the specific fields of the header*/
cfg.hdr.msgType = TCFG;
cfg.hdr.entId.ent = ENTL1;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STPSAP;
cfg.hdr.elmId.elmntInst1 = signal_data->link_id;
/* Find the d-channel */
chaniter = ftdm_span_get_chan_iterator(span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) {
d_channel_fd = (int32_t)ftdmchan->sockfd;
break;
}
}
ftdm_iterator_free(chaniter);
if(d_channel_fd < 0) {
if (!signal_data->dchan) {
ftdm_log(FTDM_LOG_ERROR, "%s:No d-channels specified\n", span->name);
return FTDM_FAIL;
}
cfg.t.cfg.s.l1PSAP.sockfd = d_channel_fd;
cfg.t.cfg.s.l1PSAP.sockfd = (int32_t)signal_data->dchan->sockfd;
switch(span->trunk_type) {
case FTDM_TRUNK_E1:
cfg.t.cfg.s.l1PSAP.type = SNG_L1_TYPE_PRI;
@ -255,8 +240,8 @@ ftdm_status_t sng_isdn_stack_cfg_phy_psap(ftdm_span_t *span)
default:
ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported trunk type %d\n", span->name, span->trunk_type);
return FTDM_FAIL;
}
cfg.t.cfg.s.l1PSAP.spId = signal_data->link_id;
}
cfg.t.cfg.s.l1PSAP.spId = signal_data->link_id;
if (sng_isdn_phy_config(&pst, &cfg)) {
return FTDM_FAIL;
@ -265,28 +250,28 @@ ftdm_status_t sng_isdn_stack_cfg_phy_psap(ftdm_span_t *span)
}
ftdm_status_t sng_isdn_stack_cfg_q921_gen(void)
ftdm_status_t sngisdn_stack_cfg_q921_gen(void)
{
BdMngmt cfg;
Pst pst;
Pst pst;
/* initalize the post structure */
stack_pst_init(&pst);
/* initalize the post structure */
stack_pst_init(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTLD;
pst.dstEnt = ENTLD;
/*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
/*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
/*fill in some general sections of the header*/
stack_hdr_init(&cfg.hdr);
cfg.hdr.msgType = TCFG;
cfg.hdr.entId.ent = ENTLD;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STGEN;
/* fill in the Gen Conf structures internal pst struct */
stack_hdr_init(&cfg.hdr);
stack_pst_init(&cfg.t.cfg.s.bdGen.sm);
cfg.hdr.msgType = TCFG;
cfg.hdr.entId.ent = ENTLD;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STGEN;
/* fill in the Gen Conf structures internal pst struct */
stack_pst_init(&cfg.t.cfg.s.bdGen.sm);
cfg.t.cfg.s.bdGen.sm.dstEnt = ENTSM; /* entity */
@ -299,8 +284,8 @@ ftdm_status_t sng_isdn_stack_cfg_q921_gen(void)
#ifdef LAPD_3_4
cfg.t.cfg.s.bdGen.timeRes = 100; /* timer resolution = 1 sec */
#endif
cfg.t.cfg.s.bdGen.poolTrUpper = 2; /* upper pool threshold */
cfg.t.cfg.s.bdGen.poolTrLower = 1; /* lower pool threshold */
cfg.t.cfg.s.bdGen.poolTrUpper = 2; /* upper pool threshold */
cfg.t.cfg.s.bdGen.poolTrLower = 1; /* lower pool threshold */
if (sng_isdn_q921_config(&pst, &cfg)) {
return FTDM_FAIL;
@ -308,30 +293,30 @@ ftdm_status_t sng_isdn_stack_cfg_q921_gen(void)
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
ftdm_status_t sngisdn_stack_cfg_q921_msap(ftdm_span_t *span)
{
BdMngmt cfg;
Pst pst;
Pst pst;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
/* initalize the post structure */
stack_pst_init(&pst);
/* initalize the post structure */
stack_pst_init(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTLD;
pst.dstEnt = ENTLD;
/*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
/*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
/*fill in some general sections of the header*/
stack_hdr_init(&cfg.hdr);
stack_hdr_init(&cfg.hdr);
cfg.hdr.msgType = TCFG;
cfg.hdr.entId.ent = ENTLD;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STMSAP;
cfg.hdr.entId.ent = ENTLD;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STMSAP;
cfg.t.cfg.s.bdMSAP.lnkNmb = signal_data->link_id;
cfg.t.cfg.s.bdMSAP.maxOutsFrms = 24; /* MAC window */
cfg.t.cfg.s.bdMSAP.tQUpperTrs = 32; /* Tx Queue Upper Threshold */
cfg.t.cfg.s.bdMSAP.tQLowerTrs = 24; /* Tx Queue Lower Threshold */
@ -343,7 +328,7 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
cfg.t.cfg.s.bdMSAP.route = RTESPEC; /* Route */
cfg.t.cfg.s.bdMSAP.dstProcId = SFndProcId(); /* destination proc id */
cfg.t.cfg.s.bdMSAP.dstEnt = ENTL1; /* entity */
cfg.t.cfg.s.bdMSAP.dstInst = S_INST; /* instance */
cfg.t.cfg.s.bdMSAP.dstInst = S_INST; /* instance */
cfg.t.cfg.s.bdMSAP.t201Tmr = 1; /* T201 - should be equal to t200Tmr */
cfg.t.cfg.s.bdMSAP.t202Tmr = 2; /* T202 */
cfg.t.cfg.s.bdMSAP.bndRetryCnt = 2; /* bind retry counter */
@ -392,7 +377,7 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
if (signal_data->setup_arb == SNGISDN_OPT_TRUE) {
cfg.t.cfg.s.bdMSAP.setUpArb = ACTIVE;
} else if (signal_data->setup_arb == SNGISDN_OPT_FALSE) {
cfg.t.cfg.s.bdMSAP.setUpArb = PASSIVE;
cfg.t.cfg.s.bdMSAP.setUpArb = PASSIVE;
}
if (sng_isdn_q921_config(&pst, &cfg)) {
@ -401,27 +386,27 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management)
ftdm_status_t sngisdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t management)
{
BdMngmt cfg;
Pst pst;
Pst pst;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
/* initalize the post structure */
stack_pst_init(&pst);
/* initalize the post structure */
stack_pst_init(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTLD;
pst.dstEnt = ENTLD;
/*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
/*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
/*fill in some general sections of the header*/
stack_hdr_init(&cfg.hdr);
stack_hdr_init(&cfg.hdr);
/*fill in the specific fields of the header*/
cfg.hdr.msgType = TCFG;
cfg.hdr.entId.ent = ENTLD;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STDLSAP;
cfg.hdr.msgType = TCFG;
cfg.hdr.entId.ent = ENTLD;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STDLSAP;
cfg.t.cfg.s.bdDLSAP.lnkNmb = signal_data->link_id;
@ -433,10 +418,10 @@ ftdm_status_t sng_isdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t managemen
} else {
cfg.t.cfg.s.bdDLSAP.k = 7; /* k */
}
cfg.t.cfg.s.bdDLSAP.n200 = 3; /* n200 */
cfg.t.cfg.s.bdDLSAP.congTmr = 300; /* congestion timer */
cfg.t.cfg.s.bdDLSAP.t200Tmr = 1; /* t1 changed from 25 */
cfg.t.cfg.s.bdDLSAP.t200Tmr = 1; /* t1 changed from 25 */
cfg.t.cfg.s.bdDLSAP.t203Tmr = 10; /* t3 changed from 50 */
cfg.t.cfg.s.bdDLSAP.mod = 128; /* modulo */
cfg.t.cfg.s.bdDLSAP.selector = 0; /* Selector 0 */
@ -483,31 +468,31 @@ ftdm_status_t sng_isdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t managemen
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_stack_cfg_q931_gen(void)
ftdm_status_t sngisdn_stack_cfg_q931_gen(void)
{
InMngmt cfg;
Pst pst;
Pst pst;
/* initalize the post structure */
stack_pst_init(&pst);
/* initalize the post structure */
stack_pst_init(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTIN;
/* insert the destination Entity */
pst.dstEnt = ENTIN;
/*clear the configuration structure*/
/*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
/*fill in some general sections of the header*/
stack_hdr_init(&cfg.hdr);
/*fill in some general sections of the header*/
stack_hdr_init(&cfg.hdr);
/*fill in the specific fields of the header*/
cfg.hdr.msgType = TCFG;
cfg.hdr.entId.ent = ENTIN;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STGEN;
/*fill in the specific fields of the header*/
cfg.hdr.msgType = TCFG;
cfg.hdr.entId.ent = ENTIN;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STGEN;
/* fill in the Gen Conf structures internal pst struct */
stack_pst_init(&cfg.t.cfg.s.inGen.sm);
/* fill in the Gen Conf structures internal pst struct */
stack_pst_init(&cfg.t.cfg.s.inGen.sm);
cfg.t.cfg.s.inGen.nmbSaps = MAX_VARIANTS+1; /* Total number of variants supported */
@ -538,29 +523,29 @@ ftdm_status_t sng_isdn_stack_cfg_q931_gen(void)
}
/* Link between CC and q931 */
ftdm_status_t sng_isdn_stack_cfg_q931_tsap(ftdm_span_t *span)
ftdm_status_t sngisdn_stack_cfg_q931_tsap(ftdm_span_t *span)
{
InMngmt cfg;
Pst pst;
Pst pst;
unsigned i;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
/* initalize the post structure */
stack_pst_init(&pst);
/* initalize the post structure */
stack_pst_init(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTIN;
/* insert the destination Entity */
pst.dstEnt = ENTIN;
/*clear the configuration structure*/
/*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
/*fill in some general sections of the header*/
stack_hdr_init(&cfg.hdr);
/*fill in some general sections of the header*/
stack_hdr_init(&cfg.hdr);
/*fill in the specific fields of the header*/
cfg.hdr.msgType = TCFG;
cfg.hdr.entId.ent = ENTIN;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STTSAP;
/*fill in the specific fields of the header*/
cfg.hdr.msgType = TCFG;
cfg.hdr.entId.ent = ENTIN;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STTSAP;
cfg.t.cfg.s.inTSAP.sapId = signal_data->cc_id;
@ -601,34 +586,34 @@ ftdm_status_t sng_isdn_stack_cfg_q931_tsap(ftdm_span_t *span)
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
{
InMngmt cfg;
Pst pst;
Pst pst;
unsigned i;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
/* initalize the post structure */
stack_pst_init(&pst);
/* initalize the post structure */
stack_pst_init(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTIN;
/* insert the destination Entity */
pst.dstEnt = ENTIN;
/*clear the configuration structure*/
/*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
/*fill in some general sections of the header*/
stack_hdr_init(&cfg.hdr);
/*fill in some general sections of the header*/
stack_hdr_init(&cfg.hdr);
/*fill in the specific fields of the header*/
cfg.hdr.msgType = TCFG;
cfg.hdr.entId.ent = ENTIN;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STDLSAP;
/*fill in the specific fields of the header*/
cfg.hdr.msgType = TCFG;
cfg.hdr.entId.ent = ENTIN;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STDLSAP;
cfg.hdr.response.selector=0;
cfg.t.cfg.s.inDLSAP.sapId = signal_data->link_id;
cfg.t.cfg.s.inDLSAP.spId = signal_data->link_id;
cfg.t.cfg.s.inDLSAP.swtch = sng_isdn_stack_switchtype(signal_data->switchtype);
@ -674,7 +659,7 @@ ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.ctldInt[1] = 1;
}
cfg.t.cfg.s.inDLSAP.numRstInd = 255;
cfg.t.cfg.s.inDLSAP.numRstInd = 255;
cfg.t.cfg.s.inDLSAP.relOpt = TRUE;
#ifdef ISDN_SRV
cfg.t.cfg.s.inDLSAP.bcas = FALSE;
@ -860,39 +845,39 @@ ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_stack_cfg_q931_lce(ftdm_span_t *span)
ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span)
{
InMngmt cfg;
Pst pst;
Pst pst;
uint8_t i;
uint8_t numCes=1;
uint8_t numCes=1;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP && signal_data->signalling == SNGISDN_SIGNALING_NET) {
numCes = 8;
}
/* initalize the post structure */
stack_pst_init(&pst);
/* initalize the post structure */
stack_pst_init(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTIN;
/* insert the destination Entity */
pst.dstEnt = ENTIN;
/*clear the configuration structure*/
/*clear the configuration structure*/
memset(&cfg, 0, sizeof(cfg));
/*fill in some general sections of the header*/
stack_hdr_init(&cfg.hdr);
/*fill in some general sections of the header*/
stack_hdr_init(&cfg.hdr);
/*fill in the specific fields of the header*/
cfg.hdr.msgType = TCFG;
cfg.hdr.entId.ent = ENTIN;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STDLC;
/*fill in the specific fields of the header*/
cfg.hdr.msgType = TCFG;
cfg.hdr.entId.ent = ENTIN;
cfg.hdr.entId.inst = S_INST;
cfg.hdr.elmId.elmnt = STDLC;
cfg.hdr.response.selector=0;
cfg.t.cfg.s.inLCe.sapId = signal_data->link_id;
cfg.t.cfg.s.inLCe.lnkUpDwnInd = TRUE;
cfg.t.cfg.s.inLCe.tCon.enb = TRUE;
@ -901,7 +886,7 @@ ftdm_status_t sng_isdn_stack_cfg_q931_lce(ftdm_span_t *span)
cfg.t.cfg.s.inLCe.tDisc.val = 35;
cfg.t.cfg.s.inLCe.t314.enb = FALSE; /* if segmentation enabled, set to TRUE */
cfg.t.cfg.s.inLCe.t314.val = 35;
cfg.t.cfg.s.inLCe.t332i.enb = FALSE; /* set to TRUE for NFAS */
#ifdef NFAS
@ -921,7 +906,6 @@ ftdm_status_t sng_isdn_stack_cfg_q931_lce(ftdm_span_t *span)
cfg.t.cfg.s.inLCe.tRstAck.enb = TRUE;
cfg.t.cfg.s.inLCe.tRstAck.val = 10;
cfg.t.cfg.s.inLCe.usid = 0;
cfg.t.cfg.s.inLCe.tid = 0;
@ -936,7 +920,7 @@ ftdm_status_t sng_isdn_stack_cfg_q931_lce(ftdm_span_t *span)
}
ftdm_status_t sng_isdn_stack_cfg_cc_gen(void)
ftdm_status_t sngisdn_stack_cfg_cc_gen(void)
{
CcMngmt cfg;
Pst pst;
@ -975,7 +959,7 @@ ftdm_status_t sng_isdn_stack_cfg_cc_gen(void)
}
ftdm_status_t sng_isdn_stack_cfg_cc_sap(ftdm_span_t *span)
ftdm_status_t sngisdn_stack_cfg_cc_sap(ftdm_span_t *span)
{
CcMngmt cfg;
Pst pst;
@ -1007,11 +991,11 @@ ftdm_status_t sng_isdn_stack_cfg_cc_sap(ftdm_span_t *span)
cfg.t.cfg.s.ccISAP.pst.dstInst = S_INST;
cfg.t.cfg.s.ccISAP.pst.dstProcId = SFndProcId();
cfg.t.cfg.s.ccISAP.pst.prior = PRIOR0;
cfg.t.cfg.s.ccISAP.pst.route = RTESPEC;
cfg.t.cfg.s.ccISAP.pst.region = S_REG;
cfg.t.cfg.s.ccISAP.pst.pool = S_POOL;
cfg.t.cfg.s.ccISAP.pst.selector = 0;
cfg.t.cfg.s.ccISAP.pst.prior = PRIOR0;
cfg.t.cfg.s.ccISAP.pst.route = RTESPEC;
cfg.t.cfg.s.ccISAP.pst.region = S_REG;
cfg.t.cfg.s.ccISAP.pst.pool = S_POOL;
cfg.t.cfg.s.ccISAP.pst.selector = 0;
cfg.t.cfg.s.ccISAP.suId = signal_data->cc_id;
cfg.t.cfg.s.ccISAP.spId = signal_data->cc_id;
@ -1029,19 +1013,19 @@ ftdm_status_t sng_isdn_stack_cfg_cc_sap(ftdm_span_t *span)
void stack_pst_init(Pst *pst)
{
memset(pst, 0, sizeof(Pst));
/*fill in the post structure*/
pst->dstProcId = SFndProcId();
pst->dstInst = S_INST;
/*fill in the post structure*/
pst->dstProcId = SFndProcId();
pst->dstInst = S_INST;
pst->srcProcId = SFndProcId();
pst->srcEnt = ENTSM;
pst->srcInst = S_INST;
pst->srcProcId = SFndProcId();
pst->srcEnt = ENTSM;
pst->srcInst = S_INST;
pst->prior = PRIOR0;
pst->route = RTESPEC;
pst->region = S_REG;
pst->pool = S_POOL;
pst->selector = 0;
pst->prior = PRIOR0;
pst->route = RTESPEC;
pst->region = S_REG;
pst->pool = S_POOL;
pst->selector = 0;
return;
}
@ -1050,21 +1034,21 @@ void stack_pst_init(Pst *pst)
void stack_hdr_init(Header *hdr)
{
hdr->msgType = 0;
hdr->msgLen = 0;
hdr->entId.ent = 0;
hdr->entId.inst = 0;
hdr->elmId.elmnt = 0;
hdr->elmId.elmntInst1 = 0;
hdr->elmId.elmntInst2 = 0;
hdr->elmId.elmntInst3 = 0;
hdr->seqNmb = 0;
hdr->version = 0;
hdr->response.prior = PRIOR0;
hdr->response.route = RTESPEC;
hdr->response.mem.region = S_REG;
hdr->response.mem.pool = S_POOL;
hdr->transId = 0;
hdr->response.selector = 0;
hdr->msgLen = 0;
hdr->entId.ent = 0;
hdr->entId.inst = 0;
hdr->elmId.elmnt = 0;
hdr->elmId.elmntInst1 = 0;
hdr->elmId.elmntInst2 = 0;
hdr->elmId.elmntInst3 = 0;
hdr->seqNmb = 0;
hdr->version = 0;
hdr->response.prior = PRIOR0;
hdr->response.route = RTESPEC;
hdr->response.mem.region = S_REG;
hdr->response.mem.pool = S_POOL;
hdr->transId = 0;
hdr->response.selector = 0;
return;
}

View File

@ -37,27 +37,26 @@
void stack_resp_hdr_init(Header *hdr);
ftdm_status_t sng_isdn_activate_phy(ftdm_span_t *span);
ftdm_status_t sng_isdn_deactivate_phy(ftdm_span_t *span);
ftdm_status_t sngisdn_activate_phy(ftdm_span_t *span);
ftdm_status_t sngisdn_deactivate_phy(ftdm_span_t *span);
ftdm_status_t sng_isdn_activate_cc(ftdm_span_t *span);
ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
ftdm_status_t sngisdn_activate_cc(ftdm_span_t *span);
ftdm_status_t sng_isdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction);
ftdm_status_t sng_isdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction);
ftdm_status_t sngisdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction);
ftdm_status_t sngisdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction);
extern ftdm_sngisdn_data_t g_sngisdn_data;
ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span);
ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span);
ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span)
ftdm_status_t sngisdn_stack_start(ftdm_span_t *span)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
if (sng_isdn_cntrl_q921(span, ABND_ENA, NOTUSED) != FTDM_SUCCESS) {
if (sngisdn_cntrl_q921(span, ABND_ENA, NOTUSED) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack q921\n", span->name);
return FTDM_FAIL;
}
@ -72,7 +71,7 @@ ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span)
ftdm_log(FTDM_LOG_DEBUG, "%s:Stack q921 activated\n", span->name);
if (!g_sngisdn_data.ccs[signal_data->cc_id].activation_done) {
g_sngisdn_data.ccs[signal_data->cc_id].activation_done = 1;
if (sng_isdn_activate_cc(span) != FTDM_SUCCESS) {
if (sngisdn_activate_cc(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack CC\n", span->name);
return FTDM_FAIL;
}
@ -80,7 +79,7 @@ ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span)
}
if (sng_isdn_cntrl_q931(span, ABND_ENA, SAELMNT) != FTDM_SUCCESS) {
if (sngisdn_cntrl_q931(span, ABND_ENA, SAELMNT) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack q931\n", span->name);
return FTDM_FAIL;
}
@ -90,20 +89,20 @@ ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span)
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span)
ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span)
{
/* Stop L1 first, so we do not receive any more frames */
if (sng_isdn_deactivate_phy(span) != FTDM_SUCCESS) {
if (sngisdn_deactivate_phy(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack phy\n", span->name);
return FTDM_FAIL;
}
if (sng_isdn_cntrl_q931(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) {
if (sngisdn_cntrl_q931(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack q931\n", span->name);
return FTDM_FAIL;
}
if (sng_isdn_cntrl_q921(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) {
if (sngisdn_cntrl_q921(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack q921\n", span->name);
return FTDM_FAIL;
}
@ -113,41 +112,7 @@ ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span)
}
ftdm_status_t sng_isdn_wake_up_phy(ftdm_span_t *span)
{
L1Mngmt cntrl;
Pst pst;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
/* initalize the post structure */
stack_pst_init(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTL1;
/* initalize the control structure */
memset(&cntrl, 0, sizeof(cntrl));
/* initalize the control header */
stack_hdr_init(&cntrl.hdr);
cntrl.hdr.msgType = TCNTRL; /* configuration */
cntrl.hdr.entId.ent = ENTL1; /* entity */
cntrl.hdr.entId.inst = S_INST; /* instance */
cntrl.hdr.elmId.elmnt = STTSAP; /* SAP Specific cntrl */
cntrl.t.cntrl.action = AENA;
cntrl.t.cntrl.subAction = SAELMNT;
cntrl.t.cntrl.sapId = signal_data->link_id;
if (sng_isdn_phy_cntrl(&pst, &cntrl)) {
return FTDM_FAIL;
}
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_activate_phy(ftdm_span_t *span)
ftdm_status_t sngisdn_activate_phy(ftdm_span_t *span)
{
/* There is no need to start phy, as it will Q921 will send a activate request to phy when it starts */
@ -155,7 +120,7 @@ ftdm_status_t sng_isdn_activate_phy(ftdm_span_t *span)
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_deactivate_phy(ftdm_span_t *span)
ftdm_status_t sngisdn_deactivate_phy(ftdm_span_t *span)
{
L1Mngmt cntrl;
Pst pst;
@ -189,8 +154,41 @@ ftdm_status_t sng_isdn_deactivate_phy(ftdm_span_t *span)
return FTDM_SUCCESS;
}
ftdm_status_t sngisdn_wake_up_phy(ftdm_span_t *span)
{
L1Mngmt cntrl;
Pst pst;
ftdm_status_t sng_isdn_activate_cc(ftdm_span_t *span)
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
/* initalize the post structure */
stack_pst_init(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTL1;
/* initalize the control structure */
memset(&cntrl, 0, sizeof(cntrl));
/* initalize the control header */
stack_hdr_init(&cntrl.hdr);
cntrl.hdr.msgType = TCNTRL; /* configuration */
cntrl.hdr.entId.ent = ENTL1; /* entity */
cntrl.hdr.entId.inst = S_INST; /* instance */
cntrl.hdr.elmId.elmnt = STTSAP; /* SAP Specific cntrl */
cntrl.t.cntrl.action = AENA;
cntrl.t.cntrl.subAction = SAELMNT;
cntrl.t.cntrl.sapId = signal_data->link_id;
if (sng_isdn_phy_cntrl(&pst, &cntrl)) {
return FTDM_FAIL;
}
return FTDM_SUCCESS;
}
ftdm_status_t sngisdn_activate_cc(ftdm_span_t *span)
{
CcMngmt cntrl;
Pst pst;
@ -224,7 +222,7 @@ ftdm_status_t sng_isdn_activate_cc(ftdm_span_t *span)
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt)
ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
switch (trace_opt) {
@ -233,7 +231,7 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra
ftdm_log(FTDM_LOG_INFO, "s%d Disabling q921 trace\n", signal_data->link_id);
sngisdn_clear_trace_flag(signal_data, SNGISDN_TRACE_Q921);
if (sng_isdn_cntrl_q921(span, ADISIMM, SATRC) != FTDM_SUCCESS) {
if (sngisdn_cntrl_q921(span, ADISIMM, SATRC) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "s%d Failed to disable q921 trace\n");
}
}
@ -241,7 +239,7 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra
ftdm_log(FTDM_LOG_INFO, "s%d Disabling q931 trace\n", signal_data->link_id);
sngisdn_clear_trace_flag(signal_data, SNGISDN_TRACE_Q931);
if (sng_isdn_cntrl_q931(span, ADISIMM, SATRC) != FTDM_SUCCESS) {
if (sngisdn_cntrl_q931(span, ADISIMM, SATRC) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "s%d Failed to disable q931 trace\n");
}
}
@ -251,7 +249,7 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra
ftdm_log(FTDM_LOG_INFO, "s%d Enabling q921 trace\n", signal_data->link_id);
sngisdn_set_trace_flag(signal_data, SNGISDN_TRACE_Q921);
if (sng_isdn_cntrl_q921(span, AENA, SATRC) != FTDM_SUCCESS) {
if (sngisdn_cntrl_q921(span, AENA, SATRC) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "s%d Failed to enable q921 trace\n");
}
}
@ -261,7 +259,7 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra
ftdm_log(FTDM_LOG_INFO, "s%d Enabling q931 trace\n", signal_data->link_id);
sngisdn_set_trace_flag(signal_data, SNGISDN_TRACE_Q931);
if (sng_isdn_cntrl_q931(span, AENA, SATRC) != FTDM_SUCCESS) {
if (sngisdn_cntrl_q931(span, AENA, SATRC) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "s%d Failed to enable q931 trace\n");
}
}
@ -271,7 +269,7 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra
}
ftdm_status_t sng_isdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction)
ftdm_status_t sngisdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction)
{
InMngmt cntrl;
Pst pst;
@ -310,7 +308,7 @@ ftdm_status_t sng_isdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t sub
}
ftdm_status_t sng_isdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction)
ftdm_status_t sngisdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction)
{
BdMngmt cntrl;
Pst pst;

View File

@ -127,10 +127,16 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_channel_add_var(ftdmchan, "isdn_specific_var", "1");
#endif
/* Fill in call information */
cpy_calling_num_from_stack(&ftdmchan->caller_data, &conEvnt->cgPtyNmb);
cpy_called_num_from_stack(&ftdmchan->caller_data, &conEvnt->cdPtyNmb);
cpy_calling_name_from_stack(&ftdmchan->caller_data, &conEvnt->display);
cpy_redir_num_from_stack(&ftdmchan->caller_data, &conEvnt->redirNmb);
get_calling_num(ftdmchan, &conEvnt->cgPtyNmb);
get_called_num(ftdmchan, &conEvnt->cdPtyNmb);
get_redir_num(ftdmchan, &conEvnt->redirNmb);
get_calling_subaddr(ftdmchan, &conEvnt->cgPtySad);
if (get_calling_name_from_display(ftdmchan, &conEvnt->display) != FTDM_SUCCESS) {
get_calling_name_from_usr_usr(ftdmchan, &conEvnt->usrUsr);
}
get_prog_ind_ie(ftdmchan, &conEvnt->progInd);
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Incoming call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits);
if (conEvnt->bearCap[0].eh.pres) {
@ -138,37 +144,43 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
ftdmchan->caller_data.bearer_capability = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].infoTranCap.val);
}
if (signal_data->switchtype == SNGISDN_SWITCH_NI2) {
if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) {
if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) {
snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]);
}
if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) {
if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) {
snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]);
}
if (signal_data->facility == SNGISDN_OPT_TRUE && conEvnt->facilityStr.eh.pres) {
/* Verify whether the Caller Name will come in a subsequent FACILITY message */
uint16_t ret_val;
char retrieved_str[255];
ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str);
/*
return values for "sng_isdn_retrieve_facility_information_following":
If there will be no information following, or fails to decode IE, returns -1
If there will be no information following, but current FACILITY IE contains a caller name, returns 0
If there will be information following, returns 1
*/
}
if (ret_val == 1) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n");
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID);
/* Launch timer in case we never get a FACILITY msg */
if (signal_data->facility_timeout) {
ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout,
sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
if (conEvnt->facilityStr.eh.pres) {
if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) {
get_facility_ie(ftdmchan, &conEvnt->facilityStr);
} else if (signal_data->facility == SNGISDN_OPT_TRUE) {
if (signal_data->switchtype == SNGISDN_SWITCH_NI2) {
/* Verify whether the Caller Name will come in a subsequent FACILITY message */
uint16_t ret_val;
char retrieved_str[255];
ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str);
/*
return values for "sng_isdn_retrieve_facility_information_following":
If there will be no information following, or fails to decode IE, returns -1
If there will be no information following, but current FACILITY IE contains a caller name, returns 0
If there will be information following, returns 1
*/
if (ret_val == 1) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n");
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID);
/* Launch timer in case we never get a FACILITY msg */
if (signal_data->facility_timeout) {
ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout,
sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
}
break;
} else if (ret_val == 0) {
strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
}
break;
} else if (ret_val == 0) {
strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
}
}
}
@ -243,11 +255,9 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
uint8_t ces = sngisdn_event->ces;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt;
/* Function does not require any info from conStEvnt struct for now */
/* CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt; */
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
@ -269,9 +279,11 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_DIALING:
get_prog_ind_ie(ftdmchan, &cnStEvnt->progInd);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
@ -335,9 +347,13 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
suId, suInstId, spInstId, ces);
switch(evntType) {
case MI_CALLPROC:
case MI_PROGRESS:
if (signal_data->switchtype == SNGISDN_SWITCH_NI2 &&
cnStEvnt->causeDgn[0].eh.pres && cnStEvnt->causeDgn[0].causeVal.pres) {
case MI_ALERTING:
get_prog_ind_ie(ftdmchan, &cnStEvnt->progInd);
if (signal_data->ignore_cause_value != SNGISDN_OPT_TRUE &&
cnStEvnt->causeDgn[0].eh.pres && cnStEvnt->causeDgn[0].causeVal.pres) {
switch(cnStEvnt->causeDgn[0].causeVal.val) {
case 17: /* User Busy */
@ -362,22 +378,20 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
goto sngisdn_process_cnst_ind_end;
}
}
/* fall-through */
case MI_ALERTING:
case MI_CALLPROC:
switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_DIALING:
if (evntType == MI_PROGRESS ||
(cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) {
case FTDM_CHANNEL_STATE_DIALING:
case FTDM_CHANNEL_STATE_PROCEED:
if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
} else if (evntType == MI_CALLPROC) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED);
} else {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS:
if (evntType == MI_PROGRESS ||
(cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) {
if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
}
break;
@ -406,7 +420,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_size_t min_digits = ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->min_digits;
ftdm_size_t num_digits;
cpy_called_num_from_stack(&ftdmchan->caller_data, &cnStEvnt->cdPtyNmb);
get_called_num(ftdmchan, &cnStEvnt->cdPtyNmb);
num_digits = strlen(ftdmchan->caller_data.dnis.digits);
if (cnStEvnt->sndCmplt.eh.pres || num_digits >= min_digits) {
@ -417,6 +431,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
}
break;
case FTDM_CHANNEL_STATE_RING:
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_UP:
@ -446,6 +461,7 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event)
uint32_t spInstId = sngisdn_event->spInstId;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
DiscEvnt *discEvnt = &sngisdn_event->event.discEvnt;
@ -454,12 +470,20 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing DISCONNECT (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
switch (ftdmchan->state) {
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_RING:
case FTDM_CHANNEL_STATE_DIALING:
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_UP:
case FTDM_CHANNEL_STATE_UP:
if (discEvnt->facilityStr.eh.pres) {
if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) {
get_facility_ie(ftdmchan, &discEvnt->facilityStr);
} else {
/* Call libsng_isdn facility decode function and copy variables here */
}
}
if (discEvnt->causeDgn[0].eh.pres && discEvnt->causeDgn[0].causeVal.pres) {
ftdmchan->caller_data.hangup_cause = discEvnt->causeDgn[0].causeVal.val;
} else {
@ -503,6 +527,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
uint32_t spInstId = sngisdn_event->spInstId;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
RelEvnt *relEvnt = &sngisdn_event->event.relEvnt;
@ -535,9 +560,10 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
case FTDM_CHANNEL_STATE_DIALING:
/* Remote side rejected our SETUP message on outbound call */
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
sng_isdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
sngisdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
}
/* fall-through */
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_UP:
@ -547,6 +573,15 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
not changed while we were waiting for ftdmchan->mutex by comparing suInstId's */
if (((sngisdn_chan_data_t*)ftdmchan->call_data)->suInstId == suInstId ||
((sngisdn_chan_data_t*)ftdmchan->call_data)->spInstId == spInstId) {
if (relEvnt->facilityStr.eh.pres) {
if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) {
get_facility_ie(ftdmchan, &relEvnt->facilityStr);
} else {
/* Call libsng_isdn facility decode function and copy variables here */
}
}
if (relEvnt->causeDgn[0].eh.pres && relEvnt->causeDgn[0].causeVal.pres) {
ftdmchan->caller_data.hangup_cause = relEvnt->causeDgn[0].causeVal.val;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "cause:%d\n", ftdmchan->caller_data.hangup_cause);
@ -725,15 +760,16 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_GET_CALLERID:
/* Update the caller ID Name */
if (facEvnt->facElmt.facStr.pres) {
char retrieved_str[255];
/* return values for "sng_isdn_retrieve_facility_information_following":
If there will be no information following, or fails to decode IE, returns -1
If there will be no information following, but current FACILITY IE contains a caller name, returns 0
If there will be information following, returns 1
*/
if (sng_isdn_retrieve_facility_caller_name(&facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len, retrieved_str) == 0) {
strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
} else {
@ -751,6 +787,25 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
/* We received the caller ID Name in FACILITY, but its too late, facility-timeout already occurred */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "FACILITY received, but we already proceeded with call\n");
break;
case FTDM_CHANNEL_STATE_UP:
{
ftdm_sigmsg_t sigev;
if (facEvnt->facElmt.facStr.pres) {
if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) {
get_facility_ie_str(ftdmchan, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len);
} else {
/* Call libsng_isdn facility decode function and copy variables here */
}
}
memset(&sigev, 0, sizeof(sigev));
sigev.chan_id = ftdmchan->chan_id;
sigev.span_id = ftdmchan->span_id;
sigev.channel = ftdmchan;
sigev.event_id = FTDM_SIGEVENT_MSG;
ftdm_span_send_signal(ftdmchan->span, &sigev);
}
break;
default:
/* We do not support other FACILITY types for now, so do nothing */
break;
@ -865,6 +920,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T302 Timer expired, proceeding with call\n");
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
break;
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Remote switch expecting OVERLAP receive, but we are already PROCEEDING\n");
@ -882,6 +938,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
break;
case 3:
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
/* T310 timer has expired */
ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;

View File

@ -34,18 +34,12 @@
#include "ftmod_sangoma_isdn.h"
void sngisdn_snd_setup(ftdm_channel_t *ftdmchan);
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan);
void sngisdn_snd_progress(ftdm_channel_t *ftdmchan);
void sngisdn_snd_connect(ftdm_channel_t *ftdmchan);
void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan);
void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare);
void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
{
ConEvnt conEvnt;
ConEvnt conEvnt;
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
ftdm_assert((!sngisdn_info->suInstId && !sngisdn_info->spInstId), "Trying to call out, but call data was not cleared\n");
@ -123,14 +117,6 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
conEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
conEvnt.progInd.eh.pres = PRSNT_NODEF;
conEvnt.progInd.location.pres = PRSNT_NODEF;
conEvnt.progInd.location.val = IN_LOC_USER;
conEvnt.progInd.codeStand0.pres = PRSNT_NODEF;
conEvnt.progInd.codeStand0.val = IN_CSTD_CCITT;
conEvnt.progInd.progDesc.pres = PRSNT_NODEF;
conEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN; /* Not end-to-end ISDN */
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) {
conEvnt.sndCmplt.eh.pres = PRSNT_NODEF;
}
@ -140,10 +126,13 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Outgoing call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits);
cpy_called_num_from_user(&conEvnt.cdPtyNmb, &ftdmchan->caller_data);
cpy_calling_num_from_user(&conEvnt.cgPtyNmb, &ftdmchan->caller_data);
cpy_redir_num_from_user(&conEvnt.redirNmb, &ftdmchan->caller_data);
cpy_calling_name_from_user(&conEvnt, ftdmchan);
set_called_num(ftdmchan, &conEvnt.cdPtyNmb);
set_calling_num(ftdmchan, &conEvnt.cgPtyNmb);
set_calling_subaddr(ftdmchan, &conEvnt.cgPtySad);
set_redir_num(ftdmchan, &conEvnt.redirNmb);
set_calling_name(ftdmchan, &conEvnt);
set_facility_ie(ftdmchan, &conEvnt.facilityStr);
set_prog_ind_ie(ftdmchan, &conEvnt.progInd, prog_ind);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
@ -330,14 +319,14 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan)
return;
}
void sngisdn_snd_progress(ftdm_channel_t *ftdmchan)
void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind)
{
CnStEvnt cnStEvnt;
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending PROGRESS, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
@ -351,14 +340,7 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan)
}
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
cnStEvnt.progInd.eh.pres = PRSNT_NODEF;
cnStEvnt.progInd.location.pres = PRSNT_NODEF;
cnStEvnt.progInd.location.val = IN_LOC_USER;
cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF;
cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT;
cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF;
cnStEvnt.progInd.progDesc.val = IN_PD_IBAVAIL;
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_PROGRESS, signal_data->dchan_id, sngisdn_info->ces)) {
@ -367,14 +349,14 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan)
return;
}
void sngisdn_snd_alert(ftdm_channel_t *ftdmchan)
void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind)
{
CnStEvnt cnStEvnt;
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending ALERT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
@ -383,13 +365,7 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan)
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
cnStEvnt.progInd.eh.pres = PRSNT_NODEF;
cnStEvnt.progInd.location.pres = PRSNT_NODEF;
cnStEvnt.progInd.location.val = IN_LOC_USER;
cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF;
cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT;
cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF;
cnStEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN;
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending ALERT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
@ -401,10 +377,10 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan)
void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
{
CnStEvnt cnStEvnt;
CnStEvnt cnStEvnt;
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending CONNECT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
@ -415,7 +391,6 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
@ -447,14 +422,8 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
cnStEvnt.progInd.eh.pres = PRSNT_NODEF;
cnStEvnt.progInd.location.pres = PRSNT_NODEF;
cnStEvnt.progInd.location.val = IN_LOC_USER;
cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF;
cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT;
cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF;
cnStEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN; /* Not end-to-end ISDN */
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_con_response(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
@ -463,6 +432,32 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
return;
}
void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan)
{
FacEvnt facEvnt;
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending FACILITY, but no call data, ignoring (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
return;
}
memset(&facEvnt, 0, sizeof(facEvnt));
set_facility_ie_str(ftdmchan, &facEvnt.facElmt.facStr.val[2], (ftdm_size_t*)&facEvnt.facElmt.facStr.len);
facEvnt.facElmt.facStr.val[0] = 0x1C;
facEvnt.facElmt.facStr.val[1] = facEvnt.facElmt.facStr.len;
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending FACILITY (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_facility_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &facEvnt, MI_FACIL, signal_data->dchan_id, sngisdn_info->ces)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused FACILITY request\n");
}
return;
}
void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan)
{
@ -517,7 +512,7 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending DISCONNECT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
@ -538,6 +533,8 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
discEvnt.causeDgn[0].recommend.pres = NOTPRSNT;
discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT;
set_facility_ie(ftdmchan, &discEvnt.facilityStr);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
if (sng_isdn_disc_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &discEvnt)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused DISCONNECT request\n");
@ -582,6 +579,8 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
spInstId = sngisdn_info->spInstId;
}
set_facility_ie(ftdmchan, &relEvnt.facilityStr);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, suInstId, spInstId);
if (glare) {
@ -597,6 +596,74 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
}
/* We received an incoming frame on the d-channel, send data to the stack */
void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len)
{
sng_l1_frame_t l1_frame;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) dchan->span->signal_data;
memset(&l1_frame, 0, sizeof(l1_frame));
l1_frame.len = len;
memcpy(&l1_frame.data, data, len);
if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC)) {
l1_frame.flags |= SNG_L1FRAME_ERROR_CRC;
}
if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME)) {
l1_frame.flags |= SNG_L1FRAME_ERROR_FRAME;
}
if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT)) {
l1_frame.flags |= SNG_L1FRAME_ERROR_ABORT;
}
if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO)) {
l1_frame.flags |= SNG_L1FRAME_ERROR_FIFO;
}
if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA)) {
l1_frame.flags |= SNG_L1FRAME_ERROR_DMA;
}
if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)) {
/* Should we trigger congestion here? */
l1_frame.flags |= SNG_L1FRAME_QUEUE_THRES;
}
if (ftdm_test_flag(&(dchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)) {
/* Should we trigger congestion here? */
l1_frame.flags |= SNG_L1FRAME_QUEUE_FULL;
}
sng_isdn_data_ind(signal_data->link_id, &l1_frame);
}
void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event)
{
sng_l1_event_t l1_event;
sngisdn_span_data_t *signal_data = NULL;
memset(&l1_event, 0, sizeof(l1_event));
signal_data = (sngisdn_span_data_t*) dchan->span->signal_data;
switch(event) {
case FTDM_OOB_ALARM_CLEAR:
l1_event.type = SNG_L1EVENT_ALARM_OFF;
sng_isdn_event_ind(signal_data->link_id, &l1_event);
break;
case FTDM_OOB_ALARM_TRAP:
l1_event.type = SNG_L1EVENT_ALARM_ON;
sng_isdn_event_ind(signal_data->link_id, &l1_event);
break;
default:
/* We do not care about the other OOB events for now */
return;
}
return;
}
/* For Emacs:
* Local Variables:

View File

@ -732,7 +732,7 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_UP);
sng_isdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_UP);
sngisdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_UP);
} else {
ftdm_log(FTDM_LOG_WARNING, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
status->t.usta.suId,
@ -741,7 +741,7 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_DOWN);
sng_isdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
sngisdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
}
}
break;
@ -862,6 +862,82 @@ end_of_trace:
return;
}
/* The stacks is wants to transmit a frame */
int16_t sngisdn_rcv_l1_data_req(uint16_t spId, sng_l1_frame_t *l1_frame)
{
ftdm_status_t status;
ftdm_wait_flag_t flags = FTDM_WRITE;
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[spId];
ftdm_size_t length = l1_frame->len;
ftdm_assert(signal_data, "Received Data request on unconfigured span\n");
do {
flags = FTDM_WRITE;
status = signal_data->dchan->fio->wait(signal_data->dchan, &flags, 1000);
if (status != FTDM_SUCCESS) {
ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_WARNING, "transmit timed-out\n");
return -1;
}
if ((flags & FTDM_WRITE)) {
status = signal_data->dchan->fio->write(signal_data->dchan, l1_frame->data, (ftdm_size_t*)&length);
if (status != FTDM_SUCCESS) {
ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_CRIT, "Failed to transmit frame\n");
return -1;
}
break;
/* On WIN32, it is possible for poll to return without FTDM_WRITE flag set, so we try to retransmit */
#ifndef WIN32
} else {
ftdm_log_chan_msg(signal_data->dchan, FTDM_LOG_WARNING, "Failed to poll for d-channel\n");
return -1;
#endif
}
} while(1);
return 0;
}
int16_t sngisdn_rcv_l1_cmd_req(uint16_t spId, sng_l1_cmd_t *l1_cmd)
{
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[spId];
ftdm_assert(signal_data, "Received Data request on unconfigured span\n");
switch(l1_cmd->type) {
case SNG_L1CMD_SET_LINK_STATUS:
{
ftdm_channel_hw_link_status_t status = FTDM_HW_LINK_CONNECTED;
ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_SET_LINK_STATUS, &status);
}
break;
case SNG_L1CMD_GET_LINK_STATUS:
{
ftdm_channel_hw_link_status_t status = 0;
ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_GET_LINK_STATUS, &status);
if (status == FTDM_HW_LINK_CONNECTED) {
l1_cmd->cmd.status = 1;
} else if (status == FTDM_HW_LINK_DISCONNECTED) {
l1_cmd->cmd.status = 0;
} else {
ftdm_log_chan(signal_data->dchan, FTDM_LOG_CRIT, "Invalid link status reported %d\n", status);
l1_cmd->cmd.status = 0;
}
}
break;
case SNG_L1CMD_FLUSH_STATS:
ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_FLUSH_IOSTATS, NULL);
break;
case SNG_L1CMD_FLUSH_BUFFERS:
ftdm_channel_command(signal_data->dchan, FTDM_COMMAND_FLUSH_BUFFERS, NULL);
break;
default:
ftdm_log_chan(signal_data->dchan, FTDM_LOG_CRIT, "Unsupported channel command:%d\n", l1_cmd->type);
return -1;
}
return 0;
}
void sngisdn_rcv_sng_assert(char *message)
{
ftdm_assert(0, message);

View File

@ -33,13 +33,22 @@
*/
#include "ftmod_sangoma_isdn.h"
#define SNGISDN_Q931_FACILITY_IE_ID 0x1C
/* ftmod_sangoma_isdn specific enum look-up functions */
SNGISDN_ENUM_NAMES(SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_STRINGS)
SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr2str, ftdm_sngisdn_progind_descr_t, SNGISDN_PROGIND_DESCR_NAMES, SNGISDN_PROGIND_DESCR_INVALID)
SNGISDN_ENUM_NAMES(SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_STRINGS)
SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t, SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_INVALID)
ftdm_status_t sngisdn_check_free_ids(void);
extern ftdm_sngisdn_data_t g_sngisdn_data;
void get_memory_info(void);
FT_DECLARE(void) clear_call_data(sngisdn_chan_data_t *sngisdn_info)
void clear_call_data(sngisdn_chan_data_t *sngisdn_info)
{
uint32_t cc_id = ((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->cc_id;
@ -56,7 +65,7 @@ FT_DECLARE(void) clear_call_data(sngisdn_chan_data_t *sngisdn_info)
return;
}
FT_DECLARE(void) clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info)
void clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info)
{
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_DEBUG, "Clearing glare data (suId:%d suInstId:%u spInstId:%u actv-suInstId:%u actv-spInstId:%u)\n",
sngisdn_info->glare.suId,
@ -81,7 +90,7 @@ FT_DECLARE(void) clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info)
}
FT_DECLARE(uint32_t) get_unique_suInstId(int16_t cc_id)
uint32_t get_unique_suInstId(int16_t cc_id)
{
uint32_t suInstId;
ftdm_assert_return((cc_id > 0 && cc_id <=MAX_VARIANTS), FTDM_FAIL, "Invalid cc_id\n");
@ -103,7 +112,7 @@ FT_DECLARE(uint32_t) get_unique_suInstId(int16_t cc_id)
return 0;
}
FT_DECLARE(ftdm_status_t) get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data)
ftdm_status_t get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data)
{
ftdm_assert_return((cc_id > 0 && cc_id <=MAX_VARIANTS), FTDM_FAIL, "Invalid cc_id\n");
ftdm_assert_return(g_sngisdn_data.ccs[cc_id].activation_done, FTDM_FAIL, "Trying to find call on unconfigured CC\n");
@ -115,7 +124,7 @@ FT_DECLARE(ftdm_status_t) get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suIns
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data)
ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data)
{
ftdm_assert_return((cc_id > 0 && cc_id <=MAX_VARIANTS), FTDM_FAIL, "Invalid cc_id\n");
ftdm_assert_return(g_sngisdn_data.ccs[cc_id].activation_done, FTDM_FAIL, "Trying to find call on unconfigured CC\n");
@ -127,9 +136,8 @@ FT_DECLARE(ftdm_status_t) get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spIns
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail)
ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail)
{
if (span->trunk_type == FTDM_TRUNK_BRI ||
span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
@ -147,77 +155,84 @@ ftdm_status_t sng_isdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail)
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb)
ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (cgPtyNmb->eh.pres != PRSNT_NODEF) {
return FTDM_FAIL;
}
if (cgPtyNmb->screenInd.pres == PRSNT_NODEF) {
ftdm->screen = cgPtyNmb->screenInd.val;
caller_data->screen = cgPtyNmb->screenInd.val;
}
if (cgPtyNmb->presInd0.pres == PRSNT_NODEF) {
ftdm->pres = cgPtyNmb->presInd0.val;
caller_data->pres = cgPtyNmb->presInd0.val;
}
if (cgPtyNmb->nmbPlanId.pres == PRSNT_NODEF) {
ftdm->cid_num.plan = cgPtyNmb->nmbPlanId.val;
caller_data->cid_num.plan = cgPtyNmb->nmbPlanId.val;
}
if (cgPtyNmb->typeNmb1.pres == PRSNT_NODEF) {
ftdm->cid_num.type = cgPtyNmb->typeNmb1.val;
caller_data->cid_num.type = cgPtyNmb->typeNmb1.val;
}
if (cgPtyNmb->nmbDigits.pres == PRSNT_NODEF) {
ftdm_copy_string(ftdm->cid_num.digits, (const char*)cgPtyNmb->nmbDigits.val, cgPtyNmb->nmbDigits.len+1);
ftdm_copy_string(caller_data->cid_num.digits, (const char*)cgPtyNmb->nmbDigits.val, cgPtyNmb->nmbDigits.len+1);
}
memcpy(&caller_data->ani, &caller_data->cid_num, sizeof(caller_data->ani));
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb)
ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (cdPtyNmb->eh.pres != PRSNT_NODEF) {
return FTDM_FAIL;
}
if (cdPtyNmb->nmbPlanId.pres == PRSNT_NODEF) {
ftdm->dnis.plan = cdPtyNmb->nmbPlanId.val;
caller_data->dnis.plan = cdPtyNmb->nmbPlanId.val;
}
if (cdPtyNmb->typeNmb0.pres == PRSNT_NODEF) {
ftdm->dnis.type = cdPtyNmb->typeNmb0.val;
caller_data->dnis.type = cdPtyNmb->typeNmb0.val;
}
if (cdPtyNmb->nmbDigits.pres == PRSNT_NODEF) {
unsigned i = strlen(ftdm->dnis.digits);
/* In overlap receive mode, append the new digits to the existing dnis */
unsigned i = strlen(caller_data->dnis.digits);
ftdm_copy_string(&ftdm->dnis.digits[i], (const char*)cdPtyNmb->nmbDigits.val, cdPtyNmb->nmbDigits.len+1);
ftdm_copy_string(&caller_data->dnis.digits[i], (const char*)cdPtyNmb->nmbDigits.val, cdPtyNmb->nmbDigits.len+1);
}
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb)
ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (redirNmb->eh.pres != PRSNT_NODEF) {
return FTDM_FAIL;
}
if (redirNmb->nmbPlanId.pres == PRSNT_NODEF) {
ftdm->rdnis.plan = redirNmb->nmbPlanId.val;
caller_data->rdnis.plan = redirNmb->nmbPlanId.val;
}
if (redirNmb->typeNmb.pres == PRSNT_NODEF) {
ftdm->rdnis.type = redirNmb->typeNmb.val;
caller_data->rdnis.type = redirNmb->typeNmb.val;
}
if (redirNmb->nmbDigits.pres == PRSNT_NODEF) {
ftdm_copy_string(ftdm->rdnis.digits, (const char*)redirNmb->nmbDigits.val, redirNmb->nmbDigits.len+1);
ftdm_copy_string(caller_data->rdnis.digits, (const char*)redirNmb->nmbDigits.val, redirNmb->nmbDigits.len+1);
}
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display)
ftdm_status_t get_calling_name_from_display(ftdm_channel_t *ftdmchan, Display *display)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (display->eh.pres != PRSNT_NODEF) {
return FTDM_FAIL;
}
@ -225,71 +240,209 @@ FT_DECLARE(ftdm_status_t) cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm,
return FTDM_FAIL;
}
ftdm_copy_string(ftdm->cid_name, (const char*)display->dispInfo.val, display->dispInfo.len+1);
ftdm_copy_string(caller_data->cid_name, (const char*)display->dispInfo.val, display->dispInfo.len+1);
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm)
ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr)
{
uint8_t len = strlen(ftdm->cid_num.digits);
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (usrUsr->eh.pres != PRSNT_NODEF) {
return FTDM_FAIL;
}
if (usrUsr->protocolDisc.val != PD_IA5) {
return FTDM_FAIL;
}
if (usrUsr->usrInfo.pres != PRSNT_NODEF) {
return FTDM_FAIL;
}
ftdm_copy_string(caller_data->cid_name, (const char*)usrUsr->usrInfo.val, usrUsr->usrInfo.len+1);
return FTDM_SUCCESS;
}
ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
{
char subaddress[100];
if (cgPtySad->eh.pres != PRSNT_NODEF) {
return FTDM_FAIL;
}
memset(subaddress, 0, sizeof(subaddress));
if(cgPtySad->sadInfo.len >= sizeof(subaddress)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Calling Party Subaddress exceeds local size limit (len:%d max:%d)\n", cgPtySad->sadInfo.len, sizeof(subaddress));
cgPtySad->sadInfo.len = sizeof(subaddress)-1;
}
memcpy(subaddress, (char*)cgPtySad->sadInfo.val, cgPtySad->sadInfo.len);
subaddress[cgPtySad->sadInfo.len] = '\0';
ftdm_channel_add_var(ftdmchan, "isdn.calling_subaddr", subaddress);
return FTDM_SUCCESS;
}
ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr)
{
if (!facilityStr->eh.pres) {
return FTDM_FAIL;
}
return get_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, facilityStr->facilityStr.len);
}
ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t data_len)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (data_len > sizeof(caller_data->raw_data)-2) {
ftdm_log(FTDM_LOG_CRIT, "Length of Facility IE exceeds maximum length\n");
return FTDM_FAIL;
}
memset(caller_data->raw_data, 0, sizeof(caller_data->raw_data));
/* Always include Facility IE identifier + len so this can be used as a sanity check by the user */
caller_data->raw_data[0] = SNGISDN_Q931_FACILITY_IE_ID;
caller_data->raw_data[1] = data_len;
memcpy(&caller_data->raw_data[2], data, data_len);
caller_data->raw_data_len = data_len+2;
return FTDM_SUCCESS;
}
ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd)
{
uint8_t val;
if (!progInd->eh.pres) {
return FTDM_FAIL;
}
if (progInd->progDesc.pres) {
switch (progInd->progDesc.val) {
case IN_PD_NOTETEISDN:
val = SNGISDN_PROGIND_DESCR_NETE_ISDN;
break;
case IN_PD_DSTNOTISDN:
val = SNGISDN_PROGIND_DESCR_DEST_NISDN;
break;
case IN_PD_ORGNOTISDN:
val = SNGISDN_PROGIND_DESCR_ORIG_NISDN;
break;
case IN_PD_CALLRET:
val = SNGISDN_PROGIND_DESCR_RET_ISDN;
break;
case IN_PD_DELRESP:
val = SNGISDN_PROGIND_DESCR_SERV_CHANGE;
break;
case IN_PD_IBAVAIL:
val = SNGISDN_PROGIND_DESCR_IB_AVAIL;
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unknown Progress Indicator Description (%d)\n", progInd->progDesc.val);
val = SNGISDN_PROGIND_DESCR_INVALID;
break;
}
ftdm_channel_add_var(ftdmchan, "isdn.prog_ind.descr", ftdm_sngisdn_progind_descr2str(val));
}
if (progInd->location.pres) {
switch (progInd->location.val) {
case IN_LOC_USER:
val = SNGISDN_PROGIND_LOC_USER;
break;
case IN_LOC_PRIVNETLU:
val = SNGISDN_PROGIND_LOC_PRIV_NET_LOCAL_USR;
break;
case IN_LOC_PUBNETLU:
val = SNGISDN_PROGIND_LOC_PUB_NET_LOCAL_USR;
break;
case IN_LOC_TRANNET:
val = SNGISDN_PROGIND_LOC_TRANSIT_NET;
break;
case IN_LOC_PUBNETRU:
val = SNGISDN_PROGIND_LOC_PUB_NET_REMOTE_USR;
break;
case IN_LOC_PRIVNETRU:
val = SNGISDN_PROGIND_LOC_PRIV_NET_REMOTE_USR;
break;
case IN_LOC_NETINTER:
val = SNGISDN_PROGIND_LOC_NET_BEYOND_INTRW;
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Unknown Progress Indicator Location (%d)", progInd->location.val);
val = SNGISDN_PROGIND_LOC_INVALID;
break;
}
ftdm_channel_add_var(ftdmchan, "isdn.prog_ind.loc", ftdm_sngisdn_progind_loc2str(val));
}
return FTDM_SUCCESS;
}
ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
uint8_t len = strlen(caller_data->cid_num.digits);
if (!len) {
return FTDM_SUCCESS;
}
cgPtyNmb->eh.pres = PRSNT_NODEF;
cgPtyNmb->screenInd.pres = PRSNT_NODEF;
cgPtyNmb->screenInd.val = ftdm->screen;
cgPtyNmb->screenInd.val = caller_data->screen;
cgPtyNmb->presInd0.pres = PRSNT_NODEF;
cgPtyNmb->presInd0.val = ftdm->pres;
cgPtyNmb->presInd0.val = caller_data->pres;
cgPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
cgPtyNmb->nmbPlanId.val = ftdm->cid_num.plan;
cgPtyNmb->nmbPlanId.val = caller_data->cid_num.plan;
cgPtyNmb->typeNmb1.pres = PRSNT_NODEF;
cgPtyNmb->typeNmb1.val = ftdm->cid_num.type;
cgPtyNmb->typeNmb1.val = caller_data->cid_num.type;
cgPtyNmb->nmbDigits.pres = PRSNT_NODEF;
cgPtyNmb->nmbDigits.len = len;
memcpy(cgPtyNmb->nmbDigits.val, ftdm->cid_num.digits, len);
memcpy(cgPtyNmb->nmbDigits.val, caller_data->cid_num.digits, len);
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm)
ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb)
{
uint8_t len = strlen(ftdm->dnis.digits);
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
uint8_t len = strlen(caller_data->dnis.digits);
if (!len) {
return FTDM_SUCCESS;
}
cdPtyNmb->eh.pres = PRSNT_NODEF;
cdPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
if (ftdm->dnis.plan == FTDM_NPI_INVALID) {
if (caller_data->dnis.plan == FTDM_NPI_INVALID) {
cdPtyNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN;
} else {
cdPtyNmb->nmbPlanId.val = ftdm->dnis.plan;
cdPtyNmb->nmbPlanId.val = caller_data->dnis.plan;
}
cdPtyNmb->typeNmb0.pres = PRSNT_NODEF;
if (ftdm->dnis.type == FTDM_TON_INVALID) {
if (caller_data->dnis.type == FTDM_TON_INVALID) {
cdPtyNmb->typeNmb0.val = FTDM_TON_UNKNOWN;
} else {
cdPtyNmb->typeNmb0.val = ftdm->dnis.type;
cdPtyNmb->typeNmb0.val = caller_data->dnis.type;
}
cdPtyNmb->nmbDigits.pres = PRSNT_NODEF;
cdPtyNmb->nmbDigits.len = len;
memcpy(cdPtyNmb->nmbDigits.val, ftdm->dnis.digits, len);
memcpy(cdPtyNmb->nmbDigits.val, caller_data->dnis.digits, len);
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm)
ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb)
{
uint8_t len = strlen(ftdm->rdnis.digits);
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
uint8_t len = strlen(caller_data->rdnis.digits);
if (!len) {
return FTDM_SUCCESS;
}
@ -297,36 +450,36 @@ FT_DECLARE(ftdm_status_t) cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_calle
redirNmb->eh.pres = PRSNT_NODEF;
redirNmb->nmbPlanId.pres = PRSNT_NODEF;
if (ftdm->rdnis.plan == FTDM_NPI_INVALID) {
if (caller_data->rdnis.plan == FTDM_NPI_INVALID) {
redirNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN;
} else {
redirNmb->nmbPlanId.val = ftdm->rdnis.plan;
redirNmb->nmbPlanId.val = caller_data->rdnis.plan;
}
redirNmb->typeNmb.pres = PRSNT_NODEF;
if (ftdm->rdnis.type == FTDM_TON_INVALID) {
if (caller_data->rdnis.type == FTDM_TON_INVALID) {
redirNmb->typeNmb.val = FTDM_TON_UNKNOWN;
} else {
redirNmb->typeNmb.val = ftdm->rdnis.type;
redirNmb->typeNmb.val = caller_data->rdnis.type;
}
redirNmb->nmbDigits.pres = PRSNT_NODEF;
redirNmb->nmbDigits.len = len;
memcpy(redirNmb->nmbDigits.val, ftdm->rdnis.digits, len);
memcpy(redirNmb->nmbDigits.val, caller_data->rdnis.digits, len);
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan)
ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt)
{
uint8_t len;
ftdm_caller_data_t *ftdm = &ftdmchan->caller_data;
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
/* sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; */
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
len = strlen(ftdm->cid_name);
len = strlen(caller_data->cid_name);
if (!len) {
return FTDM_SUCCESS;
}
@ -341,7 +494,7 @@ FT_DECLARE(ftdm_status_t) cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_chan
conEvnt->usrUsr.usrInfo.len = len;
/* in sangoma_brid we used to send usr-usr info as <cid_name>!<calling_number>,
change to previous style if current one does not work */
memcpy(conEvnt->usrUsr.usrInfo.val, ftdm->cid_name, len);
memcpy(conEvnt->usrUsr.usrInfo.val, caller_data->cid_name, len);
} else {
switch (signal_data->switchtype) {
case SNGISDN_SWITCH_NI2:
@ -359,7 +512,7 @@ FT_DECLARE(ftdm_status_t) cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_chan
conEvnt->display.eh.pres = PRSNT_NODEF;
conEvnt->display.dispInfo.pres = PRSNT_NODEF;
conEvnt->display.dispInfo.len = len;
memcpy(conEvnt->display.dispInfo.val, ftdm->cid_name, len);
memcpy(conEvnt->display.dispInfo.val, caller_data->cid_name, len);
break;
case SNGISDN_SWITCH_QSIG:
/* It seems like QSIG does not support Caller ID Name */
@ -372,6 +525,139 @@ FT_DECLARE(ftdm_status_t) cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_chan
return FTDM_SUCCESS;
}
ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
{
const char* clg_subaddr = NULL;
clg_subaddr = ftdm_channel_get_var(ftdmchan, "isdn.calling_subaddr");
if ((clg_subaddr != NULL) && (*clg_subaddr)) {
unsigned len = strlen (clg_subaddr);
cgPtySad->eh.pres = PRSNT_NODEF;
cgPtySad->typeSad.pres = 1;
cgPtySad->typeSad.val = 0; /* NSAP */
cgPtySad->oddEvenInd.pres = 1;
cgPtySad->oddEvenInd.val = 0;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Calling Party Subaddress:%s\n", clg_subaddr);
cgPtySad->sadInfo.pres = 1;
cgPtySad->sadInfo.len = len;
memcpy(cgPtySad->sadInfo.val, clg_subaddr, len);
}
return FTDM_SUCCESS;
}
ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr)
{
ftdm_status_t status;
status = set_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, (ftdm_size_t*)&facilityStr->facilityStr.len);
if (status == FTDM_SUCCESS) {
facilityStr->eh.pres = PRSNT_NODEF;
facilityStr->facilityStr.pres = PRSNT_NODEF;
}
return status;
}
ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t *data_len)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (caller_data->raw_data_len > 0 && caller_data->raw_data[0] == SNGISDN_Q931_FACILITY_IE_ID) {
*data_len = caller_data->raw_data[1];
memcpy(data, &caller_data->raw_data[2], *data_len);
return FTDM_SUCCESS;
}
return FTDM_FAIL;
}
ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind)
{
const char *str = NULL;
int descr = prog_ind.descr;
int loc = prog_ind.loc;
str = ftdm_channel_get_var(ftdmchan, "isdn.prog_ind.descr");
if (str && *str) {
/* User wants to override progress indicator */
descr = ftdm_str2ftdm_sngisdn_progind_descr(str);
}
if (descr == SNGISDN_PROGIND_DESCR_INVALID) {
/* User does not want to send progress indicator */
return FTDM_SUCCESS;
}
str = ftdm_channel_get_var(ftdmchan, "isdn.prog_ind.loc");
if (str && *str) {
loc = ftdm_str2ftdm_sngisdn_progind_loc(str);
}
if (loc == SNGISDN_PROGIND_LOC_INVALID) {
loc = SNGISDN_PROGIND_LOC_USER;
}
progInd->eh.pres = PRSNT_NODEF;
progInd->codeStand0.pres = PRSNT_NODEF;
progInd->codeStand0.val = IN_CSTD_CCITT;
progInd->progDesc.pres = PRSNT_NODEF;
switch(descr) {
case SNGISDN_PROGIND_DESCR_NETE_ISDN:
progInd->progDesc.val = IN_PD_NOTETEISDN;
break;
case SNGISDN_PROGIND_DESCR_DEST_NISDN:
progInd->progDesc.val = IN_PD_DSTNOTISDN;
break;
case SNGISDN_PROGIND_DESCR_ORIG_NISDN:
progInd->progDesc.val = IN_PD_ORGNOTISDN;
break;
case SNGISDN_PROGIND_DESCR_RET_ISDN:
progInd->progDesc.val = IN_PD_CALLRET;
break;
case SNGISDN_PROGIND_DESCR_SERV_CHANGE:
/* Trillium defines do not match ITU-T Q931 Progress descriptions,
indicate a delayed response for now */
progInd->progDesc.val = IN_PD_DELRESP;
break;
case SNGISDN_PROGIND_DESCR_IB_AVAIL:
progInd->progDesc.val = IN_PD_IBAVAIL;
break;
default:
ftdm_log(FTDM_LOG_WARNING, "Invalid prog_ind description:%d\n", descr);
progInd->progDesc.val = IN_PD_NOTETEISDN;
break;
}
progInd->location.pres = PRSNT_NODEF;
switch (loc) {
case SNGISDN_PROGIND_LOC_USER:
progInd->location.val = IN_LOC_USER;
break;
case SNGISDN_PROGIND_LOC_PRIV_NET_LOCAL_USR:
progInd->location.val = IN_LOC_PRIVNETLU;
break;
case SNGISDN_PROGIND_LOC_PUB_NET_LOCAL_USR:
progInd->location.val = IN_LOC_PUBNETLU;
break;
case SNGISDN_PROGIND_LOC_TRANSIT_NET:
progInd->location.val = IN_LOC_TRANNET;
break;
case SNGISDN_PROGIND_LOC_PUB_NET_REMOTE_USR:
progInd->location.val = IN_LOC_PUBNETRU;
break;
case SNGISDN_PROGIND_LOC_PRIV_NET_REMOTE_USR:
progInd->location.val = IN_LOC_PRIVNETRU;
break;
case SNGISDN_PROGIND_LOC_NET_BEYOND_INTRW:
progInd->location.val = IN_LOC_NETINTER;
break;
default:
ftdm_log(FTDM_LOG_WARNING, "Invalid prog_ind location:%d\n", loc);
progInd->location.val = IN_PD_NOTETEISDN;
}
return FTDM_SUCCESS;
}
void sngisdn_t3_timeout(void* p_sngisdn_info)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
@ -394,6 +680,17 @@ void sngisdn_t3_timeout(void* p_sngisdn_info)
ftdm_mutex_unlock(ftdmchan->mutex);
}
void sngisdn_delayed_setup(void* p_sngisdn_info)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
ftdm_mutex_lock(ftdmchan->mutex);
sngisdn_snd_setup(ftdmchan);
ftdm_mutex_unlock(ftdmchan->mutex);
return;
}
void sngisdn_delayed_release(void* p_sngisdn_info)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
@ -517,13 +814,12 @@ uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability)
switch(bearer_capability) {
case FTDM_BEARER_CAP_SPEECH:
return IN_ITC_SPEECH;
case FTDM_BEARER_CAP_64K_UNRESTRICTED:
return IN_ITC_UNRDIG;
case FTDM_BEARER_CAP_3_1KHZ_AUDIO:
return IN_ITC_A31KHZ;
case FTDM_BEARER_CAP_INVALID:
return IN_ITC_SPEECH;
/* Do not put a default case here, so we can see compile warnings if we have unhandled cases */
}
return FTDM_BEARER_CAP_SPEECH;
@ -534,13 +830,12 @@ uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_pr
switch(layer1_prot) {
case FTDM_USER_LAYER1_PROT_V110:
return IN_UIL1_CCITTV110;
case FTDM_USER_LAYER1_PROT_ULAW:
return IN_UIL1_G711ULAW;
case FTDM_USER_LAYER1_PROT_ALAW:
return IN_UIL1_G711ALAW;
case FTDM_USER_LAYER1_PROT_INVALID:
return IN_UIL1_G711ULAW;
/* Do not put a default case here, so we can see compile warnings if we have unhandled cases */
}
return IN_UIL1_G711ULAW;

View File

@ -613,6 +613,21 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
return 0;
break;
case PROT_Q931_IE_CALLED_PARTY_SUBADDRESS:
{
uint8_t type;
uint8_t currentOct, j=0;
char calling_subaddr_string[82];
memset(calling_subaddr_string, 0, sizeof(calling_subaddr_string));
type = get_bits(OCTET(3),5,7);
currentOct = 3;
while(currentOct++ <= len+1) {
calling_subaddr_string[j++]=ia5[get_bits(OCTET(currentOct),1,4)][get_bits(OCTET(currentOct),5,8)];
}
calling_subaddr_string[j++]='\0';
*str_len += sprintf(&str[*str_len], "%s (l:%d) type:%s(%d) \n",
calling_subaddr_string, (j-1), get_code_2_str(type, dcodQ931TypeOfSubaddressTable), type);
}
break;
case PROT_Q931_IE_REDIRECTION_NUMBER:
case PROT_Q931_IE_NOTIFICATION_IND:
case PROT_Q931_IE_DATE_TIME:

View File

@ -544,5 +544,11 @@ struct code2str dcodQ931GenDigitsTypeTable[] = {
{-1, "Invalid"},
};
struct code2str dcodQ931TypeOfSubaddressTable[] = {
{ 0x00, "NSAP"},
{ 0x02, "User-specified"},
{ -1, "Invalid"},
};
#endif /* __FTMOD_SANGOMA_ISDN_TRACE_H__ */

View File

@ -115,12 +115,16 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_next_event);
static __inline__ int tdmv_api_wait_socket(ftdm_channel_t *ftdmchan, int timeout, int *flags)
{
#ifdef LIBSANGOMA_VERSION
#ifdef LIBSANGOMA_VERSION
int err;
uint32_t inflags = *flags;
uint32_t outflags = 0;
sangoma_wait_obj_t *sangoma_wait_obj = ftdmchan->io_data;
if (timeout == -1) {
timeout = SANGOMA_WAIT_INFINITE;
}
err = sangoma_waitfor(sangoma_wait_obj, inflags, &outflags, timeout);
*flags = 0;
if (err == SANG_STATUS_SUCCESS) {
@ -169,7 +173,7 @@ static __inline__ sng_fd_t tdmv_api_open_span_chan(int span, int chan)
static __inline__ sng_fd_t __tdmv_api_open_span_chan(int span, int chan)
{
return __sangoma_open_tdmapi_span_chan(span, chan);
}
}
#endif
static ftdm_io_interface_t wanpipe_interface;
@ -333,8 +337,8 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
ftdm_log(FTDM_LOG_ERROR, "Failed to enable RBS/CAS events in device %d:%d fd:%d\n", chan->span_id, chan->chan_id, sockfd);
continue;
}
/* probably done by the driver but lets write defensive code this time */
sangoma_flush_bufs(chan->sockfd, &tdm_api);
sangoma_flush_event_bufs(chan->sockfd, &tdm_api);
#else
/*
* With wanpipe 3.4.4.2 I get failure even though the events are enabled, /var/log/messages said:
@ -513,10 +517,10 @@ static FIO_OPEN_FUNCTION(wanpipe_open)
wanpipe_tdm_api_t tdm_api;
memset(&tdm_api,0,sizeof(tdm_api));
sangoma_tdm_flush_bufs(ftdmchan->sockfd, &tdm_api);
#ifdef LIBSANGOMA_VERSION
sangoma_flush_event_bufs(ftdmchan->sockfd, &tdm_api);
#endif
sangoma_flush_stats(ftdmchan->sockfd, &tdm_api);
memset(&ftdmchan->iostats, 0, sizeof(ftdmchan->iostats));
if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921 || ftdmchan->type == FTDM_CHAN_TYPE_DQ931) {
ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE;
@ -745,6 +749,29 @@ static FIO_COMMAND_FUNCTION(wanpipe_command)
}
}
break;
case FTDM_COMMAND_FLUSH_BUFFERS:
{
err = sangoma_flush_bufs(ftdmchan->sockfd, &tdm_api);
}
break;
case FTDM_COMMAND_FLUSH_IOSTATS:
{
err = sangoma_flush_stats(ftdmchan->sockfd, &tdm_api);
memset(&ftdmchan->iostats, 0, sizeof(ftdmchan->iostats));
}
break;
case FTDM_COMMAND_SET_RX_QUEUE_SIZE:
{
uint32_t queue_size = FTDM_COMMAND_OBJ_INT;
err = sangoma_set_rx_queue_sz(ftdmchan->sockfd, &tdm_api, queue_size);
}
break;
case FTDM_COMMAND_SET_TX_QUEUE_SIZE:
{
uint32_t queue_size = FTDM_COMMAND_OBJ_INT;
err = sangoma_set_tx_queue_sz(ftdmchan->sockfd, &tdm_api, queue_size);
}
break;
default:
break;
};
@ -758,6 +785,106 @@ static FIO_COMMAND_FUNCTION(wanpipe_command)
return FTDM_SUCCESS;
}
static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *tx_stats)
{
ftdmchan->iostats.tx.errors = tx_stats->wp_api_tx_hdr_errors;
ftdmchan->iostats.tx.queue_size = tx_stats->wp_api_tx_hdr_max_queue_length;
ftdmchan->iostats.tx.queue_len = tx_stats->wp_api_tx_hdr_number_of_frames_in_queue;
/* we don't test for 80% full in tx since is typically full for voice channels, should we test tx 80% full for D-channels? */
if (ftdmchan->iostats.tx.queue_len >= ftdmchan->iostats.tx.queue_size) {
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Tx Queue Full (%d/%d)\n",
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.tx.queue_size);
ftdm_set_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
} else if (ftdm_test_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Tx Queue no longer full (%d/%d)\n",
ftdmchan->iostats.tx.queue_len, ftdmchan->iostats.tx.queue_size);
ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
}
if (ftdmchan->iostats.tx.idle_packets < tx_stats->wp_api_tx_hdr_number_of_frames_in_queue) {
ftdmchan->iostats.tx.idle_packets = tx_stats->wp_api_tx_hdr_tx_idle_packets;
/* HDLC channels do not always transmit, so its ok for drivers to fill with idle */
if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx idle: %d\n", ftdmchan->iostats.tx.idle_packets);
}
}
if (!ftdmchan->iostats.tx.packets) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet write stats: Tx queue len: %d, Tx queue size: %d, Tx idle: %d\n",
ftdmchan->iostats.tx.queue_len,
ftdmchan->iostats.tx.queue_size,
ftdmchan->iostats.tx.idle_packets);
}
ftdmchan->iostats.tx.packets++;
}
static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx_stats)
{
ftdmchan->iostats.rx.errors = rx_stats->wp_api_rx_hdr_errors;
ftdmchan->iostats.rx.queue_size = rx_stats->wp_api_rx_hdr_max_queue_length;
ftdmchan->iostats.rx.queue_len = rx_stats->wp_api_rx_hdr_number_of_frames_in_queue;
if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_ABORT_ERROR_BIT))) {
ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT);
} else {
ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_ABORT);
}
if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_DMA_ERROR_BIT))) {
ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA);
} else {
ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_DMA);
}
if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_FIFO_ERROR_BIT))) {
ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO);
} else {
ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FIFO);
}
if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_CRC_ERROR_BIT))) {
ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC);
} else {
ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_CRC);
}
if ((rx_stats->wp_api_rx_hdr_error_map & (1 << WP_FRAME_ERROR_BIT))) {
ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME);
} else {
ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_FRAME);
}
if (ftdmchan->iostats.rx.queue_len >= (0.8 * ftdmchan->iostats.rx.queue_size)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded 80% threshold (%d/%d)\n",
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES);
} else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){
/* any reason we have wanpipe_tdm_api_iface.h in ftmod_wanpipe/ dir? */
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue length reduced 80% threshold (%d/%d)\n",
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES);
}
if (ftdmchan->iostats.rx.queue_len >= ftdmchan->iostats.rx.queue_size) {
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Rx Queue Full (%d/%d)\n",
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
} else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue no longer full (%d/%d)\n",
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
}
if (!ftdmchan->iostats.rx.packets) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "First packet read stats: Rx queue len: %d, Rx queue size: %d\n",
ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size);
}
ftdmchan->iostats.rx.packets++;
}
/**
* \brief Reads data from a Wanpipe channel
* \param ftdmchan Channel to read from
@ -786,9 +913,11 @@ static FIO_READ_FUNCTION(wanpipe_read)
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno));
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read from sangoma device: %s (%d)\n", strerror(errno), rx_len);
return FTDM_FAIL;
}
}
if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS)) {
wanpipe_read_stats(ftdmchan, &hdrframe);
}
return FTDM_SUCCESS;
}
@ -814,6 +943,9 @@ static FIO_WRITE_FUNCTION(wanpipe_write)
/* should we be checking if bsent == *datalen here? */
if (bsent > 0) {
*datalen = bsent;
if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS)) {
wanpipe_write_stats(ftdmchan, &hdrframe);
}
return FTDM_SUCCESS;
}

View File

@ -1,196 +0,0 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="ftmod_wanpipe"
ProjectGUID="{1A145EE9-BBD8-45E5-98CD-EB4BE99E1DCD}"
RootNamespace="ftmod_wanpipe"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../../../src/include;../../../src/isdn/include;../../../wanpipe/include"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="freetdm.lib libsangoma.lib"
LinkIncremental="2"
AdditionalLibraryDirectories="&quot;$(OutDir)&quot;;../../../wanpipe/api/lib/x86"
GenerateDebugInformation="true"
SubSystem="1"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../../../src/include;../../../src/isdn/include;../../../wanpipe/include"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="freetdm.lib libsangoma.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="&quot;$(OutDir)&quot;;../../../wanpipe/api/lib/x86"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="0"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\ftmod_wanpipe.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@ -1,351 +0,0 @@
/*****************************************************************************
* wanpipe_tdm_api_iface.h
*
* WANPIPE(tm) AFT TE1 Hardware Support
*
* Authors: Nenad Corbic <ncorbic@sangoma.com>
*
* Copyright (c) 2007 - 08, Sangoma Technologies
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the <organization> nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY <copyright holder> ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ============================================================================
* Oct 04, 2005 Nenad Corbic Initial version.
*
* Jul 25, 2006 David Rokhvarg <davidr@sangoma.com> Ported to Windows.
*****************************************************************************/
#ifndef __WANPIPE_TDM_API_IFACE_H_
#define __WANPIPE_TDM_API_IFACE_H_
#if defined(__WINDOWS__)
typedef HANDLE sng_fd_t;
#else
typedef int sng_fd_t;
#endif
/* Indicate to library that new features exist */
#define WP_TDM_FEATURE_DTMF_EVENTS 1
#define WP_TDM_FEATURE_FE_ALARM 1
#define WP_TDM_FEATURE_EVENTS 1
#define WP_TDM_FEATURE_LINK_STATUS 1
enum wanpipe_tdm_api_cmds {
SIOC_WP_TDM_GET_USR_MTU_MRU, /* 0x00 */
SIOC_WP_TDM_SET_USR_PERIOD, /* 0x01 */
SIOC_WP_TDM_GET_USR_PERIOD, /* 0x02 */
SIOC_WP_TDM_SET_HW_MTU_MRU, /* 0x03 */
SIOC_WP_TDM_GET_HW_MTU_MRU, /* 0x04 */
SIOC_WP_TDM_SET_CODEC, /* 0x05 */
SIOC_WP_TDM_GET_CODEC, /* 0x06 */
SIOC_WP_TDM_SET_POWER_LEVEL, /* 0x07 */
SIOC_WP_TDM_GET_POWER_LEVEL, /* 0x08 */
SIOC_WP_TDM_TOGGLE_RX, /* 0x09 */
SIOC_WP_TDM_TOGGLE_TX, /* 0x0A */
SIOC_WP_TDM_GET_HW_CODING, /* 0x0B */
SIOC_WP_TDM_SET_HW_CODING, /* 0x0C */
SIOC_WP_TDM_GET_FULL_CFG, /* 0x0D */
SIOC_WP_TDM_SET_EC_TAP, /* 0x0E */
SIOC_WP_TDM_GET_EC_TAP, /* 0x0F */
SIOC_WP_TDM_ENABLE_RBS_EVENTS, /* 0x10 */
SIOC_WP_TDM_DISABLE_RBS_EVENTS, /* 0x11 */
SIOC_WP_TDM_WRITE_RBS_BITS, /* 0x12 */
SIOC_WP_TDM_GET_STATS, /* 0x13 */
SIOC_WP_TDM_FLUSH_BUFFERS, /* 0x14 */
SIOC_WP_TDM_READ_EVENT, /* 0x15 */
SIOC_WP_TDM_SET_EVENT, /* 0x16 */
SIOC_WP_TDM_SET_RX_GAINS, /* 0x17 */
SIOC_WP_TDM_SET_TX_GAINS, /* 0x18 */
SIOC_WP_TDM_CLEAR_RX_GAINS, /* 0x19 */
SIOC_WP_TDM_CLEAR_TX_GAINS, /* 0x1A */
SIOC_WP_TDM_GET_FE_ALARMS, /* 0x1B */
SIOC_WP_TDM_ENABLE_HWEC, /* 0x1C */
SIOC_WP_TDM_DISABLE_HWEC, /* 0x1D */
SIOC_WP_TDM_SET_FE_STATUS, /* 0x1E */
SIOC_WP_TDM_GET_FE_STATUS, /* 0x1F */
SIOC_WP_TDM_GET_HW_DTMF, /* 0x20 */
SIOC_WP_TDM_NOTSUPP /* */
};
#define SIOC_WP_TDM_GET_LINK_STATUS SIOC_WP_TDM_GET_FE_STATUS
enum wanpipe_tdm_api_events {
WP_TDMAPI_EVENT_NONE,
WP_TDMAPI_EVENT_RBS,
WP_TDMAPI_EVENT_ALARM,
WP_TDMAPI_EVENT_DTMF,
WP_TDMAPI_EVENT_RM_DTMF,
WP_TDMAPI_EVENT_RXHOOK,
WP_TDMAPI_EVENT_RING,
WP_TDMAPI_EVENT_RING_DETECT,
WP_TDMAPI_EVENT_RING_TRIP_DETECT,
WP_TDMAPI_EVENT_TONE,
WP_TDMAPI_EVENT_TXSIG_KEWL,
WP_TDMAPI_EVENT_TXSIG_START,
WP_TDMAPI_EVENT_TXSIG_OFFHOOK,
WP_TDMAPI_EVENT_TXSIG_ONHOOK,
WP_TDMAPI_EVENT_ONHOOKTRANSFER,
WP_TDMAPI_EVENT_SETPOLARITY,
WP_TDMAPI_EVENT_BRI_CHAN_LOOPBACK,
WP_TDMAPI_EVENT_LINK_STATUS
};
#define WP_TDMAPI_EVENT_FE_ALARM WP_TDMAPI_EVENT_ALARM
#define WP_TDMAPI_EVENT_ENABLE 0x01
#define WP_TDMAPI_EVENT_DISABLE 0x02
#define WP_TDMAPI_EVENT_MODE_DECODE(mode) \
((mode) == WP_TDMAPI_EVENT_ENABLE) ? "Enable" : \
((mode) == WP_TDMAPI_EVENT_DISABLE) ? "Disable" : \
"(Unknown mode)"
#define WPTDM_A_BIT WAN_RBS_SIG_A
#define WPTDM_B_BIT WAN_RBS_SIG_B
#define WPTDM_C_BIT WAN_RBS_SIG_C
#define WPTDM_D_BIT WAN_RBS_SIG_D
#define WP_TDMAPI_EVENT_RXHOOK_OFF 0x01
#define WP_TDMAPI_EVENT_RXHOOK_ON 0x02
#define WP_TDMAPI_EVENT_RXHOOK_DECODE(state) \
((state) == WP_TDMAPI_EVENT_RXHOOK_OFF) ? "Off-hook" : \
((state) == WP_TDMAPI_EVENT_RXHOOK_ON) ? "On-hook" : \
"(Unknown state)"
#define WP_TDMAPI_EVENT_RING_PRESENT 0x01
#define WP_TDMAPI_EVENT_RING_STOP 0x02
#define WP_TDMAPI_EVENT_RING_DECODE(state) \
((state) == WP_TDMAPI_EVENT_RING_PRESENT) ? "Ring Present" : \
((state) == WP_TDMAPI_EVENT_RING_STOP) ? "Ring Stop" : \
"(Unknown state)"
#define WP_TDMAPI_EVENT_RING_TRIP_PRESENT 0x01
#define WP_TDMAPI_EVENT_RING_TRIP_STOP 0x02
#define WP_TDMAPI_EVENT_RING_TRIP_DECODE(state) \
((state) == WP_TDMAPI_EVENT_RING_TRIP_PRESENT) ? "Ring Present" : \
((state) == WP_TDMAPI_EVENT_RING_TRIP_STOP) ? "Ring Stop" : \
"(Unknown state)"
/*Link Status */
#define WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED 0x01
#define WP_TDMAPI_EVENT_LINK_STATUS_DISCONNECTED 0x02
#define WP_TDMAPI_EVENT_LINK_STATUS_DECODE(status) \
((status) == WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED) ? "Connected" : \
((status) == WP_TDMAPI_EVENT_LINK_STATUS_DISCONNECTED) ? "Disconnected" : \
"Unknown"
#define WP_TDMAPI_EVENT_TONE_DIAL 0x01
#define WP_TDMAPI_EVENT_TONE_BUSY 0x02
#define WP_TDMAPI_EVENT_TONE_RING 0x03
#define WP_TDMAPI_EVENT_TONE_CONGESTION 0x04
/* BRI channels list */
#define WAN_BRI_BCHAN1 0x01
#define WAN_BRI_BCHAN2 0x02
#define WAN_BRI_DCHAN 0x03
typedef struct {
u_int8_t type;
u_int8_t mode;
u_int32_t time_stamp;
u_int8_t channel;
u_int32_t chan_map;
u_int8_t span;
union {
struct {
u_int8_t alarm;
} te1_alarm;
struct {
u_int8_t rbs_bits;
} te1_rbs;
struct {
u_int8_t state;
u_int8_t sig;
} rm_hook;
struct {
u_int8_t state;
} rm_ring;
struct {
u_int8_t type;
} rm_tone;
struct {
u_int8_t digit; /* DTMF: digit */
u_int8_t port; /* DTMF: SOUT/ROUT */
u_int8_t type; /* DTMF: PRESET/STOP */
} dtmf;
struct {
u_int16_t polarity;
u_int16_t ohttimer;
} rm_common;
struct{
u_int16_t status;
} linkstatus;
} wp_tdm_api_event_u;
#define wp_tdm_api_event_type type
#define wp_tdm_api_event_mode mode
#define wp_tdm_api_event_alarm wp_tdm_api_event_u.te1_alarm.alarm
#define wp_tdm_api_event_alarm wp_tdm_api_event_u.te1_alarm.alarm
#define wp_tdm_api_event_rbs_bits wp_tdm_api_event_u.te1_rbs.rbs_bits
#define wp_tdm_api_event_hook_state wp_tdm_api_event_u.rm_hook.state
#define wp_tdm_api_event_hook_sig wp_tdm_api_event_u.rm_hook.sig
#define wp_tdm_api_event_ring_state wp_tdm_api_event_u.rm_ring.state
#define wp_tdm_api_event_tone_type wp_tdm_api_event_u.rm_tone.type
#define wp_tdm_api_event_dtmf_digit wp_tdm_api_event_u.dtmf.digit
#define wp_tdm_api_event_dtmf_type wp_tdm_api_event_u.dtmf.type
#define wp_tdm_api_event_dtmf_port wp_tdm_api_event_u.dtmf.port
#define wp_tdm_api_event_ohttimer wp_tdm_api_event_u.rm_common.ohttimer
#define wp_tdm_api_event_polarity wp_tdm_api_event_u.rm_common.polarity
#define wp_tdm_api_event_link_status wp_tdm_api_event_u.linkstatus.status
} wp_tdm_api_event_t;
typedef struct {
union {
unsigned char reserved[16];
}wp_rx_hdr_u;
} wp_tdm_api_rx_hdr_t;
typedef struct {
wp_tdm_api_rx_hdr_t hdr;
unsigned char data[1];
} wp_tdm_api_rx_element_t;
typedef struct {
union {
struct {
unsigned char _rbs_rx_bits;
unsigned int _time_stamp;
}wp_tx;
unsigned char reserved[16];
}wp_tx_hdr_u;
#define wp_api_time_stamp wp_tx_hdr_u.wp_tx._time_stamp
} wp_tdm_api_tx_hdr_t;
typedef struct {
wp_tdm_api_tx_hdr_t hdr;
unsigned char data[1];
} wp_tdm_api_tx_element_t;
typedef struct wp_tdm_chan_stats
{
unsigned int rx_packets; /* total packets received */
unsigned int tx_packets; /* total packets transmitted */
unsigned int rx_bytes; /* total bytes received */
unsigned int tx_bytes; /* total bytes transmitted */
unsigned int rx_errors; /* bad packets received */
unsigned int tx_errors; /* packet transmit problems */
unsigned int rx_dropped; /* no space in linux buffers */
unsigned int tx_dropped; /* no space available in linux */
unsigned int multicast; /* multicast packets received */
#if !defined(__WINDOWS__)
unsigned int collisions;
#endif
/* detailed rx_errors: */
unsigned int rx_length_errors;
unsigned int rx_over_errors; /* receiver ring buff overflow */
unsigned int rx_crc_errors; /* recved pkt with crc error */
unsigned int rx_frame_errors; /* recv'd frame alignment error */
#if !defined(__WINDOWS__)
unsigned int rx_fifo_errors; /* recv'r fifo overrun */
#endif
unsigned int rx_missed_errors; /* receiver missed packet */
/* detailed tx_errors */
#if !defined(__WINDOWS__)
unsigned int tx_aborted_errors;
unsigned int tx_carrier_errors;
#endif
unsigned int tx_fifo_errors;
unsigned int tx_heartbeat_errors;
unsigned int tx_window_errors;
}wp_tdm_chan_stats_t;
typedef struct wanpipe_tdm_api_cmd{
unsigned int cmd;
unsigned int hw_tdm_coding; /* Set/Get HW TDM coding: uLaw muLaw */
unsigned int hw_mtu_mru; /* Set/Get HW TDM MTU/MRU */
unsigned int usr_period; /* Set/Get User Period in ms */
unsigned int tdm_codec; /* Set/Get TDM Codec: SLinear */
unsigned int power_level; /* Set/Get Power level treshold */
unsigned int rx_disable; /* Enable/Disable Rx */
unsigned int tx_disable; /* Enable/Disable Tx */
unsigned int usr_mtu_mru; /* Set/Get User TDM MTU/MRU */
unsigned int ec_tap; /* Echo Cancellation Tap */
unsigned int rbs_poll; /* Enable/Disable RBS Polling */
unsigned int rbs_rx_bits; /* Rx RBS Bits */
unsigned int rbs_tx_bits; /* Tx RBS Bits */
unsigned int hdlc; /* HDLC based device */
unsigned int idle_flag; /* IDLE flag to Tx */
unsigned int fe_alarms; /* FE Alarms detected */
wp_tdm_chan_stats_t stats; /* TDM Statistics */
/* Do NOT add anything above this! Important for binary backward compatibility. */
wp_tdm_api_event_t event; /* TDM Event */
unsigned int data_len;
void *data;
unsigned char fe_status; /* FE status - Connected or Disconnected */
unsigned int hw_dtmf; /* HW DTMF enabled */
}wanpipe_tdm_api_cmd_t;
typedef struct wanpipe_tdm_api_event{
int (*wp_rbs_event)(sng_fd_t fd, unsigned char rbs_bits);
int (*wp_dtmf_event)(sng_fd_t fd, unsigned char dtmf, unsigned char type, unsigned char port);
int (*wp_rxhook_event)(sng_fd_t fd, unsigned char hook_state);
int (*wp_ring_detect_event)(sng_fd_t fd, unsigned char ring_state);
int (*wp_ring_trip_detect_event)(sng_fd_t fd, unsigned char ring_state);
int (*wp_fe_alarm_event)(sng_fd_t fd, unsigned char fe_alarm_event);
int (*wp_link_status_event)(sng_fd_t fd, unsigned char link_status_event);
}wanpipe_tdm_api_event_t;
typedef struct wanpipe_tdm_api{
wanpipe_tdm_api_cmd_t wp_tdm_cmd;
wanpipe_tdm_api_event_t wp_tdm_event;
}wanpipe_tdm_api_t;
#endif

View File

@ -41,6 +41,7 @@
#include "ftdm_declare.h"
#include "ftdm_call_utils.h"
/*! \brief Max number of channels per physical span */
#define FTDM_MAX_CHANNELS_PHYSICAL_SPAN 32
@ -62,23 +63,6 @@
#define FTDM_INVALID_INT_PARM 0xFF
/*! \brief FreeTDM APIs possible return codes */
typedef enum {
FTDM_SUCCESS, /*!< Success */
FTDM_FAIL, /*!< Failure, generic error return code, use ftdm_channel_get_last_error or ftdm_span_get_last_error for details */
FTDM_MEMERR, /*!< Memory error, most likely allocation failure */
FTDM_TIMEOUT, /*!< Operation timed out (ie: polling on a device)*/
FTDM_NOTIMPL, /*!< Operation not implemented */
FTDM_BREAK, /*!< Request the caller to perform a break (context-dependant, ie: stop getting DNIS/ANI) */
FTDM_EINVAL /*!< Invalid argument */
} ftdm_status_t;
/*! \brief FreeTDM bool type. */
typedef enum {
FTDM_FALSE,
FTDM_TRUE
} ftdm_bool_t;
/*! \brief Thread/Mutex OS abstraction API. */
#include "ftdm_os.h"
@ -220,8 +204,10 @@ typedef enum {
FTDM_TON_SUBSCRIBER_NUMBER,
FTDM_TON_ABBREVIATED_NUMBER,
FTDM_TON_RESERVED,
FTDM_TON_INVALID = 255
FTDM_TON_INVALID
} ftdm_ton_t;
#define TON_STRINGS "unknown", "international", "national", "network-specific", "subscriber-number", "abbreviated-number", "reserved", "invalid"
FTDM_STR2ENUM_P(ftdm_str2ftdm_ton, ftdm_ton2str, ftdm_ton_t)
/*! Numbering Plan Identification (NPI) */
typedef enum {
@ -232,8 +218,52 @@ typedef enum {
FTDM_NPI_NATIONAL = 8,
FTDM_NPI_PRIVATE = 9,
FTDM_NPI_RESERVED = 10,
FTDM_NPI_INVALID = 255
FTDM_NPI_INVALID
} ftdm_npi_t;
#define NPI_STRINGS "unknown", "ISDN", "data", "telex", "national", "private", "reserved", "invalid"
FTDM_STR2ENUM_P(ftdm_str2ftdm_npi, ftdm_npi2str, ftdm_npi_t)
/*! Presentation Ind */
typedef enum {
FTDM_PRES_ALLOWED,
FTDM_PRES_RESTRICTED,
FTDM_PRES_NOT_AVAILABLE,
FTDM_PRES_RESERVED,
FTDM_PRES_INVALID
} ftdm_presentation_t;
#define PRESENTATION_STRINGS "presentation-allowed", "presentation-restricted", "number-not-available", "reserved", "Invalid"
FTDM_STR2ENUM_P(ftdm_str2ftdm_presentation, ftdm_presentation2str, ftdm_presentation_t)
/*! Screening Ind */
typedef enum {
FTDM_SCREENING_NOT_SCREENED,
FTDM_SCREENING_VERIFIED_PASSED,
FTDM_SCREENING_VERIFIED_FAILED,
FTDM_SCREENING_NETWORK_PROVIDED,
FTDM_SCREENING_INVALID
} ftdm_screening_t;
#define SCREENING_STRINGS "user-provided-not-screened", "user-provided-verified-and-passed", "user-provided-verified-and-failed", "network-provided", "invalid"
FTDM_STR2ENUM_P(ftdm_str2ftdm_screening, ftdm_screening2str, ftdm_screening_t)
/*! \brief bearer capability */
typedef enum {
FTDM_BEARER_CAP_SPEECH = 0x00,
FTDM_BEARER_CAP_64K_UNRESTRICTED = 0x02,
FTDM_BEARER_CAP_3_1KHZ_AUDIO = 0x03,
FTDM_BEARER_CAP_INVALID
} ftdm_bearer_cap_t;
#define BEARER_CAP_STRINGS "speech", "unrestricted-digital-information", "3.1-Khz-audio", "invalid"
FTDM_STR2ENUM_P(ftdm_str2ftdm_bearer_cap, ftdm_bearer_cap2str, ftdm_bearer_cap_t)
/*! \brief user information layer 1 protocol */
typedef enum {
FTDM_USER_LAYER1_PROT_V110 = 0x01,
FTDM_USER_LAYER1_PROT_ULAW = 0x02,
FTDM_USER_LAYER1_PROT_ALAW = 0x03,
FTDM_USER_LAYER1_PROT_INVALID
} ftdm_user_layer1_prot_t;
#define USER_LAYER1_PROT_STRINGS "V.110", "u-law", "a-law", "Invalid"
FTDM_STR2ENUM_P(ftdm_str2ftdm_usr_layer1_prot, ftdm_user_layer1_prot2str, ftdm_user_layer1_prot_t)
/*! \brief Number abstraction */
typedef struct {
@ -242,20 +272,6 @@ typedef struct {
uint8_t plan;
} ftdm_number_t;
/*! \brief bearer capability */
typedef enum {
FTDM_BEARER_CAP_SPEECH = 0x00,
FTDM_BEARER_CAP_64K_UNRESTRICTED = 0x02,
FTDM_BEARER_CAP_3_1KHZ_AUDIO = 0x03
} ftdm_bearer_cap_t;
/*! \brief user information layer 1 protocol */
typedef enum {
FTDM_USER_LAYER1_PROT_V110 = 0x01,
FTDM_USER_LAYER1_PROT_ULAW = 0x02,
FTDM_USER_LAYER1_PROT_ALAW = 0x03,
} ftdm_user_layer1_prot_t;
/*! \brief Caller information */
typedef struct ftdm_caller_data {
char cid_date[8]; /*!< Caller ID date */
@ -285,10 +301,12 @@ typedef enum {
/*! \brief Signaling messages sent by the stacks */
typedef enum {
FTDM_SIGEVENT_START, /*!< Incoming call (ie: incoming SETUP msg or Ring) */
FTDM_SIGEVENT_START,/*!< Incoming call (ie: incoming SETUP msg or Ring) */
FTDM_SIGEVENT_STOP, /*!< Hangup */
FTDM_SIGEVENT_RELEASED, /*!< Channel is completely released and available */
FTDM_SIGEVENT_UP, /*!< Outgoing call has been answered */
FTDM_SIGEVENT_FLASH, /*< Flash event (typically on-hook/off-hook for analog devices) */
FTDM_SIGEVENT_FLASH, /*!< Flash event (typically on-hook/off-hook for analog devices) */
FTDM_SIGEVENT_PROCEED, /*!< Outgoing call got a response */
FTDM_SIGEVENT_PROGRESS, /*!< Outgoing call is making progress */
FTDM_SIGEVENT_PROGRESS_MEDIA, /*!< Outgoing call is making progress and there is media available */
FTDM_SIGEVENT_ALARM_TRAP, /*!< Hardware alarm ON */
@ -298,11 +316,12 @@ typedef enum {
FTDM_SIGEVENT_RESTART, /*!< Restart has been requested. Typically you hangup your call resources here */
FTDM_SIGEVENT_SIGSTATUS_CHANGED, /*!< Signaling protocol status changed (ie: D-chan up), see new status in raw_data ftdm_sigmsg_t member */
FTDM_SIGEVENT_COLLISION, /*!< Outgoing call was dropped because an incoming call arrived at the same time */
FTDM_SIGEVENT_MSG, /*!< We received an in-call msg */
FTDM_SIGEVENT_INVALID
} ftdm_signal_event_t;
#define SIGNAL_STRINGS "START", "STOP", "UP", "FLASH", "PROGRESS", \
#define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROCEED", "PROGRESS", \
"PROGRESS_MEDIA", "ALARM_TRAP", "ALARM_CLEAR", \
"COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "COLLISION", "INVALID"
"COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "COLLISION", "MSG", "INVALID"
/*! \brief Move from string to ftdm_signal_event_t and viceversa */
FTDM_STR2ENUM_P(ftdm_str2ftdm_signal_event, ftdm_signal_event2str, ftdm_signal_event_t)
@ -430,12 +449,15 @@ typedef enum {
FTDM_COMMAND_FLUSH_TX_BUFFERS,
FTDM_COMMAND_FLUSH_RX_BUFFERS,
FTDM_COMMAND_FLUSH_BUFFERS,
FTDM_COMMAND_FLUSH_IOSTATS,
FTDM_COMMAND_SET_PRE_BUFFER_SIZE,
FTDM_COMMAND_SET_LINK_STATUS,
FTDM_COMMAND_GET_LINK_STATUS,
FTDM_COMMAND_ENABLE_LOOP,
FTDM_COMMAND_DISABLE_LOOP,
FTDM_COMMAND_COUNT
FTDM_COMMAND_COUNT,
FTDM_COMMAND_SET_RX_QUEUE_SIZE,
FTDM_COMMAND_SET_TX_QUEUE_SIZE,
} ftdm_command_t;
/*! \brief Custom memory handler hooks. Not recommended to use unless you need memory allocation customizations */
@ -577,7 +599,7 @@ typedef enum {
* This is used during incoming calls when you want to request the signaling stack
* to notify about indications occurring locally */
typedef enum {
FTDM_CHANNEL_INDICATE_RING,
FTDM_CHANNEL_INDICATE_RINGING,
FTDM_CHANNEL_INDICATE_PROCEED,
FTDM_CHANNEL_INDICATE_PROGRESS,
FTDM_CHANNEL_INDICATE_PROGRESS_MEDIA,

View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2010, Sangoma Technologies
* David Yat Sin <dyatsin@sangoma.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FTDM_CALL_UTILS_H__
#define __FTDM_CALL_UTILS_H__
/*!
* \brief Set the Numbering Plan Identification from a string
*
* \param npi_string string value
* \param target the target to set value to
*
* \retval FTDM_SUCCESS success
* \retval FTDM_FAIL failure
*/
FT_DECLARE(ftdm_status_t) ftdm_set_npi(const char *npi_string, uint8_t *target);
/*!
* \brief Set the Type of number from a string
*
* \param ton_string string value
* \param target the target to set value to
*
* \retval FTDM_SUCCESS success
* \retval FTDM_FAIL failure
*/
FT_DECLARE(ftdm_status_t) ftdm_set_ton(const char *ton_string, uint8_t *target);
/*!
* \brief Set the Bearer Capability from a string
*
* \param bc_string string value
* \param target the target to set value to
*
* \retval FTDM_SUCCESS success
* \retval FTDM_FAIL failure
*/
FT_DECLARE(ftdm_status_t) ftdm_set_bearer_capability(const char *bc_string, uint8_t *target);
/*!
* \brief Set the Bearer Capability - Layer 1 from a string
*
* \param bc_string string value
* \param target the target to set value to
*
* \retval FTDM_SUCCESS success
* \retval FTDM_FAIL failure
*/
FT_DECLARE(ftdm_status_t) ftdm_set_bearer_layer1(const char *bc_string, uint8_t *target);
/*!
* \brief Set the Screening Ind from a string
*
* \param screen_string string value
* \param target the target to set value to
*
* \retval FTDM_SUCCESS success
* \retval FTDM_FAIL failure
*/
FT_DECLARE(ftdm_status_t) ftdm_set_screening_ind(const char *string, uint8_t *target);
/*!
* \brief Set the Presentation Ind from an enum
*
* \param screen_string string value
* \param target the target to set value to
*
* \retval FTDM_SUCCESS success
* \retval FTDM_FAIL failure
*/
FT_DECLARE(ftdm_status_t) ftdm_set_presentation_ind(const char *string, uint8_t *target);
/*!
* \brief Checks whether a string contains only numbers
*
* \param number string value
*
* \retval FTDM_SUCCESS success
* \retval FTDM_FAIL failure
*/
FT_DECLARE(ftdm_status_t) ftdm_is_number(const char *number);
#endif /* __FTDM_CALL_UTILS_H__ */

View File

@ -171,6 +171,23 @@ typedef int ftdm_socket_t;
#include <stdarg.h>
#endif
/*! \brief FreeTDM APIs possible return codes */
typedef enum {
FTDM_SUCCESS, /*!< Success */
FTDM_FAIL, /*!< Failure, generic error return code, use ftdm_channel_get_last_error or ftdm_span_get_last_error for details */
FTDM_MEMERR, /*!< Memory error, most likely allocation failure */
FTDM_TIMEOUT, /*!< Operation timed out (ie: polling on a device)*/
FTDM_NOTIMPL, /*!< Operation not implemented */
FTDM_BREAK, /*!< Request the caller to perform a break (context-dependant, ie: stop getting DNIS/ANI) */
FTDM_EINVAL /*!< Invalid argument */
} ftdm_status_t;
/*! \brief FreeTDM bool type. */
typedef enum {
FTDM_FALSE,
FTDM_TRUE
} ftdm_bool_t;
/*!
* \brief FreeTDM channel.
* This is the basic data structure used to place calls and I/O operations

View File

@ -1,47 +0,0 @@
/*
* Copyright (c) 2010, Sangoma Technologies
* David Yat Sin <dyatsin@sangoma.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FTDM_CALL_UTILS_H__
#define __FTDM_CALL_UTILS_H__
#include "freetdm.h"
FT_DECLARE(ftdm_status_t) ftdm_span_set_npi(const char *npi_string, uint8_t *target);
FT_DECLARE(ftdm_status_t) ftdm_span_set_ton(const char *ton_string, uint8_t *target);
FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_capability(const char *bc_string, ftdm_bearer_cap_t *target);
FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_layer1(const char *bc_string, ftdm_user_layer1_prot_t *target);
FT_DECLARE(ftdm_status_t) ftdm_is_number(char *number);
#endif /* __FTDM_CALL_UTILS_H__ */

View File

@ -222,8 +222,7 @@ extern "C" {
#define ftdm_is_dtmf(key) ((key > 47 && key < 58) || (key > 64 && key < 69) || (key > 96 && key < 101) || key == 35 || key == 42 || key == 87 || key == 119)
#define FTDM_SPAN_IS_BRI(x) ((x)->trunk_type == FTDM_TRUNK_BRI || (x)->trunk_type == FTDM_TRUNK_BRI_PTMP)
#define FTDM_SPAN_IS_BRI(x) ((x)->trunk_type == FTDM_TRUNK_BRI || (x)->trunk_type == FTDM_TRUNK_BRI_PTMP)
/*!
\brief Copy flags from one arbitrary object to another
\command dest the object to copy the flags to
@ -358,6 +357,7 @@ typedef struct {
} ftdm_dtmf_debug_t;
#endif
typedef struct {
const char *file;
const char *func;
@ -367,6 +367,35 @@ typedef struct {
ftdm_time_t time;
} ftdm_channel_history_entry_t;
typedef enum {
FTDM_IOSTATS_ERROR_CRC = (1 << 0),
FTDM_IOSTATS_ERROR_FRAME = (1 << 1),
FTDM_IOSTATS_ERROR_ABORT = (1 << 2),
FTDM_IOSTATS_ERROR_FIFO = (1 << 3),
FTDM_IOSTATS_ERROR_DMA = (1 << 4),
FTDM_IOSTATS_ERROR_QUEUE_THRES = (1 << 5), /* Queue reached high threshold */
FTDM_IOSTATS_ERROR_QUEUE_FULL = (1 << 6), /* Queue is full */
} ftdm_iostats_error_type_t;
typedef struct {
struct {
uint32_t errors;
uint16_t flags;
uint8_t queue_size; /* max queue size configured */
uint8_t queue_len; /* Current number of elements in queue */
uint64_t packets;
} rx;
struct {
uint32_t errors;
uint16_t flags;
uint8_t idle_packets;
uint8_t queue_size; /* max queue size configured */
uint8_t queue_len; /* Current number of elements in queue */
uint64_t packets;
} tx;
} ftdm_channel_iostats_t;
/* 2^8 table size, one for each byte (sample) value */
#define FTDM_GAINS_TABLE_SIZE 256
struct ftdm_channel {
@ -441,6 +470,7 @@ struct ftdm_channel {
int availability_rate;
void *user_private;
ftdm_timer_id_t hangup_timer;
ftdm_channel_iostats_t iostats;
#ifdef FTDM_DEBUG_DTMF
ftdm_dtmf_debug_t dtmfdbg;
#endif
@ -637,10 +667,21 @@ FT_DECLARE(void) ftdm_channel_clear_detected_tones(ftdm_channel_t *ftdmchan);
#define ftdm_channel_lock(chan) ftdm_mutex_lock(chan->mutex)
#define ftdm_channel_unlock(chan) ftdm_mutex_unlock(chan->mutex)
#define ftdm_log_throttle(level, ...) \
time_current_throttle_log = ftdm_current_time_in_ms(); \
if (time_current_throttle_log - time_last_throttle_log > FTDM_THROTTLE_LOG_INTERVAL) {\
ftdm_log(level, __VA_ARGS__); \
time_last_throttle_log = time_current_throttle_log; \
}
#define ftdm_log_chan_ex(fchan, file, func, line, level, format, ...) ftdm_log(file, func, line, level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__)
#define ftdm_log_chan(fchan, level, format, ...) ftdm_log(level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__)
#define ftdm_log_chan_msg(fchan, level, msg) ftdm_log(level, "[s%dc%d][%d:%d] " msg, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id)
#define ftdm_log_chan_throttle(fchan, level, format, ...) ftdm_log_throttle(level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__)
#define ftdm_log_chan_msg_throttle(fchan, level, format, ...) ftdm_log_throttle(level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__)
#define ftdm_span_lock(span) ftdm_mutex_lock(span->mutex)
#define ftdm_span_unlock(span) ftdm_mutex_unlock(span->mutex)

View File

@ -181,6 +181,8 @@ typedef enum {
* after having called ftdm_send_span_signal(), which with this flag it will just enqueue the signal
* for later delivery */
FTDM_SPAN_USE_SIGNALS_QUEUE = (1 << 10),
/* If this flag is set, channel will be moved to proceed state when calls goes to routing */
FTDM_SPAN_USE_PROCEED_STATE = (1 << 11),
} ftdm_span_flag_t;
/*! \brief Channel supported features */
@ -194,6 +196,7 @@ typedef enum {
FTDM_CHANNEL_FEATURE_CALLWAITING = (1 << 6), /*!< Channel will allow call waiting (ie: FXS devices) (read/write) */
FTDM_CHANNEL_FEATURE_HWEC = (1<<7), /*!< Channel has a hardware echo canceller */
FTDM_CHANNEL_FEATURE_HWEC_DISABLED_ON_IDLE = (1<<8), /*!< hardware echo canceller is disabled when there are no calls on this channel */
FTDM_CHANNEL_FEATURE_IO_STATS = (1<<9), /*!< Channel supports IO statistics (HDLC channels only) */
} ftdm_channel_feature_t;
typedef enum {
@ -203,6 +206,7 @@ typedef enum {
FTDM_CHANNEL_STATE_DIALTONE,
FTDM_CHANNEL_STATE_COLLECT,
FTDM_CHANNEL_STATE_RING,
FTDM_CHANNEL_STATE_RINGING,
FTDM_CHANNEL_STATE_BUSY,
FTDM_CHANNEL_STATE_ATTN,
FTDM_CHANNEL_STATE_GENRING,
@ -210,6 +214,7 @@ typedef enum {
FTDM_CHANNEL_STATE_GET_CALLERID,
FTDM_CHANNEL_STATE_CALLWAITING,
FTDM_CHANNEL_STATE_RESTART,
FTDM_CHANNEL_STATE_PROCEED,
FTDM_CHANNEL_STATE_PROGRESS,
FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
FTDM_CHANNEL_STATE_UP,
@ -222,8 +227,8 @@ typedef enum {
FTDM_CHANNEL_STATE_INVALID
} ftdm_channel_state_t;
#define CHANNEL_STATE_STRINGS "DOWN", "HOLD", "SUSPENDED", "DIALTONE", "COLLECT", \
"RING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \
"RESTART", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", \
"RING", "RINGING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \
"RESTART", "PROCEED", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", \
"HANGUP", "HANGUP_COMPLETE", "IN_LOOP", "INVALID"
FTDM_STR2ENUM_P(ftdm_str2ftdm_channel_state, ftdm_channel_state2str, ftdm_channel_state_t)

View File

@ -50,7 +50,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_signal)
switch(sigmsg->event_id) {
case FTDM_SIGEVENT_START:
ftdm_channel_call_indicate(sigmsg->channel, FTDM_CHANNEL_INDICATE_RING);
ftdm_channel_call_indicate(sigmsg->channel, FTDM_CHANNEL_INDICATE_RINGING);
ftdm_log(FTDM_LOG_DEBUG, "launching thread and indicating ring\n");
ftdm_thread_create_detached(test_call, sigmsg->channel);
break;

View File

@ -45,10 +45,14 @@
#include <signal.h>
#include "freetdm.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifdef __linux__
#define __USE_BSD
#include <unistd.h>
#endif
#include "freetdm.h"
/* arbitrary limit for max calls in this sample program */
@ -338,9 +342,9 @@ int main(int argc, char *argv[])
exit(-1);
}
if (!strcasecmp(argv[2], "cpe")) {
if (!strcmp(argv[2], "cpe")) {
sigtype = "pri_cpe";
} else if (!strcasecmp(argv[2], "net")) {
} else if (!strcmp(argv[2], "net")) {
sigtype = "pri_net";
} else {
fprintf(stderr, "Valid signaling types are cpe and net only\n");

View File

@ -135,6 +135,7 @@ struct switch_core_session {
switch_mutex_t *frame_read_mutex;
switch_thread_rwlock_t *rwlock;
switch_thread_rwlock_t *io_rwlock;
void *streams[SWITCH_MAX_STREAMS];
int stream_count;

View File

@ -354,6 +354,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void);
///\ingroup core1
///\{
SWITCH_DECLARE(switch_status_t) switch_core_session_io_read_lock(switch_core_session_t *session);
SWITCH_DECLARE(switch_status_t) switch_core_session_io_write_lock(switch_core_session_t *session);
SWITCH_DECLARE(switch_status_t) switch_core_session_io_rwunlock(switch_core_session_t *session);
#ifdef SWITCH_DEBUG_RWLOCKS
SWITCH_DECLARE(switch_status_t) switch_core_session_perform_read_lock(_In_ switch_core_session_t *session, const char *file, const char *func, int line);
#endif
@ -882,6 +887,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_exec(_In_ switch_core_sessio
SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flags(_In_ switch_core_session_t *session,
_In_ const char *app, _In_opt_z_ const char *arg, _Out_opt_ int32_t *flags);
SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_async(switch_core_session_t *session, const char *app, const char *arg);
SWITCH_DECLARE(switch_status_t) switch_core_session_get_app_flags(const char *app, int32_t *flags);
/*!

View File

@ -874,6 +874,12 @@ SWITCH_DECLARE(void) switch_ivr_dmachine_set_input_timeout_ms(switch_ivr_dmachin
SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_clear_realm(switch_ivr_dmachine_t *dmachine, const char *realm);
SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_set_realm(switch_ivr_dmachine_t *dmachine, const char *realm);
SWITCH_DECLARE(switch_status_t) switch_ivr_get_file_handle(switch_core_session_t *session, switch_file_handle_t **fh);
SWITCH_DECLARE(switch_status_t) switch_ivr_release_file_handle(switch_core_session_t *session, switch_file_handle_t **fh);
SWITCH_DECLARE(switch_status_t) switch_ivr_process_fh(switch_core_session_t *session, const char *cmd, switch_file_handle_t *fhp);
SWITCH_DECLARE(switch_status_t) switch_ivr_insert_file(switch_core_session_t *session, const char *file, const char *insert_file, switch_size_t sample_point);
/** @} */
SWITCH_END_EXTERN_C

View File

@ -3968,6 +3968,47 @@ SWITCH_STANDARD_API(uuid_getvar_function)
return SWITCH_STATUS_SUCCESS;
}
#define FILEMAN_SYNTAX "<uuid> <cmd>:<val>"
SWITCH_STANDARD_API(uuid_fileman_function)
{
switch_core_session_t *psession = NULL;
char *mycmd = NULL, *argv[4] = { 0 };
int argc = 0;
if (!zstr(cmd) && (mycmd = strdup(cmd))) {
argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
if (argc >= 2 && !zstr(argv[0])) {
char *uuid = argv[0];
char *cmd = argv[1];
if ((psession = switch_core_session_locate(uuid))) {
switch_channel_t *channel;
switch_file_handle_t *fh = NULL;
channel = switch_core_session_get_channel(psession);
if (switch_ivr_get_file_handle(psession, &fh) == SWITCH_STATUS_SUCCESS) {
switch_ivr_process_fh(psession, cmd, fh);
switch_ivr_release_file_handle(psession, &fh);
}
switch_core_session_rwunlock(psession);
} else {
stream->write_function(stream, "-ERR No Such Channel!\n");
}
goto done;
}
}
stream->write_function(stream, "-USAGE: %s\n", GETVAR_SYNTAX);
done:
switch_safe_free(mycmd);
return SWITCH_STATUS_SUCCESS;
}
#define UUID_SEND_DTMF_SYNTAX "<uuid> <dtmf_data>"
SWITCH_STANDARD_API(uuid_send_dtmf_function)
{
@ -4674,6 +4715,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "uuid_display", "change display", uuid_display_function, DISPLAY_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_dump", "uuid_dump", uuid_dump_function, DUMP_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_exists", "see if a uuid exists", uuid_exists_function, EXISTS_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_fileman", "uuid_fileman", uuid_fileman_function, FILEMAN_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_flush_dtmf", "Flush dtmf on a given uuid", uuid_flush_dtmf_function, "<uuid>");
SWITCH_ADD_API(commands_api_interface, "uuid_getvar", "uuid_getvar", uuid_getvar_function, GETVAR_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_hold", "hold", uuid_hold_function, HOLD_SYNTAX);
@ -4785,6 +4827,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
switch_console_set_complete("add uuid_display ::console::list_uuid");
switch_console_set_complete("add uuid_dump ::console::list_uuid");
switch_console_set_complete("add uuid_exists ::console::list_uuid");
switch_console_set_complete("add uuid_fileman ::console::list_uuid");
switch_console_set_complete("add uuid_flush_dtmf ::console::list_uuid");
switch_console_set_complete("add uuid_getvar ::console::list_uuid");
switch_console_set_complete("add uuid_hold ::console::list_uuid");

View File

@ -95,16 +95,6 @@ should be opened for the channel. Limited to 25ms min, 500ms max.
<param name="r2-preconnect-wait" value="250"/>
-->
<!--
Enable/disable native bridge mode (known in pt_BR as "trombone") for calls
in the Khomp channel, passing the audio inside the board when both channels
(incoming and outgoing) are of type Khomp. This reduces the echo and the
audio delay, and frees the host from most audio processing.
(default = yes)
<param name="native-bridge" value="yes"/>
-->
<!--
Defines the incoming context for calls on E1 channels. Some wildcards are
accepted, and described in the bottom of this file.
@ -239,48 +229,30 @@ is enabled on the board configuration. Possible values:
<param name="input-volume" value="0"/>
-->
<!--
Sets the default AMA flags, affecting the categorization of entries in
the call detail records.
(default = default)
<param name="amaflags" value="default"/>
-->
<!--
Sets the account code for calls placed on the channel. The account code may
be any alphanumeric string
(default = KhompBoard)
default = <empty>)
<param name="accountcode" value="KhompBoard"/>
<param name="accountcode" value=""/>
-->
<!--
Set the language of the channel (useful for selecting audio messages of a
specific language on answer).
(default = <empty>)
<param name="language" value="pt_BR"/>
-->
<!--
Set the music on hold class of the channel (useful for selecting a group of
songs to play on hold).
(default = default)
<param name="mohclass" value="default"/>
-->
<!--
Sets the global orig (CALLERID) base for FXS boards. This number is added
to a sequencial number, which is incremented for each FXS board and FXS
channel in the system.
For more example of how to use this option, see channel README file,
section 'Opcoes do application Bridge', item '<action application="bridge" data="Khomp/r304" />'.
(default = 0)
<param name="fxs-global-orig" value="0200"/>
<param name="fxs-global-orig" value="0"/>
-->
<!--
@ -300,14 +272,6 @@ a FXS branch.
<param name="fxs-bina" value="yes"/>
-->
<!--
Enable/disable using CTbus for Khomp CTI boards in native bridge.
(WARNING: just used for internal testings!)
(default = no)
<param name="has-ctbus" value="no"/>
-->
<!--
This is the delay time to really disconnect a channel after the disconnect
event arrive. If a connect event comes up in this interval, then the
@ -337,18 +301,6 @@ not have any tone. Values are in milliseconds.
<param name="delay-ringback-pbx" value="2500"/>
-->
<!--
Defines if the channel should optimize audio delay by droping longstanding
packets from audio buffer. This guarantees the minimal audio delay for the
user, and avoid delays associated with miscoded SIP clients. However,
depending on the system's scheduling policy (some 2.6 kernel releases),
this may result on excessive drop of packets, and audible audio skipping.
This should not be changed naively.
(default = no)
<param name="optimize-audio-path" value="no"/>
-->
<!--
Defines if the channel should ignore some uncommon DTMF digits detected by
the board (A, B, C and D). This reduces the number of false positives which
@ -526,9 +478,8 @@ In the example above, the branch numbered 804 will have specific
configuration for default output volume set to +2.
Possible values to options is:
context, input-volume, output-volume language,
mohclass, amaflags, accountcode, calleridnum,
calleridname, mailbox, flash-to-digits.
context, input-volume, output-volume, language,
accountcode, calleridnum, calleridname, flash-to-digits.
-->
</fxs-options>

View File

@ -1,6 +1,9 @@
MODNAME := mod_khomp
VERBOSE := 1
#FreeSWITCH source PATH is needed:
# Set FREESWITCH_PATH
ifeq ($(strip $(FREESWITCH_PATH)),)
BASE := ../../../../
else
@ -11,12 +14,12 @@ curr_dir := $(shell pwd)
versions := -DFS_VERSION_MAJOR=$(shell bash $(curr_dir)/tools/getversion.sh "SWITCH_VERSION_MAJOR" $(BASE)) -DFS_VERSION_MINOR=$(shell bash $(curr_dir)/tools/getversion.sh "SWITCH_VERSION_MINOR" $(BASE)) -DFS_VERSION_MICRO=$(shell bash $(curr_dir)/tools/getversion.sh "SWITCH_VERSION_MICRO" $(BASE))
LOCAL_CFLAGS = -I./ -I./include -I./commons -I./support -D_REENTRANT -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DK3L_HOSTSYSTEM -DCOMMONS_LIBRARY_USING_FREESWITCH -g -ggdb #-DDEBUG_FLAGS
LOCAL_CFLAGS = -I./ -I./include -I./commons -I./commons/base -I./support -D_REENTRANT -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -DK3L_HOSTSYSTEM -DCOMMONS_LIBRARY_USING_FREESWITCH -g -ggdb #-DDEBUG_FLAGS
LOCAL_CFLAGS += $(versions)
LOCAL_LDFLAGS = -lk3l
LOCAL_OBJS = ./commons/k3lapi.o ./commons/k3lutil.o ./commons/config_options.o ./commons/format.o ./commons/strings.o ./commons/ringbuffer.o ./commons/verbose.o ./commons/saved_condition.o ./commons/regex.o ./commons/timer.o ./commons/configurator/configfile.o ./commons/configurator/option.o ./commons/configurator/section.o ./commons/configurator/restriction.o
LOCAL_OBJS = ./commons/base/k3lapi.o ./commons/base/k3lutil.o ./commons/base/config_options.o ./commons/base/format.o ./commons/base/strings.o ./commons/base/ringbuffer.o ./commons/base/verbose.o ./commons/base/saved_condition.o ./commons/base/regex.o ./commons/base/timer.o ./commons/base/configurator/configfile.o ./commons/base/configurator/option.o ./commons/base/configurator/section.o ./commons/base/configurator/restriction.o ./commons/base/verbose_traits.o
LOCAL_OBJS += ./support/klog-config.o ./support/klog-options.o ./support/config_defaults.o
LOCAL_OBJS += ./src/globals.o ./src/opt.o ./src/frame.o ./src/utils.o ./src/lock.o ./src/spec.o ./src/applications.o ./src/khomp_pvt_fxo.o ./src/khomp_pvt_gsm.o ./src/khomp_pvt_kxe1.o ./src/khomp_pvt_passive.o ./src/khomp_pvt.o ./src/logger.o ./src/cli.o
@ -27,7 +30,20 @@ conf_file_install = $(sysconfdir)/autoload_configs
include $(BASE)/build/modmake.rules
local_depend:
@if test ! -f $(curr_dir)/commons/base/verbose_traits.hpp || test ! -f $(curr_dir)/commons/base/verbose_traits.cpp ; then \
echo "Generating verbose_traits" ;\
bash $(curr_dir)/commons/tools/generate-verbose-headers.sh commons/base/ include/k3l.h ;\
fi;
depend_install:
@if test "w`kserver --version 2>/dev/null | grep 2.1`" == "w" ; then \
echo "###############################################################################" ;\
echo "Install k3l from KHOMP." ;\
echo "Run: $(curr_dir)/tools/getk3l.sh" ;\
echo "###############################################################################" ;\
exit 1;\
fi;
@echo "Copy $(conf_file_name)"
@if test -d $(conf_file_install) ; then \
if test -f $(conf_file_dir)/$(conf_file_name) ; then \

View File

@ -64,17 +64,31 @@ namespace Atomic
PunnedType pval; pval.valtype = VAL; \
unsigned long long vexp = *(pexp.podtype); \
unsigned long long vval = *(pval.podtype); \
unsigned long long res = (unsigned long long)exp; \
unsigned long vval32 = (unsigned long)vval; \
unsigned char chg = 0; \
asm volatile("lock; cmpxchg8b %2; sete %1;" \
asm volatile( \
"xchgl %%ebx, %4;" \
"lock; cmpxchg8b %2; sete %1;" \
"movl %4, %%ebx; " \
: "+A" (vexp), /* 0 (result) */ \
"=q" (chg) /* 1 */ \
"=c" (chg) /* 1 */ \
: "m" (*(unsigned char**)(PTR)), /* 2 */ \
"b" ((unsigned long)(vval)), \
"c" ((unsigned long)(vval >> 32))); \
"c" ((unsigned long)(vval >> 32)), \
"m" (vval32)); \
*(pexp.podtype) = vexp; \
return (chg != 0 ? true : false);
// "movl %%ecx, %4;"
//
// "m" (*((unsigned long*)(*(pval.podtype)))),
// "m" ((unsigned long)(vval >> 32))
//
// "m" (*((unsigned long*)(&vval))),
// "m" ((unsigned long)(vval >> 32))
//
// unsigned long long vval = *(pval.podtype);
// unsigned long long res = (unsigned long long)exp;
//
// Types used for making CMPXCHG instructions independent from base type.
template < typename ValType, typename PodType >

View File

@ -63,7 +63,12 @@
#error Unknown implementation selected. Please define COMMONS_LIBRARY_USING_* correctly.
#endif
#define COMMONS_INCLUDE(file) <COMMONS_IMPLEMENTATION/file>
#define COMMONS_INCLUDE(file) <system/COMMONS_IMPLEMENTATION/file>
#define COMMONS_VERSION_MAJOR 1
#define COMMONS_VERSION_MINOR 1
#define COMMONS_AT_LEAST(x,y) \
(COMMONS_VERSION_MAJOR > x || (COMMONS_VERSION_MAJOR == x && COMMONS_VERSION_MINOR >= y))
#endif /* _CONFIG_COMMONS_HPP_ */

View File

@ -0,0 +1,302 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
the specific language governing rights and limitations under the License.
Alternatively, the contents of this file may be used under the terms of the
"GNU Lesser General Public License 2.1" license (the LGPL" License), in which
case the provisions of "LGPL License" are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
the LGPL License and not to allow others to use your version of this file under
the MPL, indicate your decision by deleting the provisions above and replace them
with the notice and other provisions required by the LGPL License. If you do not
delete the provisions above, a recipient may use your version of this file under
either the MPL or the LGPL License.
The LGPL header follows below:
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <config_options.hpp>
void Config::Restriction::checkRange(const std::string & name, const SIntType value, const Range < SIntType > & range)
{
if (value < range.minimum)
throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (too low)") % value % name));
if (value > range.maximum)
throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (too high)") % value % name));
if (((value - range.minimum) % range.step) != 0)
throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (outside allowed step)") % value % name));
}
void Config::Restriction::checkRange(const std::string & name, const UIntType value, const Range < UIntType > & range)
{
if (value < range.minimum)
throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (too low)") % value % name));
if (value > range.maximum)
throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (too high)") % value % name));
if (((value - range.minimum) % range.step) != 0)
throw Failure(STG(FMT("value '%d' out-of-range for option '%s' (outside allowed step)") % value % name));
}
void Config::Restriction::checkStringSet(const std::string & name, const StringType & value, const StringSet & allowed)
{
if (allowed.empty())
return;
if (allowed.find(value) != allowed.end())
return;
std::string strlist;
for (StringSet::const_iterator i = allowed.begin(); i != allowed.end(); i++)
{
strlist += " '";
strlist += (*i);
strlist += "'";
}
throw Failure(STG(FMT("value '%s' not allowed for option '%s' (allowed values:%s)")
% value % name % strlist));
}
Config::Option::Option(std::string name, Config::Option::StringMemberType value, const StringType defvalue, StringSet & allowed, bool listme)
: _myname(name), _option(InnerStringType(name, value, defvalue, allowed)), _listme(listme), _values(NULL)
{};
Config::Option::Option(std::string name, Config::Option::StringMemberType value, const StringType defvalue, bool listme)
: _myname(name), _option(InnerStringType(name, value, defvalue)), _listme(listme), _values(NULL)
{};
Config::Option::Option(std::string name, Config::Option::BooleanMemberType value, const BooleanType defvalue, bool listme)
: _myname(name), _option(InnerBooleanType(name, value, defvalue)), _listme(listme), _values(NULL)
{};
Config::Option::Option(std::string name, Config::Option::SIntMemberType value, const SIntType defvalue,
SIntType min, SIntType max, SIntType step, bool listme)
: _myname(name), _option(InnerSIntType(name, value, defvalue, min, max, step)), _listme(listme), _values(NULL)
{};
Config::Option::Option(std::string name, Config::Option::UIntMemberType value, const UIntType defvalue,
UIntType min, UIntType max, UIntType step, bool listme)
: _myname(name), _option(InnerUIntType(name, value, defvalue, min, max, step)), _listme(listme), _values(NULL)
{};
Config::Option::Option(const Config::Option & o)
: _myname(o._myname), _option(o._option), _listme(o._listme), _values(o._values)
{};
Config::Option::Option(std::string name, Config::Option::FunctionMemberType value, const StringType defvalue, StringSet & allowed, bool listme)
: _myname(name), _option(InnerFunctionType(name, value, defvalue, allowed)), _listme(listme), _values(NULL)
{};
Config::Option::Option(std::string name, Config::Option::FunctionMemberType value, const StringType defvalue, bool listme)
: _myname(name), _option(InnerFunctionType(name, value, defvalue)), _listme(listme), _values(NULL)
{};
Config::Option::~Option(void)
{
if (_values)
{
for (unsigned int i = 0; _values[i] != NULL; i++)
delete _values[i];
delete[] _values;
_values = NULL;
}
};
const char ** Config::Option::values(void)
{
if (_values != NULL)
return _values;
/**/ if (_option.check<InnerBooleanType>())
{
_values = new const char*[3];
_values[0] = strdup("yes");
_values[1] = strdup("no");
_values[2] = NULL;
}
else if (_option.check<InnerSIntType>())
{
const InnerSIntType & tmp = _option.get<InnerSIntType>();
unsigned int count = ((tmp._range.maximum - tmp._range.minimum) / tmp._range.step) + 1;
unsigned int index = 0;
_values = new const char*[count + 1];
for (SIntType i = tmp._range.minimum; i <= tmp._range.maximum; i += tmp._range.step, ++index)
_values[index] = strdup(STG(FMT("%d") % i).c_str());
_values[index] = NULL;
}
else if (_option.check<InnerUIntType>())
{
const InnerUIntType & tmp = _option.get<InnerUIntType>();
unsigned int count = ((tmp._range.maximum - tmp._range.minimum) / tmp._range.step) + 1;
unsigned int index = 0;
_values = new const char*[count + 1];
for (UIntType i = tmp._range.minimum; i <= tmp._range.maximum; i += tmp._range.step, ++index)
_values[index] = strdup(STG(FMT("%d") % i).c_str());
_values[index] = NULL;
}
else if (_option.check<InnerStringType>())
{
const InnerStringType & tmp = _option.get<InnerStringType>();
_values = new const char*[ tmp._allowed.size() + 1 ];
unsigned int index = 0;
for (StringSet::iterator i = tmp._allowed.begin(); i != tmp._allowed.end(); ++i, ++index)
_values[index] = strdup((*i).c_str());
_values[index] = NULL;
}
else if (_option.check<InnerFunctionType>())
{
const InnerFunctionType & tmp = _option.get<InnerFunctionType>();
_values = new const char*[ tmp._allowed.size() + 1 ];
unsigned int index = 0;
for (StringSet::iterator i = tmp._allowed.begin(); i != tmp._allowed.end(); ++i, ++index)
_values[index] = strdup((*i).c_str());
_values[index] = NULL;
}
else
{
throw Failure(STG(FMT("values() not implemented for type used in option '%s'") % _myname));
}
return _values;
};
/*********************************/
Config::Options::Options(void)
: _values(NULL)
{};
Config::Options::~Options()
{
if (_values)
{
for (unsigned int i = 0; _values[i] != NULL; i++)
free((void*)(_values[i]));
delete[] _values;
_values = NULL;
}
};
bool Config::Options::add(Config::Option option)
{
std::pair<OptionMap::iterator, bool> ret = _map.insert(OptionPair(option.name(), option));
return ret.second;
}
bool Config::Options::synonym(std::string equiv_opt, std::string main_opt)
{
std::pair<SynOptionMap::iterator, bool> ret = _syn_map.insert(SynOptionPair(equiv_opt, main_opt));
return ret.second;
}
Config::StringSet Config::Options::options(void)
{
StringSet res;
for (OptionMap::iterator i = _map.begin(); i != _map.end(); i++)
res.insert(i->first);
return res;
}
const char ** Config::Options::values(const char * name)
{
OptionMap::iterator iter = find_option(name);
if (iter == _map.end())
throw Failure(STG(FMT("unknown option '%s'") % name));
return iter->second.values();
}
const char ** Config::Options::values(void)
{
if (_values != NULL)
return _values;
unsigned int count = 0;
for (OptionMap::iterator i = _map.begin(); i != _map.end(); ++i)
if (i->second.listme())
++count;
_values = new const char*[ count + 1 ];
unsigned int index = 0;
for (OptionMap::iterator i = _map.begin(); i != _map.end(); ++i)
{
if (i->second.listme())
{
_values[index] = strdup(i->first.c_str());
++index;
}
}
_values[index] = NULL;
return _values;
}
Config::Options::OptionMap::iterator Config::Options::find_option(std::string name)
{
SynOptionMap::iterator syn_iter = _syn_map.find(name);
if (syn_iter != _syn_map.end())
name = syn_iter->second;
OptionMap::iterator iter = _map.find(name);
return iter;
}

View File

@ -0,0 +1,772 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
the specific language governing rights and limitations under the License.
Alternatively, the contents of this file may be used under the terms of the
"GNU Lesser General Public License 2.1" license (the LGPL" License), in which
case the provisions of "LGPL License" are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
the LGPL License and not to allow others to use your version of this file under
the MPL, indicate your decision by deleting the provisions above and replace them
with the notice and other provisions required by the LGPL License. If you do not
delete the provisions above, a recipient may use your version of this file under
either the MPL or the LGPL License.
The LGPL header follows below:
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _CONFIG_OPTIONS_HPP_
#define _CONFIG_OPTIONS_HPP_
#include <set>
#include <map>
#include <vector>
#include <stdexcept>
#include <strings.hpp>
#include <format.hpp>
#include <tagged_union.hpp>
#include <function.hpp>
#include <variable.hpp>
namespace Config
{
/* exceptions */
struct Failure: public std::runtime_error
{
Failure(const std::string & msg) : std::runtime_error(msg) {};
};
struct EmptyValue: public std::runtime_error
{
EmptyValue(): std::runtime_error("accessed option still not loaded from configuration") {};
};
/* types */
typedef int SIntType;
typedef unsigned int UIntType;
typedef bool BooleanType;
typedef std::string StringType;
template < typename Type >
struct Value;
template < typename Type >
struct InnerOptionBase;
template < typename Type >
struct InnerOption;
struct Option;
/* here we go! */
template < typename Type >
struct Range
{
Range(const Type _minimum, const Type _maximum, const Type _step)
: minimum(_minimum), maximum(_maximum), step(_step) {};
const Type minimum, maximum, step;
};
typedef std::set < std::string > StringSet;
template < typename Type >
struct Value: COUNTER_SUPER(Value < Type >)
{
friend class COUNTER_CLASS(Value < Type >);
friend class InnerOptionBase< Type >;
friend class InnerOption < Type >;
friend class Option;
Value()
: _tmpval(0), _stored(0), _loaded(false), _inited(false)
{};
Value(const Value & o)
: COUNTER_REFER(o, Value < Type >),
_tmpval(o._tmpval), _stored(o._stored),
_loaded(o._loaded), _inited(o._inited)
{};
const Type & operator()(void) const
{
if (!_inited)
throw EmptyValue();
if (!_stored)
return *_tmpval;
return *_stored;
};
const Type & get(void) const { return operator()(); };
bool loaded(void) const { return _loaded; };
void store(const Type val)
{
if (_tmpval)
{
delete _tmpval;
_tmpval = 0;
}
_tmpval = new Type(val);
_loaded = true;
_inited = true;
}
protected:
void unreference(void)
{
_inited = false;
_loaded = false;
if (_tmpval)
{
delete _tmpval;
_tmpval = 0;
}
if (_stored)
{
delete _stored;
_stored = 0;
}
};
protected:
void commit(Type def)
{
if (_tmpval)
{
{
delete _stored;
_stored = 0;
}
_stored = _tmpval;
_tmpval = 0;
}
else
{
if (!_stored)
_stored = new Type(def);
}
_loaded = true;
_inited = true;
};
void reset(void)
{
_loaded = false;
}
protected:
const Type * _tmpval;
const Type * _stored;
bool _loaded;
bool _inited;
};
struct FunctionValue
{
friend class InnerFunctionType;
friend class Option;
FunctionValue()
: _loaded(false), _inited(false) {};
virtual ~FunctionValue() {};
public:
virtual void operator()(const StringType & val)
{
throw Failure("undefined operator() for value");
}
const StringType & get(void) const
{
if (!_inited)
throw EmptyValue();
return _stored;
};
bool loaded(void) const { return _loaded; };
protected:
void commit(const StringType def)
{
if (_tmpval.empty())
{
_stored = def;
}
else
{
_stored = _tmpval;
_tmpval.clear();
}
operator()(_stored);
_loaded = true;
_inited = true;
};
void store(const StringType val)
{
_tmpval = val;
_loaded = true;
_inited = true;
}
void reset(void)
{
_loaded = false;
}
private:
StringType _tmpval;
StringType _stored;
bool _loaded;
bool _inited;
};
/* NOTE: we use a non-templated classe to place this functions inside the .cpp */
struct Restriction
{
static void checkRange(const std::string & name, const SIntType value, const Range < SIntType > & range);
static void checkRange(const std::string & name, const UIntType value, const Range < UIntType > & range);
static void checkStringSet(const std::string & name, const StringType & value, const StringSet & allowed);
};
template < typename Type >
struct InnerOptionBase
{
typedef Variable < Value < Type > > MemberValue;
InnerOptionBase(const std::string name, MemberValue option, const Type defvalue)
: _name(name), _option(option), _default(defvalue) {};
template < typename Object >
void reset(Object * const obj) const
{
_option(obj).reset();
}
template < typename Object >
const Type & get(const Object * const obj) const
{
return _option(obj).get();
}
template < typename Object >
bool loaded(const Object * const obj) const
{
return _option(obj).loaded();
}
protected:
const std::string _name;
MemberValue _option;
const Type _default;
};
template < >
struct InnerOption < SIntType >: public InnerOptionBase < SIntType >
{
typedef InnerOptionBase < SIntType > Super;
typedef Super::MemberValue MemberValue;
InnerOption(const std::string name, MemberValue option, const SIntType defval,
const SIntType min, const SIntType max, const SIntType step)
: Super(name, option, defval), _range(min, max, step) {};
template < typename Object >
void commit(Object * const obj) const
{
Restriction::checkRange(_name, _default, _range);
_option(obj).commit(_default);
};
template < typename Object >
void store(Object * const obj, const SIntType stored) const
{
Restriction::checkRange(_name, _default, _range);
_option(obj).store(stored);
}
using Super::reset;
using Super::get;
const Range< SIntType > _range;
};
template < >
struct InnerOption < UIntType >: public InnerOptionBase < UIntType >
{
typedef InnerOptionBase < UIntType > Super;
typedef Super::MemberValue MemberValue;
InnerOption(const std::string name, MemberValue option, const UIntType defval,
const UIntType min, const UIntType max, const UIntType step)
: Super(name, option, defval), _range(min, max, step) {};
template < typename Object >
void commit(Object * const obj) const
{
Restriction::checkRange(_name, _default, _range);
_option(obj).commit(_default);
};
template < typename Object >
void store(Object * const obj, const UIntType stored) const
{
Restriction::checkRange(_name, _default, _range);
_option(obj).store(stored);
}
using Super::reset;
using Super::get;
const Range< UIntType > _range;
};
template < >
struct InnerOption < BooleanType >: public InnerOptionBase < BooleanType >
{
typedef InnerOptionBase < BooleanType > Super;
typedef Super::MemberValue MemberValue;
InnerOption(std::string name, MemberValue option, BooleanType defval)
: Super(name, option, defval) {};
template < typename Object >
void commit(Object * obj) const
{
_option(obj).commit(_default);
};
template < typename Object >
void store(Object * obj, BooleanType stored) const
{
_option(obj).store(stored);
}
using Super::reset;
using Super::get;
};
template < >
struct InnerOption < StringType >: public InnerOptionBase < StringType >
{
typedef InnerOptionBase < StringType > Super;
typedef Super::MemberValue MemberValue;
InnerOption(const std::string name, MemberValue option, const StringType defval, const StringSet & allowed)
: Super(name, option, defval), _allowed(allowed) {};
InnerOption(const std::string name, MemberValue option, const StringType defval)
: Super(name, option, defval) {};
template < typename Object >
void commit(Object * const obj) const
{
Restriction::checkStringSet(_name, _default, _allowed);
_option(obj).commit(_default);
};
template < typename Object >
void store(Object * const obj, const StringType stored) const
{
Restriction::checkStringSet(_name, _default, _allowed);
_option(obj).store(stored);
}
using Super::reset;
using Super::get;
const StringSet _allowed;
};
struct InnerFunctionType
{
typedef Variable < FunctionValue > MemberValue;
InnerFunctionType(const std::string name, MemberValue option, const StringType defval, const StringSet & allowed)
: _name(name), _option(option), _default(defval), _allowed(allowed) {};
InnerFunctionType(const std::string name, MemberValue option, const StringType defval)
: _name(name), _option(option), _default(defval) {};
template < typename Object >
const StringType & get(const Object * const obj) const
{
return _option(obj).get();
}
template < typename Object >
bool loaded(const Object * const obj) const
{
return _option(obj).loaded();
}
template < typename Object >
void reset(Object * const obj) const
{
_option(obj).reset();
}
template < typename Object >
void commit(Object * const obj) const
{
Restriction::checkStringSet(_name, _default, _allowed);
_option(obj).commit(_default);
};
template < typename Object >
void store(Object * const obj, const StringType stored) const
{
Restriction::checkStringSet(_name, _default, _allowed);
_option(obj).store(stored);
}
protected:
const std::string _name;
MemberValue _option;
const StringType _default;
public:
const StringSet _allowed;
};
struct Option
{
typedef InnerOption < SIntType > InnerSIntType;
typedef InnerOption < UIntType > InnerUIntType;
typedef InnerOption < BooleanType > InnerBooleanType;
typedef InnerOption < StringType > InnerStringType;
typedef Variable < Value < SIntType > > SIntMemberType;
typedef Variable < Value < UIntType > > UIntMemberType;
typedef Variable < Value < BooleanType > > BooleanMemberType;
typedef Variable < Value < StringType > > StringMemberType;
typedef Variable < FunctionValue > FunctionMemberType;
typedef Tagged::Union < InnerStringType,
Tagged::Union < InnerBooleanType,
Tagged::Union < InnerSIntType ,
Tagged::Union < InnerUIntType,
Tagged::Union < InnerFunctionType > > > > >
InnerType;
explicit Option(std::string, StringMemberType, const StringType, StringSet & allowed, bool listme = true);
explicit Option(std::string, StringMemberType, const StringType = "", bool listme = true);
explicit Option(std::string, SIntMemberType, const SIntType = 0, SIntType min = INT_MIN, SIntType max = INT_MAX, SIntType step = 1, bool listme = true);
explicit Option(std::string, UIntMemberType, const UIntType = 0, UIntType min = 0, UIntType max = UINT_MAX, UIntType step = 1, bool listme = true);
explicit Option(std::string, BooleanMemberType, const BooleanType = false, bool listme = true);
explicit Option(std::string, FunctionMemberType, const StringType, StringSet & allowed, bool listme = true);
explicit Option(std::string, FunctionMemberType, const StringType = "", bool listme = true);
Option(const Option & o);
~Option(void);
template < typename Object >
void set(Object * object, std::string value)
{
try
{
/**/ if (_option.check<InnerFunctionType>()) _option.get<InnerFunctionType>().store(object, value);
else if (_option.check<InnerStringType>()) _option.get<InnerStringType>().store(object, value);
else if (_option.check<InnerBooleanType>()) _option.get<InnerBooleanType>().store(object, Strings::toboolean(value));
else if (_option.check<InnerSIntType>()) _option.get<InnerSIntType>().store(object, Strings::tolong(value));
else if (_option.check<InnerUIntType>()) _option.get<InnerUIntType>().store(object, Strings::toulong(value));
else
{
throw Failure(STG(FMT("set() not implemented for type used in option '%s'") % _myname));
}
}
catch (Strings::invalid_value & e)
{
throw Failure(STG(FMT("got invalid value '%s' for option '%s'") % value % _myname));
}
catch (EmptyVariable & e)
{
throw Failure(STG(FMT("uninitialized variable while setting value '%s' for option '%s'") % value % _myname));
}
}
template < typename Object >
std::string get(const Object * const object) const
{
try
{
/**/ if (_option.check<InnerFunctionType>()) return _option.get<InnerFunctionType>().get(object);
else if (_option.check<InnerStringType>()) return _option.get<InnerStringType>().get(object);
else if (_option.check<InnerBooleanType>()) return (_option.get<InnerBooleanType>().get(object) ? "yes" : "no");
else if (_option.check<InnerSIntType>()) return STG(FMT("%d") % _option.get<InnerSIntType>().get(object));
else if (_option.check<InnerUIntType>()) return STG(FMT("%u") % _option.get<InnerUIntType>().get(object));
else
{
throw Failure(STG(FMT("get() not implemented for type used in option '%s'") % _myname));
}
}
catch (EmptyVariable & e)
{
throw Failure(STG(FMT("uninitialized variable while getting value for option '%s'") % _myname));
}
}
template < typename Object >
bool loaded(const Object * const object) const
{
try
{
/**/ if (_option.check<InnerFunctionType>()) return _option.get<InnerFunctionType>().loaded(object);
else if (_option.check<InnerBooleanType>()) return _option.get<InnerBooleanType>().loaded(object);
else if (_option.check<InnerStringType>()) return _option.get<InnerStringType>().loaded(object);
else if (_option.check<InnerSIntType>()) return _option.get<InnerSIntType>().loaded(object);
else if (_option.check<InnerUIntType>()) return _option.get<InnerUIntType>().loaded(object);
else
{
throw Failure(STG(FMT("loaded() not implemented for type used in option '%s'") % _myname));
}
}
catch (EmptyVariable & e)
{
throw Failure(STG(FMT("uninitialized variable while checking load status for option '%s'") % _myname));
}
}
template < typename Object >
void reset(Object * const object)
{
try
{
/**/ if (_option.check<InnerFunctionType>()) _option.get<InnerFunctionType>().reset(object);
else if (_option.check<InnerBooleanType>()) _option.get<InnerBooleanType>().reset(object);
else if (_option.check<InnerStringType>()) _option.get<InnerStringType>().reset(object);
else if (_option.check<InnerSIntType>()) _option.get<InnerSIntType>().reset(object);
else if (_option.check<InnerUIntType>()) _option.get<InnerUIntType>().reset(object);
else
{
throw Failure(STG(FMT("reset() not implemented for type used in option '%s'") % _myname));
}
}
catch (EmptyVariable & e)
{
throw Failure(STG(FMT("uninitialized variable while reseting status for option '%s'") % _myname));
}
}
template < typename Object >
void commit(Object * const object)
{
try
{
/**/ if (_option.check<InnerFunctionType>()) _option.get<InnerFunctionType>().commit(object);
else if (_option.check<InnerBooleanType>()) _option.get<InnerBooleanType>().commit(object);
else if (_option.check<InnerStringType>()) _option.get<InnerStringType>().commit(object);
else if (_option.check<InnerSIntType>()) _option.get<InnerSIntType>().commit(object);
else if (_option.check<InnerUIntType>()) _option.get<InnerUIntType>().commit(object);
else
{
throw Failure(STG(FMT("commit() not implemented for type used in option '%s'") % _myname));
}
}
catch (EmptyVariable & e)
{
throw Failure(STG(FMT("uninitialized variable while commiting option '%s'") % _myname));
}
}
const std::string & name(void) const { return _myname; }
bool listme(void) const { return _listme; };
const char ** values(void);
template < typename Object >
void copyFrom(const Object * const srcobj, Object * const dstobj, bool force = false)
{
if (loaded(dstobj) && !force)
return;
if (loaded(srcobj))
set(dstobj, get(srcobj));
else
reset(dstobj);
}
protected:
const std::string _myname;
InnerType _option;
const bool _listme;
const char ** _values;
};
struct Options
{
typedef std::vector < std::string > Messages;
Options();
~Options();
typedef std::set < std::string > StringSet;
typedef std::map < std::string, Option > OptionMap;
typedef std::pair < std::string, Option > OptionPair;
typedef std::map < std::string, std::string > SynOptionMap;
typedef std::pair < std::string, std::string > SynOptionPair;
bool add(Option option);
/* only valid in "process" (for backwards compatibility config files) */
bool synonym(std::string, std::string);
template < typename Type >
void set(const std::string & name, Type value)
{
OptionMap::iterator iter = find_option(name);
if (iter == _map.end())
throw Failure(STG(FMT("unknown option: %s") % name));
iter->second.set(value);
}
template < typename Object >
std::string get(const Object * const object, const std::string & name)
{
OptionMap::iterator iter = find_option(name);
if (iter == _map.end())
throw Failure(STG(FMT("unknown option: %s") % name));
return iter->second.get(object);
}
template < typename Object >
void process(Object * const object, const char * name, const char * value)
{
OptionMap::iterator iter = find_option(name);
if (iter == _map.end())
throw Failure(STG(FMT("unknown option '%s'") % name));
iter->second.set(object, value);
}
template < typename Object >
Messages commit(Object * const object)
{
Messages msgs;
for (OptionMap::iterator i = _map.begin(); i != _map.end(); ++i)
{
try
{
i->second.commit(object);
}
catch (Failure & e)
{
msgs.push_back(e.what());
}
}
return msgs;
}
template < typename Object >
void reset(Object * object)
{
for (OptionMap::iterator i = _map.begin(); i != _map.end(); ++i)
i->second.reset(object);
}
template < typename Object >
bool loaded(Object * object, std::string name)
{
OptionMap::iterator iter = find_option(name);
if (iter == _map.end())
return false;
return iter->second.loaded(object);
}
bool exists(const std::string & name)
{
OptionMap::iterator iter = find_option(name);
return (iter != _map.end());
}
StringSet options(void);
const char ** values(const char *); /* option value */
const char ** values(void); /* values from options */
template < typename Object >
void copyFrom(const std::string & name, const Object * const src_obj, Object * const dst_obj, bool force = false)
{
OptionMap::iterator iter = find_option(name);
if (iter == _map.end())
throw Failure(STG(FMT("unknown option '%s'") % name));
iter->second.copyFrom(src_obj, dst_obj, force);
}
template < typename Object >
void copyFrom(Object * src_obj, Object * dst_obj, bool force = false)
{
for (OptionMap::iterator iter = _map.begin(); iter != _map.end(); ++iter)
iter->second.copyFrom(src_obj, dst_obj, force);
}
protected:
OptionMap::iterator find_option(std::string);
protected:
OptionMap _map;
SynOptionMap _syn_map;
const char ** _values;
};
};
#endif /* _CONFIG_OPTIONS_HPP_ */

View File

@ -0,0 +1,241 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
the specific language governing rights and limitations under the License.
Alternatively, the contents of this file may be used under the terms of the
"GNU Lesser General Public License 2.1" license (the LGPL" License), in which
case the provisions of "LGPL License" are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
the LGPL License and not to allow others to use your version of this file under
the MPL, indicate your decision by deleting the provisions above and replace them
with the notice and other provisions required by the LGPL License. If you do not
delete the provisions above, a recipient may use your version of this file under
either the MPL or the LGPL License.
The LGPL header follows below:
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <errno.h>
#include <configurator/configfile.hpp>
#if _MSC_VER >= 1400
#undef close
#endif
void Configfile::ignore(const std::string & str)
{
_ignores.insert(str);
};
bool Configfile::select(Section **ptr, const std::string & str)
{
/* default section == this! */
*ptr = this;
/* always success by default */
return true;
};
bool Configfile::adjust(Section * section, const std::string & opt, const std::string & val)
{
return section->load(opt, val);
};
bool Configfile::deserialize(std::ifstream & fd)
{
Section * section = NULL;
/* default selection! */
if (!select(&section))
{
_errors.push_back("default selection has failed!");
return false;
}
size_t count = 0;
while (fd.good())
{
std::string str;
/* read one line! */
std::getline(fd, str);
size_t lst = str.size() - 1;
if (str.size() >= 1 && str[lst] == '\r') //cuida das quebras de linha do tipo \r\n
{
str.erase(lst,1);
--lst;
}
/* empty line! */
if (str.size() == 0)
continue;
/* comment! */
if (str[0] == '#')
continue;
++count;
if (str[0] == '[' && str[lst] == ']')
{
str.erase(0,1); --lst;
str.erase(lst,1); --lst;
if (!select(&section, str))
{
_errors.push_back(STG(FMT("erroneous section '%s'") % str));
/* ignore this section */
section = NULL;
continue;
}
}
else
{
std::string::size_type pos = str.find('=');
if (pos == std::string::npos)
{
_errors.push_back(STG(FMT("erroneous separator '%s'") % str));
continue;
};
if (section == NULL)
{
_errors.push_back(STG(FMT("no section for option '%s'") % str));
continue;
}
std::string opt(str.substr(0,pos));
std::string val(str.substr(pos+1));
if (_ignores.find(opt) != _ignores.end())
continue;
if (val == "@") val = "";
if (adjust(section, opt, val))
continue;
_errors.push_back(STG(FMT("option '%s' does "
"not exist or '%s' is not a valid value (at section '%s')")
% opt % val % section->name()));
}
}
// retorna 'true' se arquivo tinha alguma coisa valida.
return (count != 0);
}
bool Configfile::obtain()
{
std::ifstream fd(_filename.c_str());
if (!fd.is_open())
{
_errors.push_back(STG(FMT("unable to open file '%s': %s")
% _filename % strerror(errno)));
return false;
};
if (!deserialize(fd))
{
fd.close();
return false;
}
fd.close();
return true;
};
void Configfile::recurse(std::ofstream & fd, Section * section)
{
typedef Section::SectionMap::const_iterator SectionIter;
typedef Section::OptionMap::const_iterator OptionIter;
for (OptionIter i = section->option_begin(); i != section->option_end(); i++)
{
std::string res;
if ((*i).second.store(res))
{
if (res == "") res = "@";
fd << (*i).first << "=" << res << std::endl;
}
}
if (!section->recursive())
return;
for (SectionIter j = section->section_begin(); j != section->section_end(); j++)
recurse(fd, (*j).second);
}
bool Configfile::serialize(std::ofstream & fd)
{
recurse(fd, this);
return true;
}
bool Configfile::provide()
{
std::string tmp(_filename);
tmp += ".new";
std::ofstream fd(tmp.c_str());
if (!fd.good())
{
_errors.push_back(STG(FMT("unable to open file '%s': %s")
% tmp % strerror(errno)));
return false;
}
if (!serialize(fd))
{
fd.close();
return false;
}
fd.close();
if (rename(tmp.c_str(), _filename.c_str()) != 0)
{
_errors.push_back(STG(FMT("unable to replace config file '%s': %s")
% _filename % strerror(errno)));
return false;
}
return true;
}
#if _MSC_VER >= 1400
#define close _close
#endif

View File

@ -1,7 +1,7 @@
/*
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
Copyright (C) 2007-2009 Khomp Ind. & Com.
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
@ -23,20 +23,20 @@
The LGPL header follows below:
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <vector>
@ -53,38 +53,38 @@
struct Configfile: public Section
{
typedef std::list < std::string > ErrorVector;
typedef std::set < std::string > NameSet;
typedef std::list < std::string > ErrorVector;
typedef std::set < std::string > NameSet;
Configfile(std::string name, std::string desc)
: Section(name, desc), _good(false) {};
Configfile(const std::string & name, const std::string & desc)
: Section(name, desc), _good(false) {};
virtual ~Configfile() {};
virtual ~Configfile() {};
bool good() { return _good; };
std::string & filename() { return _filename; };
bool good() const { return _good; };
const std::string & filename() const { return _filename; };
ErrorVector & errors() { return _errors; };
const ErrorVector & errors() const { return _errors; };
void ignore(std::string);
void ignore(const std::string &);
virtual bool obtain();
virtual bool provide();
virtual bool obtain();
virtual bool provide();
protected:
virtual bool select(Section **, std::string str = "");
virtual bool adjust(Section *, std::string & opt, std::string & val);
virtual bool select(Section **, const std::string & str = "");
virtual bool adjust(Section *, const std::string & opt, const std::string & val);
virtual bool deserialize(std::ifstream &);
virtual bool serialize(std::ofstream &);
virtual bool deserialize(std::ifstream &);
virtual bool serialize(std::ofstream &);
void recurse(std::ofstream &, Section *);
void recurse(std::ofstream &, Section *);
protected:
bool _good;
ErrorVector _errors;
NameSet _ignores;
std::string _filename;
bool _good;
ErrorVector _errors;
NameSet _ignores;
std::string _filename;
};
#endif /* _CONFIG_CONFIGFILE_HPP_ */

View File

@ -0,0 +1,186 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
the specific language governing rights and limitations under the License.
Alternatively, the contents of this file may be used under the terms of the
"GNU Lesser General Public License 2.1" license (the LGPL" License), in which
case the provisions of "LGPL License" are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
the LGPL License and not to allow others to use your version of this file under
the MPL, indicate your decision by deleting the provisions above and replace them
with the notice and other provisions required by the LGPL License. If you do not
delete the provisions above, a recipient may use your version of this file under
either the MPL or the LGPL License.
The LGPL header follows below:
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <configurator/option.hpp>
bool Option::equals(const std::string & value) const
{
switch (_restriction.numeral())
{
case Restriction::N_UNIQUE:
{
Restriction::Value my_value;
if (!_restriction.get(Restriction::F_USER, my_value))
return false;
return (my_value == value);
}
case Restriction::N_MULTIPLE:
{
Restriction::Vector my_values;
if (!_restriction.get(Restriction::F_USER, my_values))
return false;
for (Restriction::Vector::iterator i = my_values.begin(); i != my_values.end(); i++)
{
if ((*i) == value)
return true;
}
return false;
}
}
return false;
}
bool Option::load(const std::string & value)
{
bool ret = _restriction.set( (const Restriction::Format)Restriction::F_FILE, value);
if (ret) _modified = false;
return ret;
}
bool Option::change(const std::string & value)
{
bool ret = _restriction.set(Restriction::F_FILE, value);
if (ret) _modified = true;
return ret;
}
bool Option::store(std::string & value) const
{
switch (_restriction.numeral())
{
case Restriction::N_UNIQUE:
return _restriction.get(Restriction::F_FILE, value);
case Restriction::N_MULTIPLE:
{
Restriction::Vector values;
if (!_restriction.get(Restriction::F_FILE, values))
return false;
Strings::Merger strs;
for (Restriction::Vector::iterator i = values.begin(); i != values.end(); i++)
strs.add(*i);
value = strs.merge(",");
return true;
}
default:
return false;
}
}
/*
Option::Flags Option::set(const char * value)
{
std::string str_value(value);
return set(str_value);
}
*/
Option::Flags Option::set(const Restriction::Value & value)
{
Restriction::Value last_value, curr_value;
Flags flags;
bool ret1 = _restriction.get(Restriction::F_USER, last_value);
if (!_restriction.set(Restriction::F_USER, value))
return flags;
flags[F_ADJUSTED] = true;
bool ret2 = _restriction.get(Restriction::F_USER, curr_value);
if (!ret1 || (ret2 && (last_value != curr_value)))
{
flags[F_MODIFIED] = true;
_modified = true;
}
return flags;
}
Option::Flags Option::set(const Restriction::Vector & values)
{
Restriction::Vector last_values, curr_values;
Flags flags;
bool ret1 = _restriction.get(Restriction::F_USER, last_values);
if (!_restriction.set(Restriction::F_USER, values))
return flags;
flags[F_ADJUSTED] = true;
bool ret2 = _restriction.get(Restriction::F_USER, curr_values);
if (!ret1 || (ret2 && (last_values != curr_values)))
{
flags[F_MODIFIED] = true;
_modified = true;
}
return flags;
}
bool Option::get(Restriction::Value & value) const
{
return _restriction.get(Restriction::F_USER, value);
}
bool Option::get(Restriction::Vector & values) const
{
return _restriction.get(Restriction::F_USER, values);
}

View File

@ -1,7 +1,7 @@
/*
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
Copyright (C) 2007-2009 Khomp Ind. & Com.
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
@ -23,20 +23,20 @@
The LGPL header follows below:
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <iostream>
@ -45,6 +45,7 @@
#include <list>
#include <vector>
#include <format.hpp>
#include <strings.hpp>
#include <configurator/restriction.hpp>
@ -56,67 +57,72 @@ struct Option
{
enum FlagTypes
{
F_MODIFIED = 0x0, /* if option was modified */
F_ADJUSTED = 0x1, /* if option was correctly formated */
F_MODIFIED = 0x0, /* if option was modified */
F_ADJUSTED = 0x1, /* if option was correctly formated */
};
struct Flags: public std::vector<bool>
{
Flags(): std::vector<bool>(2) {};
};
struct Flags: public std::vector<bool>
{
Flags(): std::vector<bool>(2) {};
};
typedef Restriction::Value Value;
typedef Restriction::Vector Vector;
typedef Restriction::Value Value;
typedef Restriction::Vector Vector;
/* exception */
struct InvalidDefaultValue
struct InvalidDefaultValue: public std::runtime_error
{
InvalidDefaultValue(std::string name, std::string value)
: _name(name), _value(value) {};
InvalidDefaultValue(const std::string & name, const std::string & value)
: std::runtime_error(STG(FMT("invalid default value '%s' for option '%s'") % value % name)),
_name(name), _value(value)
{};
std::string & name() { return _name; };
std::string & value() { return _value; };
~InvalidDefaultValue() throw ()
{};
const std::string & name() const { return _name; };
const std::string & value() const { return _value; };
protected:
std::string _name;
std::string _value;
const std::string _name;
const std::string _value;
};
Option(std::string name, std::string desc, std::string defvalue, Restriction restriction)
: _name(name), _desc(desc), _restriction(restriction), _modified(true)
{
std::string value(defvalue);
Option(const std::string & name, const std::string & desc, const std::string & defvalue, const Restriction & restriction)
: _name(name), _description(desc), _restriction(restriction), _modified(true)
{
// std::string value(defvalue);
if (!(set(value)[F_ADJUSTED]))
if (!(set(defvalue)[F_ADJUSTED]))
throw InvalidDefaultValue(name, defvalue);
}
}
const std::string & name() { return _name; };
const std::string & description() { return _desc; };
const std::string & name() const { return _name; };
const std::string & description() const { return _description; };
Restriction & restriction() { return _restriction; };
bool modified() { return _modified; };
const Restriction & restriction() const { return _restriction; };
bool modified() const { return _modified; };
public:
bool load(std::string &);
bool change(std::string &);
bool store(std::string &);
bool load(const std::string &);
bool change(const std::string &);
bool store(std::string &) const;
Flags set(const char *);
Flags set(Value &);
Flags set(Vector &);
// Flags set(const char *);
Flags set(const Value &);
Flags set(const Vector &);
bool get(Value &);
bool get(Vector &);
bool get(Value &) const;
bool get(Vector &) const;
bool equals(std::string &);
bool equals(const std::string &) const;
protected:
std::string _name;
std::string _desc;
const std::string _name;
const std::string _description;
Restriction _restriction;
bool _modified;
Restriction _restriction;
bool _modified;
};
#endif /* _CONFIG_OPTION_HPP_ */

View File

@ -0,0 +1,358 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
the specific language governing rights and limitations under the License.
Alternatively, the contents of this file may be used under the terms of the
"GNU Lesser General Public License 2.1" license (the LGPL" License), in which
case the provisions of "LGPL License" are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
the LGPL License and not to allow others to use your version of this file under
the MPL, indicate your decision by deleting the provisions above and replace them
with the notice and other provisions required by the LGPL License. If you do not
delete the provisions above, a recipient may use your version of this file under
either the MPL or the LGPL License.
The LGPL header follows below:
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <math.h>
#include <string.h>
#include <iostream>
#include <strings.hpp>
#include <configurator/restriction.hpp>
/* internal helper! */
bool Restriction::equalNumber(const double a, const double b)
{
char tmp1[64];
char tmp2[64];
snprintf(tmp1, sizeof(tmp1), "%.3f", a);
snprintf(tmp2, sizeof(tmp2), "%.3f", b);
if (strncmp(tmp1, tmp2, sizeof(tmp1)))
return false;
return true;
}
/* process value to our internal representation */
bool Restriction::process(Restriction::Format fmt,
const Restriction::Value & value, Restriction::Value & final) const
{
switch (_bounds)
{
case B_RANGE:
{
if (_kind != K_NUMBER)
return false;
std::string tmpvalue;
Restriction::Value::const_iterator itr = value.begin();
Restriction::Value::const_iterator end = value.end();
tmpvalue.reserve(value.size());
// f*cking dot/comma notation!
for (; itr != end; ++itr)
tmpvalue += ((*itr) != ',' ? (*itr) : '.');
try
{
double newvalue = Strings::todouble(tmpvalue);
if (newvalue < _init && newvalue > _fini)
return false;
double res = (newvalue - _init) / _step;
if (!Restriction::equalNumber(res, rint(res)))
return false;
final = value;
return true;
}
catch (...)
{
return false;
}
}
case B_LIST:
for (List::const_iterator i = _list.begin(); i != _list.end(); i++)
{
const Value & tmp = (*i);
if (tmp == value)
{
final = value;
return true;
}
}
return false;
case B_MAPS:
switch (fmt)
{
case F_USER:
{
Map::const_iterator i = _map_from_usr.find(value);
if (i == _map_from_usr.end())
return false;
const Value & tmp = (*i).second;
final = tmp;
return true;
}
case F_FILE:
{
Map::const_iterator i = _map_from_cfg.find(value);
if (i == _map_from_cfg.end())
return false;
final = value;
return true;
}
default:
break;
}
return false;
case B_FREE:
final = value;
return true;
default:
break;
}
return false;
}
/* unprocess the value (outputs the external representation) */
bool Restriction::unprocess(Restriction::Format fmt,
const Restriction::Value & value, Restriction::Value & final) const
{
switch (_bounds)
{
case B_MAPS:
switch (fmt)
{
case F_USER:
{
Map::const_iterator i = _map_from_cfg.find(value);
if (i == _map_from_cfg.end())
return false;
final = (*i).second;
return true;
}
default:
break;
}
default:
final = value;
return true;
}
}
/***************************** *****************************/
bool Restriction::get(Restriction::Format fmt, Restriction::Value & value) const
{
if (_numeral != N_UNIQUE)
return false;
if (!unprocess(fmt, _value._unique, value))
return false;
return true;
}
bool Restriction::get(Restriction::Format fmt, Restriction::Vector & values) const
{
if (_numeral != N_MULTIPLE)
return false;
const List & my_values = _value._multiple;
for (List::const_iterator i = my_values.begin(); i != my_values.end(); i++)
{
const Value & value = (*i);
Value final;
if (!unprocess(fmt, value, final))
return false;
values.push_back(final);
};
return true;
}
/***************************** *****************************/
bool Restriction::set(Restriction::Format fmt, const Restriction::Value & value)
{
switch (_numeral)
{
case N_UNIQUE:
{
Value final;
if (!constThis().process(fmt, value, final))
return false;
_value._unique = final;
return true;
}
case N_MULTIPLE:
{
if (value == "@" || value == "#" || value == "")
{
_value._multiple.clear();
return true;
}
Strings::vector_type values;
Strings::tokenize(value, values, ",");
return set(fmt, values);
}
default:
return false;
}
}
bool Restriction::set(Restriction::Format fmt, const Restriction::Vector & values)
{
if (_numeral != N_MULTIPLE)
return false;
if (values.empty())
{
_value._multiple.clear();
}
else
{
/* list needed to store temporary values */
List finals;
for (Vector::const_iterator i = values.begin(); i != values.end(); i++)
{
const Value & value = (*i);
Value final;
if (!constThis().process(fmt, value, final))
return false;
finals.push_back(final);
}
List & lst = _value._multiple;
/* need to clear values set before */
lst.clear();
for (List::iterator i = finals.begin(); i != finals.end(); i++)
{
Value value = (*i);
lst.push_back(value);
}
};
return true;
}
/***************************** *****************************/
void Restriction::allowed(Restriction::Vector & vals) const
{
switch (_bounds)
{
case B_FREE:
return;
case B_LIST:
for (List::const_iterator i = _list.begin(); i != _list.end(); i++)
vals.push_back(*i);
break;
case B_MAPS:
for (Map::const_iterator i = _map_from_usr.begin(); i != _map_from_usr.end(); i++)
vals.push_back(i->first);
break;
case B_RANGE:
{
if (_kind != K_NUMBER)
return;
// is there any fraction?
bool has_fraction =
(!Restriction::equalNumber(_init, rint(_init))) ||
(!Restriction::equalNumber(_fini, rint(_fini))) ||
(!Restriction::equalNumber(_step, rint(_step)));
const char * format = (has_fraction ? "%.2f" : "%02.0f");
for (double i = _init; i <= _fini; i += _step)
{
char tmp[32];
snprintf(tmp, sizeof(tmp), format, i);
vals.push_back(std::string(tmp));
}
break;
}
default:
break;
}
}
void Restriction::init_class()
{
_value._unique.clear();
_value._multiple.clear();
}

View File

@ -0,0 +1,269 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
the specific language governing rights and limitations under the License.
Alternatively, the contents of this file may be used under the terms of the
"GNU Lesser General Public License 2.1" license (the LGPL" License), in which
case the provisions of "LGPL License" are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
the LGPL License and not to allow others to use your version of this file under
the MPL, indicate your decision by deleting the provisions above and replace them
with the notice and other provisions required by the LGPL License. If you do not
delete the provisions above, a recipient may use your version of this file under
either the MPL or the LGPL License.
The LGPL header follows below:
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdarg.h>
#include <string>
#include <list>
#include <vector>
#include <map>
#include <const_this.hpp>
#ifndef _CONFIG_RESTRICTION_HPP_
#define _CONFIG_RESTRICTION_HPP_
struct Restriction: public ConstThis < Restriction >
{
/* generic types */
// TODO: change this type name for something different
// to avoid conflicting with "format.hpp".
enum Format
{
F_USER,
F_FILE
};
enum Kind
{
K_STRING,
K_NUMBER // = K_INTEGER // compatibility
};
enum Bounds
{
B_FREE,
B_RANGE,
B_LIST,
B_MAPS
};
enum Numeral
{
N_UNIQUE,
N_MULTIPLE
};
typedef std::string Value;
/* types used for data input */
struct Pair
{
const char *pretty;
const char *value;
};
typedef std::pair < Value, Value > PairMap;
typedef std::list < PairMap > ListMap;
/* types used internally */
typedef std::map < Value, Value > Map;
typedef std::vector < Value > Vector;
typedef std::list < Value > List;
typedef std::pair < Value, Value > MapPair;
struct Generic
{
Value _unique;
List _multiple;
};
Restriction(Kind kind, Numeral num)
: _kind(kind), _bounds(B_FREE), _numeral(num), _unit(""),
_init(-1), _fini(-1), _step(-1)
{
init_class();
}
Restriction(Kind kind, Numeral num,
double init, double fini, double step = 1)
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(""),
_init(init), _fini(fini), _step(step)
{
init_class();
}
Restriction(Kind kind, Numeral num,
const char *unit, double init, double fini, double step = 1.0)
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
_init(init), _fini(fini), _step(step)
{
init_class();
}
Restriction(Kind kind, Numeral num,
std::string unit, double init, double fini, double step = 1.0)
: _kind(kind), _bounds(B_RANGE), _numeral(num), _unit(unit),
_init(init), _fini(fini), _step(step)
{
init_class();
}
Restriction(Kind kind, Numeral num,
const char *first, ...)
: _kind(kind), _bounds(B_LIST), _numeral(num), _unit(""),
_init(-1), _fini(-1), _step(-1)
{
_list.push_back(std::string(first));
va_list ap;
va_start(ap, first);
while (true)
{
const char *arg = va_arg(ap, const char *);
if (arg == NULL) break;
_list.push_back(std::string(arg));
}
init_class();
}
Restriction(Kind kind, const char *unit, Numeral num,
const char *first, ...)
: _kind(kind), _bounds(B_LIST), _numeral(num), _unit(unit),
_init(-1), _fini(-1), _step(-1)
{
_list.push_back(std::string(first));
va_list ap;
va_start(ap, first);
while (true)
{
const char *arg = va_arg(ap, const char *);
if (arg == NULL) break;
_list.push_back(std::string(arg));
}
init_class();
}
Restriction(Kind kind, Numeral num,
const struct Pair first, ...)
: _kind(kind), _bounds(B_MAPS), _numeral(num), _unit(""),
_init(-1), _fini(-1), _step(-1)
{
_map_from_usr.insert(MapPair(Value(first.pretty), Value(first.value)));
_map_from_cfg.insert(MapPair(Value(first.value), Value(first.pretty)));
va_list ap;
va_start(ap, first);
while (true)
{
Pair arg = va_arg(ap, Pair);
if (arg.pretty == NULL) break;
_map_from_usr.insert(MapPair(Value(arg.pretty), Value(arg.value)));
_map_from_cfg.insert(MapPair(Value(arg.value), Value(arg.pretty)));
}
init_class();
}
Restriction(Kind kind, Numeral num, List list)
: _kind(kind), _bounds(B_LIST), _numeral(num), _unit(""),
_init(-1), _fini(-1), _step(-1), _list(list)
{
init_class();
}
Restriction(Kind kind, Numeral num, ListMap map)
: _kind(kind), _bounds(B_MAPS), _numeral(num), _unit(""),
_init(-1), _fini(-1), _step(-1)
{
for (ListMap::iterator i = map.begin(); i != map.end(); i++)
{
_map_from_usr.insert(MapPair(Value((*i).first), Value((*i).second)));
_map_from_cfg.insert(MapPair(Value((*i).second), Value((*i).first)));
}
init_class();
}
const Kind kind() const { return _kind; };
const Bounds bounds() const { return _bounds; };
const Numeral numeral() const { return _numeral; };
const std::string & unit() const { return _unit; };
bool set(Format, const Vector &);
bool set(Format, const Value &);
bool get(Format, Vector &) const;
bool get(Format, Value &) const;
void allowed(Vector &) const;
private:
bool process(const Format, const Value &, Value &) const;
bool unprocess(const Format, const Value &, Value &) const;
void init_class();
static bool equalNumber(const double, const double);
protected:
const Kind _kind;
const Bounds _bounds;
const Numeral _numeral;
Value _unit;
const double _init, _fini, _step;
Map _map_from_usr,
_map_from_cfg;
List _list;
Generic _value;
};
#endif /* _CONFIG_RESTRICTION_HPP_ */

View File

@ -1,7 +1,7 @@
/*
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
Copyright (C) 2007-2009 Khomp Ind. & Com.
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
@ -23,108 +23,114 @@
The LGPL header follows below:
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <configurator/section.hpp>
void Section::options(Section::OptionVector & vec)
void Section::options(Section::OptionVector & vec) const
{
for (OptionMap::iterator it = _options.begin(); it != _options.end();)
{
vec.push_back(&((*it).second));
++it;
}
for (OptionMap::const_iterator it = _options.begin(); it != _options.end();)
{
vec.push_back(const_cast< Option * >(&(it->second)));
++it;
}
}
void Section::sections(Section::SectionVector & vec)
void Section::sections(Section::SectionVector & vec) const
{
for (SectionMap::iterator it = _sections.begin(); it != _sections.end();)
{
vec.push_back((*it).second);
++it;
}
for (SectionMap::const_iterator it = _sections.begin(); it != _sections.end();)
{
vec.push_back(const_cast< Section * >(it->second));
++it;
}
}
/*********/
Option * Section::option_find(std::string & str, bool recurse)
Option * Section::option_find(const std::string & str, bool recurse) const
{
OptionMap::iterator i = _options.find(str);
OptionMap::const_iterator i = _options.find(str);
if (i == _options.end())
if (i == _options.end())
{
if (!recurse)
throw not_found();
throw OptionNotFound(str, _name);
// throw not_found();
for (SectionMap::iterator i = _sections.begin(); i != _sections.end(); i++)
for (SectionMap::const_iterator i = _sections.begin(); i != _sections.end(); i++)
{
try
{
return i->second->option_find(str, recurse);
}
catch (not_found & e)
catch (NotFound & e)
{
/* keep looping! */
};
}
throw not_found();
// throw not_found();
throw OptionNotFound(str, _name);
}
return &((*i).second);
return const_cast< Option * >(&(i->second));
}
/*
Option * Section::option_find(const char * str, bool recurse)
{
std::string sstr(str);
return option_find(sstr, recurse);
std::string sstr(str);
return option_find(sstr, recurse);
}
*/
/*********/
Section * Section::section_find(std::string & str, bool recurse)
Section * Section::section_find(const std::string & str, bool recurse) const
{
SectionMap::iterator i = _sections.find(str);
SectionMap::const_iterator i = _sections.find(str);
if (i == _sections.end())
if (i == _sections.end())
{
if (!recurse)
throw not_found();
throw SectionNotFound(str, _name);
for (SectionMap::iterator i = _sections.begin(); i != _sections.end(); i++)
for (SectionMap::const_iterator i = _sections.begin(); i != _sections.end(); i++)
{
try
{
return i->second->section_find(str, recurse);
}
catch (not_found & e)
catch (NotFound & e)
{
/* keep looping! */
};
}
throw not_found();
throw SectionNotFound(str, _name);
}
return ((*i).second);
return const_cast< Section * >(i->second);
}
/*
Section * Section::section_find(const char * str, bool recurse)
{
std::string sstr(str);
return section_find(sstr, recurse);
std::string sstr(str);
return section_find(sstr, recurse);
}
*/

View File

@ -0,0 +1,260 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
the specific language governing rights and limitations under the License.
Alternatively, the contents of this file may be used under the terms of the
"GNU Lesser General Public License 2.1" license (the LGPL" License), in which
case the provisions of "LGPL License" are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
the LGPL License and not to allow others to use your version of this file under
the MPL, indicate your decision by deleting the provisions above and replace them
with the notice and other provisions required by the LGPL License. If you do not
delete the provisions above, a recipient may use your version of this file under
either the MPL or the LGPL License.
The LGPL header follows below:
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _CONFIG_SECTION_HPP_
#define _CONFIG_SECTION_HPP_
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>
#include <format.hpp>
#include <configurator/option.hpp>
struct Section
{
typedef std::map < std::string, Option > OptionMap;
typedef std::vector< Option * > OptionVector;
typedef std::map < std::string, Section * > SectionMap;
typedef std::vector < Section * > SectionVector;
struct NotFound: public std::runtime_error
{
NotFound(const std::string & type, const std::string & name, const std::string & me)
: std::runtime_error(STG(FMT("%s '%s' not found on section '%s'") % type % name % me)) {};
};
struct OptionNotFound: public NotFound
{
OptionNotFound(const std::string & name, const std::string & me)
: NotFound("option", name, me) {};
};
struct SectionNotFound: public NotFound
{
SectionNotFound(const std::string & name, const std::string & me)
: NotFound("section", name, me) {};
};
typedef NotFound not_found; /* backward compatibility */
// protected:
Section(const std::string & name, const std::string & desc, bool recursive = true)
: _name(name), _description(desc), _recursive(recursive) {};
void add(const Option & o)
{
_options.insert(std::pair<std::string,Option>(o.name(), o));
};
void del(const std::string & name)
{
_options.erase(name);
};
void add(Section * s)
{
_sections.insert(std::pair< std::string, Section * >(s->name(), s));
};
public:
const std::string & name() const { return _name; };
const std::string & description() const { return _description; };
const bool recursive() const { return _recursive; };
OptionMap::const_iterator option_begin() const { return _options.begin(); };
OptionMap::const_iterator option_end() const { return _options.end(); };
SectionMap::const_iterator section_begin() const { return _sections.begin(); };
SectionMap::const_iterator section_end() const { return _sections.end(); };
/**/
// Option * option_find(const char *, bool recurse = false) const;
// Section * section_find(const char *, bool recurse = false) const;
Option * option_find(const std::string &, bool recurse = false) const;
Section * section_find(const std::string &, bool recurse = false) const;
/**/
void options(OptionVector &) const;
void sections(SectionVector &) const;
/**/
template < typename T, typename F >
bool search_and_apply(const std::string & key, T & value, F f)
{
OptionMap::iterator i = _options.find(key);
if (i != _options.end())
return f(i->second);
if (!_recursive)
return false;
return (find_if(_sections.begin(), _sections.end(), f) != _sections.end());
}
private:
struct ConstKeyValue
{
ConstKeyValue(const std::string & k, const std::string &v)
: _k(k), _v(v) {};
const std::string & _k;
const std::string & _v;
};
struct KeyValue
{
KeyValue(const std::string & k, std::string &v)
: _k(k), _v(v) {};
const std::string & _k;
std::string & _v;
};
struct load_section: protected ConstKeyValue
{
load_section(const std::string & k, const std::string & v): ConstKeyValue(k,v) {};
bool operator()(Option & o) { return o.load(_v); };
bool operator()(SectionMap::value_type & v) { return v.second->load(_k,_v); };
};
struct change_section: protected ConstKeyValue
{
change_section(const std::string & k, const std::string & v): ConstKeyValue(k,v) {};
bool operator()(Option & o) { return o.change(_v); };
bool operator()(SectionMap::value_type & v) { return v.second->change(_k,_v); };
};
struct store_section: protected KeyValue
{
store_section(const std::string & k, std::string & v): KeyValue(k,v) {};
bool operator()(Option & o) { return o.store(_v); };
bool operator()(SectionMap::value_type & v) { return v.second->store(_k,_v); };
};
struct set_section: protected ConstKeyValue
{
set_section(const std::string & k, const std::string & v): ConstKeyValue(k,v) {};
bool operator()(Option & o) { return (o.set(_v))[Option::F_ADJUSTED]; };
bool operator()(SectionMap::value_type & v) { return v.second->set(_k,_v); };
};
struct get_section: protected KeyValue
{
get_section(const std::string & k, std::string & v): KeyValue(k,v) {};
bool operator()(Option & o) { return o.get(_v); };
bool operator()(SectionMap::value_type & v) { return v.second->get(_k,_v); };
};
struct modified_section
{
bool operator()(const OptionMap::value_type & v) { return v.second.modified(); };
bool operator()(const SectionMap::value_type & v) { return v.second->modified(); };
};
public:
/*
bool load(const char * key, const std::string value)
{
std::string skey(key);
return search_and_apply(skey, value, load_section(skey, value));
}
*/
bool load(const std::string & key, const std::string & value)
{
return search_and_apply(key, value, load_section(key, value));
}
bool change(const std::string & key, const std::string & value)
{
return search_and_apply(key, value, change_section(key, value));
}
bool store(const std::string & key, std::string & value)
{
return search_and_apply(key, value, store_section(key, value));
}
bool set(const std::string & key, const std::string & value)
{
return search_and_apply(key, value, set_section(key, value));
}
bool get(const std::string & key, std::string & value)
{
return search_and_apply(key, value, get_section(key, value));
}
bool modified() const
{
return ((find_if(_options.begin(), _options.end(), modified_section()) != _options.end()) ||
(find_if(_sections.begin(), _sections.end(), modified_section()) != _sections.end()));
}
private:
Section(): _name(""), _description(""), _recursive(false) {};
protected:
const std::string _name;
const std::string _description;
OptionMap _options;
SectionMap _sections;
const bool _recursive;
};
#endif /* _CONFIG_SECTION_HPP_ */

View File

@ -0,0 +1,15 @@
#ifndef _CONST_THIS_H_
#define _CONST_THIS_H_
template < typename T >
struct ConstThis
{
T const & constThis() const
{
// TODO: will this return the right reference?
return static_cast<const T&>(*this);
}
};
#endif /* _CONST_THIS_H_ */

View File

@ -42,27 +42,7 @@
#include "format.hpp"
//#include <iostream>
Format::Format(const char * format_string, bool raise_exception)
: _format(format_string), _valid(true), _raise(raise_exception)
{
initialize(format_string);
}
/*
Format::Format(std::string & format_string, bool raise_exception)
: _format(NULL), _valid(true), _raise(raise_exception)
{
initialize(format_string.c_str());
}
*/
Format::Format(std::string format_string, bool raise_exception)
: _format(format_string), _valid(true), _raise(raise_exception)
{
initialize(format_string.c_str());
}
void Format::initialize(const char * format_string)
void FormatTraits::initialize(const char * format_string)
{
std::string txt;
@ -82,7 +62,6 @@ void Format::initialize(const char * format_string)
if (*ptr2 == '%')
{
txt += *ptr;
ptr += 2;
continue;
}
@ -238,36 +217,20 @@ void Format::initialize(const char * format_string)
push_argument(txt, T_LITERAL);
}
void Format::mark_invalid(std::string & msg)
void FormatTraits::push_argument(std::string & data, FormatTraits::Type type)
{
if (_valid)
{
_valid = false;
// std::cerr << "pushing type (" << type << ") with format (" << data << ")" << std::endl;
std::string finalmsg;
finalmsg += "** INVALID FORMAT: ";
finalmsg += msg;
finalmsg += " **";
_result = finalmsg;
}
_args.push(Argument(data, type));
data.clear();
}
void Format::raise_check(void)
void FormatTraits::pop_argument(void)
{
if (!_valid && _raise)
throw InvalidFormat(_result);
_args.pop();
}
bool Format::validity_check(void)
{
raise_check();
return _valid;
}
const Format::Argument * Format::next_argument(void)
const FormatTraits::Argument * FormatTraits::next_argument(void)
{
// std::cerr << "size: " << _args.size() << std::endl;
@ -294,38 +257,81 @@ const Format::Argument * Format::next_argument(void)
}
}
void Format::pop_argument(void)
/******************************************************************/
#if 0
Format::Format(const char * format_string, bool raise_exception)
: _format(format_string), _valid(true), _raise(raise_exception)
{
_args.pop();
FormatTraits::initialize(format_string);
}
void Format::push_argument(std::string & data, Format::Type type)
Format::Format(std::string format_string, bool raise_exception)
: _format(format_string), _valid(true), _raise(raise_exception)
{
// std::cerr << "pushing type (" << type << ") with format (" << data << ")" << std::endl;
FormatTraits::initialize(format_string.c_str());
}
_args.push(Argument(data, type));
data.clear();
/*
Format::Format(std::string & format_string, bool raise_exception)
: _format(NULL), _valid(true), _raise(raise_exception)
{
initialize(format_string.c_str());
}
*/
void Format::mark_invalid(std::string & msg)
{
if (_valid)
{
_valid = false;
_result = "** INVALID FORMAT: ";
_result += msg;
_result += " **";
}
}
void Format::raise(void) const
{
if (!_valid)
{
// call specialized class
FormatException::raise(_result);
}
}
bool Format::valid(void) const
{
// raise();
return _valid;
}
std::string Format::str()
{
if (!validity_check())
if (!valid())
return _result;
if (next_argument() == NULL)
// try
// {
if (next_argument() != NULL)
{
std::string msg;
msg += "too few arguments passed for format '";
msg += _format;
msg += "' (";
msg += _format;
msg += ")";
mark_invalid(msg);
return _result;
std::string msg;
msg += "too few arguments passed for format '";
msg += _format;
msg += "' (";
msg += _format;
msg += ")";
mark_invalid(msg);
return _result;
}
// catch (NoArgumentLeft e)
// {
// return _result;
// }
}
#endif

View File

@ -52,37 +52,35 @@
#include <stdio.h>
#ifdef WIN32 // WINDOWS
#include <KHostSystem.h>
# include <KHostSystem.h>
#endif
/* macros used for shortening lines and making the code clearer */
#define STG(x) (x).str()
#define FMT(x) Format(x)
struct Format
struct InvalidFormat
{
static const unsigned int strings_base_length = 64;
static const unsigned int generic_base_length = 64;
InvalidFormat(std::string _msg) : msg(_msg) {}
const std::string msg;
};
struct InvalidFormat
template < bool E >
struct FormatException
{
void raise(const std::string & msg) const
{
InvalidFormat(std::string msg) : _msg(msg) {}
std::string _msg;
/* DO NOTHING */
};
};
explicit Format(const char * format_string, bool raise_exception = false);
explicit Format(std::string format_string, bool raise_exception = false);
void initialize(const char *);
std::string str(void);
////////////////////////////////////////////////////////////
protected:
template < >
struct FormatException < true >
{
void raise(const std::string & msg) const
{
throw InvalidFormat(msg);
};
};
struct FormatTraits
{
enum Type
{
T_ANYTHING = 1,
@ -113,24 +111,240 @@ struct Format
Argument(std::string fmts, Type type)
: _fmts(fmts), _type(type) {};
Type type(void) const { return _type; }
const Type type(void) const { return _type; }
const std::string & fmts(void) const { return _fmts; }
protected:
std::string _fmts;
Type _type;
const std::string _fmts;
const Type _type;
};
typedef std::queue < Argument > ArgumentQueue;
////////////////////////////////////////////////////////////
public:
//////////////////////////////////
template < typename V >
Format & operator%( V value )
bool number_verify_signed_short( V value ) const
{
if (!validity_check())
return
((typeid(V) == typeid(short int) ||
typeid(V) == typeid(short) ||
typeid(V) == typeid(const short int) ||
typeid(V) == typeid(const short) ||
typeid(V) == typeid(volatile short int) ||
typeid(V) == typeid(volatile short)) &&
sizeof(V) == sizeof(short));
}
template < typename V >
bool number_verify_unsigned_short( V value ) const
{
return
((typeid(V) == typeid(unsigned short int) ||
typeid(V) == typeid(unsigned short) ||
typeid(V) == typeid(const unsigned short int) ||
typeid(V) == typeid(const unsigned short) ||
typeid(V) == typeid(volatile unsigned short int) ||
typeid(V) == typeid(volatile unsigned short)) &&
sizeof(V) == sizeof(unsigned short));
}
template < typename V >
bool number_verify_signed_long( V value ) const
{
return
((typeid(V) == typeid(long int) ||
typeid(V) == typeid(long) ||
typeid(V) == typeid(const long int) ||
typeid(V) == typeid(const long) ||
typeid(V) == typeid(volatile long int) ||
typeid(V) == typeid(volatile long)) &&
sizeof(V) == sizeof(long));
}
template < typename V >
bool number_verify_unsigned_long( V value ) const
{
return
((typeid(V) == typeid(unsigned long int) ||
typeid(V) == typeid(unsigned long) ||
typeid(V) == typeid(const unsigned long int) ||
typeid(V) == typeid(const unsigned long) ||
typeid(V) == typeid(volatile unsigned long int) ||
typeid(V) == typeid(volatile unsigned long)) &&
sizeof(V) == sizeof(long long));
}
template < typename V >
bool number_verify_signed_long_long( V value ) const
{
return
((typeid(V) == typeid(long long int) ||
typeid(V) == typeid(long long) ||
typeid(V) == typeid(const long long int) ||
typeid(V) == typeid(const long long) ||
typeid(V) == typeid(volatile long long) ||
typeid(V) == typeid(volatile long long int)) &&
sizeof(V) == sizeof(long long));
}
template < typename V >
bool number_verify_unsigned_long_long( V value ) const
{
return
((typeid(V) == typeid(unsigned long long int) ||
typeid(V) == typeid(unsigned long long) ||
typeid(V) == typeid(const unsigned long long int) ||
typeid(V) == typeid(const unsigned long long) ||
typeid(V) == typeid(volatile unsigned long long) ||
typeid(V) == typeid(volatile unsigned long long int)) &&
sizeof(V) == sizeof(unsigned long long));
}
template < typename V >
bool number_verify_signed_int( V value ) const
{
return
(sizeof(V) <= sizeof(int) ||
typeid(V) == typeid(int) ||
typeid(V) == typeid(const int) ||
typeid(V) == typeid(volatile int));
}
template < typename V >
bool number_verify_unsigned_int( V value ) const
{
return
(sizeof(V) <= sizeof(unsigned int) ||
typeid(V) == typeid(unsigned int) ||
typeid(V) == typeid(const unsigned int) ||
typeid(V) == typeid(volatile unsigned int));
}
template < typename V >
bool generic_verify( V value, const Type type ) const
{
switch (type)
{
/* EXCEPTION: consider any number an valid input. */
case T_SIGNED_INT:
case T_UNSIGNED_INT:
return
(number_verify_signed_int(value) ||
number_verify_unsigned_int(value) ||
number_verify_signed_long(value) ||
number_verify_unsigned_long(value) ||
number_verify_signed_short(value) ||
number_verify_unsigned_short(value));
case T_SIGNED_SHORT_SHORT:
return (typeid(V) == typeid(char) || typeid(V) == typeid(const char));
case T_SIGNED_SHORT:
return number_verify_signed_short(value);
case T_SIGNED_LONG:
return number_verify_signed_long(value);
case T_SIGNED_LONG_LONG:
return number_verify_signed_long_long(value);
case T_UNSIGNED_SHORT_SHORT:
return (typeid(V) == typeid(unsigned char) || typeid(V) == typeid(unsigned char));
case T_UNSIGNED_SHORT:
return number_verify_unsigned_short(value);
case T_UNSIGNED_LONG:
return number_verify_unsigned_long(value);
case T_UNSIGNED_LONG_LONG:
return number_verify_unsigned_long_long(value);
case T_FLOAT:
return (typeid(V) == typeid(float)) || (typeid(V) == typeid(double) ||
typeid(V) == typeid(const float)) || (typeid(V) == typeid(const double));
case T_CHAR:
return (typeid(V) == typeid(char)) || (typeid(V) == typeid(unsigned char) ||
typeid(V) == typeid(const char)) || (typeid(V) == typeid(const unsigned char));
case T_POINTER:
case T_STRING:
return false;
case T_ANYTHING:
return true;
case T_LITERAL:
return false;
}
return false;
};
const Argument * next_argument(void);
void push_argument(std::string & data, const Type type);
void pop_argument(void);
void initialize(const char *);
protected:
ArgumentQueue _args;
std::string _result;
};
template < bool E = false >
struct FormatBase: protected FormatTraits, protected FormatException < E >
{
static const unsigned int strings_base_length = 64;
static const unsigned int generic_base_length = 64;
explicit FormatBase(const char * format_string)
: _format(format_string), _valid(true)
{
FormatTraits::initialize(format_string);
};
explicit FormatBase(std::string format_string)
: _format(format_string), _valid(true)
{
FormatTraits::initialize(format_string.c_str());
};
bool valid(void) const
{
return _valid;
}
const std::string str()
{
if (valid() && (next_argument() != NULL))
{
std::string msg;
// TODO: why format appears two times?
msg += "too few arguments passed for format '";
msg += _format;
msg += "' (";
msg += _format;
msg += ")";
mark_invalid(msg);
}
raise();
return _result;
};
////////////////////////////////////////////////////////////
template < typename V >
FormatBase & operator%( V value )
{
if (!valid())
return *this;
const Argument * top = next_argument();
@ -149,7 +363,7 @@ struct Format
{
char temp[generic_base_length];
if (!generic_verify(value, top->type()))
if (!FormatTraits::generic_verify(value, top->type()))
{
std::string msg;
@ -171,14 +385,14 @@ struct Format
pop_argument();
}
raise_check();
raise();
return *this;
}
template < typename V >
Format & operator%( V * value )
FormatBase & operator%( V * value )
{
if (!validity_check())
if (!valid())
return *this;
const Argument * top = next_argument();
@ -256,20 +470,13 @@ struct Format
pop_argument();
}
raise_check();
raise();
return *this;
}
/*
Format & operator%( std::string value )
FormatBase & operator%( const std::string value )
{
return operator%(value);
}
*/
Format & operator%( const std::string value )
{
if (!validity_check())
if (!valid())
return *this;
const Argument * top = next_argument();
@ -313,200 +520,42 @@ struct Format
pop_argument();
}
raise_check();
raise();
return *this;
}
protected:
template < typename V >
bool number_verify_signed_short( V value )
protected:
void mark_invalid(std::string & msg)
{
return
((typeid(V) == typeid(short int) ||
typeid(V) == typeid(short) ||
typeid(V) == typeid(const short int) ||
typeid(V) == typeid(const short) ||
typeid(V) == typeid(volatile short int) ||
typeid(V) == typeid(volatile short)) &&
sizeof(V) == sizeof(short));
}
template < typename V >
bool number_verify_unsigned_short( V value )
{
return
((typeid(V) == typeid(unsigned short int) ||
typeid(V) == typeid(unsigned short) ||
typeid(V) == typeid(const unsigned short int) ||
typeid(V) == typeid(const unsigned short) ||
typeid(V) == typeid(volatile unsigned short int) ||
typeid(V) == typeid(volatile unsigned short)) &&
sizeof(V) == sizeof(unsigned short));
}
template < typename V >
bool number_verify_signed_long( V value )
{
return
((typeid(V) == typeid(long int) ||
typeid(V) == typeid(long) ||
typeid(V) == typeid(const long int) ||
typeid(V) == typeid(const long) ||
typeid(V) == typeid(volatile long int) ||
typeid(V) == typeid(volatile long)) &&
sizeof(V) == sizeof(long));
}
template < typename V >
bool number_verify_unsigned_long( V value )
{
return
((typeid(V) == typeid(unsigned long int) ||
typeid(V) == typeid(unsigned long) ||
typeid(V) == typeid(const unsigned long int) ||
typeid(V) == typeid(const unsigned long) ||
typeid(V) == typeid(volatile unsigned long int) ||
typeid(V) == typeid(volatile unsigned long)) &&
sizeof(V) == sizeof(long long));
}
template < typename V >
bool number_verify_signed_long_long( V value )
{
return
((typeid(V) == typeid(long long int) ||
typeid(V) == typeid(long long) ||
typeid(V) == typeid(const long long int) ||
typeid(V) == typeid(const long long) ||
typeid(V) == typeid(volatile long long) ||
typeid(V) == typeid(volatile long long int)) &&
sizeof(V) == sizeof(long long));
}
template < typename V >
bool number_verify_unsigned_long_long( V value )
{
return
((typeid(V) == typeid(unsigned long long int) ||
typeid(V) == typeid(unsigned long long) ||
typeid(V) == typeid(const unsigned long long int) ||
typeid(V) == typeid(const unsigned long long) ||
typeid(V) == typeid(volatile unsigned long long) ||
typeid(V) == typeid(volatile unsigned long long int)) &&
sizeof(V) == sizeof(unsigned long long));
}
template < typename V >
bool number_verify_signed_int( V value )
{
return
(sizeof(V) <= sizeof(int) ||
typeid(V) == typeid(int) ||
typeid(V) == typeid(const int) ||
typeid(V) == typeid(volatile int));
}
template < typename V >
bool number_verify_unsigned_int( V value )
{
return
(sizeof(V) <= sizeof(unsigned int) ||
typeid(V) == typeid(unsigned int) ||
typeid(V) == typeid(const unsigned int) ||
typeid(V) == typeid(volatile unsigned int));
}
template < typename V >
bool generic_verify( V value, Type type )
{
switch (type)
if (_valid)
{
/* EXCEPTION: consider any number an valid input. */
case T_SIGNED_INT:
case T_UNSIGNED_INT:
return
(number_verify_signed_int(value) ||
number_verify_unsigned_int(value) ||
number_verify_signed_long(value) ||
number_verify_unsigned_long(value) ||
number_verify_signed_short(value) ||
number_verify_unsigned_short(value));
_valid = false;
case T_SIGNED_SHORT_SHORT:
return (typeid(V) == typeid(char) || typeid(V) == typeid(const char));
case T_SIGNED_SHORT:
return number_verify_signed_short(value);
case T_SIGNED_LONG:
return number_verify_signed_long(value);
case T_SIGNED_LONG_LONG:
return number_verify_signed_long_long(value);
case T_UNSIGNED_SHORT_SHORT:
return (typeid(V) == typeid(unsigned char) || typeid(V) == typeid(unsigned char));
case T_UNSIGNED_SHORT:
return number_verify_unsigned_short(value);
case T_UNSIGNED_LONG:
return number_verify_unsigned_long(value);
case T_UNSIGNED_LONG_LONG:
return number_verify_unsigned_long_long(value);
case T_FLOAT:
return (typeid(V) == typeid(float)) || (typeid(V) == typeid(double) ||
typeid(V) == typeid(const float)) || (typeid(V) == typeid(const double));
case T_CHAR:
return (typeid(V) == typeid(char)) || (typeid(V) == typeid(unsigned char) ||
typeid(V) == typeid(const char)) || (typeid(V) == typeid(const unsigned char));
case T_POINTER:
case T_STRING:
return false;
case T_ANYTHING:
return true;
case T_LITERAL:
return false;
_result = "** INVALID FORMAT: ";
_result += msg;
_result += " **";
}
}
return false;
};
void mark_invalid(std::string &);
bool validity_check(void);
void raise_check(void);
/*
struct NoArgumentLeft
void raise(void) const
{
NoArgumentLeft(): empty(0) {};
unsigned int empty;
};
*/
const Argument * next_argument(void);
void pop_argument(void);
void push_argument(std::string & data, Type type);
if (!_valid)
{
// call specialized class
FormatException< E >::raise(_result);
}
}
private:
std::string _format;
bool _valid;
bool _raise;
std::string _result;
ArgumentQueue _args;
const std::string _format;
bool _valid;
};
#endif /* _FORMAT_H_ */
/* useful typedef for general usage (not generating exceptions) */
typedef FormatBase<> Format;
/* macros used for shortening lines and making the code clearer */
#define STG(x) (x).str()
#define FMT(x) Format(x)
#endif /* _FORMAT_H_ */

View File

@ -46,12 +46,13 @@
namespace Function
{
struct EmptyFunction {};
struct EmptyFunction {};
struct NonMemberFunction {};
/**/
template < typename FunctionTraits >
struct StorageBase: NEW_REFCOUNTER(StorageBase < FunctionTraits >)
struct StorageBase: COUNTER_SUPER(StorageBase < FunctionTraits >)
{
typedef typename FunctionTraits::BaseType BaseType;
@ -59,27 +60,33 @@ namespace Function
typedef typename FunctionTraits::ObjType ObjType;
template < typename Functor >
StorageBase(Functor f)
: _object(reinterpret_cast<ObjType>(new Functor(f))),
_function(reinterpret_cast<FunType>(&(Functor::operator()))),
StorageBase(const Functor f)
: _object(reinterpret_cast< ObjType >(new Functor(f))),
_function(reinterpret_cast< FunType >(&Functor::operator())),
_malloced(true)
{};
template < typename Functor >
StorageBase(Functor & f, bool malloced)
: _object(reinterpret_cast<ObjType>((malloced ? new Functor(f) : &f))),
_function(reinterpret_cast<FunType>(&(Functor::operator()))),
: _object(reinterpret_cast< ObjType >((malloced ? new Functor(f) : &f))),
_function(reinterpret_cast< FunType >(&Functor::operator())),
_malloced(malloced)
{};
StorageBase(FunType const * member)
: _object(reinterpret_cast< ObjType >(0)),
_function(reinterpret_cast< FunType >(member)),
_malloced(false)
{};
StorageBase()
: _object(reinterpret_cast<ObjType>(0)),
_function(reinterpret_cast<FunType>(0)),
: _object(reinterpret_cast< ObjType >(0)),
_function(reinterpret_cast< FunType >(0)),
_malloced(false)
{};
StorageBase(const StorageBase & o)
: INC_REFCOUNTER(o, StorageBase < FunctionTraits >),
: COUNTER_REFER(o, StorageBase < FunctionTraits >),
_object(o._object), _function(o._function), _malloced(o._malloced)
{};
@ -95,9 +102,9 @@ namespace Function
template < typename Functor >
void operator=(Functor f)
{
_object = reinterpret_cast<ObjType>(new Functor(f)),
_function = reinterpret_cast<FunType>(&(Functor::operator()));
_malloced = false;
_object = reinterpret_cast< ObjType >(new Functor(f)),
_function = reinterpret_cast< FunType >(&Functor::operator());
_malloced = true;
}
protected:
@ -229,10 +236,15 @@ namespace Function
typedef StorageBase < Function0Traits < R > > Storage;
template < typename Functor >
Function0(Functor f): Storage(f) {};
Function0(const Functor f)
: Storage(f) {};
template < typename Functor >
Function0(Functor & f, bool m): Storage(f, m) {};
Function0(Functor & f, bool m)
: Storage(f, m) {};
Function0(const typename Function0Traits < R >::FunType * m)
: Storage(m) {};
Function0() {};
@ -243,6 +255,18 @@ namespace Function
return ((Storage::_object)->*(Storage::_function))();
}
template < typename Object >
R operator()(Object * object)
{
if (reinterpret_cast<void *>(Storage::_function) == 0)
throw EmptyFunction();
if (reinterpret_cast<void *>(Storage::_object) != 0)
throw NonMemberFunction();
return (reinterpret_cast< typename Function0Traits < R >::ObjType *>(object)->*(Storage::_function))();
}
};
template < typename R, typename A0 >
@ -251,10 +275,15 @@ namespace Function
typedef StorageBase < Function1Traits < R, A0 > > Storage;
template < typename Functor >
Function1(Functor f): Storage(f) {};
Function1(const Functor f)
: Storage(f) {};
template < typename Functor >
Function1(Functor & f, bool m): Storage(f, m) {};
Function1(Functor & f, bool m)
: Storage(f, m) {};
Function1(const typename Function1Traits < R, A0 >::FunType * m)
: Storage(m) {};
Function1() {};
@ -265,6 +294,18 @@ namespace Function
return ((Storage::_object)->*(Storage::_function))(a0);
}
template < typename Object >
R operator()(Object * object, A0 a0)
{
if (reinterpret_cast<void *>(Storage::_function) == 0)
throw EmptyFunction();
if (reinterpret_cast<void *>(Storage::_object) != 0)
throw NonMemberFunction();
return (reinterpret_cast< typename Function1Traits < R, A0 >::ObjType *>(object)->*(Storage::_function))(a0);
}
};
template < typename R, typename A0, typename A1 >
@ -273,10 +314,15 @@ namespace Function
typedef StorageBase < Function2Traits < R, A0, A1 > > Storage;
template < typename Functor >
Function2(Functor f): Storage(f) {};
Function2(const Functor f)
: Storage(f) {};
template < typename Functor >
Function2(Functor & f, bool m): Storage(f, m) {};
Function2(Functor & f, bool m)
: Storage(f, m) {};
Function2(const typename Function2Traits < R, A0, A1 >::FunType * m)
: Storage(m) {};
Function2() {};
@ -287,6 +333,18 @@ namespace Function
return ((Storage::_object)->*(Storage::_function))(a0, a1);
}
template < typename Object >
R operator()(Object * object, A0 a0, A1 a1)
{
if (reinterpret_cast<void *>(Storage::_function) == 0)
throw EmptyFunction();
if (reinterpret_cast<void *>(Storage::_object) != 0)
throw NonMemberFunction();
return (reinterpret_cast< typename Function2Traits < R, A0, A1 >::ObjType *>(object)->*(Storage::_function))(a0, a1);
}
};
template < typename R, typename A0, typename A1, typename A2 >
@ -295,20 +353,37 @@ namespace Function
typedef StorageBase < Function3Traits < R, A0, A1, A2 > > Storage;
template < typename Functor >
Function3(Functor f): Storage(f) {};
Function3(const Functor f)
: Storage(f) {};
template < typename Functor >
Function3(Functor & f, bool m): Storage(f, m) {};
Function3(Functor & f, bool m)
: Storage(f, m) {};
Function3(const typename Function3Traits < R, A0, A1, A2 >::FunType * m)
: Storage(m) {};
Function3() {};
R operator()(A0 a0, A1 a1, A2 a2)
{
if (reinterpret_cast<void *>(Storage::_object) == 0)
if (reinterpret_cast<const void *>(Storage::_object) == 0)
throw EmptyFunction();
return ((Storage::_object)->*(Storage::_function))(a0, a1, a2);
}
template < typename Object >
R operator()(Object * object, A0 a0, A1 a1, A2 a2)
{
if (reinterpret_cast<void *>(Storage::_function) == 0)
throw EmptyFunction();
if (reinterpret_cast<void *>(Storage::_object) != 0)
throw NonMemberFunction();
return (reinterpret_cast< typename Function3Traits < R, A0, A1, A2 >::ObjType *>(object)->*(Storage::_function))(a0, a1, a2);
}
};
template < typename R, typename A0, typename A1, typename A2, typename A3 >
@ -317,10 +392,15 @@ namespace Function
typedef StorageBase < Function4Traits < R, A0, A1, A2, A3 > > Storage;
template < typename Functor >
Function4(Functor f): Storage(f) {};
Function4(const Functor f)
: Storage(f) {};
template < typename Functor >
Function4(Functor & f, bool m): Storage(f, m) {};
Function4(Functor & f, bool m)
: Storage(f, m) {};
Function4(const typename Function4Traits < R, A0, A1, A2, A3 >::FunType * m)
: Storage(m) {};
Function4() {};
@ -331,6 +411,18 @@ namespace Function
return ((Storage::_object)->*(Storage::_function))(a0, a1, a2, a3);
}
template < typename Object >
R operator()(Object * object, A0 a0, A1 a1, A2 a2, A3 a3)
{
if (reinterpret_cast<void *>(Storage::_function) == 0)
throw EmptyFunction();
if (reinterpret_cast<void *>(Storage::_object) != 0)
throw NonMemberFunction();
return (reinterpret_cast< typename Function4Traits < R, A0, A1, A2, A3 >::ObjType *>(object)->*(Storage::_function))(a0, a1, a2, a3);
}
};
};

View File

@ -47,32 +47,32 @@
template < typename Type >
struct Initializer: public std::vector< Type >
{
typedef std::vector< Type > super;
typedef std::vector< Type > Super;
Initializer(Type e) { push_back(e); };
Initializer(Type & e) { push_back(e); };
Initializer(Type e) { Super::push_back(e); };
Initializer(Type & e) { Super::push_back(e); };
Initializer & operator&(Initializer v)
Initializer & operator&(const Initializer v)
{
insert(super::end(), v.begin(), v.end());
Super::insert(Super::end(), v.begin(), v.end());
return *this;
};
Initializer & operator&(Initializer & v)
{
insert(super::end(), v.begin(), v.end());
Super::insert(Super::end(), v.begin(), v.end());
return *this;
};
Initializer & operator&(Type v)
{
insert(super::end(), v);
Super::insert(Super::end(), v);
return *this;
};
Initializer & operator&(Type & v)
{
insert(super::end(), v);
Super::insert(Super::end(), v);
return *this;
};
};

View File

@ -41,18 +41,16 @@
#include <k3lapi.hpp>
#include <format.hpp>
#include <verbose.hpp>
#include <string.h>
K3LAPI::K3LAPI(bool has_exceptions)
: _has_exceptions(has_exceptions),
_device_count(0), _channel_count(0), _link_count(0),
K3LAPIBase::K3LAPIBase()
: _device_count(0), _channel_count(0), _link_count(0),
_device_config(0), _channel_config(0), _link_config(0)
{};
/* initialize the whole thing! */
void K3LAPI::start(void)
void K3LAPIBase::start(void)
{
/* tie the used k3l to the compiled k3l version */
char *ret = k3lStart(k3lApiMajorVersion, k3lApiMinorVersion, 0); //k3lApiBuildVersion);
@ -64,7 +62,7 @@ void K3LAPI::start(void)
init();
}
void K3LAPI::stop(void)
void K3LAPIBase::stop(void)
{
k3lStop();
fini();
@ -72,7 +70,7 @@ void K3LAPI::stop(void)
/* envio de comandos para placa */
void K3LAPI::mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index)
void K3LAPIBase::mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const
{
KMixerCommand mix;
@ -83,7 +81,7 @@ void K3LAPI::mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 ind
command(dev, obj, CM_MIXER, (const char *) &mix);
}
void K3LAPI::mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int32 index)
void K3LAPIBase::mixerRecord(int32 dev, KDeviceType type, int32 obj, byte track, KMixerSource src, int32 index) const
{
/* estes buffers *NAO PODEM SER ESTATICOS*! */
char cmd[] = { 0x3f, 0x03, (char)obj, (char)track, 0xff, 0xff };
@ -131,12 +129,12 @@ void K3LAPI::mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int
break;
}
int32 dsp = get_dsp(dev, DSP_AUDIO);
int32 dsp = get_dsp(type, DSP_AUDIO);
raw_command(dev, dsp, cmd, sizeof(cmd));
}
void K3LAPI::mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index)
void K3LAPIBase::mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const
{
KMixerCommand mix;
@ -147,12 +145,12 @@ void K3LAPI::mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int3
command(dev, obj, CM_MIXER_CTBUS, (const char *) &mix);
}
void K3LAPI::command(int32 dev, int32 obj, int32 code, std::string & str)
void K3LAPIBase::command(int32 dev, int32 obj, int32 code, std::string & str) const
{
command(dev, obj, code, str.c_str());
}
void K3LAPI::command (int32 dev, int32 obj, int32 code, const char * parms)
void K3LAPIBase::command (int32 dev, int32 obj, int32 code, const char * parms) const
{
K3L_COMMAND cmd;
@ -166,12 +164,12 @@ void K3LAPI::command (int32 dev, int32 obj, int32 code, const char * parms)
throw failed_command(code, dev, obj, rc);
}
void K3LAPI::raw_command(int32 dev, int32 dsp, std::string & str)
void K3LAPIBase::raw_command(int32 dev, int32 dsp, std::string & str) const
{
raw_command(dev, dsp, str.data(), str.size());
}
void K3LAPI::raw_command(int32 dev, int32 dsp, const char * cmds, int32 size)
void K3LAPIBase::raw_command(int32 dev, int32 dsp, const char * cmds, int32 size) const
{
std::string str(cmds, size);
@ -181,7 +179,7 @@ void K3LAPI::raw_command(int32 dev, int32 dsp, const char * cmds, int32 size)
throw failed_raw_command(dev, dsp, rc);
}
KLibraryStatus K3LAPI::get_param(K3L_EVENT *ev, const char *name, std::string &res)
KLibraryStatus K3LAPIBase::get_param(K3L_EVENT *ev, const char *name, std::string &res) const
{
char tmp_param[256];
memset((void*)tmp_param, 0, sizeof(tmp_param));
@ -195,7 +193,7 @@ KLibraryStatus K3LAPI::get_param(K3L_EVENT *ev, const char *name, std::string &r
return ksSuccess;
}
std::string K3LAPI::get_param(K3L_EVENT *ev, const char *name)
std::string K3LAPIBase::get_param(K3L_EVENT *ev, const char *name) const
{
std::string res;
@ -207,7 +205,7 @@ std::string K3LAPI::get_param(K3L_EVENT *ev, const char *name)
return res;
}
void K3LAPI::init(void)
void K3LAPIBase::init(void)
{
if (_device_count != 0) return;
@ -217,20 +215,16 @@ void K3LAPI::init(void)
_device_config = new device_conf_type[_device_count];
_channel_config = new channel_ptr_conf_type[_device_count];
_link_config = new link_ptr_conf_type[_device_count];
_channel_count = new unsigned int[_device_count];
_link_count = new unsigned int[_device_count];
_channel_count = new unsigned int[_device_count];
_link_count = new unsigned int[_device_count];
for (unsigned int dev = 0; dev < _device_count; dev++)
{
KLibraryStatus ret = ksSuccess;
_device_type[dev] = (KDeviceType) k3lGetDeviceType(dev);
/* caches each device config */
ret = (KLibraryStatus)k3lGetDeviceConfig(dev, ksoDevice + dev, &(_device_config[dev]), sizeof(_device_config[dev]));
if (ret != ksSuccess)
throw start_failed(STG(FMT("k3lGetDeviceConfig(dev=%d): %s") % dev % Verbose::status(ret)));
if (k3lGetDeviceConfig(dev, ksoDevice + dev, &(_device_config[dev]), sizeof(_device_config[dev])) != ksSuccess)
throw start_failed("k3lGetDeviceConfig(device)");
/* adjust channel/link count for device */
_channel_count[dev] = _device_config[dev].ChannelCount;
@ -241,10 +235,9 @@ void K3LAPI::init(void)
for (unsigned int obj = 0; obj < _channel_count[dev]; obj++)
{
ret = (KLibraryStatus)k3lGetDeviceConfig(dev, ksoChannel + obj, &(_channel_config[dev][obj]), sizeof(_channel_config[dev][obj]));
if (ret != ksSuccess)
throw start_failed(STG(FMT("k3lGetDeviceConfig(dev=%d,chan=%d): %s") % dev % obj % Verbose::status(ret)));
if (k3lGetDeviceConfig(dev, ksoChannel + obj, &(_channel_config[dev][obj]),
sizeof(_channel_config[dev][obj])) != ksSuccess)
throw start_failed("k3lGetDeviceConfig(channel)");
}
/* adjust link count for device */
@ -255,15 +248,14 @@ void K3LAPI::init(void)
for (unsigned int obj = 0; obj < _link_count[dev]; obj++)
{
ret = (KLibraryStatus)k3lGetDeviceConfig(dev, ksoLink + obj, &(_link_config[dev][obj]), sizeof(_link_config[dev][obj]));
if (ret != ksSuccess)
throw start_failed(STG(FMT("k3lGetDeviceConfig(dev=%d,link=%d): %s") % dev % obj % Verbose::status(ret)));
if (k3lGetDeviceConfig(dev, ksoLink + obj, &(_link_config[dev][obj]),
sizeof(_link_config[dev][obj])) != ksSuccess)
throw start_failed("k3lGetDeviceConfig(link)");
}
}
}
void K3LAPI::fini(void)
void K3LAPIBase::fini(void)
{
for (unsigned int dev = 0; dev < _device_count; dev++)
{
@ -290,9 +282,9 @@ void K3LAPI::fini(void)
if (_link_count) { delete[] _link_count; _link_count = NULL; }
}
int32 K3LAPI::get_dsp(int32 dev, K3LAPI::DspType type)
int32 K3LAPIBase::get_dsp(KDeviceType devtype, K3LAPI::DspType type) const
{
switch (device_type(dev))
switch (devtype)
{
case kdtFXO:
case kdtFXOVoIP:
@ -311,3 +303,7 @@ int32 K3LAPI::get_dsp(int32 dev, K3LAPI::DspType type)
}
}
int32 K3LAPIBase::get_dsp(const K3LAPIBase::GenericTarget & tgt, K3LAPI::DspType type) const
{
return get_dsp(_device_type[tgt.device], type);
}

View File

@ -40,6 +40,9 @@
*/
#include <string>
#include <stdexcept>
#include <format.hpp>
#include <k3l.h>
@ -59,15 +62,110 @@
#ifndef _K3LAPI_HPP_
#define _K3LAPI_HPP_
struct K3LAPI
struct K3LAPITraits
{
struct invalid_device;
struct invalid_channel;
struct invalid_link;
struct invalid_target: public std::runtime_error
{
friend class invalid_device;
friend class invalid_channel;
friend class invalid_link;
const int32 device, object;
protected:
invalid_target(int32 _device, int32 _object, const std::string & msg)
: std::runtime_error(msg), device(_device), object(_object) {};
};
struct invalid_device: public invalid_target
{
invalid_device(int32 _device)
: invalid_target(_device, -1, STG(FMT("invalid device number '%d'") % _device)) {};
};
struct invalid_channel: public invalid_target
{
invalid_channel(int32 _device, int32 _channel)
: invalid_target(_device, _channel, STG(FMT("invalid channel number '%d' on device '%d'") % _channel % _device)) {};
};
struct invalid_link: public invalid_target
{
invalid_link(int32 _device, int32 _link)
: invalid_target(_device, _link, STG(FMT("invalid link number '%d' on device '%d'") % _link % _device)) {};
};
};
struct K3LAPIBase
{
/* High level checked object identifier. */
struct GenericTarget
{
typedef enum { DEVICE, CHANNEL, MIXER, LINK } Type;
GenericTarget(const K3LAPIBase & k3lapi, Type _type, int32 _device, int32 _object)
: type(_type), device((unsigned int)_device), object((unsigned int)_object)
{
switch (_type)
{
case DEVICE:
if (!k3lapi.valid_device(_device))
throw K3LAPITraits::invalid_device(_device);
break;
case CHANNEL:
case MIXER:
if (!k3lapi.valid_channel(_device, _object))
throw K3LAPITraits::invalid_channel(_device, _object);
break;
case LINK:
if (!k3lapi.valid_link(_device, _object))
throw K3LAPITraits::invalid_link(_device, _object);
break;
}
};
const Type type;
const unsigned int device;
const unsigned int object;
};
/*
struct LinkTarget : public GenericTarget
{
LinkTarget(const K3LAPIBase & k3lapi, int32 _device, int32 _object)
: GenericTarget(k3lapi, GenericTarget::LINK, _device, _object) {};
};
struct ChannelTarget : public GenericTarget
{
ChannelTarget(const K3LAPIBase & k3lapi, int32 _device, int32 _object)
: GenericTarget(k3lapi, GenericTarget::CHANNEL, _device, _object) {};
};
*/
template < GenericTarget::Type T >
struct Target: public GenericTarget
{
Target(const K3LAPIBase & k3lapi, int32 _device, int32 _object)
: GenericTarget(k3lapi, T, _device, _object) {};
// operator const GenericTarget&() const { return static_cast<const GenericTarget &>(*this); };
};
/* exceptions */
struct start_failed
struct start_failed: public std::runtime_error
{
start_failed(const char * _msg) : msg(_msg) {};
start_failed(std::string _msg) : msg(_msg) {};
std::string msg;
start_failed(const char * msg)
: std::runtime_error(msg) {};
};
struct failed_command
@ -91,30 +189,6 @@ struct K3LAPI
int32 rc;
};
struct invalid_device
{
invalid_device(int32 _device)
: device(_device) {};
int32 device;
};
struct invalid_channel
{
invalid_channel(int32 _device, int32 _channel)
: device(_device), channel(_channel) {};
int32 device, channel;
};
struct invalid_link
{
invalid_link(unsigned int _device, unsigned int _link)
: device(_device), link(_link) {};
int32 device, link;
};
struct get_param_failed
{
get_param_failed(std::string _name, int32 _rc)
@ -124,6 +198,8 @@ struct K3LAPI
KLibraryStatus rc;
};
/* typedefs essenciais */
typedef K3L_DEVICE_CONFIG device_conf_type;
typedef K3L_CHANNEL_CONFIG channel_conf_type;
typedef K3L_CHANNEL_CONFIG * channel_ptr_conf_type;
@ -132,8 +208,8 @@ struct K3LAPI
/* constructors/destructors */
K3LAPI(bool has_exceptions = false);
virtual ~K3LAPI() {};
K3LAPIBase();
virtual ~K3LAPIBase() {};
/* (init|final)ialize the whole thing! */
@ -142,239 +218,106 @@ struct K3LAPI
/* verificacao de intervalos */
inline bool valid_device(int32 dev)
inline bool valid_device(int32 dev) const
{
return (dev >= 0 && dev < ((int32)_device_count));
}
inline bool valid_channel(int32 dev, int32 obj)
inline bool valid_channel(int32 dev, int32 obj) const
{
return (valid_device(dev) && obj >= 0 && obj < ((int32)_channel_count[dev]));
}
inline bool valid_link(int32 dev, int32 obj)
inline bool valid_link(int32 dev, int32 obj) const
{
return (valid_device(dev) && obj >= 0 && obj < ((int32)_link_count[dev]));
}
/*!
\brief High level object identifier
Since Khomp works with an object concept, this is used to map the
object id with its proper type.
*/
struct target
{
/*! The types a target can have */
typedef enum { DEVICE, CHANNEL, MIXER, LINK } target_type;
target(K3LAPI & k3lapi, target_type type_init, int32 device_value, int32 object_value)
: type(type_init),
device((unsigned short)device_value),
object((unsigned short)object_value)
{
switch (type_init)
{
case DEVICE:
if (!k3lapi.valid_device(device_value))
throw invalid_device(device_value);
break;
case CHANNEL:
case MIXER:
if (!k3lapi.valid_channel(device_value, object_value))
throw invalid_channel(device_value, object_value);
break;
case LINK:
if (!k3lapi.valid_link(device_value, object_value))
throw invalid_link(device_value, object_value);
break;
}
};
const target_type type;
const unsigned short device;
const unsigned short object;
};
/* envio de comandos para placa (geral) */
void raw_command(int32 dev, int32 dsp, std::string & str);
void raw_command(int32 dev, int32 dsp, const char * cmds, int32 size);
void raw_command(int32 dev, int32 dsp, std::string & str) const;
void raw_command(int32 dev, int32 dsp, const char * cmds, int32 size) const;
/* obter dados 'cacheados' (geral) */
inline unsigned int device_count(void)
inline unsigned int device_count(void) const
{
return _device_count;
}
/* envio de comandos para placa (sem identificadores) */
void mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index);
void mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int32 index);
void mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index);
void mixer(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const;
void mixerRecord(int32 dev, KDeviceType type, int32 obj, byte track, KMixerSource src, int32 index) const;
void mixerCTbus(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const;
void command (int32 dev, int32 obj, int32 code, std::string & str);
void command (int32 dev, int32 obj, int32 code, const char * parms = NULL);
void command (int32 dev, int32 obj, int32 code, std::string & str) const;
void command (int32 dev, int32 obj, int32 code, const char * parms = NULL) const;
/* obter dados 'cacheados' (sem identificadores) */
inline unsigned int channel_count(int32 dev)
{
if (!valid_device(dev))
{
if (_has_exceptions)
throw invalid_device(dev);
else
return 0;
}
return _channel_count[dev];
}
inline unsigned int link_count(int32 dev)
{
if (!valid_device(dev))
{
if (_has_exceptions)
throw invalid_device(dev);
else
return 0;
}
return _link_count[dev];
}
inline uint32 channel_stats(int32 dev, int32 obj, uint32 index)
{
if (!valid_channel(dev, obj))
{
if (_has_exceptions)
throw invalid_channel(dev, obj);
else
return 0;
}
uint32 res_value = (uint32)-1;
stt_code stt_res = ksFail;
#if K3L_AT_LEAST(2,1,0)
stt_res = k3lGetChannelStats(dev, obj, index, &res_value);
#endif
if(stt_res != ksSuccess)
{
return (uint32)-1;
}
return res_value;
}
KDeviceType device_type(int32 dev)
{
if (!valid_device(dev))
{
if (_has_exceptions)
throw invalid_device(dev);
else
return kdtDevTypeCount;
}
return _device_type[dev];
}
K3L_DEVICE_CONFIG & device_config(int32 dev)
{
if (!valid_device(dev))
throw invalid_device(dev);
return _device_config[dev];
}
K3L_CHANNEL_CONFIG & channel_config(int32 dev, int32 obj)
{
if (!valid_channel(dev, obj))
throw invalid_channel(dev, obj);
return _channel_config[dev][obj];
}
K3L_LINK_CONFIG & link_config(int32 dev, int32 obj)
{
if (!valid_link(dev, obj))
throw invalid_channel(dev, obj);
return _link_config[dev][obj];
}
/* envio de comandos para placa (com identificadores) */
void mixer(target & tgt, byte track, KMixerSource src, int32 index)
void mixer(const GenericTarget & tgt, byte track, KMixerSource src, int32 index) const
{
mixer((int32)tgt.device, (int32)tgt.object, track, src, index);
mixer(tgt.device, tgt.object, track, src, index);
}
void mixerRecord(target & tgt, byte track, KMixerSource src, int32 index)
void mixerRecord(const GenericTarget & tgt, byte track, KMixerSource src, int32 index) const
{
mixerRecord((int32)tgt.device, (int32)tgt.object, track, src, index);
mixerRecord((int32)tgt.device, _device_type[tgt.device], (int32)tgt.object, track, src, index);
}
void mixerCTbus(target & tgt, byte track, KMixerSource src, int32 index)
void mixerCTbus(const GenericTarget & tgt, byte track, KMixerSource src, int32 index) const
{
mixerCTbus((int32)tgt.device, (int32)tgt.object, track, src, index);
}
void command (target & tgt, int32 code, std::string & str)
void command(const GenericTarget & tgt, int32 code, std::string & str) const
{
command((int32)tgt.device, (int32)tgt.object, code, str);
};
void command (target & tgt, int32 code, const char * parms = NULL)
void command(const GenericTarget & tgt, int32 code, const char * parms = NULL) const
{
command((int32)tgt.device, (int32)tgt.object, code, parms);
};
/* obter dados 'cacheados' (com indentificadores) */
inline unsigned int channel_count(target & tgt)
inline unsigned int channel_count(const GenericTarget & tgt) const
{
return _channel_count[tgt.device];
}
inline unsigned int link_count(target & tgt)
inline unsigned int link_count(const GenericTarget & tgt) const
{
return _link_count[tgt.device];
}
KDeviceType device_type(target & tgt)
KDeviceType device_type(const GenericTarget & tgt) const
{
return _device_type[tgt.device];
}
K3L_DEVICE_CONFIG & device_config(target & tgt)
const K3L_DEVICE_CONFIG & device_config(const GenericTarget & tgt) const
{
return _device_config[tgt.device];
}
K3L_CHANNEL_CONFIG & channel_config(target & tgt)
const K3L_CHANNEL_CONFIG & channel_config(const Target<GenericTarget::CHANNEL> & tgt) const
{
return _channel_config[tgt.device][tgt.object];
}
K3L_LINK_CONFIG & link_config(target & tgt)
const K3L_LINK_CONFIG & link_config(const Target<GenericTarget::LINK> & tgt) const
{
return _link_config[tgt.device][tgt.object];
}
/* pega valores em strings de eventos */
KLibraryStatus get_param(K3L_EVENT *ev, const char *name, std::string &res);
std::string get_param(K3L_EVENT *ev, const char *name);
KLibraryStatus get_param(K3L_EVENT *ev, const char *name, std::string &res) const;
std::string get_param(K3L_EVENT *ev, const char *name) const;
/* inicializa valores em cache */
@ -389,12 +332,12 @@ struct K3LAPI
DSP_SIGNALING,
};
int32 get_dsp(int32, DspType);
int32 get_dsp(KDeviceType, DspType) const;
int32 get_dsp(const GenericTarget &, DspType) const;
protected:
const bool _has_exceptions;
unsigned int _device_count;
unsigned int * _channel_count;
unsigned int * _link_count;
@ -405,4 +348,145 @@ struct K3LAPI
KDeviceType * _device_type;
};
/* exceptions */
template < bool E = false >
struct K3LAPIException
{
void invalid_device(const int32 device) const
{
/* NOTHING */
}
void invalid_channel(const int32 device, const int32 channel) const
{
/* NOTHING */
}
void invalid_link(const int32 device, const int32 link) const
{
/* NOTHING */
}
};
template < >
struct K3LAPIException < true >
{
void invalid_device(const int32 device) const
{
throw K3LAPITraits::invalid_device(device);
}
void invalid_channel(const int32 device, const int32 channel) const
{
throw K3LAPITraits::invalid_channel(device, channel);
}
void invalid_link(const int32 device, const int32 link) const
{
throw K3LAPITraits::invalid_link(device, link);
}
};
template < bool E = false >
struct K3LAPITemplate: public K3LAPIBase, protected K3LAPIException < E >
{
using K3LAPIBase::device_config;
using K3LAPIBase::channel_config;
using K3LAPIBase::link_config;
using K3LAPIBase::device_type;
using K3LAPIBase::get_dsp;
using K3LAPIBase::mixerRecord;
/* obter dados 'cacheados' (sem identificadores) */
inline unsigned int channel_count(int32 dev) const
{
if (!valid_device(dev))
{
K3LAPIException< E >::invalid_device(dev);
return 0;
}
return _channel_count[dev];
}
inline unsigned int link_count(int32 dev) const
{
if (!valid_device(dev))
{
K3LAPIException< E >::invalid_device(dev);
return 0;
}
return _link_count[dev];
}
inline uint32 channel_stats(int32 dev, int32 obj, uint32 index) const
{
if (!valid_channel(dev, obj))
{
K3LAPIException< E >::invalid_channel(dev, obj);
return 0u;
}
uint32 res_value = 0u;
#if K3L_AT_LEAST(2,1,0)
if (k3lGetChannelStats(dev, obj, index, &res_value) != ksSuccess)
return 0u;
return res_value;
#endif
}
KDeviceType device_type(int32 dev) const
{
if (!valid_device(dev))
{
K3LAPIException< E >::invalid_device(dev);
return kdtDevTypeCount;
}
return _device_type[dev];
}
const K3L_DEVICE_CONFIG & device_config(int32 dev) const
{
if (!valid_device(dev))
throw K3LAPITraits::invalid_device(dev);
return _device_config[dev];
}
const K3L_CHANNEL_CONFIG & channel_config(int32 dev, int32 obj) const
{
if (!valid_channel(dev, obj))
throw K3LAPITraits::invalid_channel(dev, obj);
return _channel_config[dev][obj];
}
const K3L_LINK_CONFIG & link_config(int32 dev, int32 obj) const
{
if (!valid_link(dev, obj))
throw K3LAPITraits::invalid_link(dev, obj);
return _link_config[dev][obj];
}
int32 get_dsp(int32 dev, DspType type) const
{
return get_dsp(device_type(dev), type);
}
void mixerRecord(int32 dev, int32 obj, byte track, KMixerSource src, int32 index) const
{
mixerRecord(dev, device_type(dev), obj, track, src, index);
}
};
typedef K3LAPITemplate<> K3LAPI;
#endif /* _K3LAPI_HPP_ */

View File

@ -46,7 +46,8 @@ std::string K3LUtil::channelStatus(int32 dev, int32 channel,
{
try
{
K3L_CHANNEL_CONFIG & config = _k3lapi.channel_config(dev, channel);
const K3L_CHANNEL_CONFIG & config = _k3lapi.channel_config(dev, channel);
K3L_CHANNEL_STATUS status;
KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus (dev,
@ -60,7 +61,7 @@ std::string K3LUtil::channelStatus(int32 dev, int32 channel,
: "Unknown (fail)");
}
}
catch(K3LAPI::invalid_channel & e)
catch(K3LAPITraits::invalid_channel & e)
{
return (fmt == Verbose::EXACT ? "<unknown[fail]>" : "Unknown (fail)");
}
@ -83,64 +84,35 @@ std::string K3LUtil::callStatus(int32 dev, int32 channel,
}
std::string K3LUtil::linkStatus(int32 dev, int32 link,
Verbose::Presentation fmt, KSignaling sig)
Verbose::Presentation fmt, KSignaling signaling, bool simpleStatus)
{
try
{
if (sig == ksigInactive)
if (signaling == ksigInactive)
{
K3L_LINK_CONFIG & config = _k3lapi.link_config(dev, link);
sig = config.Signaling;
const K3L_LINK_CONFIG & config = _k3lapi.link_config(dev, link);
signaling = config.Signaling;
}
K3L_LINK_STATUS status;
K3L_LINK_STATUS status;
KLibraryStatus ret = (KLibraryStatus) k3lGetDeviceStatus (dev,
link + ksoLink, &status, sizeof(status));
switch (ret)
{
case ksSuccess: return Verbose::linkStatus(sig, status.E1, fmt);
case ksSuccess: return Verbose::linkStatus(signaling, status.E1, fmt, simpleStatus);
default: return (fmt == Verbose::EXACT ?
"<unknown[failure]>" : "Unknown (failure)");
}
}
catch(K3LAPI::invalid_channel & e)
catch(K3LAPITraits::invalid_channel & e)
{
return (fmt == Verbose::EXACT ? "<unknown[failure]>"
: "Unknown (failure)");
}
}
std::string K3LUtil::getLinkStatus(int32 dev, int32 link,
Verbose::Presentation fmt)
{
switch (_k3lapi.device_type(dev))
{
#if K3L_AT_LEAST(1,6,0)
case kdtFXS:
case kdtFXSSpx:
return linkStatus(dev, link, fmt, ksigAnalogTerminal);
#if K3L_AT_LEAST(2,1,0)
case kdtE1FXSSpx:
if (link == 1)
return linkStatus(dev, link, fmt, ksigAnalogTerminal);
#endif
#endif
default:
break;
}
K3L_LINK_CONFIG & conf = _k3lapi.link_config(dev, link);
std::string res = linkStatus(dev, link, fmt);
if (conf.ReceivingClock & 0x01)
res += (fmt == Verbose::EXACT ? ",sync" : " (sync)");
return res;
}
unsigned int K3LUtil::physicalLinkCount(int32 dev, bool count_virtual)
{
@ -199,7 +171,7 @@ unsigned int K3LUtil::physicalLinkCount(int32 dev, bool count_virtual)
break;
}
}
catch(K3LAPI::invalid_device & e)
catch(K3LAPITraits::invalid_device & e)
{
return 0;
}

View File

@ -64,10 +64,8 @@ struct K3LUtil
std::string linkStatus(int32, int32,
Verbose::Presentation fmt = Verbose::HUMAN,
KSignaling sig = ksigInactive);
std::string getLinkStatus(int32, int32,
Verbose::Presentation fmt = Verbose::HUMAN);
KSignaling sig = ksigInactive,
bool simpleStatus = false);
unsigned int physicalLinkCount(int32 dev, bool count_virtual = false);

View File

@ -55,6 +55,7 @@
#if defined(COMMONS_LIBRARY_USING_ASTERISK)
extern "C"
{
#include <asterisk.h>
#include <asterisk/localtime.h>
}
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER)
@ -443,35 +444,17 @@ struct Logger
localtime_r (&tv, &lt);
#endif
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d] ")
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour
% lt.tm_min % lt.tm_sec);
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER)
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER) || defined(COMMONS_LIBRARY_USING_FREESWITCH)
time_t tv;
struct tm lt;
time (&tv);
localtime_r (&tv, &lt);
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d] ")
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour
% lt.tm_min % lt.tm_sec);
#elif defined(COMMONS_LIBRARY_USING_FREESWITCH)
time_t tv;
struct tm lt;
time (&tv);
localtime_r (&tv, &lt);
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d] ")
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour
% lt.tm_min % lt.tm_sec);
#endif
out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d] ")
% (lt.tm_year % 100) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour
% lt.tm_min % lt.tm_sec);
}
if (opt._flags[Option::DATETIMEMS])
@ -497,16 +480,16 @@ struct Logger
#endif
#if ASTERISK_AT_LEAST(1,6,0)
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ")
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d:%04d] ")
% (lt.tm_year % 100) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
% lt.tm_sec % (tv.tv_usec / 1000));
#else
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ")
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d:%04d] ")
% (lt.tm_year % 100) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
% lt.tm_sec % (tv * 1000));
#endif
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER)
#elif defined(COMMONS_LIBRARY_USING_CALLWEAVER) || defined(COMMONS_LIBRARY_USING_FREESWITCH)
time_t tv;
struct tm lt;
@ -514,22 +497,9 @@ struct Logger
localtime_r (&tv, &lt);
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ")
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
out_msg += STG(FMT("[%02d-%02d-%02d %02d:%02d:%02d:%04d] ")
% (lt.tm_year % 100) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
% lt.tm_sec % (tv * 1000));
#elif defined(COMMONS_LIBRARY_USING_FREESWITCH)
time_t tv;
struct tm lt;
time (&tv);
localtime_r (&tv, &lt);
out_msg += STG(FMT("[%04d-%02d-%02d %02d:%02d:%02d:%04d] ")
% (lt.tm_year + 1900) % (lt.tm_mon + 1) % lt.tm_mday % lt.tm_hour % lt.tm_min
% lt.tm_sec % (tv * 1000));
#endif
}
@ -538,7 +508,7 @@ struct Logger
if (opt._flags[Option::THREADID])
{
#if defined (COMMONS_LIBRARY_USING_ASTERISK) || defined(COMMONS_LIBRARY_USING_CALLWEAVER) || defined(COMMONS_LIBRARY_USING_FREESWITCH)
out_msg += STG(FMT("t=%08p ") % ((void*)pthread_self()));
out_msg += STG(FMT("%08x ") % ((unsigned long)pthread_self()));
#endif
}

View File

@ -45,6 +45,11 @@
#ifndef _REFCOUNTER_HPP_
#define _REFCOUNTER_HPP_
#define COUNTER_CLASS(...) ReferenceCounter< __VA_ARGS__ >
#define COUNTER_SUPER(...) public COUNTER_CLASS( __VA_ARGS__ )
#define COUNTER_REFER(o, ...) COUNTER_CLASS( __VA_ARGS__ )(static_cast< const COUNTER_CLASS( __VA_ARGS__ ) & >(o))
// DEPRECATED DECLARATIONS ///
#define NEW_REFCOUNTER(...) public ReferenceCounter< __VA_ARGS__ >
#define INC_REFCOUNTER(o, ...) ReferenceCounter< __VA_ARGS__ >(static_cast< const ReferenceCounter < __VA_ARGS__ > & >(o))
@ -179,13 +184,13 @@ struct ReferenceCounter
};
template < typename T >
struct ReferenceContainer: NEW_REFCOUNTER(ReferenceContainer< T >)
struct ReferenceContainer: COUNTER_SUPER(ReferenceContainer< T >)
{
/* type */
typedef T Type;
/* shorthand */
typedef ReferenceCounter < ReferenceContainer< Type > > Counter;
typedef COUNTER_CLASS(ReferenceContainer< Type >) Counter;
// TODO: make this a generic exception someday
struct NotFound {};
@ -249,7 +254,7 @@ struct ReferenceContainer: NEW_REFCOUNTER(ReferenceContainer< T >)
};
// return value (pointer)!
Type * operator()(void)
Type * operator()(void) const
{
return _reference_value;
};

View File

@ -74,7 +74,7 @@ void Regex::Expression::initialize(void)
_errorstate = regcomp(&_comp_regex, _expression, _flags);
}
std::string Regex::Expression::regerror_as_string(void)
std::string Regex::Expression::regerror_as_string(void) const
{
unsigned int count = regerror(_errorstate, &_comp_regex, 0, 0) + 1;
@ -95,6 +95,7 @@ void Regex::Match::initialize(void)
{
_subcounter = (_expression.subcount() + 2); // 0 + N.. + invalid
_submatches = new regmatch_t[_subcounter];
_subcaching = new std::string[_subcounter];
_have_match = (regexec(_expression.repr(), _basestring.c_str(),
_subcounter, _submatches, _flags) == 0);
}
@ -117,7 +118,7 @@ std::string Regex::Match::replace(Regex::ReplaceMap & map)
try
{
if (_submatches[0].rm_so != 0 && (map.find(0) != map.end()))
return _basestring.replace(_submatches[0].rm_so, _submatches[0].rm_eo - _submatches[0].rm_so, map.find(0)->second);
return buffer.replace(_submatches[0].rm_so, _submatches[0].rm_eo - _submatches[0].rm_so, map.find(0)->second);
for (unsigned int n = 1; (_submatches[n].rm_so != -1) && (n < _subcounter); n++)
{

View File

@ -111,12 +111,12 @@ struct Regex
}
}
bool valid(void) { return (_errorstate == 0); }
bool valid(void) const { return (_errorstate == 0); }
unsigned int subcount(void) { return _subcounter; }
const regex_t * repr(void) { return &_comp_regex; }
unsigned int subcount(void) const { return _subcounter; }
const regex_t * repr(void) const { return &_comp_regex; }
std::string error(void)
std::string error(void) const
{
switch (_errorstate)
{
@ -127,31 +127,33 @@ struct Regex
}
private:
void initialize(void);
std::string regerror_as_string(void);
std::string regerror_as_string(void) const;
private:
void initialize(void);
protected:
const char * _expression;
bool _alloced;
const bool _alloced;
unsigned int _subcounter;
int _errorstate;
regex_t _comp_regex;
unsigned int _flags;
const unsigned int _flags;
};
struct Match: NEW_REFCOUNTER(Match)
struct Match: COUNTER_SUPER(Match)
{
Match(const char * basestring, Expression & expression, unsigned int flags = 0)
Match(const char * basestring, const Expression & expression, unsigned int flags = 0)
: _basestring(basestring), _expression(expression), _subcounter(0), _submatches(0),
_have_match(false), _flags(flags)
{
initialize();
}
Match(std::string & basestring, Expression & expression, unsigned int flags = 0)
Match(const std::string & basestring, const Expression & expression, unsigned int flags = 0)
: _basestring(basestring), _expression(expression), _subcounter(0), _submatches(0),
_have_match(false), _flags(flags)
{
@ -159,7 +161,7 @@ struct Regex
}
Match(const Match & o)
: INC_REFCOUNTER(o, Match),
: COUNTER_REFER(o, Match),
_basestring(o._basestring), _expression(o._expression),
_subcounter(o._subcounter), _submatches(o._submatches),
_have_match(o._have_match), _flags(o._flags)
@ -169,6 +171,10 @@ struct Regex
void unreference()
{
delete[] _submatches;
delete[] _subcaching;
_submatches = 0;
_subcaching = 0;
}
bool matched(void)
@ -184,34 +190,23 @@ struct Regex
return false;
}
std::string submatch(int number)
const std::string & submatch(int number)
{
if (!matched(number))
return "";
return _subcaching[_subcounter - 1 /* invalid, always empty! */ ];
return _basestring.substr(_submatches[number].rm_so,
_submatches[number].rm_eo - _submatches[number].rm_so);
}
/**
* \brief gets a map with all matches
* \return std::map<int,std::string> with all matches
* \note index 0 in map, is the complete string
* \author Eduardo Nunes Pereira
*
* If fails the empty map is returned
*/
std::map<int, std::string> obtain_match_map()
{
int match_counter = 0;
std::map<int,std::string> tmp_map;
while(matched(match_counter))
if (_subcaching[number].empty())
{
tmp_map.insert(std::make_pair(match_counter,submatch(match_counter)));
match_counter++;
_subcaching[number].assign(_basestring, _submatches[number].rm_so,
_submatches[number].rm_eo - _submatches[number].rm_so);
}
return tmp_map;
return _subcaching[number];
}
const std::string & operator[](int number)
{
return submatch(number);
}
/**
@ -226,25 +221,21 @@ struct Regex
std::string replace(ReplaceMap &);
std::string replace(std::string, unsigned int index = REP_BASE);
std::string operator[](int number)
{
return submatch(number);
}
// NOTE: there is already a way to get subcount defined on EXPRESSION class!
private:
void initialize(void);
protected:
std::string _basestring;
Expression & _expression;
const std::string _basestring;
const Expression & _expression;
unsigned int _subcounter;
regmatch_t * _submatches;
std::string * _subcaching;
bool _have_match;
unsigned int _flags;
const unsigned int _flags;
};
};

View File

@ -0,0 +1,485 @@
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
the specific language governing rights and limitations under the License.
Alternatively, the contents of this file may be used under the terms of the
"GNU Lesser General Public License 2.1" license (the LGPL" License), in which
case the provisions of "LGPL License" are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms of
the LGPL License and not to allow others to use your version of this file under
the MPL, indicate your decision by deleting the provisions above and replace them
with the notice and other provisions required by the LGPL License. If you do not
delete the provisions above, a recipient may use your version of this file under
either the MPL or the LGPL License.
The LGPL header follows below:
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <ringbuffer.hpp>
// #include <stdio.h>
/* Documentation of the formula used in the buffer arithmetic.
*
* [0|1|2|3|4|5|6|7] => size=8
* | |
* reader |
* writer
*
* => writer has places [5,6,7,0,1] to write (5 places).
*
* => 8 - (4-2+1) = 8 - (2+1) = 8 - 3 = 5
*
* > writer goes 1 up, amount goes 1 down.
* > reader goes 1 up, amount goes 1 up.
* > size goes 1 down, amount goes 1 down.
*
*/
/********** BUFFER FUNCTIONS **********/
/* writes everything or nothing */
bool Ringbuffer_traits::traits_provide(char * buffer, const char * value, unsigned int amount, bool do_not_overwrite)
{
/* avoid using different values */
Buffer_table cache = _pointers;
bool need_overwrite = false;
if (amount > free_blocks(cache))
{
if (do_not_overwrite)
return false;
/* if we are allowed to overwrite, just the buffer size matters for us */
if (amount >= _size)
return false;
/* we need to change reader pointer below... */
need_overwrite = true;
}
const unsigned int wr = cache.writer.complete;
const unsigned int wp = cache.writer.complete - 1;
/* should we go around the buffer for writing? */
if ((wr + amount) > _size)
{
// fprintf(stderr, "%p> first if matched\n", this);
if (need_overwrite)
{
do
{
Buffer_pointer extra(cache.reader);
extra.complete = ((wr + amount) % _size); // (extra.complete + amount) % _size;
// extra.complete = (extra.complete + amount) % _size;
if (update(cache.reader, extra))
break;
}
while (true);
}
unsigned int wr1 = _size - wr + 1; /* writer is already 1 position after */
unsigned int wr2 = amount - wr1;
// fprintf(stderr, "%p> partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, _size, reader, writer);
/* two partial writes (one at the end, another at the beginning) */
memcpy((void *) &(buffer[wp]), (const void *) (value), _block * wr1);
memcpy((void *) (buffer), (const void *) &(value[wr1]), _block * wr2);
}
else
{
// fprintf(stderr, "%p> second if matched\n", this);
if (need_overwrite)
{
do
{
Buffer_pointer extra(cache.reader);
extra.complete = ((wr + amount) % _size); // (extra.complete + amount) % _size;
if (update(cache.reader, extra))
break;
}
while (true);
}
// fprintf(stderr, "%p> full write: a=%d/s=%d [r=%d/w=%d]\n", this, amount, _size, reader, writer);
/* we are talking about buffers here, man! */
memcpy((void *) &(buffer[wp]), (const void *) value, _block * amount);
}
_pointers.writer.complete = ((wp + amount) % _size) + 1;
_pointers.writer.partial = 1;
// if (need_overwrite)
// fprintf(stdout, "%p> write end: w=%d/r=%d\n", this, _pointers.writer.complete, _pointers.reader.complete);
return true;
}
/* returns the number of itens that have been read */
unsigned int Ringbuffer_traits::traits_consume(const char * buffer, char * value, unsigned int amount, bool atomic_mode)
{
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int available = used_blocks(cache);
if (atomic_mode && amount > available)
return false;
const unsigned int rd = _pointers.reader.complete;
unsigned int total = std::min(amount, available);
/* should we go around the buffer for reading? */
if ((rd + total) >= _size)
{
unsigned int rd1 = _size - rd;
unsigned int rd2 = total - rd1;
// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer);
/* two partial consumes (one at the end, another at the beginning) */
memcpy((void *) (value), (const void *) &(buffer[rd]), _block * rd1);
memcpy((void *) &(value[rd1]), (const void *) (buffer), _block * rd2);
}
else
{
// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer);
/* we are talking about buffers here, man! */
memcpy((void *) value, (const void *) &(buffer[rd]), _block * total);
}
do
{
/* jump the reader forward */
Buffer_pointer index((cache.reader.complete + total) % _size, 0);
if (update(cache.reader, index))
break;
}
while (true);
// fprintf(stderr, "%p> read end: %d [block=%d]\n", this, reader, _block);
return total;
}
/********** TWO-PHASE BUFFER FUNCTIONS ***********/
/* returns the number of itens that have been read */
unsigned int Ringbuffer_traits::traits_consume_begins(const char * buffer, char * value, unsigned int amount, bool atomic_mode)
{
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int available = used_blocks(cache);
if (amount > available)
{
if (atomic_mode)
return false;
}
const unsigned int rd = _pointers.reader.complete;
unsigned int total = std::min(amount, available);
/* should we go around the buffer for reading? */
if ((rd + total) >= _size)
{
unsigned int rd1 = _size - rd;
unsigned int rd2 = total - rd1;
// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer);
/* two partial consumes (one at the end, another at the beginning) */
memcpy((void *) (value), (const void *) &(buffer[rd]), _block * rd1);
memcpy((void *) &(value[rd1]), (const void *) (buffer), _block * rd2);
}
else
{
// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer);
/* we are talking about buffers here, man! */
memcpy((void *) value, (const void *) &(buffer[rd]), _block * total);
}
return total;
}
bool Ringbuffer_traits::traits_consume_commit(unsigned int amount)
{
if (amount == 0)
return true;
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int available = used_blocks(cache);
/* cannot commit more than available! */
if (amount > available)
return false;
unsigned int total = std::min(amount, available);
do
{
/* jump the reader forward */
Buffer_pointer index((cache.reader.complete + total) % _size, 0);
if (update(cache.reader, index))
break;
}
while (true);
// fprintf(stderr, "%p> read end: %d [block=%d]\n", this, reader, _block);
return true;
}
/********** PARTIAL BUFFER FUNCTIONS (bytes) ***********/
/* writes everything or nothing */
bool Ringbuffer_traits::traits_provide_partial(char * buffer, const char * value, unsigned int amount)
{
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int memsize = (_size * _block);
if (amount > (free_blocks(cache) * _block))
return false;
const unsigned int wr = ((cache.writer.complete - 1) * _block) + cache.writer.partial;
const unsigned int wp = wr - 1;
/* should we go around the buffer for writing? */
if ((wr + amount) > memsize)
{
// fprintf(stderr, "%p> first if matched\n", this);
unsigned int wr1 = memsize - wr + 1; /* writer is already 1 position after */
unsigned int wr2 = amount - wr1;
// fprintf(stderr, "%p> partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, _size, reader, writer);
/* two partial writes (one at the end, another at the beginning) */
memcpy((void *) &(buffer[wp]), (const void *) (value), wr1);
memcpy((void *) (buffer), (const void *) &(value[wr1]), wr2);
}
else
{
// fprintf(stderr, "%p> second if matched\n", this);
// fprintf(stderr, "%p> full write: a=%d/s=%d [r=%d/w=%d]\n", this, amount, _size, reader, writer);
/* we are talking about buffers here, man! */
memcpy((void *) &(buffer[wp]), (const void *) value, amount);
}
const unsigned int new_wp = (wp + amount) % memsize;
_pointers.writer.complete = (unsigned int)(floor((double)new_wp / (double)_block) + 1);
_pointers.writer.partial = (new_wp % _block) + 1;
// if (need_overwrite)
// fprintf(stdout, "%p> write end: w=%d/r=%d\n", this, _pointers.writer.complete, _pointers.reader.complete);
return true;
}
/* returns the number of bytes that have been read */
unsigned int Ringbuffer_traits::traits_consume_partial(const char * buffer, char * value, unsigned int amount)
{
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int available = used_blocks(cache) * _block;
const unsigned int rd = (_pointers.reader.complete * _block) + _pointers.reader.partial;
const unsigned int memsize = _size * _block;
unsigned int total = std::min(amount, available);
/* should we go around the buffer for reading? */
if ((rd + total) >= _size)
{
unsigned int rd1 = memsize - rd;
unsigned int rd2 = total - rd1;
// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer);
/* two partial consumes (one at the end, another at the beginning) */
memcpy((void *) (value), (const void *) &(buffer[rd]), rd1);
memcpy((void *) &(value[rd1]), (const void *) (buffer), rd2);
}
else
{
// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer);
/* we are talking about buffers here, man! */
memcpy((void *) value, (const void *) &(buffer[rd]), total);
}
do
{
const unsigned int new_rd = (((cache.reader.complete * _block) + cache.reader.partial) + total) % memsize;
/* jump the reader forward */
Buffer_pointer index((unsigned int)floor((double)new_rd / (double)_block), (unsigned short)(new_rd % _block));
if (update(cache.reader, index))
break;
}
while (true);
// fprintf(stderr, "%p> read end: %d [block=%d]\n", this, reader, _block);
return total;
}
/********** IO FUNCTIONS **********/
/* returns the number of items written to from buffer to stream */
unsigned int Ringbuffer_traits::traits_put(const char * buffer, std::ostream &fd, unsigned int amount)
{
/* avoid using different values */
Buffer_table cache = _pointers;
const unsigned int available = used_blocks(cache);
if (amount > available)
return false;
const unsigned int wr = _pointers.writer.complete;
const unsigned int rd = _pointers.reader.complete;
unsigned int total = std::min(amount, available);
/* should we go around the buffer for reading? */
if ((rd + total) >= _size)
{
unsigned int rd1 = _size - rd;
unsigned int rd2 = total - rd1;
// fprintf(stderr, "%p> partial read: (%d/%d) %d/%d [%d/%d]\n", this, rd1, rd2, total, _size, reader, writer);
/* two partial consumes (one at the end, another at the beginning) */
fd.write((const char *) &(buffer[rd]), _block * rd1);
fd.write((const char *) (buffer), _block * rd2);
}
else
{
// fprintf(stderr, "%p> full read: %d/%d [%d/%d]\n", this, total, _size, reader, writer);
fd.write((const char *) &(buffer[rd]), _block * total);
}
do
{
/* jump the reader forward */
Buffer_pointer index((cache.reader.complete + total) % _size, 0);
if (update(cache.reader, index))
break;
}
while (true);
// fprintf(stderr, "%p> read end: %d [block=%d]\n", this, reader, _block);
return total;
}
/* returns number of items read from stream to buffer */
unsigned int Ringbuffer_traits::traits_get(char * buffer, std::istream &fd, unsigned int amount)
{
/* avoid using different values */
Buffer_table cache = _pointers;
if (amount > free_blocks(cache))
return false;
const unsigned int wr = cache.writer.complete;
const unsigned int wp = cache.writer.complete - 1;
unsigned int real_amount = 0;
/* should we go around the buffer for writing? */
if ((wr + amount) > _size)
{
// fprintf(stderr, "%p> first if matched\n", this);
unsigned int wr1 = _size - wr + 1; /* writer is already 1 position after */
unsigned int wr2 = amount - wr1;
// fprintf(stderr, "%p> partial write: (%d/%d) %d/%d [%d/%d]\n", this, wr1, wr2, amount, _size, reader, writer);
/* two partial writes (one at the end, another at the beginning) */
unsigned int char_amount = 0;
/* one partial write on the buffer (at the end) */
fd.read((char *) &(buffer[wp]), _block * wr1);
char_amount += fd.gcount();
if (fd.gcount() == (int)(_block * wr1))
{
/* another partial write on the buffer (at the beginning) */
fd.read((char *) (buffer), _block * wr2);
char_amount += fd.gcount();
}
real_amount = char_amount / _block;
}
else
{
// fprintf(stderr, "%p> second if matched\n", this);
// fprintf(stderr, "%p> full write: a=%d/s=%d [r=%d/w=%d]\n", this, amount, _size, reader, writer);
/* we are talking about buffers here, man! */
fd.read((char *) &(buffer[wp]), _block * amount);
real_amount = fd.gcount() / _block;
}
_pointers.writer.complete = ((wp + amount) % _size) + 1;
_pointers.writer.partial = 1;
// fprintf(stdout, "%p> write end: %d\n", this, _pointers.writer.complete);
return real_amount;
}

View File

@ -46,6 +46,12 @@
Also, it works only for single-reader + single-writer, since it does not depends
on external mutex functions.
NOTE: for single element provide/consume, this abstraction has standard C++ semantics.
for multiple and partial element provide/consume, memcpy is used - thus complex C++
objects which need correct copy constructor semantics should not copied this way.
*/
#include <string.h>
@ -61,7 +67,7 @@
struct Buffer_pointer
{
Buffer_pointer(unsigned int _complete = 0u, unsigned short _partial = 0u)
Buffer_pointer(unsigned int _complete, unsigned short _partial)
: complete(_complete), partial(_partial)
{};
@ -134,6 +140,10 @@ __attribute__((packed));
struct Ringbuffer_traits
{
struct BufferFull {};
struct BufferEmpty {};
protected:
Ringbuffer_traits(unsigned int block, unsigned int size)
: _block(block), _size(size)
{};
@ -155,6 +165,28 @@ struct Ringbuffer_traits
return Atomic::doCAS(&(_pointers.reader), &cache, update);
}
inline unsigned int free_blocks(const Buffer_table & cache) const
{
const unsigned int r = cache.reader.complete;
const unsigned int w = cache.writer.complete;
if (r >= w)
return (r - w);
return _size - (w - r);
}
inline unsigned int used_blocks(const Buffer_table & cache) const
{
const unsigned int r = cache.reader.complete;
const unsigned int w = cache.writer.complete;
if (r >= w)
return (_size - (r - w)) - 1;
return (w - r) - 1;
}
protected:
const unsigned int _block;
const unsigned int _size;
@ -163,11 +195,8 @@ struct Ringbuffer_traits
};
template <typename T>
struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
struct Ringbuffer: public Ringbuffer_traits, public NonCopyable
{
struct BufferFull {};
struct BufferEmpty {};
Ringbuffer(unsigned int size)
: Ringbuffer_traits(sizeof(T), size)
{
@ -189,15 +218,17 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
}
/***** GENERIC RANGE/INDEX CALCULATION FUNCTIONS *****/
bool may_write(Buffer_table & cache)
protected:
inline bool may_write(const Buffer_table & cache) const
{
const unsigned int r = cache.reader.complete;
const unsigned int w = cache.writer.complete;
return (((r - w) != 1) && (!(r == 0 && w == _size)));
return (((r - w) != 0) && (!(r == 0 && w == _size)));
}
bool may_read(Buffer_table & cache)
inline bool may_read(const Buffer_table & cache) const
{
if ((cache.writer.complete - cache.reader.complete) == 1)
return false;
@ -205,7 +236,7 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
return true;
}
unsigned int writer_next(Buffer_pointer & cache, Buffer_pointer & index)
inline unsigned int writer_next(const Buffer_pointer & cache, Buffer_pointer & index) const
{
unsigned int dest = cache.complete - 1,
temp = cache.complete + 1;
@ -218,7 +249,7 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
return dest;
};
void reader_next(Buffer_pointer & cache, Buffer_pointer & index)
inline void reader_next(const Buffer_pointer & cache, Buffer_pointer & index) const
{
unsigned int temp = cache.complete + 1;
@ -230,6 +261,7 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
/***** BUFFER FUNCTIONS *****/
public:
bool provide(const T & value)
{
Buffer_table cache = _pointers;
@ -280,9 +312,9 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
}
/* writes everything or nothing */
inline bool provide(const T * value, unsigned int amount, bool skip_overwrite = true)
inline bool provide(const T * value, unsigned int amount, bool do_not_overwrite = true)
{
return traits_provide((char *)_buffer, (const char *) value, amount, skip_overwrite);
return traits_provide((char *)_buffer, (const char *) value, amount, do_not_overwrite);
}
/* returns the number of items that have been read (atomic_mode == true means 'all or nothing') */
@ -337,7 +369,7 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
// fprintf(stderr, "%p> write: %d/%d [%d/%d]\n", this, _pointers.reader, _pointers.writer, _pointers.reader_partial, _pointers.writer_partial);
}
T & consumer_start(void)
const T & consumer_start(void)
{
Buffer_table cache = _pointers;
@ -391,13 +423,13 @@ struct Ringbuffer: protected Ringbuffer_traits, public NonCopyable
/* returns the number of items written to from buffer to stream */
inline unsigned int put(std::ostream &fd, unsigned int amount)
{
return traits_put((char *)_buffer, fd, amount);
return traits_put((const char *)_buffer, fd, amount);
}
/* returns number of items read from stream to buffer */
inline unsigned int get(std::istream &fd, unsigned int amount)
{
return traits_get((const char *)_buffer, fd, amount);
return traits_get((char *)_buffer, fd, amount);
}
void clear()

View File

@ -55,7 +55,7 @@
* implement the "unreference()" method for releasing resources. */
template < typename Implementor >
struct SimpleLockCommon: NEW_REFCOUNTER( SimpleLockCommon < Implementor > )
struct SimpleLockCommon: COUNTER_SUPER( SimpleLockCommon < Implementor > )
{
friend class ReferenceCounter < SimpleLockCommon < Implementor > >;
@ -71,7 +71,7 @@ struct SimpleLockCommon: NEW_REFCOUNTER( SimpleLockCommon < Implementor > )
{};
SimpleLockCommon(const SimpleLockCommon & o)
: INC_REFCOUNTER(o, SimpleLockCommon)
: COUNTER_REFER(o, SimpleLockCommon)
{};
virtual ~SimpleLockCommon()

View File

@ -141,6 +141,38 @@ unsigned int Strings::tokenize(const std::string & str, Strings::vector_type & t
return (cur_token - 1);
}
long Strings::tolong(const std::string & str, int base)
{
return tolong(str.c_str(), base);
}
unsigned long Strings::toulong(const std::string & str, int base)
{
return toulong(str.c_str(), base);
}
unsigned long long Strings::toulonglong(const std::string & str, int base)
{
return toulonglong(str.c_str(), base);
}
double Strings::todouble(const std::string & str)
{
return todouble(str.c_str());
}
long Strings::tolong(const char * str, int base)
{
char *str_end = 0;
unsigned long value = strtol(str, &str_end, base);
if (str_end && *str_end == 0)
return value;
throw invalid_value(str);
}
bool Strings::toboolean(std::string str)
{
std::string tmp(str);
@ -153,11 +185,11 @@ bool Strings::toboolean(std::string str)
throw invalid_value(str);
}
long Strings::tolong(std::string str, int base)
unsigned long Strings::toulong(const char * str, int base)
{
char *str_end = 0;
unsigned long value = strtol(str.c_str(), &str_end, base);
unsigned long value = strtoul(str, &str_end, base);
if (str_end && *str_end == 0)
return value;
@ -165,26 +197,14 @@ long Strings::tolong(std::string str, int base)
throw invalid_value(str);
}
unsigned long Strings::toulong(std::string str, int base)
{
char *str_end = 0;
unsigned long value = strtoul(str.c_str(), &str_end, base);
if (str_end && *str_end == 0)
return value;
throw invalid_value(str);
}
unsigned long long Strings::toulonglong(std::string str, int base)
unsigned long long Strings::toulonglong(const char * str, int base)
{
#if defined(_WINDOWS) || defined(_Windows) || defined(_WIN32) || defined(WIN32)
throw not_implemented();
#else
char *str_end = 0;
unsigned long long value = strtoull(str.c_str(), &str_end, base);
unsigned long long value = strtoull(str, &str_end, base);
if (str_end && *str_end == 0)
return value;
@ -193,11 +213,11 @@ unsigned long long Strings::toulonglong(std::string str, int base)
#endif
}
double Strings::todouble(std::string str)
double Strings::todouble(const char * str)
{
char *str_end = 0;
double value = strtod(str.c_str(), &str_end);
double value = strtod(str, &str_end);
if (str_end && *str_end == 0)
return value;

View File

@ -68,6 +68,8 @@ struct Strings
bool empty() { return _list.empty(); };
const list_type & list() { return _list; };
protected:
list_type _list;
};
@ -75,8 +77,8 @@ struct Strings
public:
struct invalid_value
{
invalid_value(const char * value): _value(value) {};
invalid_value(std::string value): _value(value) {};
invalid_value(const char * value): _value(value) {};
invalid_value(const std::string & value): _value(value) {};
std::string & value() { return _value; }
@ -92,10 +94,15 @@ struct Strings
static bool toboolean(std::string);
static std::string fromboolean(bool);
static long tolong(std::string, int base = 10);
static unsigned long toulong(std::string, int base = 10);
static unsigned long long toulonglong(std::string, int base = 10);
static double todouble(std::string);
static long tolong(const std::string &, int base = 10);
static unsigned long toulong(const std::string &, int base = 10);
static unsigned long long toulonglong(const std::string &, int base = 10);
static double todouble(const std::string &);
static long tolong(const char *, int base = 10);
static unsigned long toulong(const char *, int base = 10);
static unsigned long long toulonglong(const char *, int base = 10);
static double todouble(const char *);
static std::string lower(std::string);
static std::string hexadecimal(std::string);

View File

@ -1,7 +1,7 @@
/*
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
Copyright (C) 2007-2009 Khomp Ind. & Com.
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
@ -23,40 +23,40 @@
The LGPL header follows below:
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "saved_condition.hpp"
bool SavedCondition::wait(unsigned int msec)
{
bool ret = true;
bool ret = true;
switch_mutex_lock(_mutex);
if (!_signaled)
{
{
/* msec * 1000 = The amount of time in microseconds to wait. */
if (switch_thread_cond_timedwait(_condition, _mutex, (switch_interval_time_t)msec * 1000) != 0)
ret = false;
}
if (switch_thread_cond_timedwait(_condition, _mutex, (switch_interval_time_t)msec * 1000) != 0)
ret = false;
}
_signaled = false;
switch_mutex_unlock(_mutex);
switch_mutex_unlock(_mutex);
return ret;
return ret;
}

View File

@ -1,7 +1,7 @@
/*
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
Copyright (C) 2007-2009 Khomp Ind. & Com.
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
@ -23,20 +23,20 @@
The LGPL header follows below:
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _SAVED_CONDITION_
@ -104,7 +104,7 @@ struct SavedCondition : public SavedConditionCommon// : public RefCounter < Save
if (!_signaled)
switch_thread_cond_wait(_condition, _mutex);
_signaled = false;
switch_mutex_unlock(_mutex);

View File

@ -1,7 +1,7 @@
/*
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
Copyright (C) 2007-2009 Khomp Ind. & Com.
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
@ -23,20 +23,20 @@
The LGPL header follows below:
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _SIMPLE_LOCK_HPP_
@ -72,7 +72,7 @@ struct SimpleLockBasic: public SimpleLockCommon < Implementor >
{
/* do nothing */
};
void unreference()
{
switch_mutex_destroy(_mutex);

View File

@ -1,7 +1,7 @@
/*
/*
KHOMP generic endpoint/channel library.
Copyright (C) 2007-2009 Khomp Ind. & Com.
Copyright (C) 2007-2009 Khomp Ind. & Com.
The contents of this file are subject to the Mozilla Public License Version 1.1
(the "License"); you may not use this file except in compliance with the
License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
@ -23,20 +23,20 @@
The LGPL header follows below:
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _THREAD_HPP_
@ -66,7 +66,7 @@ struct Thread : ThreadCommon
T _data;
A _arg;
};
template<typename T, typename R>
struct ThreadData < T, R, void > : ThreadDataCommon
{
@ -79,7 +79,7 @@ struct Thread : ThreadCommon
T _data;
};
template<typename T, typename A>
struct ThreadData < T, void, A > : ThreadDataCommon
{
@ -111,7 +111,7 @@ struct Thread : ThreadCommon
};
template<typename T>
Thread(T obj, switch_memory_pool_t *pool=NULL) :
Thread(T obj, switch_memory_pool_t *pool=NULL) :
_thread_info(new ThreadData<T, typename DecomposeFunction<T>::Return, void>(obj)),
_pool(pool),
_can_delete_pool(false)
@ -134,7 +134,7 @@ struct Thread : ThreadCommon
}
switch_threadattr_stacksize_set(
(switch_threadattr_t *)_thread_info->_attribute,
(switch_threadattr_t *)_thread_info->_attribute,
SWITCH_THREAD_STACKSIZE);
if(!priority())
@ -143,9 +143,9 @@ struct Thread : ThreadCommon
}
}
template<typename T, typename A>
Thread(T obj, A arg, switch_memory_pool_t *pool=NULL) :
Thread(T obj, A arg, switch_memory_pool_t *pool=NULL) :
_thread_info(new ThreadData<T, typename DecomposeFunction<T>::Return, A>(obj, arg)),
_pool(pool),
_can_delete_pool(false)
@ -168,7 +168,7 @@ struct Thread : ThreadCommon
}
switch_threadattr_stacksize_set(
(switch_threadattr_t *)_thread_info->_attribute,
(switch_threadattr_t *)_thread_info->_attribute,
SWITCH_THREAD_STACKSIZE);
if(!priority())
@ -178,11 +178,11 @@ struct Thread : ThreadCommon
}
~Thread()
~Thread()
{
if(_thread_info)
delete _thread_info;
if (_can_delete_pool)
switch_core_destroy_memory_pool(&_pool);
}
@ -202,10 +202,10 @@ struct Thread : ThreadCommon
if(!_pool || !_thread_info->_attribute)
return false;
switch_thread_create((switch_thread_t**)&_thread_info->_self,
(switch_threadattr_t *)_thread_info->_attribute,
run,
_thread_info,
switch_thread_create((switch_thread_t**)&_thread_info->_self,
(switch_threadattr_t *)_thread_info->_attribute,
run,
_thread_info,
_pool);
if(!_thread_info->_self)
@ -223,13 +223,13 @@ struct Thread : ThreadCommon
*
* SWITCH_DECLARE(switch_status_t) switch_thread_join(switch_status_t *retval, switch_thread_t *thd);
*/
if(!_thread_info->_self)
return -2;
int retval = 0;
if(switch_thread_join((switch_status_t*)&retval,
if(switch_thread_join((switch_status_t*)&retval,
(switch_thread_t *)_thread_info->_self) != 0)
return -1;
@ -267,7 +267,7 @@ private:
{
#ifndef WIN32
struct sched_param param;
struct apr_threadattr_t *myattr = (struct apr_threadattr_t *)_thread_info->_attribute;
if (pthread_attr_setschedpolicy(
@ -307,13 +307,13 @@ protected:
static void *SWITCH_THREAD_FUNC run(BaseThreadType *thread, void * obj)
{
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
// "Starting new Thread\n");
ThreadDataCommon * data = (ThreadDataCommon *)obj;
int retval = data->run();
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
// "Stopping new Thread = %d\n", retval);
((Thread *)(data->_thread))->exit(retval);

View File

@ -42,11 +42,14 @@
#ifndef _TAGGED_UNION_HPP_
#define _TAGGED_UNION_HPP_
#include <stdexcept>
#include <iostream>
#include <unistd.h>
#include <typeinfo>
#include <stdexcept>
#include <iostream>
#include <format.hpp>
namespace Tagged
{
struct EmptyUnion
@ -69,7 +72,7 @@ namespace Tagged
~EmptyUnion() { _adjusted = false; };
bool operator==(const EmptyUnion & o)
bool operator==(const EmptyUnion & o) const
{
return true;
};
@ -80,24 +83,24 @@ namespace Tagged
void setup(void) { _adjusted = true; };
protected:
bool value_set(void) { return false; };
bool value_get(void) { return false; };
bool value_set(void) const { return false; };
bool value_get(void) const { return false; };
bool value_check(void) { return false; };
bool value_check(void) const { return false; };
template < typename S >
bool value_visit(S & visitor, typename S::ReturnType & ret)
bool value_visit(S & visitor, typename S::ReturnType & ret) const
{
return false;
};
template < typename S >
bool value_visit_void(S & visitor)
bool value_visit_void(S & visitor) const
{
return false;
};
bool adjusted() { return _adjusted; };
bool adjusted() const { return _adjusted; };
private:
bool _adjusted;
@ -114,7 +117,7 @@ namespace Tagged
// constructor with initializer
template < typename U >
Union( U value )
Union(U value)
: _value(0)
{
set(value);
@ -123,7 +126,7 @@ namespace Tagged
// copy constructor
Union(const Union & o)
: E(static_cast<const E&>(o)),
_value( (o._value ? new const V(*(o._value)) : 0) )
_value( (o._value ? new V(*(o._value)) : 0) )
{};
// copy assignment operator
@ -137,7 +140,7 @@ namespace Tagged
if (o._value)
{
_value = new const V(*(o._value));
_value = new V(*(o._value));
}
E::operator=(static_cast<const E&>(o));
@ -163,18 +166,21 @@ namespace Tagged
}
template < typename U >
bool check(void)
bool check(void) const
{
return value_check(static_cast<const U * const>(0));
return value_check(static_cast< const U * const>(0));
};
template < typename U >
const U & get(void)
U & get(void) const
{
const U * res = 0;
U * res = 0;
if (!E::adjusted())
throw std::runtime_error("tagged union empty!");
if (!value_get(&res) || !res)
throw std::runtime_error("type mismatch");
throw std::runtime_error(STG(FMT("type mismatch when asked for '%s'") % typeid(U).name()));
return *res;
};
@ -190,7 +196,7 @@ namespace Tagged
};
template < typename S >
typename S::ReturnType visit(S visitor)
typename S::ReturnType visit(S visitor) const
{
typename S::ReturnType ret;
@ -201,7 +207,7 @@ namespace Tagged
};
template < typename S >
void visit_void(S visitor)
void visit_void(S visitor) const
{
if (!value_visit_void(visitor))
throw std::runtime_error("unable to visit empty value");
@ -219,7 +225,7 @@ namespace Tagged
};
// compare (equal) operator
bool operator==(const Union & o)
bool operator==(const Union & o) const
{
bool are_equal = false;
@ -236,7 +242,7 @@ namespace Tagged
};
// compare types
bool sameType(const Union & o)
bool sameType(const Union & o) const
{
if ((!(_value) && !(o._value)) || (_value && o._value))
return E::operator==(static_cast<const E&>(o));
@ -254,13 +260,13 @@ namespace Tagged
bool value_set(V val)
{
_value = new const V(val);
_value = new V(val);
E::setup();
return true;
};
bool value_get(const V ** val)
bool value_get(V ** val) const
{
if (!_value)
return false;
@ -269,14 +275,14 @@ namespace Tagged
return true;
}
bool value_check(const V * const junk)
bool value_check(const V * const junk) const
{
(void)junk;
return (_value != 0);
};
template < typename S >
bool value_visit(S & visitor, typename S::ReturnType & ret)
bool value_visit(S & visitor, typename S::ReturnType & ret) const
{
if (_value)
{
@ -288,7 +294,7 @@ namespace Tagged
};
template < typename S >
bool value_visit_void(S & visitor)
bool value_visit_void(S & visitor) const
{
if (_value)
{
@ -300,7 +306,7 @@ namespace Tagged
};
private:
const V * _value;
V * _value;
};
};

View File

@ -276,6 +276,20 @@ bool TimerTraits::traits_restart (TimerTraits::Index & idx, bool force)
return ret;
}
void TimerTraits::traits_setup(TimerTraits::Index * idx, unsigned int msecs, const void * func, void * data, unsigned int value)
{
_mutex.lock();
if (idx->valid)
{
(void)traits_del_unlocked(*idx);
}
*idx = traits_add_unlocked(msecs, func, data, value);
_mutex.unlock();
}
bool TimerTraits::traits_del_unlocked (TimerTraits::Index & idx)
{
bool ret = false;

Some files were not shown because too many files have changed in this diff Show More