Merge branch 'smgmaster' into releases.3.4

Conflicts:
	libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c
	libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c
This commit is contained in:
Moises Silva 2011-06-13 14:18:23 -04:00
commit 5882e06f70
307 changed files with 12194 additions and 7889 deletions

View File

@ -9,12 +9,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchConsole", "w32\Co
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchCoreLib", "w32\Library\FreeSwitchCore.2008.vcproj", "{202D7A4E-760D-4D0E-AFA1-D7459CED30FF}"
ProjectSection(ProjectDependencies) = postProject
{D331904D-A00A-4694-A5A3-FCFF64AB5DBE} = {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}
{8D04B550-D240-4A44-8A18-35DA3F7038D9} = {8D04B550-D240-4A44-8A18-35DA3F7038D9}
{89385C74-5860-4174-9CAF-A39E7C48909C} = {89385C74-5860-4174-9CAF-A39E7C48909C}
{1CBB0077-18C5-455F-801C-0A0CE7B0BBF5} = {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}
{F057DA7F-79E5-4B00-845C-EF446EF055E3} = {F057DA7F-79E5-4B00-845C-EF446EF055E3}
{03207781-0D1C-4DB3-A71D-45C608F28DBD} = {03207781-0D1C-4DB3-A71D-45C608F28DBD}
{F6C55D93-B927-4483-BB69-15AEF3DD2DFF} = {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}
{87EE9DA4-DE1E-4448-8324-183C98DCA588} = {87EE9DA4-DE1E-4448-8324-183C98DCA588}
{EEF031CB-FED8-451E-A471-91EC8D4F6750} = {EEF031CB-FED8-451E-A471-91EC8D4F6750}
{6EDFEFD5-3596-4FA9-8EBA-B331547B35A3} = {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}
EndProjectSection

View File

@ -379,12 +379,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchConsole", "w32\Co
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchCoreLib", "w32\Library\FreeSwitchCore.2008.vcproj", "{202D7A4E-760D-4D0E-AFA1-D7459CED30FF}"
ProjectSection(ProjectDependencies) = postProject
{D331904D-A00A-4694-A5A3-FCFF64AB5DBE} = {D331904D-A00A-4694-A5A3-FCFF64AB5DBE}
{8D04B550-D240-4A44-8A18-35DA3F7038D9} = {8D04B550-D240-4A44-8A18-35DA3F7038D9}
{89385C74-5860-4174-9CAF-A39E7C48909C} = {89385C74-5860-4174-9CAF-A39E7C48909C}
{1CBB0077-18C5-455F-801C-0A0CE7B0BBF5} = {1CBB0077-18C5-455F-801C-0A0CE7B0BBF5}
{F057DA7F-79E5-4B00-845C-EF446EF055E3} = {F057DA7F-79E5-4B00-845C-EF446EF055E3}
{03207781-0D1C-4DB3-A71D-45C608F28DBD} = {03207781-0D1C-4DB3-A71D-45C608F28DBD}
{F6C55D93-B927-4483-BB69-15AEF3DD2DFF} = {F6C55D93-B927-4483-BB69-15AEF3DD2DFF}
{87EE9DA4-DE1E-4448-8324-183C98DCA588} = {87EE9DA4-DE1E-4448-8324-183C98DCA588}
{EEF031CB-FED8-451E-A471-91EC8D4F6750} = {EEF031CB-FED8-451E-A471-91EC8D4F6750}
{6EDFEFD5-3596-4FA9-8EBA-B331547B35A3} = {6EDFEFD5-3596-4FA9-8EBA-B331547B35A3}
EndProjectSection

View File

@ -709,6 +709,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_say_pt", "src\mod\say\m
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ldns", "libs\win32\ldns\ldns-lib\ldns-lib.2010.vcxproj", "{23B4D303-79FC-49E0-89E2-2280E7E28940}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_callcenter", "src\mod\applications\mod_callcenter\mod_callcenter.2010.vcxproj", "{47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
All|Win32 = All|Win32
@ -3633,6 +3635,19 @@ Global
{23B4D303-79FC-49E0-89E2-2280E7E28940}.Release|x64.Build.0 = Release|x64
{23B4D303-79FC-49E0-89E2-2280E7E28940}.Release|x64 Setup.ActiveCfg = Release|x64
{23B4D303-79FC-49E0-89E2-2280E7E28940}.Release|x86 Setup.ActiveCfg = Release|x64
{47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}.All|Win32.ActiveCfg = Release|x64
{47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}.All|x64.ActiveCfg = Release|x64
{47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}.All|x64.Build.0 = Release|x64
{47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}.All|x64 Setup.ActiveCfg = Release|x64
{47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}.All|x86 Setup.ActiveCfg = Release|x64
{47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}.Debug|Win32.ActiveCfg = Debug|Win32
{47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}.Debug|x64.ActiveCfg = Debug|x64
{47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}.Debug|x64 Setup.ActiveCfg = Debug|x64
{47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}.Debug|x86 Setup.ActiveCfg = Debug|x64
{47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}.Release|Win32.ActiveCfg = Release|Win32
{47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}.Release|x64.ActiveCfg = Release|x64
{47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}.Release|x64 Setup.ActiveCfg = Release|x64
{47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A}.Release|x86 Setup.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -3680,6 +3695,7 @@ Global
{2E250296-0C08-4342-9C8A-BCBDD0E7DF65} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78}
{B889A18E-70A7-44B5-B2C9-47798D4F43B3} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78}
{5C2B4D88-3BEA-4FE0-90DF-FA9836099D5F} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78}
{47886A6C-CCA6-4F9F-A7D4-F97D06FB2B1A} = {E72B5BCB-6462-4D23-B419-3AF1A4AC3D78}
{07113B25-D3AF-4E04-BA77-4CD1171F022C} = {C5F182F9-754A-4EC5-B50F-76ED02BE13F4}
{A27CCA23-1541-4337-81A4-F0A6413078A0} = {C5F182F9-754A-4EC5-B50F-76ED02BE13F4}
{E7BC026C-7CC5-45A3-BC7C-3B88EEF01F24} = {C5F182F9-754A-4EC5-B50F-76ED02BE13F4}

View File

@ -106,7 +106,10 @@ CORE_CFLAGS += -I$(switch_srcdir)/libs/spandsp/src -I$(switch_srcdir)/libs/tiff-
CORE_LIBS = libs/apr-util/libaprutil-1.la libs/apr/libapr-1.la
CORE_LIBS += libs/sqlite/libsqlite3.la libs/pcre/libpcre.la libs/speex/libspeex/libspeexdsp.la
if ENABLE_SRTP
CORE_CFLAGS += -DENABLE_SRTP
CORE_LIBS += libs/srtp/libsrtp.la
endif
MOD_LINK = $(switch_srcdir)/libfreeswitch.la
CLEANFILES = src/include/switch_version.h src/include/switch_swigable_cpp.h

View File

@ -15,7 +15,7 @@
. /etc/init.d/functions
PROG_NAME=freeswitch
PID_FILE=${PID_FILE-/opt/freeswitch/run/freeswitch.pid}
PID_FILE=${PID_FILE-/var/run/freeswitch/freeswitch.pid}
FS_USER=${FS_USER-freeswitch}
FS_FILE=${FS_FILE-/opt/freeswitch/bin/freeswitch}
FS_HOME=${FS_HOME-/opt/freeswitch}

View File

@ -1,119 +1,13 @@
loggers/mod_console
loggers/mod_logfile
loggers/mod_syslog
#applications/mod_cidlookup
applications/mod_commands
applications/mod_conference
applications/mod_dptools
applications/mod_enum
#applications/mod_osp
applications/mod_fifo
#applications/mod_curl
applications/mod_db
applications/mod_commands
applications/mod_hash
#applications/mod_redis
applications/mod_voicemail
#applications/mod_directory
#applications/mod_lcr
applications/mod_expr
applications/mod_esf
#applications/mod_easyroute
applications/mod_fsv
#applications/mod_nibblebill
#applications/mod_soundtouch
#applications/mod_rss
applications/mod_spandsp
#applications/mod_snom
#applications/mod_vmd
#applications/mod_avmd
#applications/mod_memcache
#applications/mod_spy
applications/mod_cluechoo
applications/mod_valet_parking
#applications/mod_distributor
#applications/mod_stress
#applications/mod_snapshot
#applications/mod_snipe_hunt
#applications/mod_callcenter
#applications/mod_fsk
#applications/mod_ladspa
codecs/mod_g723_1
codecs/mod_amr
#codecs/mod_amrwb
#codecs/mod_silk
#codecs/mod_codec2
codecs/mod_g729
#codecs/mod_com_g729
codecs/mod_h26x
codecs/mod_bv
codecs/mod_ilbc
codecs/mod_speex
codecs/mod_siren
#codecs/mod_celt
#codecs/mod_opus
#codecs/mod_sangoma_codec
#codecs/mod_dahdi_codec
#dialplans/mod_dialplan_directory
dialplans/mod_dialplan_xml
dialplans/mod_dialplan_asterisk
#directories/mod_ldap
#endpoints/mod_dingaling
#endpoints/mod_portaudio
endpoints/mod_sofia
endpoints/mod_loopback
#endpoints/mod_alsa
#endpoints/mod_opal
#endpoints/mod_skinny
#endpoints/mod_skypopen
#endpoints/mod_h323
#endpoints/mod_khomp
#../../libs/openzap/mod_openzap
#../../libs/freetdm/mod_freetdm
#asr_tts/mod_unimrcp
#asr_tts/mod_flite
#asr_tts/mod_pocketsphinx
#asr_tts/mod_cepstral
#asr_tts/mod_tts_commandline
#event_handlers/mod_event_multicast
event_handlers/mod_event_socket
#event_handlers/mod_event_zmq
event_handlers/mod_cdr_csv
event_handlers/mod_cdr_sqlite
#event_handlers/mod_cdr_pg_csv
#event_handlers/mod_radius_cdr
#event_handlers/mod_erlang_event
#event_handlers/mod_snmp
formats/mod_native_file
formats/mod_sndfile
#formats/mod_shout
formats/mod_local_stream
formats/mod_tone_stream
#formats/mod_portaudio_stream
#formats/mod_shell_stream
#languages/mod_python
languages/mod_spidermonkey
languages/mod_lua
#languages/mod_perl
#languages/mod_yaml
#languages/mod_java
#languages/mod_managed
xml_int/mod_xml_rpc
#xml_int/mod_xml_curl
../../libs/freetdm/mod_freetdm
xml_int/mod_xml_cdr
#xml_int/mod_xml_ldap
say/mod_say_en
#say/mod_say_de
#say/mod_say_es
#say/mod_say_fr
#say/mod_say_it
#say/mod_say_nl
#say/mod_say_pt
#say/mod_say_ru
#say/mod_say_zh
#say/mod_say_hu
#say/mod_say_th
#say/mod_say_he
#timers/mod_timerfd
## Experimental Modules (don't cry if they're broken)
#../../contrib/mod/xml_int/mod_xml_odbc
event_handlers/mod_event_socket
codecs/mod_sangoma_codec

View File

@ -1,3 +1,3 @@
en-us-callie 1.0.14
en-us-callie 1.0.16
ru-RU-elena 1.0.12

View File

@ -0,0 +1,12 @@
<configuration name="cepstral.conf" description="Cepstral TTS configuration">
<settings>
<!--
Possible encodings:
* utf-8
* us-ascii
* iso8859-1 (default)
* iso8859-15
-->
<param name="encoding" value="utf-8"/>
</settings>
</configuration>

View File

@ -113,7 +113,7 @@
<!-- Say -->
<load module="mod_say_en"/>
<load module="mod_say_ru"/>
<!-- <load module="mod_say_ru"/> -->
<!-- <load module="mod_say_zh"/> -->
<!-- Third party modules -->

View File

@ -0,0 +1,7 @@
<configuration name="mongo.conf">
<settings>
<param name="host" value="127.0.0.1:27017"/>
<param name="min-connections" value="10"/>
<param name="max-connections" value="100"/>
</settings>
</configuration>

View File

@ -24,6 +24,17 @@
<!--Colorize the Console -->
<param name="colorize-console" value="true"/>
<!-- Run the timer at 20ms by default and drop down as needed unless you set 1m-timer=true which was previous default -->
<!-- <param name="1ms-timer" value="true"/> -->
<!--
Set the Switch Name for HA environments.
When setting the switch name, it will override the system hostname for all DB and CURL requests
allowing cluster environments such as RHCS to have identical FreeSWITCH configurations but run
as different hostnames.
-->
<!-- <param name="switchname" value="freeswitch"/>-->
<!-- maximum number of simo db handles open -->
<param name="max-db-handles" value="50"/>
<!-- maximum number of seconds to wait for a new db handle before failing -->

View File

@ -0,0 +1,26 @@
<include>
<extension name="Talking Clock Time" ><!--e.g. 10:56pm-->
<condition field="destination_number" expression="^9170$">
<action application="say" data="en CURRENT_TIME pronounced
${strepoch()}"/>
<action application="hangup"/>
</condition>
</extension>
<extension name="Talking Clock Date" ><!--e.g. March 8, 2011-->
<condition field="destination_number" expression="^9171$">
<action application="say" data="en CURRENT_DATE pronounced
${strepoch()}"/>
<action application="hangup"/>
</condition>
</extension>
<extension name="Talking Clock Date and Time" ><!--e.g. March 8, 2011
10:56pm-->
<condition field="destination_number" expression="^9172$">
<action application="say" data="en CURRENT_DATE_TIME pronounced
${strepoch()}"/>
<action application="hangup"/>
</condition>
</extension>
</include>

View File

@ -52,14 +52,12 @@
<X-PRE-PROCESS cmd="include" data="directory/*.xml"/>
</section>
<!-- phrases section (under development still) -->
<section name="phrases" description="Speech Phrase Management">
<macros>
<X-PRE-PROCESS cmd="include" data="lang/de/*.xml"/>
<X-PRE-PROCESS cmd="include" data="lang/en/*.xml"/>
<X-PRE-PROCESS cmd="include" data="lang/fr/*.xml"/>
<X-PRE-PROCESS cmd="include" data="lang/ru/*.xml"/>
<X-PRE-PROCESS cmd="include" data="lang/he/*.xml"/>
</macros>
<!-- languages section (under development still) -->
<section name="languages" description="Language Management">
<X-PRE-PROCESS cmd="include" data="lang/de/*.xml"/>
<X-PRE-PROCESS cmd="include" data="lang/en/*.xml"/>
<X-PRE-PROCESS cmd="include" data="lang/fr/*.xml"/>
<X-PRE-PROCESS cmd="include" data="lang/ru/*.xml"/>
<X-PRE-PROCESS cmd="include" data="lang/he/*.xml"/>
</section>
</document>

View File

@ -1,7 +1,11 @@
<include>
<language name="de" sound-path="/snds" tts-engine="cepstral" tts-voice="david">
<X-PRE-PROCESS cmd="include" data="demo/demo.xml"/>
<!--voicemail_de_tts is purely implemented with tts, we need a files based implementation too -->
<X-PRE-PROCESS cmd="include" data="vm/tts.xml"/>
<language name="de" sound-prefix="/snds" tts-engine="cepstral" tts-voice="david">
<phrases>
<macros>
<X-PRE-PROCESS cmd="include" data="demo/demo.xml"/>
<!--voicemail_de_tts is purely implemented with tts, we need a files based implementation too -->
<X-PRE-PROCESS cmd="include" data="vm/tts.xml"/>
</macros>
</phrases>
</language>
</include>

407
conf/lang/de/vm/sounds.xml Normal file
View File

@ -0,0 +1,407 @@
<include><!--This line will be ignored it's here to validate the xml and is optional -->
<macro name="voicemail_enter_id">
<input pattern="(.*)">
<match>
<action function="play-file" data="voicemail/vm-enter_id.wav"/>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
</match>
</input>
</macro>
<macro name="voicemail_enter_pass">
<input pattern="(.*)">
<match>
<action function="play-file" data="voicemail/vm-enter_pass.wav"/>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
</match>
</input>
</macro>
<macro name="voicemail_fail_auth">
<input pattern="(.*)">
<match>
<action function="play-file" data="voicemail/vm-fail_auth.wav"/>
</match>
</input>
</macro>
<macro name="voicemail_hello">
<input pattern="(.*)">
<match>
<!--<action function="play-file" data="voicemail/vm-hello.wav"/> -->
</match>
</input>
</macro>
<macro name="voicemail_goodbye">
<input pattern="(.*)">
<match>
<action function="play-file" data="voicemail/vm-goodbye.wav"/>
</match>
</input>
</macro>
<macro name="voicemail_abort">
<input pattern="(.*)">
<match>
<action function="play-file" data="voicemail/vm-abort.wav"/>
</match>
</input>
</macro>
<macro name="voicemail_message_count">
<input pattern="^(1):(.*)$" break_on_match="true">
<match>
<action function="play-file" data="voicemail/vm-you_have.wav"/>
<action application="log" data="INFO $1 $2"/>
<action function="say" data="$1" method="pronounced" type="items" gender="feminine"/>
<action function="play-file" data="voicemail/vm-$2.wav"/>
<action function="play-file" data="voicemail/vm-message.wav"/>
</match>
</input>
<input pattern="^(\d+):(.*)$">
<match>
<action function="play-file" data="voicemail/vm-you_have.wav"/>
<action function="say" data="$1" method="pronounced" type="items" gender="feminine"/>
<action function="play-file" data="voicemail/vm-$2.wav"/>
<action function="play-file" data="voicemail/vm-messages.wav"/>
</match>
</input>
</macro>
<macro name="voicemail_menu">
<input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*])$">
<match>
<!-- To listen to new messages -->
<action function="play-file" data="voicemail/vm-listen_new.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
<action function="execute" data="sleep(100)"/>
<!-- To listen to saved messages -->
<action function="play-file" data="voicemail/vm-listen_saved.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$2" method="pronounced" type="name_spelled"/>
<action function="execute" data="sleep(100)"/>
<!-- For advanced options -->
<action function="play-file" data="voicemail/vm-advanced.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$3" method="pronounced" type="name_spelled"/>
<action function="execute" data="sleep(100)"/>
<!-- To exit -->
<action function="play-file" data="voicemail/vm-to_exit.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$4" method="pronounced" type="name_phonetic"/>
</match>
</input>
</macro>
<macro name="voicemail_config_menu">
<input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*])$">
<match>
<!-- To record a greeting -->
<action function="play-file" data="voicemail/vm-to_record_greeting.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
<action function="execute" data="sleep(100)"/>
<!-- To choose greeting -->
<action function="play-file" data="voicemail/vm-choose_greeting.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$2" method="pronounced" type="name_spelled"/>
<action function="execute" data="sleep(100)"/>
<!-- To record your name -->
<action function="play-file" data="voicemail/vm-record_name2.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$3" method="pronounced" type="name_spelled"/>
<action function="execute" data="sleep(100)"/>
<!-- To change password -->
<action function="play-file" data="voicemail/vm-change_password.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$4" method="pronounced" type="name_spelled"/>
<action function="execute" data="sleep(100)"/>
<!-- To return to main menu -->
<action function="play-file" data="voicemail/vm-main_menu.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$5" method="pronounced" type="name_spelled"/>
</match>
</input>
</macro>
<macro name="voicemail_record_name">
<input pattern="^(.*)$">
<match>
<action function="play-file" data="voicemail/vm-record_name1.wav"/>
</match>
</input>
</macro>
<macro name="voicemail_record_file_check">
<input pattern="^([0-9#*]):([0-9#*]):([0-9#*])$">
<match>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
<action function="play-file" data="voicemail/vm-listen_to_recording.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$2" method="pronounced" type="name_spelled"/>
<action function="play-file" data="voicemail/vm-save_recording.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$3" method="pronounced" type="name_spelled"/>
<action function="play-file" data="voicemail/vm-rerecord.wav"/>
</match>
</input>
</macro>
<macro name="voicemail_record_urgent_check">
<input pattern="^([0-9#*]):([0-9#*])$">
<match>
<action function="play-file" data="voicemail/vm-mark-urgent.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
<action function="play-file" data="voicemail/vm-continue.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$2" method="pronounced" type="name_spelled"/>
</match>
</input>
</macro>
<macro name="voicemail_forward_prepend">
<input pattern="^([0-9#*]):([0-9#*])$">
<match>
<action function="play-file" data="voicemail/vm-forward_add_intro.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
<action function="play-file" data="voicemail/vm-send_message_now.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$2" method="pronounced" type="name_spelled"/>
</match>
</input>
</macro>
<macro name="voicemail_forward_message_enter_extension">
<input pattern="^([0-9#*])$">
<match>
<action function="play-file" data="voicemail/vm-forward_enter_ext.wav"/>
<action function="play-file" data="voicemail/vm-followed_by.wav"/>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
</match>
</input>
</macro>
<macro name="voicemail_invalid_extension">
<input pattern="^(.*)$">
<match>
<action function="play-file" data="voicemail/vm-that_was_an_invalid_ext.wav"/>
</match>
</input>
</macro>
<macro name="voicemail_listen_file_check">
<input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*]):(.*)$">
<match>
<action function="play-file" data="voicemail/vm-listen_to_recording.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
<action function="play-file" data="voicemail/vm-save_recording.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$2" method="pronounced" type="name_spelled"/>
<action function="play-file" data="voicemail/vm-delete_recording.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$3" method="pronounced" type="name_spelled"/>
<action function="play-file" data="voicemail/vm-forward_to_email.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$4" method="pronounced" type="name_spelled"/>
<action function="play-file" data="voicemail/vm-return_call.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$5" method="pronounced" type="name_spelled"/>
<action function="play-file" data="voicemail/vm-to_forward.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$6" method="pronounced" type="name_spelled"/>
</match>
</input>
<input pattern="^([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*]):([0-9#*])$">
<match>
<action function="play-file" data="voicemail/vm-listen_to_recording.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
<action function="play-file" data="voicemail/vm-save_recording.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$2" method="pronounced" type="name_spelled"/>
<action function="play-file" data="voicemail/vm-delete_recording.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$3" method="pronounced" type="name_spelled"/>
<action function="play-file" data="voicemail/vm-return_call.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$5" method="pronounced" type="name_spelled"/>
<action function="play-file" data="voicemail/vm-to_forward.wav"/>
<action function="play-file" data="voicemail/vm-press.wav"/>
<action function="say" data="$6" method="pronounced" type="name_spelled"/>
</match>
</input>
</macro>
<macro name="voicemail_choose_greeting">
<input pattern="^(.*)$">
<match>
<action function="play-file" data="voicemail/vm-choose_greeting_choose.wav"/>
</match>
</input>
</macro>
<macro name="voicemail_choose_greeting_fail">
<input pattern="^(.*)$">
<match>
<action function="play-file" data="voicemail/vm-choose_greeting_fail.wav"/>
</match>
</input>
</macro>
<macro name="voicemail_record_greeting">
<input pattern="^(.*)$">
<match>
<action function="play-file" data="voicemail/vm-record_greeting.wav"/>
</match>
</input>
</macro>
<macro name="voicemail_record_message">
<input pattern="^(.*)$">
<match>
<action function="play-file" data="voicemail/vm-record_message.wav"/>
</match>
</input>
</macro>
<macro name="voicemail_greeting_selected">
<input pattern="^(\d+)$">
<match>
<action function="play-file" data="voicemail/vm-greeting.wav"/>
<action function="say" data="$1" method="pronounced" type="items"/>
<action function="play-file" data="voicemail/vm-selected.wav"/>
</match>
</input>
</macro>
<macro name="voicemail_play_greeting">
<input pattern="^(.*)$">
<match>
<action function="play-file" data="voicemail/vm-person.wav"/>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
<action function="play-file" data="voicemail/vm-not_available.wav"/>
</match>
</input>
</macro>
<macro name="voicemail_say_number">
<input pattern="^(\d+)$">
<match>
<action function="say" data="$1" method="pronounced" type="items"/>
</match>
</input>
</macro>
<macro name="voicemail_say_message_number">
<input pattern="^([a-z]+):(\d+)$">
<match>
<action function="play-file" data="voicemail/vm-$1.wav"/>
<action function="play-file" data="voicemail/vm-message_number.wav"/>
<action application="log" data="INFO $1 $2"/>
<action function="say" data="$2" method="pronounced" type="items"/>
</match>
</input>
</macro>
<macro name="voicemail_say_phone_number">
<input pattern="^(.*)$">
<match>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
</match>
</input>
</macro>
<macro name="voicemail_say_name">
<input pattern="^(.*)$">
<match>
<action function="say" data="$1" method="pronounced" type="name_spelled"/>
</match>
</input>
</macro>
<!-- Note: Update this to marked-urgent,emailed and saved once new sound files are recorded -->
<macro name="voicemail_ack">
<input pattern="^(too-small)$">
<match>
<action function="play-file" data="voicemail/vm-too-small.wav"/>
</match>
</input>
<input pattern="^(deleted)$">
<match>
<action function="play-file" data="voicemail/vm-message.wav"/>
<action function="play-file" data="voicemail/vm-$1.wav"/>
</match>
</input>
<input pattern="^(saved)$">
<match>
<action function="play-file" data="voicemail/vm-message.wav"/>
<action function="play-file" data="voicemail/vm-$1.wav"/>
</match>
</input>
<input pattern="^(emailed)$">
<match>
<action function="play-file" data="voicemail/vm-message.wav"/>
<action function="play-file" data="voicemail/vm-$1.wav"/>
</match>
</input>
<input pattern="^(marked-urgent)$">
<match>
<action function="play-file" data="voicemail/vm-message.wav"/>
<action function="play-file" data="voicemail/vm-$1.wav"/>
</match>
</input>
</macro>
<macro name="voicemail_say_date">
<input pattern="^(.*)$">
<match>
<action application="log" data="INFO $1"/>
<action function="say" data="$1" method="counted" type="current_date_time"/>
</match>
</input>
</macro>
<macro name="voicemail_disk_quota_exceeded">
<input pattern="^(.*)$">
<match>
<action function="play-file" data="voicemail/vm-mailbox_full.wav"/>
</match>
</input>
</macro>
<macro name="valet_announce_ext">
<input pattern="^([^\:]+):(.*)$">
<match>
<action function="say" data="$2" method="pronounced" type="name_spelled"/>
</match>
</input>
</macro>
<macro name="valet_lot_full">
<input pattern="^(.*)$">
<match>
<action function="play-file" data="tone_stream://%(275,10,600);%(275,100,300)"/>
</match>
</input>
</macro>
<macro name="valet_lot_empty">
<input pattern="^(.*)$">
<match>
<action function="play-file" data="tone_stream://%(275,10,600);%(275,100,300)"/>
</match>
</input>
</macro>
</include><!--This line will be ignored it's here to validate the xml and is optional -->

View File

@ -1,8 +1,12 @@
<include>
<language name="en" sound-path="$${sounds_dir}/en/us/callie" tts-engine="cepstral" tts-voice="callie">
<X-PRE-PROCESS cmd="include" data="demo/*.xml"/> <!-- Note: this now grabs whole subdir, previously grabbed only demo.xml -->
<!--voicemail_en_tts is purely implemented with tts, we have the files based one that is the default. -->
<X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/> <!-- vm/tts.xml if you want to use tts and have cepstral -->
<X-PRE-PROCESS cmd="include" data="dir/sounds.xml"/> <!-- dir/tts.xml if you want to use tts and have cepstral -->
<language name="en" say-module="en" sound-prefix="$${sounds_dir}/en/us/callie" tts-engine="cepstral" tts-voice="callie">
<phrases>
<macros>
<X-PRE-PROCESS cmd="include" data="demo/*.xml"/> <!-- Note: this now grabs whole subdir, previously grabbed only demo.xml -->
<!--voicemail_en_tts is purely implemented with tts, we have the files based one that is the default. -->
<X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/> <!-- vm/tts.xml if you want to use tts and have cepstral -->
<X-PRE-PROCESS cmd="include" data="dir/sounds.xml"/> <!-- dir/tts.xml if you want to use tts and have cepstral -->
</macros>
</phrases>
</language>
</include>

View File

@ -0,0 +1,11 @@
<include> <!--This line will be ignored it's here to validate the xml and is optional -->
<macro name="queue_position">
<input pattern="^(\d+)$">
<match>
<action function="play-file" data="ivr/ivr-you_are_number.wav"/>
<action function="say" data="$1" method="pronounced" type="items"/>
<action function="play-file" data="ivr/ivr-in_line.wav"/>
</match>
</input>
</macro>
</include>

View File

@ -1,8 +1,12 @@
<include>
<language name="fr" sound-path="/snds" tts-engine="cepstral" tts-voice="david">
<X-PRE-PROCESS cmd="include" data="demo/demo.xml"/>
<!--voicemail_fr_tts is purely implemented with tts, we need a files based implementation too -->
<X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/>
<X-PRE-PROCESS cmd="include" data="dir/sounds.xml"/> <!-- dir/tts.xml if you want to use tts and have cepstral -->
<language name="fr" say-module="fr" sound-prefix="$${sounds_dir}/fr/ca/june" tts-engine="cepstral" tts-voice="david">
<phrases>
<macros>
<X-PRE-PROCESS cmd="include" data="demo/demo.xml"/>
<!--voicemail_fr_tts is purely implemented with tts, we need a files based implementation too -->
<X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/>
<X-PRE-PROCESS cmd="include" data="dir/sounds.xml"/> <!-- dir/tts.xml if you want to use tts and have cepstral -->
</macros>
</phrases>
</language>
</include>

View File

@ -1,7 +1,11 @@
<include>
<language name="he" sound-path="$${sounds_dir}/he/daniel" tts-engine="cepstral" tts-voice="daniel">
<X-PRE-PROCESS cmd="include" data="demo/*.xml"/> <!-- Note: this now grabs whole subdir, previously grabbed only demo.xml -->
<X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/>
<X-PRE-PROCESS cmd="include" data="dir/sounds.xml"/>
<language name="he" sound-prefix="$${sounds_dir}/he/daniel" tts-engine="cepstral" tts-voice="daniel">
<phrases>
<macros>
<X-PRE-PROCESS cmd="include" data="demo/*.xml"/> <!-- Note: this now grabs whole subdir, previously grabbed only demo.xml -->
<X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/>
<X-PRE-PROCESS cmd="include" data="dir/sounds.xml"/>
</macros>
</phrases>
</language>
</include>

View File

@ -1,9 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!--тестовые файлы Вы звуковые файлы можно взять тут svn co http://svn.freeswitch.ru/bbv/mod_say_ru/ru/ -->
<include>
<language name="ru" sound-path="$${sounds_dir}/ru/RU/elena" tts-engine="cepstral" tts-voice="elena">
<X-PRE-PROCESS cmd="include" data="demo/*.xml"/> <!-- Note: this now grabs whole subdir, previously grabbed only demo.xml -->
<!--voicemail_en_tts is purely implemented with tts, we have the files based one that is the default. -->
<X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/> <!-- vm/tts.xml if you want to use tts and have cepstral -->
<language name="ru" sound-prefix="$${sounds_dir}/ru/RU/elena" tts-engine="cepstral" tts-voice="elena">
<phrases>
<macros>
<X-PRE-PROCESS cmd="include" data="demo/*.xml"/> <!-- Note: this now grabs whole subdir, previously grabbed only demo.xml -->
<!--voicemail_en_tts is purely implemented with tts, we have the files based one that is the default. -->
<X-PRE-PROCESS cmd="include" data="vm/sounds.xml"/> <!-- vm/tts.xml if you want to use tts and have cepstral -->
</macros>
</phrases>
</language>
</include>

View File

@ -347,6 +347,11 @@ AC_ARG_ENABLE(cpp,
AM_CONDITIONAL([ENABLE_CPP],[test "${enable_cpp}" = "yes"])
AC_ARG_ENABLE(srtp,
[AC_HELP_STRING([--disable-srtp],[build without srtp support])],[enable_srtp="$enableval"],[enable_srtp="yes"])
AM_CONDITIONAL([ENABLE_SRTP],[test "${enable_srtp}" = "yes"])
AC_ARG_ENABLE(zrtp,
[AS_HELP_STRING([--enable-zrtp], [Compile with zrtp Support])],,[enable_zrtp="no"])
if test "x$enable_zrtp" = "xyes" ; then
@ -583,6 +588,21 @@ if test x"$ac_cv_gcc_declaration_after_statement" = xyes; then
fi
CFLAGS="$saved_CFLAGS"
# Tested and fixed lot of modules, but some are untested. Will be added back when the core team decide it ready
# Untested modules : mod_osp mod_soundtouch mod_sangoma_codec mod_dingaling mod_opal mod_skypopen mod_h323 mod_khomp
# mod_unimrcp mod_cepstral mod_erlang_event mod_snmp mod_perl mod_java mod_managed
#
#saved_CFLAGS="$CFLAGS"
#AC_CACHE_CHECK([whether compiler supports -Wunused-but-set-variable], [ac_cv_gcc_unused_but_set_variable], [
#CFLAGS="$CFLAGS -Wunused-but-set-variable"
#AC_TRY_COMPILE([],[return 0;],[ac_cv_gcc_unused_but_set_variable=yes],[ac_cv_gcc_unused_but_set_variable=no])
#])
#AC_MSG_RESULT($ac_cv_gcc_unused_but_set_variable)
#if test x"$ac_cv_gcc_unused_but_set_variable" = xyes; then
# APR_ADDTO(SWITCH_ANSI_CFLAGS, -Wunused-but-set-variable)
#fi
#CFLAGS="$saved_CFLAGS"
AC_C_BIGENDIAN(AC_DEFINE([SWITCH_BYTE_ORDER],__BIG_ENDIAN,[Big Endian]),AC_DEFINE([SWITCH_BYTE_ORDER],__LITTLE_ENDIAN,[Little Endian]))
# Checks for integer size
@ -788,6 +808,7 @@ SAC_OPENSSL
if test x$HAVE_OPENSSL = x1; then
openssl_CFLAGS="$openssl_CFLAGS -DHAVE_OPENSSL";
APR_ADDTO(SWITCH_AM_CFLAGS, -DHAVE_OPENSSL)
fi
AX_CHECK_JAVA

View File

@ -1,3 +1,4 @@
/opt/freeswitch/conf/lang/de/demo/demo.xml
/opt/freeswitch/conf/lang/de/de.xml
/opt/freeswitch/conf/lang/de/vm/tts.xml
/opt/freeswitch/conf/lang/de/vm/sounds.xml

View File

@ -1,4 +1,5 @@
opt/freeswitch/conf/lang/de/demo/demo.xml
opt/freeswitch/conf/lang/de/de.xml
opt/freeswitch/conf/lang/de/vm/tts.xml
/opt/freeswitch/conf/lang/de/vm/sounds.xml
opt/freeswitch/mod/mod_say_de.so*

View File

@ -22,6 +22,7 @@
/opt/freeswitch/conf/autoload_configs/logfile.conf.xml
/opt/freeswitch/conf/autoload_configs/memcache.conf.xml
/opt/freeswitch/conf/autoload_configs/modules.conf.xml
/opt/freeswitch/conf/autoload_configs/mongo.conf.xml
/opt/freeswitch/conf/autoload_configs/nibblebill.conf.xml
/opt/freeswitch/conf/autoload_configs/opal.conf.xml
/opt/freeswitch/conf/autoload_configs/pocketsphinx.conf.xml

View File

@ -29,6 +29,7 @@ opt/freeswitch/conf/autoload_configs/local_stream.conf.xml
opt/freeswitch/conf/autoload_configs/logfile.conf.xml
opt/freeswitch/conf/autoload_configs/memcache.conf.xml
opt/freeswitch/conf/autoload_configs/modules.conf.xml
opt/freeswitch/conf/autoload_configs/mongo.conf.xml
opt/freeswitch/conf/autoload_configs/nibblebill.conf.xml
opt/freeswitch/conf/autoload_configs/opal.conf.xml
opt/freeswitch/conf/autoload_configs/pocketsphinx.conf.xml

View File

@ -24,6 +24,7 @@ freeswitch (1.0.7)
build: VS2010 libportaudio project improvements for DirectX builds and switch to build DirectX by default (r:e9e33f51/FS-3033)
build: add make targets for mod_com_g729 mod_com_g729-activate mod_com_g729-install mod_com_g729-clean mod_com_g729-uninstall (r:17d52112)
build: add support for bz2 to getlibs (r:b61fc396)
build: Bump callie sounds to 1.0.15 (r:c8eaef60)
codec2: working prototype, still for testing only (r:04ca0751)
config: move limit.conf to db.conf
config: Update VM phrase macros to voice option then action on main, config menus
@ -41,6 +42,7 @@ freeswitch (1.0.7)
config: docs for acl (r:57b410eb)
config: add default to conf to demonstrate min-idle-cpu (r:b8b7266a)
config: change min/max enforcements to >= instead of > (r:0d5fcf65)
config: Add README_IMPORTANT.txt to default configuration (r:6cd5ce72)
core: Add RTCP support (FSRTP-14)
core: handle some errors on missing db handle conditions
core: add ... and shutdown as a fail-safe when no modules are loaded
@ -214,6 +216,35 @@ freeswitch (1.0.7)
core: add limits to simo open sql handles (r:61cdf0da)
core: Fix db locks affecting mod_callcenter (r:8da371c7/FS-3127)
core: improve flow of dtmf through a bridge when timer is disabled (r:59da356d)
core: Fix Freeswitch crash on Debian ARM (r:a80fae92/FS-3126)
core: switch_xml: reloadxml will(should) never lock again. It will load the XML structure into a new XML structure, and just replace the currently available ROOT XML. It then the job of the last user of the switch_xml structure to free it. (r:471bd6df)
core: switch_xml: Remove commented out mmap. With the changes in the past 2 year, mmap can't really be put back in it current state. (r:34bd0e5e)
core: Fix jitterbuffer with SRTP enabled (r:069f5f7d/FS-3075)
core: this will remove the reported symptom but does not change the fact that 1khz resolution is ideal for proper performance (r:5f18ec94/FS-3168)
core: this was specific to the user channel which is not a real channel in every sense of the word as it has no running thread or any usable state changes so this new line of code in 233d3164be4412aaaf8f9f42d8042e48279a018a to wait for the state machine to stabilize before returning from originate caused an issue with user/ channels (r:88a6ac2f/FS-3170)
core: this also fixes the incorrect usage of L16 on payload 10 which may or may not break interop with other sip devices if we do it right. also added rtp_disable_byteswap variable that can be set to false to disable byteswap when a device is encountered that is incompat (including all previous version of FS up till now) (r:e657e32f/FS-3172)
core: dont calibrate clock when timerfd enabled (r:26f5ebd4)
core: fix DTMF in SRTP/ZRTP (r:fd608901/FS-3165)
core: add switch_atomic_* type and functions switch_apr.c and switch_apr.h (r:3b56c119/FS-3173)
core: improve some defaults to tune performance if you use -heavy_timer, try not using it (r:5d783134)
core: Fix api_hangup_hook with no args (r:484a397d/FS-3194)
core: allow 100 microsecond tolerance on timer loop (r:6388e03d)
core: Fix X-PREPROCESS exec to wait pid (r:dae2cb4a)
core: Ability to use mod_say with native files; native is a special case so use the extension native e.g. en.native (r:3a2e1d03/FS-3176)
core: Fix: Bridging a call to multiple legs and using leg_delay_start, legs that lost the race before the leg_delay_start time is up still get originated for a brief moment (r:c5daf80e/FS-3218)
core: Have UPNP/PMP active without opening port mappings in the router/firewall (r:008f9889/FS-3208)
core: add execute_on function so you can have execute_on_answer_1 execute_on_answer_2 execute_on_answer_3 etc (r:27c6d111)
core: do this slightly safer so we don't have the mutex locked when we exec the app (r:ef175741)
core: Fix argument parsing for tone_detect app (r:38c3a67a/FS-3229)
core: add L16 def for 32ms and allow timer matrix to drop to 1ms to support nelly (r:82e3d49f)
core: fix segfault in zrtp srtcp (r:2330b340)
core: add switch_clean_name_string util function to strip out caller id name chars that can cause issues (r:244048f8)
core: switch_core_sqldb - clear pointer on release (r:aaef33cc)
core: all [] {} and <> can be stacked and override the delim per set <><^^:>{}{^^:}{^^;}[][^^:] (r:4c4bf59e/FS-3246)
core: fix default tipping point it was too low (r:e4eade33)
core: enable optimal defaults on linux kernels that can support newer features. (r:0b51aca3)
core: Lower NAT port mapping disabled log msg from WARNING to INFO (r:973a850d)
core: Change the structure of the phrases/language system. Previously it was fxml->phrases->macros->language->macro. Changed it so fxml->languages->language->phrases->macros->macro You can have sub macros <macros name="voicemail"><macro ...> and allow you to call it login@voicemail. Change the sound-path to sound-prefix to make it constistant with the rest of freeswitch. Also allow to set a sound-prefix to a macros, so you can override it for a specific file set. You can set say-modules="en" or whatever in the <language section to define that say module to use. (r:4137b360)
embedded languages: Provide core level support for conditional Set Global Variable (r:c017c24b/FSCORE-612)
embedded languages: add insertFile front end to switch_ivr_insert_file and reswig (r:c4e350ab)
fs_cli: block control-z from fs cli and print a warning how to exit properly (r:dc436b82)
@ -250,12 +281,18 @@ freeswitch (1.0.7)
libesl: add optional job-uuid param to bgapi in oop mod (r:e96acac3)
libesl: fix linger support in esl client lib (r:0444626b)
libesl: fix segfault (r:30813ca5/FS-3130)
libesl: Don't destroy last_event pointer until it's being set to a new pointer - fixes rare segfault (r:e8474d60/ESL-57)
libesl: Add 'make perlmod-install' to ESL (please test) (r:06c42179)
libesl: build python esl bindings and ship them in freeswitch-python-package (r:44bfcf1d/FS-3128)
libesl: use poll instead of select in ESL client lib because select is not your friend.... (r:ae595cd5)
libesl: Add digit_timeout to ESL::IVR's playAndGetDigits method (r:f564d383)
libfreetdm: implemented freetdm config nodes and ss7 initial configuration
libfreetdm: fix codec for CAS signaling (r:b76e7f18)
libfreetdm: freetdm: ss7- added support for incoming group blocks, started adding support for ansi (r:c219a73c)
libg7221: A bunch of tweaks to the G.722.1 codec (r:5d548570)
libgnutls: link to libgcrypt as well, please report any platforms this breaks, but it should be portable (r:c569fb0f/FS-1248)
libjs: non-portable comment syntax in .s files
libldns: select on FD > 1024 get this patch to ldns ppl (r:710fc7a7/FS-3110)
libopenzap: Add CLI tracing
libs: Merged OpenZAP and FreeTDM into the FreeSWITCH tree.
libs: Add support for TLS on Windows using openssl (r:1abe3b93/MODSOFIA-92)
@ -265,6 +302,7 @@ freeswitch (1.0.7)
libsofiasip: VS2010 sofia posix problem (r:46dd24c2/SFSIP-220)
libsofiasip: set minimum initital sip t1 timer to 1000ms to work around race condition on retry timer firing before all the things that are supposed to be handled by the timer are set. The base resolution on this timer is 500ms, so doubling up makes sure we always hit the initial retry timer on the next run, where everything should be set. The side effect was, 1/2 the time on a request that did not get immediate response, the timer would be fired and cleared, but the action (sending retry) was never done, and a new timer was not set, causing the request to just sit zombied and never retry. A better solution would be to find and correct the race condition so the timer is never set to early and we never hit this condition. (r:20c2740c)
libsofiasip: fix bad assert (r:56404641/FS-3133)
libsofiasip: lower stack and boost priority of sofia schedule thread (r:257bc9ff)
libspandsp: Fixed a typo in spandsp's msvc/inttypes.h Updated sig_tone processing in spandsp to the latest, to allow moy to proceed with his signaling work.
libspandsp: removed a saturate16 from spandsp that was causing problems fixed a typo in the MSVC inttypes.h file for spandsp
libspandsp: Changes to the signaling tone detector to detect concurrent 2400Hz + 2600Hz tones. This passes voice immunity and other key tests, but it bounces a bit when transitions like 2400 -> 2400+2600 -> 2600 occur. Transitions between tone off and tone on are clean. (r:bc13e944)
@ -272,6 +310,7 @@ freeswitch (1.0.7)
libspandsp: Fix for T.30 processing of operator interrupts, to improve compatibility with some machines, which seem to send them when no operator is around. (r:84ee0ae6)
libspandsp: spandsp t38 fax receiving error in win XP - regression from f029f7ef (r:761cec8f/FS-2766)
libspandsp: Added missing error codes when an ECM FAX is abandoned with the T30_ERR message (r:ec57dc7a)
libspandsp: Fixed a vulnerability in T.4 and T.6 processing which is similar to <a href="http://bugzilla.maptools.org/show_bug.cgi?id=2297">http://bugzilla.maptools.org/show_bug.cgi?id=2297</a> in libtiff. A really screwed up 2D T.4 image, or a maliciously constructed T.4 2D or T.6 image should potential run off the end of an image decoder buffer. (r:c6f67322)
libstfu: add param to jb to try to recapture latency (disabled by default) (r:d59d41d7)
mod_avmd: Initial check in - Advanced Voicemail Detect (r:10c6a30a) (by Eric Des Courtis)
mod_avmd: Add to windows build (r:df4bd935)
@ -299,11 +338,24 @@ freeswitch (1.0.7)
mod_callcenter: IMPORTANT UPDATE, DTMF during moh created an loop to reactivate MOH but got canceled right away because of pending DTMF in the queue never been cleaned. Could cause masive disk write of debug, and can cause problem to the rest of FS stability. This patch also include basic fundation for DTMF capture support for member waiting. (r:cd1982ce)
mod_callcenter: force loopback_bowout=false on originate. This will need to be reworked, but should fix basic issues call to an agent using loopback (r:2e399b0b)
mod_callcenter: segfault using busy-delay-time parameter (r:c6f044d5/FS-3067)
mod_callcenter: Fix a bug when an caller leave the queue from a BREAK Call (Transfer...), it doesn't think an agent answered. (r:51a531aa)
mod_callcenter: Add new CLI cmd and change some to be more standard. Patch from Francois Delawarde, thanks. (r:30dd1774)
mod_callcenter: >WARNING, some event value got removed< Adding new event time value that can then be used to calculate the Wait;Talk;Total duration of a member were on call. CC-Wait-Time CC-Talk-Time and CC-Total-Time are no longer returned. Visit the code or check the wiki for the updated variable. (r:5f233785)
mod_callcenter: Add better support when agent doesn't answer, including creating a new variable for the delay that is different than reject or busy. Thanks to Francois Delawarde (r:26303c5c)
mod_callcenter: Add better handle of failed agent, member channel getting a break, and debuging info upon leaving. Thanks to Fran?ois Delawarde (with some changes) (r:25cee255)
mod_callcenter: New Agent order Possibility: Agent order by Level and Position by agents.last_offered_call. Change the default and sequentially-by-agent-order strategy to include the longest-idle-agent. This should offer a default consistant way to go through all the agent within the same tier/position. (Before, it was left to the DB to return the order of the result) (r:dcafff20/FS-3158)
mod_callcenter: Generate per member uuid different from the member session uuid. Might fix transfer between queue. More changes are coming (r:b63a72f8)
mod_callcenter: Remove the concept of Caller for Members. Event Socket event have been changed (CC-Caller.* to CC-Member.*) Also CC-Caller-UUID is renamed to CC-Member-Session-UUID. The reason for this is you could actually put people to be call in the queue. So they are not caller per say. But they are a member of a queue. (r:40a134bd)
mod_callcenter: Reload a queue wont delete all the currently waiting members. Only a reload of the module will. (r:c5ae5de0/FS-3250)
mod_callcenter: Add a very prototype (and maybe not functional) strategy called : sequentially-by-next-agent-order. It will try to find the last agent we tried to reach, and start calling more agent after that one based on position. It will use the level for the next agent, but once that level is done, it start back at the lowest level (r:bef6f0f4)
mod_callcenter: New strategies: round-robin, random, and 'top-down' (r:2b4b23aa,r:bee247ca)
mod_cdr_sqlite: initial commit (r:f625fe3b)
mod_cdr_sqlite: config file for mod_cdr_sqlite (r:25bc8fe3)
mod_cdr_sqlite: Drop transaction BEGIN/END around INSERT. We're only executing one command, and autocommit will automatically rollback if the INSERT fails. Sync state_handlers with mod_cdr_csv. Minor libpq fixups. (r:0f95b870)
mod_celt: Bump celt to 0.10.0 (r:231fbe5e)
mod_celt: update code in mod_celt to match API of 0.10.0 (r:6e4c30ea)
mod_celt: Add dependency to fix parallel builds (r:6e37a8b2)
mod_cepstral: add ability to set encoding of text (r:28738b06/FS-3001)
mod_cidlookup: null xml is bad (r:095815f8)
mod_cid_lookup: honor skipcitystate when using whitepages (r:a66654de/FSMOD-53)
mod_commands: make break uuid_break and add cascade flag
@ -326,6 +378,7 @@ freeswitch (1.0.7)
mod_commands: add uuid_buglist to fetch the current media-bugs attached to a given session uuid (r:f6eab64c)
mod_commands: add recovery_refresh app and api and use it in mod_conference to send a message to the channel telling it to sync its recovery snapshot (r:650393fb)
mod_commands: add moh by default to uuid_broadcast when only broadcasting to A leg use aleg arg to disable this (r:d164a797)
mod_commands: add API uuid_limit - thanks to Francois Delawarde (r:98a95016/FS-1792)
mod_conference: Fix reporting of volume up/down (MODAPP-419)
mod_conference: add last talking time per member to conference xml list
mod_conference: add terminate-on-silence conference param
@ -351,6 +404,13 @@ freeswitch (1.0.7)
mod_conference: clear talk flag when you mute (r:b7419add)
mod_conference: fix pthread mutex lock error and add some tab completion and help messages from cli (r:547d5393/FS-3095)
mod_conference: Use the channel's sound_prefix if it's not set in the conference's config (r:0911ed74/FS-3124)
mod_conference: Add conf_uuid chan var for djbinter (Thanks Math) (r:3c9ee25a)
mod_conference: removes the existing conference transfer function and replaces it using the core transfer it also introduces a new tracking method where the same conference id is reserved for a particular member for the lifetime of the call allowing a user to transfer in and out of conferences and ivr and bridges etc and retain the same member id for the duration of that call (r:246b2195/FS-3095)
mod_conference: prevent race condition on conference join/exit (r:1552ecf5)
mod_conference: I finally tracked this down to the actual recordings generated by mod_conference. This patch delays the recording slightly to allow time for the buffer to fill up, we were riding it so closely that sometimes we would come up short and inject silence into the file to preserve time passing (r:3253bcb3/FS-3147)
mod_conference: wait for channels to come up in paging mode (r:b8063c3d)
mod_conference: Conference APIs for enabling/disabling enter/exit sounds for active conferences (r:31cebd4f/FS-3219)
mod_conference: Fix pool swelling, replaced a pool strdup that could recur with a strdup/free to avoid it (r:bcd6c3a1/FS-3137)
mod_curl: use method=post when post requested (r:c6a4ddd0/FSMOD-69)
mod_db: fix stack corruption (MODAPP-407)
mod_dialplan_xml: Add in the INFO log the caller id number when processing a request (Currenly only show the caller name) (r:e1df5e13)
@ -360,6 +420,7 @@ freeswitch (1.0.7)
mod_dingaling: Fix NULL pointer (r:e3eff816/FS-1103)
mod_dingaling: fix leak in chat_send (r:eb109a85)
mod_dingaling: use the login as message source when not in component mode. (chat_send) (r:58c28aab)
mod_dingaling: fix mod_dingaling/iksemel/gnutls link error when using newer autotools (r:294b0779/FS-3182)
mod_directory: Add variable directory_search_order to allow to search by first name by default is set to "first_name" (r:163ca31f)
mod_distributor: Add mod_distributor to VS2010 - not built by default (r:bac79ba1)
mod_dptools: add eavesdrop_enable_dtmf chan var (r:596c0012)
@ -371,7 +432,14 @@ freeswitch (1.0.7)
mod_dptools: Log error when there's no IVR menus configured when you call 'ivr' DP app (r:30034891)
mod_dptools: reset signal_bond variable back to its original value on failed dial in att_xfer (r:330d7418)
mod_dptools: Fix storage class for 'cause' in user_outgoing_channel() so that each call has its very own hangup cause (r:cb6f1ed6)
mod_dptools: transfer_on_fail note I changed the variable name to auto_cause (r:45edec4c/FS-3193)
mod_dptools: merge file_string into dptools (r:eefdb764)
mod_dptools: change mod_dptools to use the better method of fetching user xml that does not hang onto the xml root (r:e52e44e3)
mod_dptools: the intent for having the module and lang separate is for things where the same module can use different sets of sounds like en module and en-male or en-female lang (sound dirs) there was indeed a disconnect in the dialplan version of this app. Originally say was only available in phrase macros so I change the syntax of the say app so you can specify both the module and the lang absolte from the dp with something like he:he as the module name. (r:44304f49)
mod_dptools: Set the default lang if not supplied (mod_say_en) (r:5382972a/FS-3215)
mod_easyroute: Fix possible segfaults and memory leak during unload, and add new setting odbc-retries (r:7fbc47f8/FS-2973)
mod_enum: switch mod_enum to use new portable in-tree version (r:2bbc37e3)
mod_enum: fix race condition between ldns configure creating ldns/util.h and mod_enum (r:87884c5c)
mod_erlang_event: Make XML fetch reply ACKs distinguishable, update freeswitch.erl (r:9d44ed04)
mod_erlang_event: Add 3 new commands; session_event, session_noevents, session_nixevent (r:698fa045)
mod_erlang_event: generate long node names the same as erlang does (r:9ad509c2)
@ -384,6 +452,8 @@ freeswitch (1.0.7)
mod_event_socket: Fix small mem leaks (r:e4f90584/MODEVENT-68)
mod_event_socket: Add "-ERR" to api cmd response when failure occurs (r:58759052/FS-2827)
mod_event_socket: clear unique headers on event_socket filters (r:436413e0)
mod_event_socket: Unlock mutex to prevent mortuus obfirmo (r:64bc1938/FS-3156/FS-3157)
mod_event_zmq: Intitial mod_event_zmq code (r:4d554067)
mod_fifo: allow multiple dtmf to exit fifo, set fifo_caller_exit_key to specify which (MODAPP-420)
mod_fifo: cancel outbound call if customer hangs up (r:cadb4d94)
mod_fifo: add taking_calls param to fifo member add and config file (r:821488bf)
@ -396,6 +466,7 @@ freeswitch (1.0.7)
mod_fifo: Fix crash when using fifo_destroy_after_use (r:ee562c82/FS-2879)
mod_fifo: don't seg in edge case error conditions (r:9ee13b72)
mod_fifo: set tracking data before enabling hooks (r:34267869)
mod_file_string: Fix segfault when using file string in conference (r:9c40e8e9/FS-3122)
mod_freetdm: Fix for TON and NPI not passed through to channel variables on incoming calls
mod_freetdm: add pvt data to freetdm channels fix fxs features (r:9d456900)
mod_freetdm: export and import boost custom data (r:edb2d582)
@ -447,10 +518,11 @@ freeswitch (1.0.7)
mod_hash: use 5 seconds connection timeouts for remote connections (r:7431fbe9)
mod_hash: use esl_recv_timed with a 5000ms timeout when doing api commands (r:27d8378f)
mod_hash: limit_remote_thread sending invalid handle to esl_connect_timeout causing core (r:6cdd3e2a/MODAPP-446)
mod_hash: avoid scheduler caling a function on null hash during shutdown (r:8458adeb)
mod_hash: avoid scheduler calling a function on null hash during shutdown (r:8458adeb)
mod_hash: add realm filter to hash_dump db command so that you can quickly dump all entries that belong only to a specific realm without getting the whole db (r:81347126)
mod_h323: initial t.38 support. remake logical channel opening. add missing param name in example config. (r:8c58074c)
mod_h323: some t.38 and lockinng improvements. replace ptrace with switch_log_printf. (r:5efe5c88)
mod_h323: add missing conf prameter (r:0b353d7a)
mod_h323: some t.38 and locking improvements. replace ptrace with switch_log_printf. (r:5efe5c88)
mod_h323: add missing conf praameter (r:0b353d7a)
mod_h323: Add mod_h323 to windows (r:015bcaf6/MODENDP-301)
mod_h323: move PTrace level set to FSH323EndPoint::Initialise. partially apply patch from from Peter Olsson, Remove UnLock() when TryLock() failed and DEBUG_RTP_PACKETS directiv e. (r:7b5803f7)
mod_h323: set network_addr of caller profile to signaling ip address. (requested by Steven Ayre) (r:072bf5ad)
@ -459,6 +531,8 @@ freeswitch (1.0.7)
mod_json_cdr: Fix segfault in mod_json_cdr.c (r:f347698a/MODEVENT-66)
mod_khomp: Added mod_khomp Endpoint. (r:5fea197b)
mod_khomp: Removed alternative contexts / extensions - New struct for matchs - On calls originated from an FXS branch, the Endpoint searches for a valid extension (digits sent) after the DTMF '#' or after the timeout (option fxs-digit-timeout). That search is done in the context defined in section <fxs-options>, or if no context configured, the search is done in context defined in context-fxs. - Added "dialplan" configuration: Name of the dialplan module in use (default XML) - Group context enabled. If set, the search for a valid extension is done only in that context. - Updated documentation (r:1ef3fc9a)
mod_ladspa: Add mod_ladspa (Audio plugin framework for linux) (r:2d3d8f8d)
mod_ladspa: add string params to ladspa so you can connect files to audio ports (string params don't count towards number params) (r:b7891511)
mod_lcr: Expand variables (MODAPP-418)
mod_lcr: add enable_sip_redir parameter (r:70bf7a0a/MODAPP-427)
mod_lcr: don't validate profiles with ${} vars since they are dynamic and we can't guess what the proper value should be (r:af33afaa)
@ -466,6 +540,8 @@ freeswitch (1.0.7)
mod_lcr: assign default profile even if testing is skipped (r:6420099c)
mod_lcr: fix compiler warning on newer gcc (r:bfa414cb)
mod_lcr: don't count twice (r:eaeabc7b/FS-1810)
mod_lcr: properly destroy lcr object when done (r:084819a3/FS-3199)
mod_lcr: don't add routes that have no rate of the desired type (r:82e3ccf8)
mod_loopback: add loopback_bowout_on_execute var to make 1 legged loopback calls bow out of the picture
mod_loopback: only execute app once in app mode (r:64f58f2d)
mod_loopback: fix bug in mod_loopback where bowout=false (r:e9ab5368)
@ -479,6 +555,7 @@ freeswitch (1.0.7)
mod_lua: Make dbh:connected accessible from Lua - thanks Grmt (r:09e6fd3f)
mod_lua: Added optional core: prefix to first arg passed to freeswitch.Dbh for giving direct access to sqlite db (r:a0181479)
mod_lua: expose switch_simple_email as "email" method (r:89c5f3bf/FS-3023)
mod_lua: Fix setInputCallback crash (r:c49c1fde/FS-3161)
mod_managed: Added wrapper for switch_event_bind for .net (r:a5f07a80/MODLANG-165)
mod_managed: add additional support (r:5be58aac)
mod_managed: add mono 2.8 patch file see FS-2774 (r:6a948bd9/FS-2774)
@ -495,10 +572,13 @@ freeswitch (1.0.7)
mod_openzap: disable dtmf app and cmd line option (r:fb4b7f7a)
mod_openzap: add enable dtmf app (r:3c95106e)
mod_opus: add mod_opus (r:8f565277)
mod_opus: Use libtool archives for linking, add dependencies to fix parallel builds (r:74bbd4be)
mod_osp: initial check (Open Settlement Protocol)
mod_osp:Changed OSP TCP port from 1080 to 5045. (r:03abefdf)
mod_portaudio: Fix inbound state (CS_ROUTING not CS_INIT) (MODENDP-302)
mod_portaudio: mod_portaudio improvements and bug fixes (r:33b74ca8/FS-3006)
mod_portaudio: Add pa devlist to portaudio webapi (r:e8f10ea3)
mod_protovm: This is a very early new prototype voicemail ivr system. You need to copy the sounds.xml and make it loadale in the language folder and protovm.conf.xml inside the autoload_configs folder. Configs file will most definitly change. Once stabilized, we make it install those file by default. (r:fb549777)
mod_sangoma_codec: Add sample config file
mod_sangoma_codec: added load/noload options for the supported codecs
mod_sangoma_codec: rename load/noload to register/noregister
@ -513,9 +593,14 @@ freeswitch (1.0.7)
mod_sangoma_codec: add G722 (r:ca8c2336)
mod_sangoma_codec: add siren7 32kbps (r:fcaf2677)
mod_sangoma_codec: add SIREN7 24kbps (r:3acc5fdb)
mod_say: Fix crash for Say Number Pronounced with numbers of more than 9 digits (r:06bccf28/FS-3202)
mod_say_en: introduce new say_string method of doing say and use it in mod_say_en as an example. try: eval ${say_string en.gsm en current_date_time pronounced ${strepoch()}} from the cli with this patch. We can do more to centralize the say things and go back and apply it to other langs, using this method you can set the desired file ext as well which I think is a bounty.... (r:d5ef86d7)
mod_say_en: If you only tell SAY CURRENCY to say 100 it should only say 100 dollars without the "0 cents" (r:426a4e76/FS-2922)
mod_say_es: fix grammar when saying dates and time (r:6bed19b2/MODAPP-429)
mod_say_he: Add Hebrew say module (r:ebd9c83e/FS-3211)
mod_say_ja: initial commit, still needs sound files (r:b2423158/FS-2755)
mod_say_ru: Fix saying time with +1 hour of current time (r:68d74c31/MODAPP-444)
mod_say_ru: now support say_string like mod_say_en. Now support channel variables gender,cases can be set in english and russian for example: <action application="set" data="cases=nominativus/> <action application="set" data="gender=male_h"/> <action application="say" data="ru NUMBER PRONOUNCED 1001"/> (r:8b5ecd2f)
mod_say_zh: Number reading should now be OK for the whole range of integers for Cantonese and Mandarin
mod_shout: bump mod_shout to use mpg123-1.13.2 to hopefully address unwanted calls to exit() and inherit other upstream fixes (r:079f3f73)
mod_silk: Fix mod_silk compliance and performance issues (r:2ddbc457/MODCODEC-20)
@ -543,6 +628,8 @@ freeswitch (1.0.7)
mod_skypopen: making XEvents to works when EARLYMEDIA, and correctly manage threads death
mod_skypopen: now answer a call only when directed to do it (before was trying to answer any incoming call). Lot of changes to a messy part, so maybe some problem will come out... (r:45c6c4d3)
mod_skypopen: ignore early media sent by channels to be bridged before our channel is answered (r:ef14b78a)
mod_skypopen: OSS driver, refinement (r:b0a23f8e)
mod_skypopen: deleted osscuse subdir (r:4842a620)
mod_snapshot: fix bad codepaths in mod_snapshot (r:844ac220)
mod_sndfile: Add support for .alaw and .ulaw to mod_sndfile (r:facf09b8/MODFORM-41)
mod_sndfile: return break in mod_sndfile when seek returns failure (r:564dc7e4)
@ -689,6 +776,20 @@ freeswitch (1.0.7)
mod_sofia: Send BYE to endpoints that lose race even if they answered (r:8c3651fa/FS-640)
mod_sofia: do not renegotiate codecs on hold re-invites (r:bfd0ba97)
mod_sofia: add rtp-notimer-during-bridge (alternative to rtp-autoflush-during-bridge (r:2a35dfb5)
mod_sofia: send another presence event on calls that were cancelled from LOSE_RACE to fix winnable race in Broadsoft SCA (r:59f6654e)
mod_sofia: pass header in X-FS headers on attended transfer CID update to indicate specific situation to flip callee/caller id when targeting a 1 legged call (r:24a97292)
mod_sofia: change text of error message to be more descriptive (r:4c435ec5)
mod_sofia: Correct a problem where restarting profile would cause some profile hash entry to remain. (r:81bfe435)
mod_sofia: New Sofia API to look up the username of a given user (r:7556ec57/FS-3187)
mod_sofia: sip_authentication was not cleared after nonce expired -caused sofia_reg_internal.db grow bigger and bigger with time (r:c735e28a/FS-3190)
mod_sofia: pass failure across in T.38 passthru mode (r:31273b42)
mod_sofia: auto-aleg-full and auto-aleg-domain for from_domain field in gateway (r:fda2283b)
mod_sofia: After further review I can concede the point that we should always say partial considering how we do things. With this commit we should at least be sending separate partial updates for each existing dialog to everyone with a subscription. If we need to introduce more data, consolidate them etc. We need to do it in small chunks and keep things sane. (r:7eae7f37/FS-2877)
mod_sofia: Fix:Attended transfer with bypass media fails in various ways (r:4b706dac/FS-3227)
mod_sofia: SO, If the RFC told you to jump off a cliff......? (r:07b9186d/FS-3226)
mod_sofia: Don't assume incoming "gw" contact param is valid (prevent possible DoS) (r:2b6f7070/FS-3244)
mod_sofia: offer both avp and savp when using srtp (r:5857495e)
mod_sofia: fix race in sla (r:a4ed829d)
mod_spandsp: initial checkin of mod_fax/mod_voipcodecs merge into mod_spandsp (r:fa9a59a8)
mod_spandsp: rework of new mod_spandsp to have functions broken up into different c files (r:65400642)
mod_spandsp: improve duplicate digit detection and add 'min_dup_digit_spacing_ms' channel variable for use with the dtmf detector (r:eab4f246/FSMOD-45)
@ -701,15 +802,22 @@ freeswitch (1.0.7)
mod_spandsp: T.38 reINVITE glare condition causes FAX processing to stop. (r:04aa7ef9/FS-1682)
mod_spandsp: improve nat handling when using stun or host as ext-rtp-ip (r:03e74c51/FS-526)
mod_spandsp: Fire event when fax is finished; indicates result of fax attempt (r:314a2a1e/FS-3004)
mod_spandsp: new option to set sip_execute_on_image to 't38_gateway self nocng' this should skip the tone detection adn go right into the gateway mode so you should be able to do only this and have it work based on remote re-invite (r:9227b538/FS-3252)
mod_spandsp: additional fix to this bug and add better fax detect code to mod_spandsp (r:7fe313cf/FS-3252)
mod_spidermonkey: allow vars to be set containing vars from languages (r:5cd072a3)
mod_spidermonkey: fix seg in js hangup (r:7d554c11)
mod_spidermonkey: Fix mod_spidermonkey build on FreeBSD, (Undefined symbol PR_LocalTimeParameters). (r:3edb8419)
mod_spidermonkey: Add session.ringReady() to check for CF_RING_READY (r:7386b9f8)
mod_spy: add support for loopback endpoint (MODAPP-416)
mod_spy: fix crash when session can't be located (r:c4154633/FS-2929)
mod_timer_fd: external timerfd module by Timo Ter?s (r:48b11935)
mod_timer_fd: add timerfd support to the core for now you must enable it in switch.conf.xml with the param enable-softtimer-timerfd=true later if it proves to work well we can make it on by default, please test if you have a new kernel that supports this option kernel >= 2.6.25 and libc >= 2.8 (r:10174ea6)
mod_tts_commandline: fix core dump, temp file problem. flush can be called several times (FSMOD-35)
mod_unimrcp: fix fortify findings for mod_unimrcp (r:336f0b4e/FSMOD-67)
mod_unimrcp: fix truncated TTS (r:e37dd41e/FS-3201)
mod_unimrcp: Destroy schannel only *after* cleanup of its contents is done (r:0f17bcc5)
mod_unimrcp: add locking to mrcp dtmf generator (r:f5704114/FS-3163)
mod_unimrcp: check for NULL recog_hdr (r:478d5186/FS-3247)
mod_valet_parking: add event data to valet parking hold event
mod_valet_parking: add event for Valet Parking action exit
mod_valet_parking: pass hold class on transfer (r:76a065ec)
@ -729,19 +837,24 @@ freeswitch (1.0.7)
mod_voicemail: let vmain-key and operator-key be set empty (r:de49305a)
mod_voicemail: add ability to jump to a specific message (r:0f8fb4b1)
mod_voicemail: vm-skip-instructions param in xml directory to disable instructions how to record a file (r:ed7e1f39)
mod_voicemail: Implement 10 new standard api function call that allow you to control fs voicemail storage system. The goal is to have a standard API set for any additional storage system we wish the voicemail to run off. Current list of added api name are : vm_fsdb_msg_count, vm_fsdb_msg_list, vm_fsdb_msg_get, vm_fsdb_msg_delete, vm_fsdb_msg_undelete, vm_fsdb_msg_purge, vm_fsdb_msg_save, vm_fsdb_pref_greeting_set, vm_fsdb_pref_recname_set, vm_fsdb_pref_password_set. (r:1f4cb488)
mod_voicemail: Adding a new voicemail fsdb api vm_fsdb_auth_login that does basic login authentication for a user (r:bfdfac5e)
mod_xml_cdr: add force_process_cdr var to process b leg cdr on a case by case basis when b leg cdr is disabled (XML-17)
mod_xml_cdr: add leg param to query string (XML-24)
mod_xml_cdr: fix locked sessions (XML-26)
mod_xml_cdr: fix minor memory leaks and config bug (r:19253d83/MODEVENT-62)
mod_xml_cdr: Fix prefix-a-leg not respected for url submission (r:ea9021a2/FS-2998)
mod_xml_cdr: Fix delay to 5 sec from 5000 sec (r:34a38009/FS-2815)
mod_xml_rpc: Fix crash if unauthorized XML RPC is attempted (r:9835395c/FS-184)
scripts: added honeypot.pl and blacklist.pl which add extra SIP security options (r:b6a81ba7)
scripts: do simple verification to make sure we are getting IP addresses from VoIP abuse blacklist (r:b0049160)
scripts: add_user - cmd line utility that lets admin create new users very easily. (r:ec8f2c2b)
sofia-sip: fix null derefernce segfault in soa (r:f356c5e6)
sofia-sip: extend timeout for session expires on short timeouts to be 90% of timeout instead of 1/3 to handle devices that do not refresh in time such as polycom (r:a7f48928/SFSIP-212)
support: update fscore_pb to work with git (r:8f67e93a)
tools: Add fs_encode tool (r:89b17601)
tools: Add randomize-passwords.pl script to main tree (r:5e6123ef)
tools: Change logger.pl host flag to -H from -h (conflicted w/ -h for help); add -H/--host to usage (r:73ca862c)
freeswitch (1.0.6)
@ -1513,7 +1626,7 @@ freeswitch (1.0.4)
build: use different version file for moh version (r:13093)
build: de-couple version numbers and builds of sound files and moh files (FSBUILD-153/r:13096)
build: use sound_version.txt and moh_version.txt to determine sound file version on windows (FSBUILD-152/r:13097)
build: use in tree libtiff for msvc build and fix some header generation checks (r:13150)
build: use in tree libtiff for msvc build and fix some header generation checks (r:13097)
build: clean esl on make current (r:13204,13205)
build: fix warning-as-error that stops MSVC from building solution (FSCORE-367/r:13301)
build: fix MSVC build issue from r13294 (FSBUILD-159/r:13302)

View File

@ -5,6 +5,23 @@
<prompt phrase="Pound" filename="35.wav"/>
<prompt phrase="Star" filename="42.wav"/>
<prompt phrase="Dot" filename="46.wav"/>
<prompt phrase="Hyphen" filename="45.wav"/>
<prompt phrase="Exclamation point" filename="33.wav"/>
<prompt phrase="At" filename="64.wav"/>
<prompt phrase="Dollar sign" filename="36.wav"/>
<prompt phrase="Percent" filename="37.wav"/>
<prompt phrase="Ampersand" filename="38.wav"/>
<prompt phrase="Double quote" filename="34.wav"/>
<prompt phrase="Single quote" filename="39.wav"/>
<prompt phrase="Forward slash" filename="47.wav"/>
<prompt phrase="Underscore" filename="95.wav"/>
<prompt phrase="Backslash" filename="92.wav"/>
<prompt phrase="Tilde" filename="126.wav"/>
<prompt phrase="Equal sign" filename="61.wav"/>
<prompt phrase="Colon" filename="58.wav"/>
<prompt phrase="Semicolon" filename="59.wav"/>
<prompt phrase="Caret" filename="94.wav"/>
<prompt phrase="Pipe" filename="124.wav"/>
<prompt phrase="A" filename="97.wav"/>
<prompt phrase="B" filename="98.wav"/>
<prompt phrase="C" filename="99.wav"/>
@ -222,6 +239,8 @@
<prompt phrase="I need to record your first and last name. This recording is used throughout the system, including in the company directory." filename="vm-tutorial_record_name.wav"/>
<prompt phrase="Your personal identification number, or 'pin', is used to prevent others from accessing your voicemail messages. Would you like to change it now?" filename="vm-tutorial_change_pin.wav"/>
<prompt phrase="The person you are trying to reach is not available and does not have voicemail." filename="vm-not_available_no_voicemail.wav"/>
<prompt phrase="The PIN you entered is below the minimum length." filename="voicemail/vm-pin_below_minimum_length.wav"/>
<prompt phrase="The minimum PIN length is..." filename="voicemail/vm-minimum_pin_length_is.wav"/>
</voicemail>
<directory>
<prompt phrase="Please enter the first few letters of the persons" filename="dir-enter_person.wav"/>
@ -268,6 +287,14 @@
<prompt phrase="...has left the conference." filename="conf-has_left.wav"/>
<prompt phrase="You are already muted." filename="conf-you_are_already_muted.wav"/>
<prompt phrase="You are now bi-directionally muted." filename="conf-you_are_now_bidirectionally_muted.wav"/>
<prompt phrase="Enter the number of listeners at this location, then press pound." filename="conf-number_of_listeners.wav"/>
<prompt phrase="...listeners in this conference." filename="conf-listeners_in_conference.wav"/>
<prompt phrase="...listener in this conference." filename="conf-listener_in_conference.wav"/>
<prompt phrase="...members in this conference." filename="conf-members_in_conference.wav"/>
<prompt phrase="This conference is in Q and A mode." filename="conference/conf-conference_is_in_qna_mode.wav"/>
<prompt phrase="Q and A mode..." filename="conference/conf-qna_mode.wav"/>
<prompt phrase="Entry sound..." filename="conference/conf-entry_sound.wav"/>
<prompt phrase="Exit sound..." filename="conference/conf-exit_sound.wav"/>
</conference>
<ivr>
<prompt phrase="Account number" filename="ivr-account_number.wav"/>
@ -425,17 +452,47 @@
<prompt phrase="Barracuda Networks" filename="ivr-barracuda_networks.wav"/>
<prompt phrase="CudaTel Communication Server" filename="ivr-cudatel_communication_server.wav"/>
<prompt phrase="There are no calls waiting in this queue." filename="ivr-no_calls_waiting_in_queue.wav"/>
<!-- The following phrases still need to be recorded -->
<prompt phrase="You are caller number one. Of course, *every* caller is number one in our book so you may be waiting a while." filename="ivr-youre_number_one.wav"/>
<prompt phrase="...has called emergency services" filename="ivr-has_called_emergency_services.wav"/>
<prompt phrase="There are..." filename="ivr-there_are.wav"/>
<prompt phrase="Enter the number of listeners at this location, then press pound." filename="conf-number_of_listeners.wav"/>
<prompt phrase="...listeners in this conference." filename="conf-listeners_in_conference.wav"/>
<prompt phrase="...members in this conference." filename="conf-members_in_conference.wav"/>
<prompt phrase="Please enter the source telephone number, then press pound." filename="ivr-enter_source_telephone_number.wav"/>
<prompt phrase="Please enter the destination telephone number, then press pound." filename="ivr-enter_destination_telephone_number.wav"/>
<prompt phrase="Recording started." filename="ivr-recording_started.wav"/>
<prompt phrase="Recording stopped." filename="ivr-recording_stopped.wav"/>
<prompt phrase="Recording paused." filename="ivr-recording_paused.wav"/>
<prompt phrase="Recording deleted." filename="ivr-recording_deleted.wav"/>
<prompt phrase="You are no longer in queue." filename="ivr-no_longer_in_queue.wav"/>
<prompt phrase="...withdrawn." filename="ivr-withdrawn.wav"/>
<prompt phrase="question..." filename="ivr-question.wav"/>
<prompt phrase="...questions." filename="ivr-questions.wav"/>
<prompt phrase="...has been answered." filename="ivr-has_been_answered.wav"/>
<prompt phrase="...has been removed." filename="ivr-has_been_removed.wav"/>
<prompt phrase="No questions in queue." filename="ivr-no_questions_in_queue.wav"/>
<prompt phrase="...is now on." filename="ivr/ivr_is_now_on.wav"/>
<prompt phrase="...is now off." filename="ivr/ivr_is_now_off.wav"/>
<prompt phrase="This phone is not allowed to make external calls." filename="ivr-phone_not_make_external_calls.wav"/>
<prompt phrase="I.D. number..." filename="ivr-id_number.wav"/>
<prompt phrase="To skip these instructions..." filename="ivr-skip_instructions.wav"/>
<prompt phrase="Hang up the call without pressing a key to discard the recording." filename="ivr-hangup_to_discard.wav"/>
<prompt phrase="...or press..." filename="ivr-or_press.wav"/>
<prompt phrase="For English, press..." filename="ivr-for_english_press.wav"/>
<prompt phrase="Your call cannot be completed as dialed." filename="ivr-call_cannot_be_completed_as_dialed.wav"/>
<prompt phrase="Please check the number and try again." filename="ivr-please_check_number_try_again.wav"/>
<prompt phrase="Failure reason is..." filename="ivr-failure_reason_is.wav"/>
<prompt phrase="Unallocated number" filename="ivr-unallocated_number.wav"/>
<prompt phrase="No user response" filename="ivr-no_user_response.wav"/>
<prompt phrase="Invalid number format" filename="ivr-invalid_number_format.wav"/>
<prompt phrase="Gateway down" filename="ivr-gateway_down.wav"/>
<prompt phrase="No route to destination" filename="ivr-no_route_destination.wav"/>
<prompt phrase="User busy" filename="ivr-user_busy.wav"/>
<prompt phrase="Call rejected" filename="ivr-call_rejected.wav"/>
<prompt phrase="Normal unspecified" filename="ivr-normal_unspecified.wav"/>
<prompt phrase="Incompatible destination" filename="ivr-incompatible_destination.wav"/>
<prompt phrase="Normal clearing" filename="ivr-normal_clearing.wav"/>
<!-- The following phrases still need to be recorded -->
</ivr>
<misc>
<prompt phrase="This call has been secured" filename="call_secured.wav"/>
<prompt phrase="Followed by pound" filename="followed.wav"/>

View File

@ -219,14 +219,14 @@
<prompt phrase="urgent" filename="vm-urgent.wav"/>
</voicemail>
<directory>
<prompt phrase="Veuillez entrer les premiere lettre du" filename="dir-enter-person.wav"/>
<prompt phrase="Veuillez entrer les premiere lettre du" filename="dir-enter_person.wav"/>
<prompt phrase="nom de famille." filename="dir-last_name.wav"/>
<prompt phrase="Pour chercher par" filename="dir-to_search_by.wav"/>
<prompt phrase="prénom." filename="dir-first_name.wav"/>
<prompt phrase="Votre recherche a retourner aucune résultat, essayer de nouveaux." filename="dir-no_match_entry.wav"/>
<prompt phrase="résultats correspond a votre recherche." filename="dir-result_match.wav"/>
<prompt phrase="Votre recherche retourne trop de résultat, essayer de nouveaux." filename="dir-to_many_result.wav"/>
<prompt phrase="Fin des résultats." filename="dir-no_more_result.wav"/>
<prompt phrase="Votre recherche retourne trop de résultat, essayer de nouveaux." filename="dir-too_many_result.wav"/>
<prompt phrase="Fin des résultats." filename="dir-no_more_results.wav"/>
<prompt phrase="Résultat numéro" filename="dir-result_number.wav"/>
<prompt phrase="aux poste" filename="dir-at_extension.wav"/>
<prompt phrase="Pour selectionner ce nom" filename="dir-to_select_entry.wav"/>

View File

@ -2,7 +2,7 @@
# Copyright and license
##############################################################################
#
# Spec file for package freeswitch-sounds-en-us-callie (version 1.0.12-8)
# Spec file for package freeswitch-sounds-en-us-callie (version 1.0.16-8)
#
# Copyright (c) 2009 Patrick Laimbock
# Some fixes and additions (c) 2011 Michal Bielicki
@ -20,7 +20,7 @@
# Set variables
##############################################################################
%define version 1.0.14
%define version 1.0.16
%define release 1
%define fsname freeswitch
@ -299,6 +299,8 @@ cd %{_prefix}/sounds/en/us/callie
##############################################################################
%changelog
* Sun May 22 2011 Michal Bielicki <michal.bielicki@seventhsignal.de> - 1.0.16-1
- bump up version
* Tue Jan 18 2011 Michal Bielicki <michal.bielicki@seventhsignal.de> - 1.0.14-1
- bump up version
- include script into freeswitch core

View File

@ -63,12 +63,12 @@ Vendor: http://www.freeswitch.org/
# Source files and where to get them
#
######################################################################################################################
Source0: http://files.freeswitch.org/%{name}-%{version}.tar.bz2
Source0: http://files.freeswitch.org/%{name}-%{version}.tar.bz2
Source1: http://files.freeswitch.org/downloads/libs/celt-0.10.0.tar.gz
Source2: http://files.freeswitch.org/downloads/libs/flite-1.3.99-latest.tar.gz
Source3: http://files.freeswitch.org/downloads/libs/lame-3.97.tar.gz
Source4: http://files.freeswitch.org/downloads/libs/libshout-2.2.2.tar.gz
Source5: http://files.freeswitch.org/downloads/libs/mpg123.tar.gz
Source5: http://files.freeswitch.org/downloads/libs/mpg123-1.13.2.tar.gz
Source6: http://files.freeswitch.org/downloads/libs/openldap-2.4.11.tar.gz
Source7: http://files.freeswitch.org/downloads/libs/pocketsphinx-0.5.99-20091212.tar.gz
Source8: http://files.freeswitch.org/downloads/libs/soundtouch-1.3.1.tar.gz
@ -752,6 +752,7 @@ fi
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/cdr_csv.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/cdr_pg_csv.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/cdr_sqlite.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/cepstral.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/cidlookup.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/conference.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/console.conf.xml
@ -775,6 +776,7 @@ fi
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/logfile.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/memcache.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/modules.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/mongo.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/nibblebill.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/opal.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/osp.conf.xml
@ -1064,10 +1066,13 @@ fi
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/lang/en
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/lang/en/demo
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/lang/en/vm
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/lang/en/dir
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/lang/en/ivr
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/lang/en/*.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/lang/en/demo/*.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/lang/en/vm/*.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/lang/en/dir/*.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/lang/en/ivr/*.xml
%{prefix}/mod/mod_say_en.so*
%files lang-de
@ -1085,6 +1090,7 @@ fi
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/lang/fr
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/lang/fr/demo
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/lang/fr/vm
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/lang/fr/dir
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/lang/fr/*.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/lang/fr/demo/*.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/lang/fr/vm/*.xml
@ -1096,6 +1102,7 @@ fi
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/lang/ru
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/lang/ru/demo
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/lang/ru/vm
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/lang/ru/dir
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/lang/ru/*.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/lang/ru/demo/*.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/lang/ru/vm/*.xml
@ -1107,6 +1114,7 @@ fi
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/lang/he/
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/lang/he/demo
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/lang/he/vm
%dir %attr(0750, freeswitch, daemon) %{prefix}/conf/lang/he/dir
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/lang/he/*.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/lang/he/demo/*.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/lang/he/vm/*.xml

View File

@ -8,6 +8,7 @@
#include <signal.h>
#define CMD_BUFLEN 1024
#define PROMPT_PREFIX "netborder-ss7"
static int WARN_STOP = 0;
#ifdef WIN32
@ -839,9 +840,9 @@ static const char *basic_gets(int *cnt)
}
Sleep(20);
}
#endif
return command_buf;
#endif
}
#endif
@ -851,17 +852,10 @@ static void print_banner(FILE *stream)
fprintf(stream,
" _____ ____ ____ _ ___ \n"
" | ___/ ___| / ___| | |_ _| \n"
" | |_ \\___ \\ | | | | | | \n"
" | _| ___) | | |___| |___ | | \n"
" |_| |____/ \\____|_____|___| \n"
"\n"
"*******************************************************\n"
"* Anthony Minessale II, Ken Rice, Michael Jerris *\n"
"* FreeSWITCH (http://www.freeswitch.org) *\n"
"* Paypal Donations Appreciated: paypal@freeswitch.org *\n"
"* Brought to you by ClueCon http://www.cluecon.com/ *\n"
"* Netborder SS7 Gateway *\n"
"* Powered by FreeSWITCH (http://www.freeswitch.org) *\n"
"*******************************************************\n"
"\n"
"Type /help <enter> to see a list of commands\n\n\n"
@ -1008,13 +1002,13 @@ int main(int argc, char *argv[])
int rv = 0;
#ifndef WIN32
char hfile[512] = "/etc/fs_cli_history";
char cfile[512] = "/etc/fs_cli.conf";
char dft_cfile[512] = "/etc/fs_cli.conf";
char hfile[512] = "/etc/nbess7_cli_history";
char cfile[512] = "/etc/nbess7_cli.conf";
char dft_cfile[512] = "/etc/nbess7_cli.conf";
#else
char hfile[512] = "fs_cli_history";
char cfile[512] = "fs_cli.conf";
char dft_cfile[512] = "fs_cli.conf";
char hfile[512] = "nbess7_cli_history";
char cfile[512] = "nbess7_cli.conf";
char dft_cfile[512] = "nbess7_cli.conf";
#endif
char *home = getenv("HOME");
/* Vars for optargs */
@ -1055,13 +1049,13 @@ int main(int argc, char *argv[])
strncpy(internal_profile.host, "127.0.0.1", sizeof(internal_profile.host));
strncpy(internal_profile.pass, "ClueCon", sizeof(internal_profile.pass));
strncpy(internal_profile.name, "internal", sizeof(internal_profile.name));
internal_profile.port = 8021;
internal_profile.port = 8821;
set_fn_keys(&internal_profile);
if (home) {
snprintf(hfile, sizeof(hfile), "%s/.fs_cli_history", home);
snprintf(cfile, sizeof(cfile), "%s/.fs_cli_conf", home);
snprintf(hfile, sizeof(hfile), "%s/.nbess7_cli_history", home);
snprintf(cfile, sizeof(cfile), "%s/.nbess7_cli_conf", home);
}
signal(SIGINT, handle_SIGINT);
@ -1157,7 +1151,7 @@ int main(int argc, char *argv[])
esl_set_string(profiles[pcount].name, cur_cat);
esl_set_string(profiles[pcount].host, "localhost");
esl_set_string(profiles[pcount].pass, "ClueCon");
profiles[pcount].port = 8021;
profiles[pcount].port = 8821;
set_fn_keys(&profiles[pcount]);
esl_log(ESL_LOG_DEBUG, "Found Profile [%s]\n", profiles[pcount].name);
pcount++;
@ -1236,13 +1230,13 @@ int main(int argc, char *argv[])
esl_log(ESL_LOG_DEBUG, "Using profile %s [%s]\n", profile->name, profile->host);
if (argv_host) {
if (argv_port && profile->port != 8021) {
snprintf(prompt_str, sizeof(prompt_str), "freeswitch@%s:%u@%s> ", profile->host, profile->port, profile->name);
if (argv_port && profile->port != 8821) {
snprintf(prompt_str, sizeof(prompt_str), PROMPT_PREFIX "@%s:%u@%s> ", profile->host, profile->port, profile->name);
} else {
snprintf(prompt_str, sizeof(prompt_str), "freeswitch@%s@%s> ", profile->host, profile->name);
snprintf(prompt_str, sizeof(prompt_str), PROMPT_PREFIX "@%s@%s> ", profile->host, profile->name);
}
} else {
snprintf(prompt_str, sizeof(prompt_str), "freeswitch@%s> ", profile->name);
snprintf(prompt_str, sizeof(prompt_str), PROMPT_PREFIX "@%s> ", profile->name);
}
connect:
@ -1374,7 +1368,7 @@ int main(int argc, char *argv[])
print_banner(stdout);
esl_log(ESL_LOG_INFO, "FS CLI Ready.\nenter /help for a list of commands.\n");
esl_log(ESL_LOG_INFO, "Netborder SS7 CLI Ready.\nenter /help for a list of commands.\n");
printf("%s\n", handle.last_sr_reply);
while (running > 0) {

View File

@ -4,7 +4,7 @@
host => 127.0.0.1
password => ClueCon
port => 8021
port => 8821
debug => 2
key_f1 => help

View File

@ -0,0 +1,26 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ESL", "esl_lua.2010.vcxproj", "{86B6AB99-A261-455A-9CD6-9142A5A1652E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{86B6AB99-A261-455A-9CD6-9142A5A1652E}.Debug|Win32.ActiveCfg = Debug|Win32
{86B6AB99-A261-455A-9CD6-9142A5A1652E}.Debug|Win32.Build.0 = Debug|Win32
{86B6AB99-A261-455A-9CD6-9142A5A1652E}.Debug|x64.ActiveCfg = Debug|x64
{86B6AB99-A261-455A-9CD6-9142A5A1652E}.Debug|x64.Build.0 = Debug|x64
{86B6AB99-A261-455A-9CD6-9142A5A1652E}.Release|Win32.ActiveCfg = Release|Win32
{86B6AB99-A261-455A-9CD6-9142A5A1652E}.Release|Win32.Build.0 = Release|Win32
{86B6AB99-A261-455A-9CD6-9142A5A1652E}.Release|x64.ActiveCfg = Release|x64
{86B6AB99-A261-455A-9CD6-9142A5A1652E}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,178 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<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>ESL</ProjectName>
<ProjectGuid>{86B6AB99-A261-455A-9CD6-9142A5A1652E}</ProjectGuid>
<RootNamespace>esl_lua.2010</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" 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)'=='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)'=='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|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.40219.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</LinkIncremental>
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
<CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\src\mod\languages\mod_lua\lua\;$(ProjectDir)..\src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>ESL_DECLARE_STATIC;WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>esl.lib;lua51.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\$(Platform)\$(Configuration)\;$(ProjectDir)..\..\..\libs\esl\src\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\src\mod\languages\mod_lua\lua\;$(ProjectDir)..\src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>ESL_DECLARE_STATIC;WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>esl.lib;lua51.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\$(Platform)\$(Configuration)\;$(ProjectDir)..\..\..\libs\esl\src\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\src\mod\languages\mod_lua\lua\;$(ProjectDir)..\src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>ESL_DECLARE_STATIC;WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>esl.lib;lua51.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\$(Platform)\$(Configuration);$(ProjectDir)..\..\..\libs\esl\src\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>$(ProjectDir)..\..\..\src\mod\languages\mod_lua\lua\;$(ProjectDir)..\src\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>ESL_DECLARE_STATIC;WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>esl.lib;lua51.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\$(Platform)\$(Configuration);$(ProjectDir)..\..\..\libs\esl\src\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\src\esl_oop.cpp" />
<ClCompile Include="esl_wrap.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx</Extensions>
</Filter>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\esl_oop.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="esl_wrap.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -73,13 +73,13 @@ sub setVar($;) {
sub playAndGetDigits($;) {
my $self = shift;
my ($min, $max, $tries, $to, $term, $file, $invalid_file, $var, $regex) = @_;
my ($min, $max, $tries, $to, $term, $file, $invalid_file, $var, $regex, $digit_timeout) = @_;
if (!$self->{_esl}->connected()) {
return undef;
}
$self->execute("play_and_get_digits", "$min $max $tries $to $term $file $invalid_file $var $regex");
$self->execute("play_and_get_digits", "$min $max $tries $to $term $file $invalid_file $var $regex $digit_timeout");
return $self->getVar($var);

View File

@ -323,7 +323,7 @@ static void default_logger(const char *file, const char *func, int line, int lev
ret = esl_vasprintf(&data, fmt, ap);
if (ret != -1) {
fprintf(stderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], file, line, func, data);
fprintf(stderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], fp, line, func, data);
free(data);
}

View File

@ -235,6 +235,7 @@ ftmod_sangoma_isdn_la_SOURCES = \
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c \
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c \
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_trace.c \
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_transfer.c \
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c \
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c \
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c \

View File

@ -18,6 +18,11 @@ with the signaling protocols that you can run on top of your I/O interfaces.
-->
<!--<param name="enable-analog-option" value="call-swap"/>-->
<!--<param name="enable-analog-option" value="3-way"/>-->
<!--
Refuse to load the module if there is configuration errors
Defaults to 'no'
-->
<!--<param name="fail-on-error" value="no"/>-->
</settings>
<!-- Sample analog configuration (The analog_spans tag is for ftmod_analog) -->

View File

@ -2,6 +2,7 @@ APIs that result in an event when the API returns FTDM_SUCCESS
ftdm_channel_call_answer()
ftdm_channel_call_indicate()
ftdm_channel_call_transfer()
FTDM_SIGEVENT_INDICATION_COMPLETED
*note that FTDM_SIGEVENT_INDICATION_COMPLETED has associated data to indicate the result of the indication
*note this event is only delivered on non-blocking channels

View File

@ -67,7 +67,8 @@ typedef enum {
TFLAG_CODEC = (1 << 2),
TFLAG_BREAK = (1 << 3),
TFLAG_HOLD = (1 << 4),
TFLAG_DEAD = (1 << 5)
TFLAG_DEAD = (1 << 5),
TFLAG_TRANSFER = (1 << 6),
} TFLAGS;
static struct {
@ -88,6 +89,8 @@ static struct {
switch_hash_t *ss7_configs;
int sip_headers;
uint8_t crash_on_assert;
uint8_t fail_on_error;
uint8_t config_error;
} globals;
/* private data attached to each fs session */
@ -130,6 +133,10 @@ struct span_config {
int limit_calls;
int limit_seconds;
limit_reset_event_t limit_reset_event;
/* digital codec and digital sampling rate are used to configure the codec
* when bearer capability is set to unrestricted digital */
const char *digital_codec;
int digital_sampling_rate;
chan_pvt_t pvts[FTDM_MAX_CHANNELS_SPAN];
};
@ -294,13 +301,11 @@ static void cycle_foreground(ftdm_channel_t *ftdmchan, int flash, const char *bc
}
}
static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *session, ftdm_channel_t *ftdmchan)
static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *session, ftdm_channel_t *ftdmchan, ftdm_caller_data_t *caller_data)
{
const char *dname = NULL;
uint32_t interval = 0, srate = 8000;
uint32_t span_id;
ftdm_codec_t codec;
tech_pvt->ftdmchan = ftdmchan;
@ -321,6 +326,16 @@ static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *ses
return SWITCH_STATUS_GENERR;
}
span_id = ftdm_channel_get_span_id(ftdmchan);
if (caller_data->bearer_capability == FTDM_BEARER_CAP_UNRESTRICTED
&& SPAN_CONFIG[span_id].digital_codec) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Initializing digital call with codec %s at %dhz.\n",
SPAN_CONFIG[span_id].digital_codec, SPAN_CONFIG[span_id].digital_sampling_rate);
dname = SPAN_CONFIG[span_id].digital_codec;
srate = SPAN_CONFIG[span_id].digital_sampling_rate;
goto init_codecs;
}
if (FTDM_SUCCESS != ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_CODEC, &codec)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to retrieve channel codec.\n");
return SWITCH_STATUS_GENERR;
@ -349,6 +364,7 @@ static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *ses
}
}
init_codecs:
if (switch_core_codec_init(&tech_pvt->read_codec,
dname,
@ -720,7 +736,6 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
ftdm_size_t len;
unsigned char data[SWITCH_RECOMMENDED_BUFFER_SIZE] = {0};
ftdm_wait_flag_t wflags = FTDM_WRITE;
ftdm_status_t status;
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
@ -755,7 +770,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
wflags = FTDM_WRITE;
status = ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, ftdm_channel_get_io_interval(tech_pvt->ftdmchan) * 10);
ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, ftdm_channel_get_io_interval(tech_pvt->ftdmchan) * 10);
if (!(wflags & FTDM_WRITE)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Dropping frame! (write not ready)\n");
@ -868,10 +883,30 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
ftdm_channel_call_answer(tech_pvt->ftdmchan);
}
break;
case SWITCH_MESSAGE_INDICATE_REDIRECT:
case SWITCH_MESSAGE_INDICATE_DEFLECT:
{
ftdm_usrmsg_t usrmsg;
const char *val = NULL;
memset(&usrmsg, 0, sizeof(usrmsg));
if ((val = switch_channel_get_variable(channel, "freetdm_transfer_data"))) {
ftdm_usrmsg_add_var(&usrmsg, "transfer_data", val);
}
switch_set_flag(tech_pvt, TFLAG_TRANSFER);
if (ftdm_channel_call_transfer_ex(tech_pvt->ftdmchan, msg->string_arg, &usrmsg) != FTDM_SUCCESS) {
switch_clear_flag(tech_pvt, TFLAG_TRANSFER);
}
while (switch_test_flag(tech_pvt, TFLAG_TRANSFER)) {
switch_yield(100000);
}
}
default:
break;
}
return SWITCH_STATUS_SUCCESS;
}
@ -1094,7 +1129,7 @@ static ftdm_status_t on_channel_found(ftdm_channel_t *fchan, ftdm_caller_data_t
span_id = ftdm_channel_get_span_id(fchan);
chan_id = ftdm_channel_get_id(fchan);
tech_init(hdata->tech_pvt, hdata->new_session, fchan);
tech_init(hdata->tech_pvt, hdata->new_session, fchan, caller_data);
snprintf(name, sizeof(name), "FreeTDM/%u:%u/%s", span_id, chan_id, caller_data->dnis.digits);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connect outbound channel %s\n", name);
@ -1557,7 +1592,7 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session
tech_pvt = (private_t *) switch_core_session_alloc(session, sizeof(private_t));
assert(tech_pvt != NULL);
channel = switch_core_session_get_channel(session);
if (tech_init(tech_pvt, session, sigmsg->channel) != SWITCH_STATUS_SUCCESS) {
if (tech_init(tech_pvt, session, sigmsg->channel, channel_caller_data) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Initilization Error!\n");
switch_core_session_destroy(&session);
return FTDM_FAIL;
@ -1735,11 +1770,13 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session
static FIO_SIGNAL_CB_FUNCTION(on_common_signal)
{
switch_event_t *event = NULL;
ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE;
uint32_t chanid, spanid;
switch_event_t *event = NULL;
ftdm_alarm_flag_t alarmbits = FTDM_ALARM_NONE;
chanid = ftdm_channel_get_id(sigmsg->channel);
spanid = ftdm_channel_get_span_id(sigmsg->channel);
switch (sigmsg->event_id) {
case FTDM_SIGEVENT_ALARM_CLEAR:
@ -1774,14 +1811,44 @@ static FIO_SIGNAL_CB_FUNCTION(on_common_signal)
}
return FTDM_SUCCESS;
}
case FTDM_SIGEVENT_TRANSFER_COMPLETED:
{
switch_core_session_t *session = NULL;
switch_channel_t *channel = NULL;
private_t *tech_pvt = NULL;
case FTDM_SIGEVENT_RELEASED:
if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
channel = switch_core_session_get_channel(session);
tech_pvt = switch_core_session_get_private(session);
switch_clear_flag_locked(tech_pvt, TFLAG_TRANSFER);
switch_channel_set_variable(channel, "freetdm_transfer_response", ftdm_transfer_response2str(sigmsg->ev_data.transfer_completed.response));
switch_core_session_rwunlock(session);
}
return FTDM_SUCCESS;
}
break;
case FTDM_SIGEVENT_RELEASED:
case FTDM_SIGEVENT_INDICATION_COMPLETED:
case FTDM_SIGEVENT_DIALING:
{
{
/* Swallow these events */
return FTDM_BREAK;
}
}
break;
case FTDM_SIGEVENT_STOP:
case FTDM_SIGEVENT_RESTART:
{
switch_core_session_t *session = NULL;
private_t *tech_pvt = NULL;
while((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
tech_pvt = switch_core_session_get_private(session);
switch_clear_flag_locked(tech_pvt, TFLAG_TRANSFER);
switch_core_session_rwunlock(session);
return FTDM_SUCCESS;
}
}
break;
default:
return FTDM_SUCCESS;
@ -2336,6 +2403,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
break;
case FTDM_SIGEVENT_PROCEED:
case FTDM_SIGEVENT_FACILITY:
case FTDM_SIGEVENT_TRANSFER_COMPLETED:
/* FS does not have handlers for these messages, so ignore them for now */
break;
default:
@ -2415,6 +2483,10 @@ static uint32_t enable_analog_option(const char *str, uint32_t current_options)
}
#define CONFIG_ERROR(...) do { \
ftdm_log(FTDM_LOG_ERROR, __VA_ARGS__); \
globals.config_error = 1; \
} while(0)
/* create ftdm_conf_node_t tree based on a fixed pattern XML configuration list
* last 2 args are for limited aka dumb recursivity
* */
@ -2607,7 +2679,7 @@ static int add_profile_parameters(switch_xml_t cfg, const char *profname, ftdm_c
profnode = switch_xml_child(cfg, "config_profiles");
if (!profnode) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "cannot find profile '%s', there is no 'config_profiles' XML section\n", profname);
CONFIG_ERROR("cannot find profile '%s', there is no 'config_profiles' XML section\n", profname);
return 0;
}
@ -2623,7 +2695,7 @@ static int add_profile_parameters(switch_xml_t cfg, const char *profname, ftdm_c
}
if (!profile) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to find profile '%s'\n", profname);
CONFIG_ERROR("failed to find profile '%s'\n", profname);
return 0;
}
@ -2658,7 +2730,7 @@ static void parse_bri_pri_spans(switch_xml_t cfg, switch_xml_t spans)
unsigned paramindex = 0;
if (!name && !id) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sangoma isdn span missing required attribute 'id' or 'name', skipping ...\n");
CONFIG_ERROR("sangoma isdn span missing required attribute 'id' or 'name', skipping ...\n");
continue;
}
@ -2676,7 +2748,7 @@ static void parse_bri_pri_spans(switch_xml_t cfg, switch_xml_t spans)
}
if (zstatus != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
CONFIG_ERROR("Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
continue;
}
@ -2697,13 +2769,14 @@ static void parse_bri_pri_spans(switch_xml_t cfg, switch_xml_t spans)
/* some defaults first */
SPAN_CONFIG[span_id].limit_backend = "hash";
SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_TIMEOUT;
SPAN_CONFIG[span_id].digital_sampling_rate = 8000;
for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if (ftdm_array_len(spanparameters) - 1 == paramindex) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Too many parameters for ss7 span, ignoring any parameter after %s\n", var);
CONFIG_ERROR("Too many parameters for ss7 span, ignoring any parameter after %s\n", var);
break;
}
@ -2711,6 +2784,21 @@ static void parse_bri_pri_spans(switch_xml_t cfg, switch_xml_t spans)
context = val;
} else if (!strcasecmp(var, "dialplan")) {
dialplan = val;
} else if (!strcasecmp(var, "unrestricted-digital-codec")) {
//switch_core_strdup(pool, val);
const switch_codec_implementation_t *codec = NULL;
int num_codecs;
num_codecs = switch_loadable_module_get_codecs_sorted(&codec, 1, &val, 1);
if (num_codecs != 1 || !codec) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Failed finding codec %s for unrestricted digital calls\n", val);
} else {
SPAN_CONFIG[span_id].digital_codec = switch_core_strdup(module_pool, codec->iananame);
SPAN_CONFIG[span_id].digital_sampling_rate = codec->samples_per_second;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
"Unrestricted digital codec is %s at %dhz for span %d\n",
SPAN_CONFIG[span_id].digital_codec, SPAN_CONFIG[span_id].digital_sampling_rate, span_id);
}
} else if (!strcasecmp(var, "call_limit_backend")) {
SPAN_CONFIG[span_id].limit_backend = val;
ftdm_log(FTDM_LOG_DEBUG, "Using limit backend %s for span %d\n", SPAN_CONFIG[span_id].limit_backend, span_id);
@ -2718,10 +2806,10 @@ static void parse_bri_pri_spans(switch_xml_t cfg, switch_xml_t spans)
int calls;
int seconds;
if (sscanf(val, "%d/%d", &calls, &seconds) != 2) {
ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter, format example: 3/1 for 3 calls per second\n", var);
CONFIG_ERROR("Invalid %s parameter, format example: 3/1 for 3 calls per second\n", var);
} else {
if (calls < 1 || seconds < 1) {
ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter value, minimum call limit must be 1 per second\n", var);
CONFIG_ERROR("Invalid %s parameter value, minimum call limit must be 1 per second\n", var);
} else {
SPAN_CONFIG[span_id].limit_calls = calls;
SPAN_CONFIG[span_id].limit_seconds = seconds;
@ -2731,7 +2819,7 @@ static void parse_bri_pri_spans(switch_xml_t cfg, switch_xml_t spans)
if (!strcasecmp(val, "answer")) {
SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_ANSWER;
} else {
ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter value, only accepted event is 'answer'\n", var);
CONFIG_ERROR("Invalid %s parameter value, only accepted event is 'answer'\n", var);
}
} else {
spanparameters[paramindex].var = var;
@ -2744,7 +2832,7 @@ static void parse_bri_pri_spans(switch_xml_t cfg, switch_xml_t spans)
"sangoma_isdn",
on_clear_channel_signal,
spanparameters) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error configuring Sangoma ISDN FreeTDM span %d\n", span_id);
CONFIG_ERROR("Error configuring Sangoma ISDN FreeTDM span %d\n", span_id);
continue;
}
SPAN_CONFIG[span_id].span = span;
@ -2761,15 +2849,11 @@ static switch_status_t load_config(void)
const char *cf = "freetdm.conf";
switch_xml_t cfg, xml, settings, param, spans, myspan;
ftdm_conf_node_t *ss7confnode = NULL;
ftdm_span_t *boost_spans[FTDM_MAX_PHYSICAL_SPANS_PER_LOGICAL_SPAN];
ftdm_span_t *boost_span = NULL;
unsigned boosti = 0;
unsigned int i = 0;
ftdm_channel_t *fchan = NULL;
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
memset(boost_spans, 0, sizeof(boost_spans));
memset(&globals, 0, sizeof(globals));
switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, module_pool);
if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
@ -2788,6 +2872,8 @@ static switch_status_t load_config(void)
switch_set_string(globals.hold_music, val);
} else if (!strcasecmp(var, "crash-on-assert")) {
globals.crash_on_assert = switch_true(val);
} else if (!strcasecmp(var, "fail-on-error")) {
globals.fail_on_error = switch_true(val);
} else if (!strcasecmp(var, "sip-headers")) {
globals.sip_headers = switch_true(val);
} else if (!strcasecmp(var, "enable-analog-option")) {
@ -2818,11 +2904,11 @@ static switch_status_t load_config(void)
uint32_t span_id = 0;
unsigned paramindex = 0;
if (!name && !id) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ss7 span missing required attribute 'id' or 'name', skipping ...\n");
CONFIG_ERROR("ss7 span missing required attribute 'id' or 'name', skipping ...\n");
continue;
}
if (!configname) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ss7 span missing required attribute, skipping ...\n");
CONFIG_ERROR("ss7 span missing required attribute, skipping ...\n");
continue;
}
if (name) {
@ -2839,7 +2925,7 @@ static switch_status_t load_config(void)
}
if (zstatus != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
CONFIG_ERROR("Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
continue;
}
@ -2849,7 +2935,7 @@ static switch_status_t load_config(void)
ss7confnode = get_ss7_config_node(cfg, configname);
if (!ss7confnode) {
ftdm_log(FTDM_LOG_ERROR, "Error finding ss7config '%s' for FreeTDM span id: %s\n", configname, switch_str_nil(id));
CONFIG_ERROR("Error finding ss7config '%s' for FreeTDM span id: %s\n", configname, switch_str_nil(id));
continue;
}
@ -2863,7 +2949,7 @@ static switch_status_t load_config(void)
char *val = (char *) switch_xml_attr_soft(param, "value");
if (ftdm_array_len(spanparameters) - 1 == paramindex) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Too many parameters for ss7 span, ignoring any parameter after %s\n", var);
CONFIG_ERROR("Too many parameters for ss7 span, ignoring any parameter after %s\n", var);
break;
}
@ -2882,7 +2968,7 @@ static switch_status_t load_config(void)
"sangoma_ss7",
on_clear_channel_signal,
spanparameters) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error configuring ss7 FreeTDM span %d\n", span_id);
CONFIG_ERROR("Error configuring ss7 FreeTDM span %d\n", span_id);
continue;
}
SPAN_CONFIG[span_id].span = span;
@ -2933,7 +3019,7 @@ static switch_status_t load_config(void)
}
if (zstatus != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
CONFIG_ERROR("Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
continue;
}
@ -2967,10 +3053,10 @@ static switch_status_t load_config(void)
int calls;
int seconds;
if (sscanf(val, "%d/%d", &calls, &seconds) != 2) {
ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter, format example: 3/1 for 3 calls per second\n", var);
CONFIG_ERROR("Invalid %s parameter, format example: 3/1 for 3 calls per second\n", var);
} else {
if (calls < 1 || seconds < 1) {
ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter value, minimum call limit must be 1 per second\n", var);
CONFIG_ERROR("Invalid %s parameter value, minimum call limit must be 1 per second\n", var);
} else {
SPAN_CONFIG[span_id].limit_calls = calls;
SPAN_CONFIG[span_id].limit_seconds = seconds;
@ -2980,7 +3066,7 @@ static switch_status_t load_config(void)
if (!strcasecmp(val, "answer")) {
SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_ANSWER;
} else {
ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter value, only accepted event is 'answer'\n", var);
CONFIG_ERROR("Invalid %s parameter value, only accepted event is 'answer'\n", var);
}
} else if (!strcasecmp(var, "dial-regex")) {
dial_regex = val;
@ -3008,7 +3094,7 @@ static switch_status_t load_config(void)
}
if (!id && !name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\n");
CONFIG_ERROR("span missing required param 'id'\n");
continue;
}
@ -3038,7 +3124,7 @@ static switch_status_t load_config(void)
}
if (zstatus != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
CONFIG_ERROR("Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
continue;
}
@ -3058,7 +3144,7 @@ static switch_status_t load_config(void)
"callwaiting", &callwaiting,
"wait_dialtone_timeout", &dialtone_timeout,
FTDM_TAG_END) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM analog span %s\n", ftdm_span_get_name(span));
CONFIG_ERROR("Error configuring FreeTDM analog span %s\n", ftdm_span_get_name(span));
continue;
}
@ -3134,7 +3220,7 @@ static switch_status_t load_config(void)
}
if (!id && !name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\n");
CONFIG_ERROR("span missing required param 'id'\n");
continue;
}
@ -3166,7 +3252,7 @@ static switch_status_t load_config(void)
}
if (zstatus != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
CONFIG_ERROR("Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
continue;
}
@ -3180,7 +3266,7 @@ static switch_status_t load_config(void)
"digit_timeout", &to,
"max_dialstr", &max,
FTDM_TAG_END) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error starting FreeTDM span %d\n", span_id);
CONFIG_ERROR("Error starting FreeTDM span %d\n", span_id);
continue;
}
@ -3217,7 +3303,7 @@ static switch_status_t load_config(void)
uint32_t span_id = 0;
if (!name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required attribute 'name'\n");
CONFIG_ERROR("span missing required attribute 'name'\n");
continue;
}
@ -3228,7 +3314,7 @@ static switch_status_t load_config(void)
char *val = (char *) switch_xml_attr_soft(param, "value");
if (ftdm_array_len(spanparameters) - 1 == paramindex) {
ftdm_log(FTDM_LOG_ERROR, "Too many parameters for pri span '%s', ignoring everything after '%s'\n", name, var);
CONFIG_ERROR("Too many parameters for pri span '%s', ignoring everything after '%s'\n", name, var);
break;
}
@ -3250,13 +3336,13 @@ static switch_status_t load_config(void)
zstatus = ftdm_span_find_by_name(name, &span);
if (zstatus != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span %s\n", name);
CONFIG_ERROR("Error finding FreeTDM span %s\n", name);
continue;
}
span_id = ftdm_span_get_id(span);
if (ftdm_configure_span_signaling(span, "isdn", on_clear_channel_signal, spanparameters) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM span %s\n", name);
CONFIG_ERROR("Error configuring FreeTDM span %s\n", name);
continue;
}
@ -3283,7 +3369,7 @@ static switch_status_t load_config(void)
int span_id = 0;
if (!name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required attribute 'name'\n");
CONFIG_ERROR("span missing required attribute 'name'\n");
continue;
}
@ -3294,7 +3380,7 @@ static switch_status_t load_config(void)
char *val = (char *) switch_xml_attr_soft(param, "value");
if (ftdm_array_len(spanparameters) - 1 == paramindex) {
ftdm_log(FTDM_LOG_ERROR, "Too many parameters for pritap span '%s', ignoring everything after '%s'\n", name, var);
CONFIG_ERROR("Too many parameters for pritap span '%s', ignoring everything after '%s'\n", name, var);
break;
}
@ -3311,13 +3397,13 @@ static switch_status_t load_config(void)
zstatus = ftdm_span_find_by_name(name, &span);
if (zstatus != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span %s\n", name);
CONFIG_ERROR("Error finding FreeTDM span %s\n", name);
continue;
}
span_id = ftdm_span_get_id(span);
if (ftdm_configure_span_signaling(span, "pritap", on_clear_channel_signal, spanparameters) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM span %s\n", name);
CONFIG_ERROR("Error configuring FreeTDM span %s\n", name);
continue;
}
@ -3343,7 +3429,7 @@ static switch_status_t load_config(void)
uint32_t span_id = 0;
if (!name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required attribute 'name'\n");
CONFIG_ERROR("span missing required attribute 'name'\n");
continue;
}
@ -3354,7 +3440,7 @@ static switch_status_t load_config(void)
char *val = (char *) switch_xml_attr_soft(param, "value");
if (ftdm_array_len(spanparameters) - 1 == paramindex) {
ftdm_log(FTDM_LOG_ERROR, "Too many parameters for libpri span, ignoring everything after '%s'\n", var);
CONFIG_ERROR("Too many parameters for libpri span, ignoring everything after '%s'\n", var);
break;
}
@ -3376,13 +3462,13 @@ static switch_status_t load_config(void)
zstatus = ftdm_span_find_by_name(name, &span);
if (zstatus != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span %s\n", name);
CONFIG_ERROR("Error finding FreeTDM span %s\n", name);
continue;
}
span_id = ftdm_span_get_id(span);
if (ftdm_configure_span_signaling(span, "libpri", on_clear_channel_signal, spanparameters) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM span %s\n", name);
CONFIG_ERROR("Error configuring FreeTDM span %s\n", name);
continue;
}
@ -3395,86 +3481,6 @@ static switch_status_t load_config(void)
}
}
if ((spans = switch_xml_child(cfg, "boost_spans"))) {
for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
char *id = (char *) switch_xml_attr(myspan, "id");
char *name = (char *) switch_xml_attr(myspan, "name");
char *sigmod = (char *) switch_xml_attr(myspan, "sigmod");
ftdm_status_t zstatus = FTDM_FAIL;
const char *context = "default";
const char *dialplan = "XML";
uint32_t span_id = 0;
ftdm_span_t *span = NULL;
ftdm_conf_parameter_t spanparameters[30];
unsigned paramindex = 0;
if (!id && !name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "boost span requires an id or name as attribute: <span id=ftid|name=ftname>\n");
continue;
}
memset(spanparameters, 0, sizeof(spanparameters));
if (sigmod) {
spanparameters[paramindex].var = "sigmod";
spanparameters[paramindex].val = sigmod;
paramindex++;
}
for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if (ftdm_array_len(spanparameters) - 1 == paramindex) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Too many parameters for boost span, ignoring any parameter after %s\n", var);
break;
}
if (!strcasecmp(var, "context")) {
context = val;
} else if (!strcasecmp(var, "dialplan")) {
dialplan = val;
} else {
spanparameters[paramindex].var = var;
spanparameters[paramindex].val = val;
paramindex++;
}
}
if (name) {
zstatus = ftdm_span_find_by_name(name, &span);
} else {
if (switch_is_number(id)) {
span_id = atoi(id);
zstatus = ftdm_span_find(span_id, &span);
}
if (zstatus != FTDM_SUCCESS) {
zstatus = ftdm_span_find_by_name(id, &span);
}
}
if (zstatus != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name));
continue;
}
if (!span_id) {
span_id = ftdm_span_get_id(span);
}
if (ftdm_configure_span_signaling(span, "sangoma_boost", on_clear_channel_signal, spanparameters) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error starting FreeTDM span %d error: %s\n", span_id, ftdm_span_get_last_error(span));
continue;
}
SPAN_CONFIG[span_id].span = span;
switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context));
switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan));
switch_copy_string(SPAN_CONFIG[span_id].type, "Sangoma (boost)", sizeof(SPAN_CONFIG[span_id].type));
boost_spans[boosti++] = span;
}
}
if ((spans = switch_xml_child(cfg, "r2_spans"))) {
for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
char *name = (char *) switch_xml_attr(myspan, "name");
@ -3493,7 +3499,7 @@ static switch_status_t load_config(void)
unsigned paramindex = 0;
if (!name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "'name' attribute required for R2 spans!\n");
CONFIG_ERROR("'name' attribute required for R2 spans!\n");
continue;
}
@ -3528,14 +3534,13 @@ static switch_status_t load_config(void)
zstatus = ftdm_span_find_by_name(name, &span);
if (zstatus != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM R2 Span '%s'\n", name);
CONFIG_ERROR("Error finding FreeTDM R2 Span '%s'\n", name);
continue;
}
span_id = ftdm_span_get_id(span);
if (ftdm_configure_span_signaling(span, "r2", on_r2_signal, spanparameters) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM R2 span %s, error: %s\n",
name, ftdm_span_get_last_error(span));
CONFIG_ERROR("Error configuring FreeTDM R2 span %s, error: %s\n", name, ftdm_span_get_last_error(span));
continue;
}
@ -3553,24 +3558,12 @@ static switch_status_t load_config(void)
switch_copy_string(SPAN_CONFIG[span_id].type, "R2", sizeof(SPAN_CONFIG[span_id].type));
if (ftdm_span_start(span) == FTDM_FAIL) {
ftdm_log(FTDM_LOG_ERROR, "Error starting FreeTDM R2 span %s, error: %s\n", name, ftdm_span_get_last_error(span));
CONFIG_ERROR("Error starting FreeTDM R2 span %s, error: %s\n", name, ftdm_span_get_last_error(span));
continue;
}
}
}
/* start all boost spans now that we're done configuring. Unfortunately at this point boost modules have the limitation
* of needing all spans to be configured before starting them */
for (i=0 ; i < boosti; i++) {
boost_span = boost_spans[i];
ftdm_log(FTDM_LOG_DEBUG, "Starting boost span %d\n", ftdm_span_get_id(boost_span));
if (ftdm_span_start(boost_span) == FTDM_FAIL) {
ftdm_log(FTDM_LOG_ERROR, "Error starting boost FreeTDM span %d, error: %s\n",
ftdm_span_get_id(boost_span), ftdm_span_get_last_error(boost_span));
continue;
}
}
if (globals.crash_on_assert) {
ftdm_log(FTDM_LOG_WARNING, "Crash on assert enabled\n");
ftdm_global_set_crash_policy(FTDM_CRASH_ON_ASSERT);
@ -3578,6 +3571,11 @@ static switch_status_t load_config(void)
switch_xml_free(xml);
if (globals.fail_on_error && globals.config_error) {
ftdm_log(FTDM_LOG_ERROR, "Refusing to load module with errors\n");
return SWITCH_STATUS_TERM;
}
return SWITCH_STATUS_SUCCESS;
}
@ -3632,6 +3630,12 @@ void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stre
"physical_span_id: %u\n"
"physical_chan_id: %u\n"
"physical_status: %s\n"
"physical_status_red: %d\n"
"physical_status_yellow: %d\n"
"physical_status_rai: %d\n"
"physical_status_blue: %d\n"
"physical_status_ais: %d\n"
"physical_status_general: %d\n"
"signaling_status: %s\n"
"type: %s\n"
"state: %s\n"
@ -3652,7 +3656,13 @@ void dump_chan(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *stre
phspan_id,
phchan_id,
alarmflag ? "alarmed" : "ok",
ftdm_signaling_status2str(sigstatus),
(alarmflag & FTDM_ALARM_RED) ? 1 : 0,
(alarmflag & FTDM_ALARM_YELLOW) ? 1 : 0,
(alarmflag & FTDM_ALARM_RAI) ? 1 : 0,
(alarmflag & FTDM_ALARM_BLUE) ? 1 : 0,
(alarmflag & FTDM_ALARM_AIS) ? 1 : 0,
(alarmflag & FTDM_ALARM_GENERAL) ? 1 : 0,
ftdm_signaling_status2str(sigstatus),
chan_type,
state,
last_state,
@ -3708,6 +3718,12 @@ void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *
" <physical-span-id>%u</physical-span-id>\n"
" <physical-chan-id>%u</physical-chan-id>\n"
" <physical-status>%s</physical-status>\n"
" <physical-status-red>%d</physical-status-red>\n"
" <physical-status-yellow>%d</physical-status-yellow>\n"
" <physical-status-rai>%d</physical-status-rai>\n"
" <physical-status-blue>%d</physical-status-blue>\n"
" <physical-status-ais>%d</physical-status-ais>\n"
" <physical-status-general>%d</physical-status-general>\n"
" <signaling-status>%s</signaling-status>\n"
" <type>%s</type>\n"
" <state>%s</state>\n"
@ -3728,7 +3744,13 @@ void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *
phspan_id,
phchan_id,
alarmflag ? "alarmed" : "ok",
ftdm_signaling_status2str(sigstatus),
(alarmflag & FTDM_ALARM_RED) ? 1 : 0,
(alarmflag & FTDM_ALARM_YELLOW) ? 1 : 0,
(alarmflag & FTDM_ALARM_RAI) ? 1 : 0,
(alarmflag & FTDM_ALARM_BLUE) ? 1 : 0,
(alarmflag & FTDM_ALARM_AIS) ? 1 : 0,
(alarmflag & FTDM_ALARM_GENERAL) ? 1 : 0,
ftdm_signaling_status2str(sigstatus),
chan_type,
state,
last_state,

View File

@ -58,6 +58,8 @@ struct tm *localtime_r(const time_t *clock, struct tm *result);
#define FTDM_READ_TRACE_INDEX 0
#define FTDM_WRITE_TRACE_INDEX 1
#define MAX_CALLIDS 6000
#define FTDM_HALF_DTMF_PAUSE 500
#define FTDM_FULL_DTMF_PAUSE 1000
ftdm_time_t time_last_throttle_log = 0;
ftdm_time_t time_current_throttle_log = 0;
@ -306,25 +308,13 @@ FTDM_ENUM_NAMES(CALLING_PARTY_CATEGORY_NAMES, CALLING_PARTY_CATEGORY_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_calling_party_category, ftdm_calling_party_category2str, ftdm_calling_party_category_t, CALLING_PARTY_CATEGORY_NAMES, FTDM_CPC_INVALID)
FTDM_ENUM_NAMES(INDICATION_NAMES, INDICATION_STRINGS)
FTDM_STR2ENUM(ftdm_str2channel_indication, ftdm_channel_indication2str, ftdm_channel_indication_t, INDICATION_NAMES, FTDM_CHANNEL_INDICATE_INVALID)
FTDM_STR2ENUM(ftdm_str2ftdm_channel_indication, ftdm_channel_indication2str, ftdm_channel_indication_t, INDICATION_NAMES, FTDM_CHANNEL_INDICATE_INVALID)
FTDM_ENUM_NAMES(TRANSFER_RESPONSE_NAMES, TRANSFER_RESPONSE_STRINGS)
FTDM_STR2ENUM(ftdm_str2ftdm_transfer_response, ftdm_transfer_response2str, ftdm_transfer_response_t, TRANSFER_RESPONSE_NAMES, FTDM_TRANSFER_RESPONSE_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)
{
const char *p, *ret = in;
char delims[] = "/\\";
char *i;
for (i = delims; *i; i++) {
p = in;
while ((p = strchr(p, *i)) != 0) {
ret = ++p;
}
}
return ret;
}
static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
{
if (file && func && line && level && fmt) {
@ -350,7 +340,6 @@ static int ftdm_log_level = FTDM_LOG_LEVEL_DEBUG;
static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
{
const char *fp;
char data[1024];
va_list ap;
@ -360,14 +349,11 @@ static void default_logger(const char *file, const char *func, int line, int lev
if (level > ftdm_log_level) {
return;
}
fp = cut_path(file);
va_start(ap, fmt);
vsnprintf(data, sizeof(data), fmt, ap);
fprintf(stderr, "[%s] %s:%d %s() %s", FTDM_LEVEL_NAMES[level], file, line, func, data);
va_end(ap);
@ -508,13 +494,16 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_set_caller_data(ftdm_channel_t *ftdmchan,
{
ftdm_status_t err = FTDM_SUCCESS;
if (!ftdmchan) {
ftdm_log(FTDM_LOG_CRIT, "Error: trying to set caller data, but no ftdmchan!\n");
ftdm_log(FTDM_LOG_CRIT, "trying to set caller data, but no ftdmchan!\n");
return FTDM_FAIL;
}
if ((err = ftdm_set_caller_data(ftdmchan->span, caller_data)) != FTDM_SUCCESS) {
return err;
}
ftdmchan->caller_data = *caller_data;
if (ftdmchan->caller_data.bearer_capability == FTDM_BEARER_CAP_UNRESTRICTED) {
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_DIGITAL_MEDIA);
}
return FTDM_SUCCESS;
}
@ -1207,6 +1196,10 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read_event(ftdm_channel_t *ftdmchan, ftdm
goto done;
}
if (ftdm_test_io_flag(ftdmchan, FTDM_CHANNEL_IO_EVENT)) {
ftdm_clear_io_flag(ftdmchan, FTDM_CHANNEL_IO_EVENT);
}
status = span->fio->channel_next_event(ftdmchan, event);
if (status != FTDM_SUCCESS) {
goto done;
@ -1968,6 +1961,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_set_blocking_mode(const ftdm_span_t *span, f
if (!citer) {
return FTDM_ENOMEM;
}
for (curr = citer ; curr; curr = ftdm_iterator_next(curr)) {
fchan = ftdm_iterator_current(curr);
if (enabled) {
@ -2092,12 +2086,12 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_unhold(const char *file, const char
FT_DECLARE(void) ftdm_ack_indication(ftdm_channel_t *fchan, ftdm_channel_indication_t indication, ftdm_status_t status)
{
ftdm_sigmsg_t msg;
if (!ftdm_test_flag(fchan, FTDM_CHANNEL_IND_ACK_PENDING)) {
return;
}
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Acknowledging indication %s in state %s (rc = %d)\n",
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Acknowledging indication %s in state %s (rc = %d)\n",
ftdm_channel_indication2str(indication), ftdm_channel_state2str(fchan->state), status);
ftdm_clear_flag(fchan, FTDM_CHANNEL_IND_ACK_PENDING);
memset(&msg, 0, sizeof(msg));
@ -2171,11 +2165,36 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char
return status;
}
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_transfer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, const char* arg, ftdm_usrmsg_t *usrmsg)
{
ftdm_status_t status;
ftdm_usrmsg_t *msg = NULL;
ftdm_bool_t free_msg = FTDM_FALSE;
if (!usrmsg) {
msg = ftdm_calloc(1, sizeof(*msg));
ftdm_assert_return(msg, FTDM_FAIL, "Failed to allocate usr msg");
memset(msg, 0, sizeof(*msg));
free_msg = FTDM_TRUE;
} else {
msg = usrmsg;
}
ftdm_usrmsg_add_var(msg, "transfer_arg", arg);
/* we leave the locking up to ftdm_channel_call_indicate, DO NOT lock here since ftdm_channel_call_indicate expects
* the lock recursivity to be 1 */
status = _ftdm_channel_call_indicate(file, func, line, ftdmchan, FTDM_CHANNEL_INDICATE_TRANSFER, msg);
if (free_msg == FTDM_TRUE) {
ftdm_safe_free(msg);
}
return status;
}
/* lock must be acquired by the caller! */
static ftdm_status_t _ftdm_channel_call_hangup_nl(const char *file, const char *func, int line, ftdm_channel_t *chan, ftdm_usrmsg_t *usrmsg)
{
ftdm_status_t status = FTDM_SUCCESS;
if (chan->state != FTDM_CHANNEL_STATE_DOWN) {
if (chan->state == FTDM_CHANNEL_STATE_HANGUP) {
/* make user's life easier, and just ignore double hangup requests */
@ -2367,6 +2386,14 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
case FTDM_CHANNEL_INDICATE_ANSWER:
status = _ftdm_channel_call_answer_nl(file, func, line, ftdmchan, usrmsg);
break;
case FTDM_CHANNEL_INDICATE_TRANSFER:
if (!ftdm_test_flag(ftdmchan->span, FTDM_SPAN_USE_TRANSFER)) {
ftdm_log_chan_ex_msg(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "Transfer not supported\n");
status = FTDM_EINVAL;
goto done;
}
status = ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_TRANSFER, 1, usrmsg);
break;
default:
/* See if signalling module can provide this indication */
status = ftdm_channel_sig_indicate(ftdmchan, indication, usrmsg);
@ -2628,6 +2655,7 @@ static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan)
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_MEDIA);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_ANSWERED);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_USER_HANGUP);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DIGITAL_MEDIA);
ftdm_mutex_lock(ftdmchan->pre_buffer_mutex);
ftdm_buffer_destroy(&ftdmchan->pre_buffer);
ftdmchan->pre_buffer_size = 0;
@ -2735,10 +2763,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_close(ftdm_channel_t **ftdmchan)
return status;
}
static ftdm_status_t ftdmchan_activate_dtmf_buffer(ftdm_channel_t *ftdmchan)
{
if (!ftdmchan->dtmf_buffer) {
if (ftdm_buffer_create(&ftdmchan->dtmf_buffer, 1024, 3192, 0) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Failed to allocate DTMF Buffer!\n");
@ -2767,10 +2793,29 @@ static ftdm_status_t ftdmchan_activate_dtmf_buffer(ftdm_channel_t *ftdmchan)
return FTDM_SUCCESS;
}
/*
* ftdmchan_activate_dtmf_buffer to initialize ftdmchan->dtmf_buffer should be called prior to
* calling ftdm_insert_dtmf_pause
*/
static ftdm_status_t ftdm_insert_dtmf_pause(ftdm_channel_t *ftdmchan, ftdm_size_t pausems)
{
void *data = NULL;
unsigned int datalen = pausems * sizeof(uint16_t);
data = ftdm_malloc(datalen);
ftdm_assert(data, "Failed to allocate memory\n");
memset(data, FTDM_SILENCE_VALUE(ftdmchan), datalen);
ftdm_buffer_write(ftdmchan->dtmf_buffer, data, datalen);
ftdm_safe_free(data);
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) ftdm_channel_command(ftdm_channel_t *ftdmchan, ftdm_command_t command, void *obj)
{
ftdm_status_t status = FTDM_FAIL;
ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "No channel\n");
ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "No IO attached to channel\n");
@ -3534,13 +3579,18 @@ skipdebug:
status = ftdm_buffer_write(ftdmchan->digit_buffer, dtmf, wr) ? FTDM_SUCCESS : FTDM_FAIL;
ftdm_mutex_unlock(ftdmchan->mutex);
return status;
}
static FIO_WRITE_FUNCTION(ftdm_raw_write)
FIO_WRITE_FUNCTION(ftdm_raw_write)
{
int dlen = (int) *datalen;
if (ftdm_test_io_flag(ftdmchan, FTDM_CHANNEL_IO_WRITE)) {
ftdm_clear_io_flag(ftdmchan, FTDM_CHANNEL_IO_WRITE);
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TX_DISABLED)) {
ftdmchan->txdrops++;
if (ftdmchan->txdrops <= 10) {
@ -3560,13 +3610,18 @@ static FIO_WRITE_FUNCTION(ftdm_raw_write)
return ftdmchan->fio->write(ftdmchan, data, datalen);
}
static FIO_READ_FUNCTION(ftdm_raw_read)
FIO_READ_FUNCTION(ftdm_raw_read)
{
ftdm_status_t status = ftdmchan->fio->read(ftdmchan, data, datalen);
ftdm_status_t status;
if (ftdm_test_io_flag(ftdmchan, FTDM_CHANNEL_IO_READ)) {
ftdm_clear_io_flag(ftdmchan, FTDM_CHANNEL_IO_READ);
}
status = ftdmchan->fio->read(ftdmchan, data, datalen);
if (status == FTDM_SUCCESS && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_USE_RX_GAIN)
if (status == FTDM_SUCCESS && ftdm_test_flag(ftdmchan, FTDM_CHANNEL_USE_RX_GAIN)
&& (ftdmchan->native_codec == FTDM_CODEC_ALAW || ftdmchan->native_codec == FTDM_CODEC_ULAW)) {
int i = 0;
ftdm_size_t i = 0;
unsigned char *rdata = data;
for (i = 0; i < *datalen; i++) {
rdata[i] = ftdmchan->rxgain_table[rdata[i]];
@ -3631,30 +3686,31 @@ static ftdm_status_t handle_tone_generation(ftdm_channel_t *ftdmchan)
if (ftdm_buffer_read(ftdmchan->gen_dtmf_buffer, digits, dblen) && !ftdm_strlen_zero_buf(digits)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Generating DTMF [%s]\n", digits);
cur = digits;
if (*cur == 'F') {
ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLASH, NULL);
cur++;
}
for (; *cur; cur++) {
if ((wrote = teletone_mux_tones(&ftdmchan->tone_session, &ftdmchan->tone_session.TONES[(int)*cur]))) {
ftdm_buffer_write(ftdmchan->dtmf_buffer, ftdmchan->tone_session.buffer, wrote * 2);
x++;
if (*cur == 'F') {
ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLASH, NULL);
} else if (*cur == 'w') {
ftdm_insert_dtmf_pause(ftdmchan, FTDM_HALF_DTMF_PAUSE);
} else if (*cur == 'W') {
ftdm_insert_dtmf_pause(ftdmchan, FTDM_FULL_DTMF_PAUSE);
} else {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Problem adding DTMF sequence [%s]\n", digits);
return FTDM_FAIL;
if ((wrote = teletone_mux_tones(&ftdmchan->tone_session, &ftdmchan->tone_session.TONES[(int)*cur]))) {
ftdm_buffer_write(ftdmchan->dtmf_buffer, ftdmchan->tone_session.buffer, wrote * 2);
x++;
} else {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Problem adding DTMF sequence [%s]\n", digits);
return FTDM_FAIL;
}
}
if (x) {
ftdmchan->skip_read_frames = (wrote / (ftdmchan->effective_interval * 8)) + 4;
}
}
if (x) {
ftdmchan->skip_read_frames = (wrote / (ftdmchan->effective_interval * 8)) + 4;
}
}
}
if (!ftdmchan->buffer_delay || --ftdmchan->buffer_delay == 0) {
/* time to pick a buffer, either the dtmf or fsk buffer */
@ -3714,6 +3770,7 @@ static ftdm_status_t handle_tone_generation(ftdm_channel_t *ftdmchan)
}
FT_DECLARE(void) ftdm_generate_sln_silence(int16_t *data, uint32_t samples, uint32_t divisor)
{
int16_t x;
@ -3735,51 +3792,18 @@ FT_DECLARE(void) ftdm_generate_sln_silence(int16_t *data, uint32_t samples, uint
}
}
FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen)
FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen)
{
ftdm_status_t status = FTDM_FAIL;
fio_codec_t codec_func = NULL;
ftdm_size_t max = *datalen;
ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "ftdmchan is null\n");
ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "No I/O module attached to ftdmchan\n");
ftdm_channel_lock(ftdmchan);
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "channel not open");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "cannot read from channel that is not open\n");
status = FTDM_FAIL;
goto done;
}
if (!ftdmchan->fio->read) {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "method not implemented");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "read method not implemented\n");
status = FTDM_FAIL;
goto done;
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED)) {
ftdmchan->rxdrops++;
if (ftdmchan->rxdrops <= 10) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "cannot read from channel with rx disabled\n");
}
if (ftdmchan->rxdrops == 10) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "too many rx drops, not logging anymore\n");
}
status = FTDM_FAIL;
goto done;
}
status = ftdm_raw_read(ftdmchan, data, datalen);
if (status != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "raw I/O read filed\n");
goto done;
}
handle_tone_generation(ftdmchan);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DIGITAL_MEDIA)) {
goto done;
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE) && ftdmchan->effective_codec != ftdmchan->native_codec) {
if (ftdmchan->native_codec == FTDM_CODEC_ULAW && ftdmchan->effective_codec == FTDM_CODEC_SLIN) {
codec_func = fio_ulaw2slin;
@ -3800,8 +3824,10 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data
}
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT) || ftdm_test_flag(ftdmchan, FTDM_CHANNEL_PROGRESS_DETECT) ||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT) ||
ftdm_test_flag(ftdmchan, FTDM_CHANNEL_PROGRESS_DETECT) ||
ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALLERID_DETECT)) {
uint8_t sln_buf[1024] = {0};
int16_t *sln;
ftdm_size_t slen = 0;
@ -3905,8 +3931,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data
}
}
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT) && !ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen);
teletone_dtmf_get(&ftdmchan->dtmf_detect, digit_str, sizeof(digit_str));
@ -3915,7 +3940,9 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data
if (ftdmchan->state == FTDM_CHANNEL_STATE_CALLWAITING && (*digit_str == 'D' || *digit_str == 'A')) {
ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK]++;
} else {
ftdm_channel_queue_dtmf(ftdmchan, digit_str);
if (!ftdmchan->span->sig_dtmf || (ftdmchan->span->sig_dtmf(ftdmchan, (const char*)digit_str) != FTDM_BREAK)) {
ftdm_channel_queue_dtmf(ftdmchan, digit_str);
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUPRESS_DTMF)) {
ftdmchan->skip_read_frames = 20;
@ -3926,36 +3953,81 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data
}
if (ftdmchan->skip_read_frames > 0 || ftdm_test_flag(ftdmchan, FTDM_CHANNEL_MUTE)) {
ftdm_mutex_lock(ftdmchan->pre_buffer_mutex);
if (ftdmchan->pre_buffer && ftdm_buffer_inuse(ftdmchan->pre_buffer)) {
ftdm_buffer_zero(ftdmchan->pre_buffer);
}
ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex);
memset(data, 255, *datalen);
memset(data, FTDM_SILENCE_VALUE(ftdmchan), *datalen);
if (ftdmchan->skip_read_frames > 0) {
ftdmchan->skip_read_frames--;
}
} else {
} else {
ftdm_mutex_lock(ftdmchan->pre_buffer_mutex);
if (ftdmchan->pre_buffer_size && ftdmchan->pre_buffer) {
ftdm_buffer_write(ftdmchan->pre_buffer, data, *datalen);
if (ftdm_buffer_inuse(ftdmchan->pre_buffer) >= ftdmchan->pre_buffer_size) {
ftdm_buffer_read(ftdmchan->pre_buffer, data, *datalen);
} else {
memset(data, 255, *datalen);
memset(data, FTDM_SILENCE_VALUE(ftdmchan), *datalen);
}
}
ftdm_mutex_unlock(ftdmchan->pre_buffer_mutex);
}
done:
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen)
{
ftdm_status_t status = FTDM_FAIL;
ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "ftdmchan is null\n");
ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "No I/O module attached to ftdmchan\n");
ftdm_channel_lock(ftdmchan);
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "cannot read from channel that is not open\n");
status = FTDM_FAIL;
goto done;
}
if (!ftdmchan->fio->read) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "read method not implemented\n");
status = FTDM_FAIL;
goto done;
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED)) {
ftdmchan->rxdrops++;
if (ftdmchan->rxdrops <= 10) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "cannot read from channel with rx disabled\n");
}
if (ftdmchan->rxdrops == 10) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "too many rx drops, not logging anymore\n");
}
status = FTDM_FAIL;
goto done;
}
status = ftdm_raw_read(ftdmchan, data, datalen);
if (status != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "raw I/O read filed\n");
goto done;
}
status = ftdm_channel_process_media(ftdmchan, data, datalen);
if (status != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to process media\n");
}
done:
ftdm_channel_unlock(ftdmchan);
return status;
}
@ -3983,17 +4055,19 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "cannot write in channel not open\n");
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "channel not open");
status = FTDM_FAIL;
goto done;
}
if (!ftdmchan->fio->write) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "write method not implemented\n");
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "method not implemented");
status = FTDM_FAIL;
goto done;
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DIGITAL_MEDIA)) {
goto do_write;
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_TRANSCODE) && ftdmchan->effective_codec != ftdmchan->native_codec) {
if (ftdmchan->native_codec == FTDM_CODEC_ULAW && ftdmchan->effective_codec == FTDM_CODEC_SLIN) {
@ -4010,8 +4084,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat
status = codec_func(data, max, datalen);
} else {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Do not know how to handle transcoding from %d to %d\n",
ftdmchan->effective_codec, ftdmchan->native_codec);
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!");
ftdmchan->effective_codec, ftdmchan->native_codec);
status = FTDM_FAIL;
goto done;
}
@ -4025,6 +4098,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat
}
}
do_write:
if (ftdmchan->span->sig_write) {
status = ftdmchan->span->sig_write(ftdmchan, data, *datalen);
if (status == FTDM_BREAK) {
@ -5374,10 +5449,12 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED);
ftdm_call_set_call_id(sigmsg->channel, &sigmsg->channel->caller_data);
/* when cleaning up the public API I added this because mod_freetdm.c on_fxs_signal was
* doing it during SIGEVENT_START, but now that flags are private they can't, wonder if
* is needed at all?
* */
* doing it during SIGEVENT_START, but now that flags are private they can't, wonder if
* is needed at all? */
ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_HOLD);
if (sigmsg->channel->caller_data.bearer_capability == FTDM_BEARER_CAP_UNRESTRICTED) {
ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_DIGITAL_MEDIA);
}
}
break;

View File

@ -426,7 +426,6 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = analog_data->wait_dialtone_timeout;
uint32_t answer_on_polarity_counter = 0;
ftdm_sigmsg_t sig;
ftdm_status_t status;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "ANALOG CHANNEL thread starting.\n");
@ -916,7 +915,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
}
if (codec_func) {
status = codec_func(frame, sizeof(frame), &rlen);
codec_func(frame, sizeof(frame), &rlen);
} else {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!");
goto done;

View File

@ -221,7 +221,6 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
ftdm_channel_t *closed_chan;
uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = 30000;
ftdm_sigmsg_t sig;
ftdm_status_t status;
ftdm_log(FTDM_LOG_DEBUG, "ANALOG EM CHANNEL thread starting.\n");
@ -545,7 +544,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
}
if (codec_func) {
status = codec_func(frame, sizeof(frame), &rlen);
codec_func(frame, sizeof(frame), &rlen);
} else {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!");
goto done;

View File

@ -979,7 +979,6 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
{
Q931ie_CallingNum *callingnum = Q931GetIEPtr(gen->CallingNum, gen->buf);
Q931ie_CalledNum *callednum = Q931GetIEPtr(gen->CalledNum, gen->buf);
uint32_t cplen = mlen;
int overlap_dial = 0;
int fail_cause = 0;
int fail = 1;
@ -2128,7 +2127,7 @@ static int ftdm_isdn_q921_log(void *pvt, Q921LogLevel_t level, char *msg, L2INT
return 0;
}
static L3INT ftdm_isdn_q931_log(void *pvt, Q931LogLevel_t level, char *msg, L3INT size)
static L3INT ftdm_isdn_q931_log(void *pvt, Q931LogLevel_t level, const char *msg, L3INT size)
{
ftdm_span_t *span = (ftdm_span_t *) pvt;

View File

@ -562,14 +562,18 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
sig.chan_id = ftdm_channel_get_id(chan);
sig.span_id = ftdm_channel_get_span_id(chan);
sig.channel = chan;
ftdm_channel_complete_state(chan);
switch (ftdm_channel_get_state(chan)) {
case FTDM_CHANNEL_STATE_DOWN:
{
ftdm_channel_t *chtmp = chan;
chan->call_data = NULL;
if (call) {
pri_destroycall(isdn_data->spri.pri, call);
chan->call_data = NULL;
}
if (ftdm_channel_close(&chtmp) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_WARNING, "-- Failed to close channel %d:%d\n",
@ -776,8 +780,7 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
pri_hangup(isdn_data->spri.pri, call, caller_data->hangup_cause);
// pri_destroycall(isdn_data->spri.pri, call);
chan->call_data = NULL;
// chan->call_data = NULL;
}
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
}
@ -785,10 +788,10 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
{
if (call) {
pri_destroycall(isdn_data->spri.pri, call);
chan->call_data = NULL;
}
// if (call) {
// pri_destroycall(isdn_data->spri.pri, call);
// chan->call_data = NULL;
// }
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_DOWN);
}
break;
@ -854,7 +857,6 @@ static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even
{
ftdm_span_t *span = spri->span;
ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->hangup.channel);
q931_call *call = NULL;
if (!chan) {
ftdm_log(FTDM_LOG_CRIT, "-- Hangup on channel %d:%d %s but it's not in use?\n", ftdm_span_get_id(spri->span), pevent->hangup.channel);
@ -863,27 +865,61 @@ static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even
ftdm_channel_lock(chan);
if (ftdm_channel_get_state(chan) >= FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Ignoring remote hangup in state %s\n", ftdm_channel_get_state_str(chan));
goto done;
switch (event_type) {
case LPWRAP_PRI_EVENT_HANGUP_REQ: /* DISCONNECT */
if (ftdm_channel_get_state(chan) >= FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Ignoring remote hangup in state %s\n",
ftdm_channel_get_state_str(chan));
goto done;
}
ftdm_log(FTDM_LOG_DEBUG, "-- Hangup REQ on channel %d:%d\n",
ftdm_span_get_id(spri->span), pevent->hangup.channel);
pri_hangup(spri->pri, pevent->hangup.call, pevent->hangup.cause);
chan->caller_data.hangup_cause = pevent->hangup.cause;
ftdm_set_state(chan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case LPWRAP_PRI_EVENT_HANGUP_ACK: /* */
ftdm_log(FTDM_LOG_DEBUG, "-- Hangup ACK on channel %d:%d\n",
ftdm_span_get_id(spri->span), pevent->hangup.channel);
pri_hangup(spri->pri, pevent->hangup.call, pevent->hangup.cause);
ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
break;
case LPWRAP_PRI_EVENT_HANGUP: /* "RELEASE/RELEASE_COMPLETE/other" */
ftdm_log(FTDM_LOG_DEBUG, "-- Hangup on channel %d:%d\n",
ftdm_span_get_id(spri->span), pevent->hangup.channel);
switch (ftdm_channel_get_state(chan)) {
case FTDM_CHANNEL_STATE_DIALING:
case FTDM_CHANNEL_STATE_RINGING:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_UP:
chan->caller_data.hangup_cause = pevent->hangup.cause;
ftdm_set_state(chan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case FTDM_CHANNEL_STATE_HANGUP:
chan->caller_data.hangup_cause = pevent->hangup.cause;
ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
break;
// case FTDM_CHANNEL_STATE_TERMINATING:
// ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP);
// break;
// case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
// ftdm_set_state(chan, FTDM_CHANNEL_STATE_DOWN);
// break;
}
break;
default:
break;
}
if (!chan->call_data) {
ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Ignoring remote hangup in state %s with no call data\n", ftdm_channel_get_state_str(chan));
goto done;
}
call = (q931_call *)chan->call_data;
ftdm_log(FTDM_LOG_DEBUG, "-- Hangup on channel %d:%d\n", ftdm_span_get_id(spri->span), pevent->hangup.channel);
pri_release(spri->pri, call, 0);
pri_destroycall(spri->pri, call);
chan->caller_data.hangup_cause = pevent->hangup.cause;
chan->call_data = NULL;
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING);
done:
ftdm_channel_unlock(chan);
return 0;
@ -1654,6 +1690,7 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_UP, on_dchan_up);
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_DOWN, on_dchan_down);
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP_REQ, on_hangup);
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP_ACK, on_hangup);
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP, on_hangup);
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_INFO_RECEIVED, on_info);
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RESTART, on_restart);
@ -1928,6 +1965,10 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
assert(isdn_data != NULL);
memset(isdn_data, 0, sizeof(*isdn_data));
/* set some default values */
isdn_data->mode = PRI_CPE;
isdn_data->ton = PRI_UNKNOWN;
switch (ftdm_span_get_trunk_type(span)) {
case FTDM_TRUNK_BRI:
case FTDM_TRUNK_BRI_PTMP:
@ -1938,12 +1979,14 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
#endif
case FTDM_TRUNK_E1:
ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ALAW since this is an E1/BRI/BRI PTMP trunk\n");
isdn_data->layer1 = PRI_LAYER_1_ALAW;
isdn_data->layer1 = PRI_LAYER_1_ALAW;
isdn_data->dialect = PRI_SWITCH_EUROISDN_E1;
break;
case FTDM_TRUNK_T1:
case FTDM_TRUNK_J1:
ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ULAW since this is a T1/J1 trunk\n");
isdn_data->layer1 = PRI_LAYER_1_ULAW;
isdn_data->layer1 = PRI_LAYER_1_ULAW;
isdn_data->dialect = PRI_SWITCH_LUCENT5E;
break;
default:
ftdm_log(FTDM_LOG_ERROR, "Invalid trunk type: '%s'\n", ftdm_span_get_trunk_type_str(span));

View File

@ -44,6 +44,7 @@
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);
static ftdm_status_t ftdm_sangoma_isdn_dtmf(ftdm_channel_t *ftdmchan, const char* dtmf);
ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event);
static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span);
@ -53,10 +54,13 @@ static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_ev
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 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_ENUM_NAMES(SNGISDN_TRANSFER_TYPE_NAMES, SNGISDN_TRANSFER_TYPE_STRINGS)
FTDM_STR2ENUM(ftdm_str2sngisdn_transfer_type, sngisdn_transfer_type2str, sngisdn_transfer_type_t, SNGISDN_TRANSFER_TYPE_NAMES, SNGISDN_TRANSFER_INVALID)
ftdm_state_map_t sangoma_isdn_state_map = {
{
@ -126,8 +130,7 @@ ftdm_state_map_t sangoma_isdn_state_map = {
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}
{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_CHANNEL_STATE_TRANSFER, FTDM_END}
},
{
ZSD_INBOUND,
@ -151,7 +154,14 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_UP, FTDM_END},
{FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
{FTDM_CHANNEL_STATE_TRANSFER, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
},
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_TRANSFER, FTDM_END},
{FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_TERMINATING,FTDM_END},
},
{
ZSD_INBOUND,
@ -352,49 +362,96 @@ static void ftdm_sangoma_isdn_wakeup_phy(ftdm_channel_t *dchan)
return;
}
static void *ftdm_sangoma_isdn_dchan_run(ftdm_thread_t *me, void *obj)
static void *ftdm_sangoma_isdn_io_run(ftdm_thread_t *me, void *obj)
{
uint8_t data[1000];
unsigned i;
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_channel_t *ftdmchan = NULL;
unsigned waitms = 10000;
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *citer = NULL;
short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count);
/* Initialize the d-channel */
ftdm_assert(((sngisdn_span_data_t*)span->signal_data)->dchan, "Span does not have a dchannel");
ftdm_channel_set_feature(((sngisdn_span_data_t*)span->signal_data)->dchan, FTDM_CHANNEL_FEATURE_IO_STATS);
ftdm_sangoma_isdn_dchan_set_queue_size(((sngisdn_span_data_t*)span->signal_data)->dchan);
ftdm_channel_open_chan(((sngisdn_span_data_t*)span->signal_data)->dchan);
chaniter = ftdm_span_get_chan_iterator(span, NULL);
if (!chaniter) {
ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
goto done;
}
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))) {
len = 1000;
waitms = 1000;
wflags = FTDM_READ;
status = ftdm_channel_wait(dchan, &wflags, 10000);
switch(status) {
memset(poll_events, 0, sizeof(short)*span->chan_count);
for (i = 0, citer = ftdm_span_get_chan_iterator(span, chaniter); citer; citer = ftdm_iterator_next(citer), i++) {
ftdmchan = ftdm_iterator_current(citer);
if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED)) {
poll_events[i] |= FTDM_READ;
waitms = 20;
}
} else {
/* We always read the d-channel */
poll_events[i] |= FTDM_READ;
}
}
status = ftdm_span_poll_event(span, waitms, poll_events);
switch (status) {
case FTDM_FAIL:
ftdm_log_chan_msg(dchan, FTDM_LOG_CRIT, "Failed to wait for d-channel\n");
ftdm_log(FTDM_LOG_CRIT, "Failed to poll span for IO\n");
break;
case FTDM_TIMEOUT:
break;
case FTDM_SUCCESS:
if ((wflags & FTDM_READ)) {
for (citer = ftdm_span_get_chan_iterator(span, chaniter); citer; citer = ftdm_iterator_next(citer)) {
len = 1000;
status = ftdm_channel_read(dchan, data, &len);
if (status == FTDM_SUCCESS) {
sngisdn_snd_data(dchan, data, len);
ftdmchan = ftdm_iterator_current(citer);
if (FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED)) {
if (ftdm_test_io_flag(ftdmchan, FTDM_CHANNEL_IO_READ)) {
status = ftdm_raw_read(ftdmchan, data, &len);
if (status != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "raw I/O read failed\n");
continue;
}
status = ftdm_channel_process_media(ftdmchan, data, &len);
if (status != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to process media\n");
continue;
}
}
}
} else {
ftdm_log_chan_msg(dchan, FTDM_LOG_WARNING, "Failed to read from channel \n");
if (ftdm_test_io_flag(ftdmchan, FTDM_CHANNEL_IO_READ)) {
status = ftdm_channel_read(ftdmchan, data, &len);
if (status == FTDM_SUCCESS) {
sngisdn_snd_data(ftdmchan, data, len);
}
}
}
#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_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Unhandled IO event\n");
}
}
}
done:
ftdm_iterator_free(chaniter);
ftdm_safe_free(poll_events);
return NULL;
}
@ -600,10 +657,10 @@ static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_ev
/* this function is called with the channel already locked by the core */
static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
{
ftdm_sigmsg_t sigev;
ftdm_channel_state_t initial_state;
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
uint8_t state_change = 0;
ftdm_sigmsg_t sigev;
ftdm_channel_state_t initial_state;
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
uint8_t state_change = 0;
memset(&sigev, 0, sizeof(sigev));
@ -632,18 +689,15 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm
break;
case FTDM_CHANNEL_STATE_GET_CALLERID:
{
if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
/* By default, we do not send a progress indicator in the proceed */
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID};
sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
sngisdn_snd_proceed(ftdmchan, prog_ind);
}
/* Wait in this state until we get FACILITY msg */
/* By default, we do not send a progress indicator in the proceed */
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID};
sngisdn_snd_proceed(ftdmchan, prog_ind);
/* 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*/
@ -678,13 +732,8 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
}
} else {
if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
/* By default, we do not send a progress indicator in the proceed */
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID};
sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
sngisdn_snd_proceed(ftdmchan, prog_ind);
}
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_INVALID};
sngisdn_snd_proceed(ftdmchan, prog_ind);
}
}
break;
@ -846,7 +895,6 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm
ftdm_channel_close(&close_chan);
}
if (glare) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Glare detected, processing saved call\n");
/* We are calling sngisdn_rcv_con_ind with ftdmchan->mutex being locked,
so no other threads will be able to touch this channel. The next time we will
@ -856,11 +904,17 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm
}
}
break;
case FTDM_CHANNEL_STATE_TRANSFER:
{
/* sngisdn_transfer function will always result in a state change */
sngisdn_transfer(ftdmchan);
state_change++;
}
break;
case FTDM_CHANNEL_STATE_RESTART:
{
/* IMPLEMENT ME */
}
break;
case FTDM_CHANNEL_STATE_SUSPENDED:
{
@ -984,6 +1038,21 @@ static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_span_sig_status)
return FTDM_NOTIMPL;
}
static ftdm_status_t ftdm_sangoma_isdn_dtmf(ftdm_channel_t *ftdmchan, const char* dtmf)
{
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
switch(sngisdn_info->transfer_data.type) {
case SNGISDN_TRANSFER_ATT_COURTESY_VRU:
case SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA:
return sngisdn_att_transfer_process_dtmf(ftdmchan, dtmf);
default:
/* We do not care about DTMF events, do nothing */
break;
}
return FTDM_SUCCESS;
}
static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
{
sngisdn_span_data_t *signal_data = span->signal_data;
@ -992,6 +1061,7 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name);
return FTDM_FAIL;
}
/* clear the monitor thread stop flag */
ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD);
ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
@ -1015,7 +1085,7 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
}
/*start the dchan monitor thread*/
if (ftdm_thread_create_detached(ftdm_sangoma_isdn_dchan_run, span) != FTDM_SUCCESS) {
if (ftdm_thread_create_detached(ftdm_sangoma_isdn_io_run, span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT,"Failed to start Sangoma ISDN d-channel Monitor Thread!\n");
return FTDM_FAIL;
}
@ -1106,6 +1176,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
span->indicate = ftdm_sangoma_isdn_indicate;
span->channel_request = NULL;
span->signal_cb = sig_cb;
span->sig_dtmf = ftdm_sangoma_isdn_dtmf;
span->get_channel_sig_status = ftdm_sangoma_isdn_get_chan_sig_status;
span->set_channel_sig_status = ftdm_sangoma_isdn_set_chan_sig_status;
span->get_span_sig_status = ftdm_sangoma_isdn_get_span_sig_status;
@ -1117,10 +1188,9 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE);
ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES);
ftdm_set_flag(span, FTDM_SPAN_NON_STOPPABLE);
ftdm_set_flag(span, FTDM_SPAN_USE_TRANSFER);
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
span->trunk_type == FTDM_TRUNK_BRI) {
if (FTDM_SPAN_IS_BRI(span)) {
sngisdn_set_span_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
}
@ -1156,10 +1226,9 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init)
g_sngisdn_event_interface.cc.sng_fac_ind = sngisdn_rcv_fac_ind;
g_sngisdn_event_interface.cc.sng_sta_cfm = sngisdn_rcv_sta_cfm;
g_sngisdn_event_interface.cc.sng_srv_ind = sngisdn_rcv_srv_ind;
g_sngisdn_event_interface.cc.sng_srv_ind = sngisdn_rcv_srv_cfm;
g_sngisdn_event_interface.cc.sng_rst_ind = sngisdn_rcv_rst_cfm;
g_sngisdn_event_interface.cc.sng_srv_cfm = sngisdn_rcv_srv_cfm;
g_sngisdn_event_interface.cc.sng_rst_ind = sngisdn_rcv_rst_ind;
g_sngisdn_event_interface.cc.sng_rst_cfm = sngisdn_rcv_rst_cfm;
g_sngisdn_event_interface.cc.sng_rst_cfm = sngisdn_rcv_rst_cfm;
g_sngisdn_event_interface.lg.sng_log = sngisdn_rcv_sng_log;
g_sngisdn_event_interface.lg.sng_assert = sngisdn_rcv_sng_assert;
@ -1199,9 +1268,17 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_isdn_unload)
return FTDM_SUCCESS;
}
#define SANGOMA_ISDN_API_USAGE_TRACE "ftdm sangoma_isdn trace <q921|q931> <span name>\n"
#define SANGOMA_ISDN_API_USAGE_SHOW_L1_STATS "ftdm sangoma_isdn l1_stats <span name>\n"
#define SANGOMA_ISDN_API_USAGE_SHOW_SPANS "ftdm sangoma_isdn show_spans [<span name>]\n"
#define SANGOMA_ISDN_API_USAGE "\t"SANGOMA_ISDN_API_USAGE_TRACE \
"\t"SANGOMA_ISDN_API_USAGE_SHOW_L1_STATS \
"\t"SANGOMA_ISDN_API_USAGE_SHOW_SPANS
static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
{
ftdm_status_t status = FTDM_SUCCESS;
ftdm_status_t status = FTDM_EINVAL;
char *mycmd = NULL, *argv[10] = { 0 };
int argc = 0;
@ -1223,7 +1300,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
ftdm_span_t *span;
if (argc < 3) {
ftdm_log(FTDM_LOG_ERROR, "Usage: ftdm sangoma_isdn trace <q921|q931> <span name>\n");
ftdm_log(FTDM_LOG_ERROR, "Usage: %s\n", SANGOMA_ISDN_API_USAGE_TRACE);
status = FTDM_FAIL;
goto done;
}
@ -1232,34 +1309,40 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
status = ftdm_span_find_by_name(argv[2], &span);
if (FTDM_SUCCESS != status) {
stream->write_function(stream, "-ERR failed to find span by name %s\n", argv[2]);
status = FTDM_FAIL;
goto done;
}
if (!strcasecmp(trace_opt, "q921")) {
sngisdn_activate_trace(span, SNGISDN_TRACE_Q921);
status = sngisdn_activate_trace(span, SNGISDN_TRACE_Q921);
} else if (!strcasecmp(trace_opt, "q931")) {
sngisdn_activate_trace(span, SNGISDN_TRACE_Q931);
status = sngisdn_activate_trace(span, SNGISDN_TRACE_Q931);
} else if (!strcasecmp(trace_opt, "disable")) {
sngisdn_activate_trace(span, SNGISDN_TRACE_DISABLE);
status = sngisdn_activate_trace(span, SNGISDN_TRACE_DISABLE);
} else {
stream->write_function(stream, "-ERR invalid trace option <q921|q931> <span name>\n");
status = FTDM_FAIL;
}
goto done;
}
if (!strcasecmp(argv[0], "l1_stats")) {
ftdm_span_t *span;
if (argc < 2) {
stream->write_function(stream, "Usage: ftdm sangoma_isdn l1_stats <span name>\n");
stream->write_function(stream, "Usage: %s\n", SANGOMA_ISDN_API_USAGE_SHOW_L1_STATS);
status = FTDM_FAIL;
goto done;
}
status = ftdm_span_find_by_name(argv[1], &span);
if (FTDM_SUCCESS != status) {
stream->write_function(stream, "-ERR failed to find span with name %s\n", argv[1]);
/* Return SUCCESS because we do not want to print the general FTDM usage list */
status = FTDM_SUCCESS;
status = FTDM_FAIL;
goto done;
}
sngisdn_print_phy_stats(stream, span);
status = sngisdn_show_l1_stats(stream, span);
goto done;
}
if (!strcasecmp(argv[0], "show_spans")) {
@ -1268,24 +1351,47 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
status = ftdm_span_find_by_name(argv[1], &span);
if (FTDM_SUCCESS != status) {
stream->write_function(stream, "-ERR failed to find span with name %s\n", argv[1]);
/* Return SUCCESS because we do not want to print the general FTDM usage list */
status = FTDM_SUCCESS;
stream->write_function(stream, "Usage: %s\n", SANGOMA_ISDN_API_USAGE_SHOW_SPANS);
status = FTDM_FAIL;
goto done;
}
sngisdn_print_span(stream, span);
status = FTDM_SUCCESS;
status = sngisdn_show_span(stream, span);
goto done;
}
sngisdn_print_spans(stream);
status = sngisdn_show_spans(stream);
goto done;
}
if (!strcasecmp(argv[0], "check_ids")) {
sngisdn_check_free_ids();
status = sngisdn_check_free_ids();
goto done;
}
if (!strcasecmp(argv[0], "check_mem")) {
sngisdn_get_memory_info();
}
done:
switch (status) {
case FTDM_SUCCESS:
stream->write_function(stream, "Command executed OK\n");
break;
case FTDM_EINVAL:
stream->write_function(stream, "Invalid arguments [%s]\n", mycmd);
stream->write_function(stream, "Usage:\n%s\n", SANGOMA_ISDN_API_USAGE);
break;
default:
/* FTDM_FAIL - Do nothing since we already printed the cause of the error */
break;
}
/* Return SUCCESS because we do not want to print the general FTDM usage list */
status = FTDM_SUCCESS;
ftdm_safe_free(mycmd);
return status;
}
static FIO_IO_LOAD_FUNCTION(ftdm_sangoma_isdn_io_init)
{
memset(&g_sngisdn_io_interface, 0, sizeof(g_sngisdn_io_interface));

View File

@ -82,6 +82,8 @@ typedef enum {
FLAG_MEDIA_READY = (1 << 11),
/* Set when we already sent a Channel ID IE */
FLAG_SENT_CHAN_ID = (1 << 12),
/* Set when we already sent a Connect */
FLAG_SENT_CONNECT = (1 << 13),
} sngisdn_flag_t;
@ -152,10 +154,11 @@ typedef struct ftdm_sngisdn_prog_ind {
} ftdm_sngisdn_progind_t;
/* Only timers that can be cancelled are listed here */
#define SNGISDN_NUM_TIMERS 1
#define SNGISDN_NUM_TIMERS 2
/* Increase NUM_TIMERS as number of ftdm_sngisdn_timer_t increases */
typedef enum {
SNGISDN_TIMER_FACILITY = 0,
SNGISDN_TIMER_ATT_TRANSFER,
} ftdm_sngisdn_timer_t;
typedef struct sngisdn_glare_data {
@ -165,8 +168,35 @@ typedef struct sngisdn_glare_data {
int16_t dChan;
ConEvnt setup;
uint8_t ces;
}sngisdn_glare_data_t;
} sngisdn_glare_data_t;
typedef enum {
SNGISDN_TRANSFER_NONE = 0, /* Default value, no transfer being done */
SNGISDN_TRANSFER_ATT_COURTESY_VRU,
SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA,
SNGISDN_TRANSFER_INVALID,
} sngisdn_transfer_type_t;
#define SNGISDN_TRANSFER_TYPE_STRINGS "NONE", "ATT_COURTESY_VRU", "ATT_COURTERY_VRU_DATA", "INVALID"
FTDM_STR2ENUM_P(ftdm_str2sngisdn_transfer_type, sngisdn_transfer_type2str, sngisdn_transfer_type_t)
/* From section 4.2 of TR50075, max length of data is 100 when single UUI is sent */
#define COURTESY_TRANSFER_MAX_DATA_SIZE 100
typedef struct _att_courtesy_vru
{
char dtmf_digits [20];
char data[COURTESY_TRANSFER_MAX_DATA_SIZE];
} att_courtesy_vru_t;
typedef struct _sngisdn_transfer_data
{
sngisdn_transfer_type_t type; /* Specifies which type of transfer is being used */
ftdm_transfer_response_t response;
union
{
att_courtesy_vru_t att_courtesy_vru;
} tdata;
} sngisdn_transfer_data_t;
/* Channel specific data */
typedef struct sngisdn_chan_data {
@ -180,7 +210,8 @@ typedef struct sngisdn_chan_data {
uint8_t globalFlg;
sngisdn_glare_data_t glare;
ftdm_timer_id_t timers[SNGISDN_NUM_TIMERS];
ftdm_timer_id_t timers[SNGISDN_NUM_TIMERS];
sngisdn_transfer_data_t transfer_data;
/* variables saved here will be sent to the user application
on next SIGEVENT_XXX */
@ -211,8 +242,10 @@ typedef struct sngisdn_span_data {
uint8_t facility_ie_decode;
uint8_t facility;
int8_t facility_timeout;
uint8_t att_remove_dtmf;
int32_t transfer_timeout;
uint8_t num_local_numbers;
uint8_t ignore_cause_value;
uint8_t ignore_cause_value;
uint8_t trace_q931; /* TODO: combine with trace_flags */
uint8_t trace_q921; /* TODO: combine with trace_flags */
uint8_t raw_trace_q931; /* TODO: combine with trace_flags */
@ -292,6 +325,12 @@ typedef struct ftdm_sngisdn_data {
sngisdn_span_data_t *spans[MAX_L1_LINKS+1]; /* spans are indexed by link_id */
}ftdm_sngisdn_data_t;
typedef struct ftdm2trillium
{
uint8_t ftdm_val;
uint8_t trillium_val;
}ftdm2trillium_t;
/* TODO implement these 2 functions */
#define ISDN_FUNC_TRACE_ENTER(a)
@ -388,7 +427,7 @@ void sngisdn_trace_interpreted_q931(sngisdn_span_data_t *signal_data, ftdm_trace
void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
void get_memory_info(void);
void sngisdn_get_memory_info(void);
ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
ftdm_status_t sngisdn_check_free_ids(void);
@ -426,18 +465,23 @@ ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId);
ftdm_status_t set_restart_ind_ie(ftdm_channel_t *ftdmchan, RstInd *rstInd);
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, uint8_t *data_len);
ftdm_status_t set_user_to_user_ie(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr);
ftdm_status_t set_cause_ie(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn);
ftdm_status_t sngisdn_add_var(sngisdn_chan_data_t *sngisdn_info, const char* var, const char* val);
ftdm_status_t sngisdn_add_raw_data(sngisdn_chan_data_t *sngisdn_info, uint8_t* data, ftdm_size_t data_len);
ftdm_status_t sngisdn_clear_data(sngisdn_chan_data_t *sngisdn_info);
void sngisdn_send_signal(sngisdn_chan_data_t *sngisdn_info, ftdm_signal_event_t event_id);
uint8_t sngisdn_get_infoTranCap_from_user(ftdm_bearer_cap_t bearer_capability);
uint8_t sngisdn_get_usrInfoLyr1Prot_from_user(ftdm_user_layer1_prot_t layer1_prot);
ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_stack(uint8_t bearer_capability);
ftdm_user_layer1_prot_t sngisdn_get_usrInfoLyr1Prot_from_stack(uint8_t layer1_prot);
ftdm_status_t sngisdn_transfer(ftdm_channel_t *ftdmchan);
ftdm_status_t sngisdn_att_transfer_process_dtmf(ftdm_channel_t *ftdmchan, const char* dtmf);
static __inline__ uint32_t sngisdn_test_flag(sngisdn_chan_data_t *sngisdn_info, sngisdn_flag_t flag)
{
return (uint32_t) sngisdn_info->flags & flag;
@ -471,9 +515,9 @@ 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);
void sngisdn_print_span(ftdm_stream_handle_t *stream, ftdm_span_t *span);
ftdm_status_t sngisdn_show_l1_stats(ftdm_stream_handle_t *stream, ftdm_span_t *span);
ftdm_status_t sngisdn_show_spans(ftdm_stream_handle_t *stream);
ftdm_status_t sngisdn_show_span(ftdm_stream_handle_t *stream, ftdm_span_t *span);
#endif /* __FTMOD_SNG_ISDN_H__ */

View File

@ -285,7 +285,9 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
signal_data->timer_t3 = 8;
signal_data->restart_opt = SNGISDN_OPT_DEFAULT;
signal_data->link_id = span->span_id;
signal_data->transfer_timeout = 20000;
signal_data->att_remove_dtmf = 1;
span->default_caller_data.dnis.plan = FTDM_NPI_INVALID;
span->default_caller_data.dnis.type = FTDM_TON_INVALID;
span->default_caller_data.cid_num.plan = FTDM_NPI_INVALID;
@ -365,6 +367,13 @@ 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, "transfer-timeout")) {
signal_data->transfer_timeout = atoi(val);
if (signal_data->transfer_timeout < 0) {
signal_data->transfer_timeout = 0;
}
} else if (!strcasecmp(var, "att-remove-dtmf")) {
parse_yesno(var, val, &signal_data->att_remove_dtmf);
} else if (!strcasecmp(var, "facility-ie-decode")) {
parse_yesno(var, val, &signal_data->facility_ie_decode);
} else if (!strcasecmp(var, "ignore-cause-value")) {

View File

@ -745,8 +745,16 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
/* TODO: Fill in these timers with proper values - eventually pass them */
cfg.t.cfg.s.inDLSAP.tmr.t301.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t301.val = 180;
cfg.t.cfg.s.inDLSAP.tmr.t302.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t302.val = 15;
/* It looks like ETSI is the only variant that supports Overlap */
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) {
cfg.t.cfg.s.inDLSAP.tmr.t302.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t302.val = 15;
} else {
cfg.t.cfg.s.inDLSAP.tmr.t302.enb = FALSE;
cfg.t.cfg.s.inDLSAP.tmr.t302.val = 0;
}
cfg.t.cfg.s.inDLSAP.tmr.t303.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t303.val = 4;
cfg.t.cfg.s.inDLSAP.tmr.t304.enb = TRUE;

View File

@ -35,6 +35,7 @@
#include "ftmod_sangoma_isdn.h"
static ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn);
static void sngisdn_process_restart_confirm(ftdm_channel_t *ftdmchan);
static ftdm_status_t sngisdn_force_down(ftdm_channel_t *ftdmchan);
/* Remote side transmit a SETUP */
void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
@ -191,8 +192,7 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
}
}
#endif
#endif
if (signal_data->overlap_dial == SNGISDN_OPT_TRUE && !conEvnt->sndCmplt.eh.pres) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
} else {
@ -318,8 +318,9 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
}
} else {
switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_TRANSFER:
case FTDM_CHANNEL_STATE_UP:
/* This is the only valid state we should get a CONNECT ACK on */
/* These are the only valid states we should get a CONNECT ACK on */
/* do nothing */
break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
@ -831,7 +832,7 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
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 {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to retrieve Caller Name from Facility IE\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Failed to retrieve Caller Name from Facility IE\n");
}
if (signal_data->facility_timeout) {
/* Cancel facility timeout */
@ -920,36 +921,8 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
switch(call_state) {
/* Sere ITU-T Q931 for definition of call states */
case 0: /* Remote switch thinks there are no calls on this channel */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_COLLECT:
case FTDM_CHANNEL_STATE_DIALING:
case FTDM_CHANNEL_STATE_UP:
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case FTDM_CHANNEL_STATE_TERMINATING:
/* We are in the process of clearing local states,
just make sure we will not send any messages to remote switch */
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
break;
case FTDM_CHANNEL_STATE_HANGUP:
/* This cannot happen, state_advance always sets
ftdmchan to STATE_HANGUP_COMPLETE when in STATE_HANGUP
and we called check_for_state_change earlier so something is very wrong here!!! */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "How can we we in FTDM_CHANNEL_STATE_HANGUP after checking for state change?\n");
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* We were waiting for remote switch to send RELEASE COMPLETE
but this will not happen, so just clear local state */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
break;
case FTDM_CHANNEL_STATE_DOWN:
/* If our local state is down as well, then there is nothing to do */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
break;
if (sngisdn_force_down(ftdmchan) != FTDM_SUCCESS) {
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
}
break;
case 1:
@ -1159,6 +1132,48 @@ static void sngisdn_process_restart_confirm(ftdm_channel_t *ftdmchan)
return;
}
static ftdm_status_t sngisdn_force_down(ftdm_channel_t *ftdmchan)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data;
ftdm_status_t status = FTDM_SUCCESS;
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Forcing channel to DOWN state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_DOWN:
/* Do nothing */
break;
case FTDM_CHANNEL_STATE_RESET:
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
break;
case FTDM_CHANNEL_STATE_COLLECT:
case FTDM_CHANNEL_STATE_DIALING:
case FTDM_CHANNEL_STATE_UP:
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case FTDM_CHANNEL_STATE_TERMINATING:
/* We are already waiting for usr to respond to SIGEVENT stop.
FreeTDM already scheduled a timout in case the User does respond to
SIGEVENT_STOP, no need to do anything here */
break;
case FTDM_CHANNEL_STATE_HANGUP:
/* This cannot happen, state_advance always sets
ftdmchan to STATE_HANGUP_COMPLETE when in STATE_HANGUP
and we called check_for_state_change earlier so something is very wrong here!!! */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "How can we we in FTDM_CHANNEL_STATE_HANGUP after checking for state change?\n");
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* We were waiting for remote switch to send RELEASE COMPLETE
but this will not happen, so just clear local state */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
break;
default:
status = FTDM_FAIL;
}
return status;
}
void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
{
@ -1171,12 +1186,12 @@ void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
sngisdn_span_data_t *signal_data = g_sngisdn_data.dchans[dChan].spans[1];
if (!signal_data) {
ftdm_log(FTDM_LOG_CRIT, "Received RESTART on unconfigured span (suId:%d)\n", suId);
ftdm_log(FTDM_LOG_CRIT, "Received RESTART CFM on unconfigured span (suId:%d)\n", suId);
return;
}
if (!rstEvnt->rstInd.eh.pres || !rstEvnt->rstInd.rstClass.pres) {
ftdm_log(FTDM_LOG_DEBUG, "Receved RESTART, but Restart Indicator IE not present\n");
if (rstEvnt->rstInd.eh.pres != PRSNT_NODEF && rstEvnt->rstInd.rstClass.pres != PRSNT_NODEF) {
ftdm_log(FTDM_LOG_DEBUG, "Received RESTART, but Restart Indicator IE not present\n");
return;
}
@ -1233,24 +1248,105 @@ void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
}
/* The remote side sent us a RESTART Msg. Trillium automatically acks with RESTART ACK, but
we need to clear our call states if there is a call on this channel */
void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
{
uint8_t chan_no = 0;
int16_t suId = sngisdn_event->suId;
int16_t dChan = sngisdn_event->dChan;
uint8_t ces = sngisdn_event->ces;
uint8_t evntType = sngisdn_event->evntType;
Rst *rstEvnt = NULL;
sngisdn_span_data_t *signal_data = NULL;
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
/* Function does not require any info from ssHlEvnt struct for now */
/*Rst *rstEvnt = &sngisdn_event->event.rstEvnt;*/
ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART CFM (suId:%u dChan:%d ces:%d %s)\n", suId, dChan, ces,
rstEvnt = &sngisdn_event->event.rstEvnt;
/* TODO: readjust this when NFAS is implemented as signal_data will not always be the first
* span for that d-channel */
if (!rstEvnt->rstInd.eh.pres || !rstEvnt->rstInd.rstClass.pres) {
ftdm_log(FTDM_LOG_DEBUG, "Received RESTART IND, but Restart Indicator IE not present\n");
return;
}
signal_data = g_sngisdn_data.dchans[dChan].spans[1];
if (!signal_data) {
ftdm_log(FTDM_LOG_CRIT, "Received RESTART IND on unconfigured span (suId:%d)\n", suId);
return;
}
ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART IND (suId:%u dChan:%d ces:%d %s)\n", suId, dChan, ces,
(evntType == IN_LNK_DWN)?"LNK_DOWN":
(evntType == IN_LNK_UP)?"LNK_UP":
(evntType == IN_INDCHAN)?"b-channel":
(evntType == IN_LNK_DWN_DM_RLS)?"NFAS service procedures":
(evntType == IN_SWCHD_BU_DCHAN)?"NFAS switchover to backup":"Unknown");
if (!rstEvnt->rstInd.eh.pres || !rstEvnt->rstInd.rstClass.pres) {
ftdm_log(FTDM_LOG_DEBUG, "Received RESTART IND, but Restart Indicator IE not present\n");
return;
}
switch(rstEvnt->rstInd.rstClass.val) {
case IN_CL_INDCHAN: /* Indicated b-channel */
if (rstEvnt->chanId.eh.pres) {
if (rstEvnt->chanId.intType.val == IN_IT_BASIC) {
if (rstEvnt->chanId.infoChanSel.pres == PRSNT_NODEF) {
chan_no = rstEvnt->chanId.infoChanSel.val;
}
} else if (rstEvnt->chanId.intType.val == IN_IT_OTHER) {
if (rstEvnt->chanId.chanNmbSlotMap.pres == PRSNT_NODEF) {
chan_no = rstEvnt->chanId.chanNmbSlotMap.val[0];
}
}
}
if (!chan_no) {
ftdm_log(FTDM_LOG_CRIT, "Failed to determine channel from RESTART\n");
return;
}
break;
case IN_CL_SNGINT: /* Single interface */
case IN_CL_ALLINT: /* All interfaces */
/* In case restart class indicates all interfaces, we will duplicate
this event on each span associated to this d-channel in sngisdn_rcv_rst_cfm,
so treat it as a single interface anyway */
break;
default:
ftdm_log(FTDM_LOG_CRIT, "Invalid restart indicator class:%d\n", rstEvnt->rstInd.rstClass.val);
return;
}
if (chan_no) { /* For a single channel */
if (chan_no > ftdm_span_get_chan_count(signal_data->ftdm_span)) {
ftdm_log(FTDM_LOG_CRIT, "Received RESTART IND on invalid channel:%d\n", chan_no);
} else {
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
if (ftdmchan->physical_chan_id == chan_no) {
sngisdn_force_down(ftdmchan);
}
}
ftdm_iterator_free(chaniter);
}
} else { /* for all channels */
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
sngisdn_force_down((ftdm_channel_t*)ftdm_iterator_current(curr));
}
ftdm_iterator_free(chaniter);
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}

View File

@ -146,13 +146,18 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_i
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_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) {
return;
}
sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED);
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);
return;
}
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
/* Indicate channel ID only in first response */
@ -161,7 +166,7 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_i
}
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROCEED (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_CALLPROC, signal_data->dchan_id, sngisdn_info->ces)) {
@ -230,12 +235,17 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind
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) {
if (sngisdn_test_flag(sngisdn_info, FLAG_SENT_CONNECT)) {
return;
}
sngisdn_set_flag(sngisdn_info, FLAG_SENT_CONNECT);
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);
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
@ -353,22 +363,12 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
return;
}
memset(&discEvnt, 0, sizeof(discEvnt));
/* Fill discEvnt here */
/* TODO move this to set_cause_ie function */
discEvnt.causeDgn[0].eh.pres = PRSNT_NODEF;
discEvnt.causeDgn[0].location.pres = PRSNT_NODEF;
discEvnt.causeDgn[0].location.val = IN_LOC_PRIVNETLU;
discEvnt.causeDgn[0].codeStand3.pres = PRSNT_NODEF;
discEvnt.causeDgn[0].codeStand3.val = IN_CSTD_CCITT;
discEvnt.causeDgn[0].causeVal.pres = PRSNT_NODEF;
discEvnt.causeDgn[0].causeVal.val = ftdmchan->caller_data.hangup_cause;
discEvnt.causeDgn[0].recommend.pres = NOTPRSNT;
discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT;
set_facility_ie(ftdmchan, &discEvnt.facilityStr);
memset(&discEvnt, 0, sizeof(discEvnt));
set_cause_ie(ftdmchan, &discEvnt.causeDgn[0]);
set_facility_ie(ftdmchan, &discEvnt.facilityStr);
set_user_to_user_ie(ftdmchan, &discEvnt.usrUsr);
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)) {

View File

@ -707,10 +707,12 @@ void sngisdn_rcv_q921_ind(BdMngmt *status)
}
void sngisdn_rcv_q931_ind(InMngmt *status)
{
#ifndef WIN32
if (status->t.usta.alarm.cause == 287) {
get_memory_info();
sngisdn_get_memory_info();
return;
}
#endif
switch (status->t.usta.alarm.event) {
case LCM_EVENT_UP:
@ -779,7 +781,6 @@ void sngisdn_rcv_cc_ind(CcMngmt *status)
void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
{
MsgLen mlen;
MsgLen i;
int16_t j;
Buffer *tmp;
Data *cptr;
@ -802,7 +803,6 @@ void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
tmp = mBuf->b_cont;
cptr = tmp->b_rptr;
data = *cptr++;
i = 0;
for(j=0;j<mlen;j++) {
tdata[j]= data;

View File

@ -43,10 +43,53 @@ SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr
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);
static uint8_t get_trillium_val(ftdm2trillium_t *vals, uint8_t ftdm_val, uint8_t default_val);
static uint8_t get_ftdm_val(ftdm2trillium_t *vals, uint8_t trillium_val, uint8_t default_val);
extern ftdm_sngisdn_data_t g_sngisdn_data;
void get_memory_info(void);
ftdm2trillium_t npi_codes[] = {
{FTDM_NPI_UNKNOWN, IN_NP_UNK},
{FTDM_NPI_ISDN, IN_NP_ISDN},
{FTDM_NPI_DATA, IN_NP_DATA},
{FTDM_NPI_TELEX, IN_NP_TELEX},
{FTDM_NPI_NATIONAL, IN_NP_NATIONAL},
{FTDM_NPI_PRIVATE, IN_NP_PRIVATE},
{FTDM_NPI_RESERVED, IN_NP_EXT},
};
ftdm2trillium_t ton_codes[] = {
{FTDM_TON_UNKNOWN, IN_TON_UNK},
{FTDM_TON_INTERNATIONAL, IN_TON_INT},
{FTDM_TON_NATIONAL, IN_TON_NAT},
{FTDM_TON_NETWORK_SPECIFIC, IN_TON_NETSPEC},
{FTDM_TON_SUBSCRIBER_NUMBER, IN_TON_SUB},
{FTDM_TON_ABBREVIATED_NUMBER, IN_TON_ABB},
{FTDM_TON_RESERVED, IN_TON_EXT},
};
static uint8_t get_trillium_val(ftdm2trillium_t *vals, uint8_t ftdm_val, uint8_t default_val)
{
ftdm2trillium_t *val = vals;
while(val++) {
if (val->ftdm_val == ftdm_val) {
return val->trillium_val;
}
}
return default_val;
}
static uint8_t get_ftdm_val(ftdm2trillium_t *vals, uint8_t trillium_val, uint8_t default_val)
{
ftdm2trillium_t *val = vals;
while(val++) {
if (val->trillium_val == trillium_val) {
return val->ftdm_val;
}
}
return default_val;
}
void clear_call_data(sngisdn_chan_data_t *sngisdn_info)
{
@ -57,11 +100,12 @@ void clear_call_data(sngisdn_chan_data_t *sngisdn_info)
g_sngisdn_data.ccs[cc_id].active_spInstIds[sngisdn_info->spInstId]=NULL;
g_sngisdn_data.ccs[cc_id].active_suInstIds[sngisdn_info->suInstId]=NULL;
ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].mutex);
sngisdn_info->suInstId = 0;
sngisdn_info->spInstId = 0;
sngisdn_info->globalFlg = 0;
sngisdn_info->flags = 0;
sngisdn_info->transfer_data.type = SNGISDN_TRANSFER_NONE;
return;
}
@ -259,11 +303,11 @@ ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb)
}
if (cdPtyNmb->nmbPlanId.pres == PRSNT_NODEF) {
caller_data->dnis.plan = cdPtyNmb->nmbPlanId.val;
caller_data->dnis.plan = get_ftdm_val(npi_codes, cdPtyNmb->nmbPlanId.val, IN_NP_UNK);
}
if (cdPtyNmb->typeNmb0.pres == PRSNT_NODEF) {
caller_data->dnis.type = cdPtyNmb->typeNmb0.val;
caller_data->dnis.type = get_ftdm_val(ton_codes, cdPtyNmb->typeNmb0.val, IN_TON_UNK);
}
if (cdPtyNmb->nmbDigits.pres == PRSNT_NODEF) {
@ -283,11 +327,11 @@ ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb)
}
if (redirNmb->nmbPlanId.pres == PRSNT_NODEF) {
caller_data->rdnis.plan = redirNmb->nmbPlanId.val;
caller_data->rdnis.plan = get_ftdm_val(npi_codes, redirNmb->nmbPlanId.val, IN_NP_UNK);
}
if (redirNmb->typeNmb.pres == PRSNT_NODEF) {
caller_data->rdnis.type = redirNmb->typeNmb.val;
caller_data->rdnis.type = get_ftdm_val(ton_codes, redirNmb->typeNmb.val, IN_TON_UNK);
}
if (redirNmb->nmbDigits.pres == PRSNT_NODEF) {
@ -382,11 +426,13 @@ ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8
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) {
/* TODO: use get_ftdm_val function and table here */
switch (progInd->progDesc.val) {
case IN_PD_NOTETEISDN:
val = SNGISDN_PROGIND_DESCR_NETE_ISDN;
@ -464,19 +510,11 @@ ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
cgPtyNmb->presInd0.val = caller_data->pres;
cgPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
if (caller_data->cid_num.plan >= FTDM_NPI_INVALID) {
cgPtyNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN;
} else {
cgPtyNmb->nmbPlanId.val = caller_data->cid_num.plan;
}
cgPtyNmb->nmbPlanId.val = get_trillium_val(npi_codes, caller_data->cid_num.plan, IN_NP_UNK);
cgPtyNmb->typeNmb1.pres = PRSNT_NODEF;
if (caller_data->cid_num.type >= FTDM_TON_INVALID) {
cgPtyNmb->typeNmb1.val = FTDM_TON_UNKNOWN;
} else {
cgPtyNmb->typeNmb1.val = caller_data->cid_num.type;
}
cgPtyNmb->typeNmb1.val = get_trillium_val(ton_codes, caller_data->cid_num.type, IN_TON_UNK);
cgPtyNmb->nmbDigits.pres = PRSNT_NODEF;
cgPtyNmb->nmbDigits.len = len;
@ -510,7 +548,7 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
val = FTDM_SCREENING_INVALID;
string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.screening_ind");
if ((string != NULL) && (*string)) {
if (!ftdm_strlen_zero(string)) {
val = ftdm_str2ftdm_screening(string);
}
@ -527,7 +565,7 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
val = FTDM_PRES_INVALID;
string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.presentation_ind");
if ((string != NULL) && (*string)) {
if (!ftdm_strlen_zero(string)) {
val = ftdm_str2ftdm_presentation(string);
}
@ -542,14 +580,14 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
val = FTDM_NPI_INVALID;
string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.npi");
if ((string != NULL) && (*string)) {
if (!ftdm_strlen_zero(string)) {
val = ftdm_str2ftdm_npi(string);
}
if (val == FTDM_NPI_INVALID) {
cgPtyNmb->nmbPlanId.val = caller_data->cid_num.plan;
} else {
cgPtyNmb->nmbPlanId.val = val;
cgPtyNmb->nmbPlanId.val = get_trillium_val(npi_codes, val, IN_NP_UNK);
}
cgPtyNmb->typeNmb1.pres = PRSNT_NODEF;
@ -557,14 +595,14 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
/* Type of Number */
val = FTDM_TON_INVALID;
string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.ton");
if ((string != NULL) && (*string)) {
if (!ftdm_strlen_zero(string)) {
val = ftdm_str2ftdm_ton(string);
}
if (val == FTDM_TON_INVALID) {
cgPtyNmb->typeNmb1.val = caller_data->cid_num.type;
} else {
cgPtyNmb->typeNmb1.val = val;
cgPtyNmb->typeNmb1.val = get_trillium_val(ton_codes, val, IN_TON_UNK);
}
return FTDM_SUCCESS;
}
@ -577,21 +615,14 @@ ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb)
if (!len) {
return FTDM_SUCCESS;
}
cdPtyNmb->eh.pres = PRSNT_NODEF;
cdPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
if (caller_data->dnis.plan >= FTDM_NPI_INVALID) {
cdPtyNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN;
} else {
cdPtyNmb->nmbPlanId.val = caller_data->dnis.plan;
}
cdPtyNmb->typeNmb0.pres = PRSNT_NODEF;
if (caller_data->dnis.type >= FTDM_TON_INVALID) {
cdPtyNmb->typeNmb0.val = FTDM_TON_UNKNOWN;
} else {
cdPtyNmb->typeNmb0.val = caller_data->dnis.type;
}
cdPtyNmb->eh.pres = PRSNT_NODEF;
cdPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
cdPtyNmb->nmbPlanId.val = get_trillium_val(npi_codes, caller_data->dnis.plan, IN_NP_UNK);
cdPtyNmb->typeNmb0.pres = PRSNT_NODEF;
cdPtyNmb->typeNmb0.val = get_trillium_val(ton_codes, caller_data->dnis.type, IN_TON_UNK);
cdPtyNmb->nmbDigits.pres = PRSNT_NODEF;
cdPtyNmb->nmbDigits.len = len;
@ -612,18 +643,10 @@ ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb)
redirNmb->eh.pres = PRSNT_NODEF;
redirNmb->nmbPlanId.pres = PRSNT_NODEF;
if (caller_data->rdnis.plan >= FTDM_NPI_INVALID) {
redirNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN;
} else {
redirNmb->nmbPlanId.val = caller_data->rdnis.plan;
}
redirNmb->nmbPlanId.val = get_trillium_val(npi_codes, caller_data->rdnis.plan, IN_NP_UNK);
redirNmb->typeNmb.pres = PRSNT_NODEF;
if (caller_data->rdnis.type >= FTDM_TON_INVALID) {
redirNmb->typeNmb.val = FTDM_TON_UNKNOWN;
} else {
redirNmb->typeNmb.val = caller_data->rdnis.type;
}
redirNmb->typeNmb.val = get_trillium_val(ton_codes, caller_data->rdnis.type, IN_TON_UNK);
redirNmb->nmbDigits.pres = PRSNT_NODEF;
redirNmb->nmbDigits.len = len;
@ -823,6 +846,41 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s
return FTDM_SUCCESS;
}
ftdm_status_t set_user_to_user_ie(ftdm_channel_t *ftdmchan, UsrUsr *usrUsr)
{
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
if (sngisdn_info->transfer_data.type == SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA) {
usrUsr->eh.pres = PRSNT_NODEF;
usrUsr->protocolDisc.pres = PRSNT_NODEF;
usrUsr->protocolDisc.val = 0x08;
usrUsr->usrInfo.pres = PRSNT_NODEF;
usrUsr->usrInfo.len = strlen(sngisdn_info->transfer_data.tdata.att_courtesy_vru.data);
memcpy(usrUsr->usrInfo.val, sngisdn_info->transfer_data.tdata.att_courtesy_vru.data, usrUsr->usrInfo.len);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending AT&T Transfer data len:%d\n", usrUsr->usrInfo.len);
return FTDM_SUCCESS;
}
return FTDM_SUCCESS;
}
ftdm_status_t set_cause_ie(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn)
{
causeDgn->eh.pres = PRSNT_NODEF;
causeDgn->location.pres = PRSNT_NODEF;
causeDgn->location.val = IN_LOC_PRIVNETLU;
causeDgn->codeStand3.pres = PRSNT_NODEF;
causeDgn->codeStand3.val = IN_CSTD_CCITT;
causeDgn->causeVal.pres = PRSNT_NODEF;
causeDgn->causeVal.val = ftdmchan->caller_data.hangup_cause;
causeDgn->recommend.pres = NOTPRSNT;
causeDgn->dgnVal.pres = NOTPRSNT;
return FTDM_SUCCESS;
}
ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data;
@ -831,7 +889,7 @@ ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId)
}
ftdm_set_flag(sngisdn_info, FLAG_SENT_CHAN_ID);
chanId->eh.pres = PRSNT_NODEF;
chanId->prefExc.pres = PRSNT_NODEF;
chanId->prefExc.val = IN_PE_EXCLSVE;
@ -840,8 +898,7 @@ ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId)
chanId->intIdentPres.pres = PRSNT_NODEF;
chanId->intIdentPres.val = IN_IIP_IMPLICIT;
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
if (FTDM_SPAN_IS_BRI(ftdmchan->span)) {
/* BRI only params */
chanId->intType.pres = PRSNT_NODEF;
@ -1062,10 +1119,17 @@ ftdm_status_t sngisdn_check_free_ids(void)
return FTDM_SUCCESS;
}
void get_memory_info(void)
void sngisdn_get_memory_info(void)
{
#ifdef WIN32
/* SRegInfoShow is not formally supported by Trillium with Windows */
ftdm_log(FTDM_LOG_WARNING, "SRegInfoShow not supported on Windows\n");
#else
/* SRegInfoShow is not formally supported by Trillium in Linux either, but
* it seems like its working fine so far */
U32 availmen = 0;
SRegInfoShow(S_REG, &availmen);
#endif
return;
}
@ -1108,7 +1172,7 @@ ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_stack(uint8_t bearer_capability)
{
switch(bearer_capability) {
case IN_ITC_SPEECH:
return FTDM_BEARER_CAP_SPEECH;
return FTDM_BEARER_CAP_SPEECH;
case IN_ITC_UNRDIG:
return FTDM_BEARER_CAP_UNRESTRICTED;
case IN_ITC_A31KHZ:
@ -1134,7 +1198,7 @@ ftdm_user_layer1_prot_t sngisdn_get_usrInfoLyr1Prot_from_stack(uint8_t layer1_pr
return FTDM_USER_LAYER1_PROT_ULAW;
}
void sngisdn_print_phy_stats(ftdm_stream_handle_t *stream, ftdm_span_t *span)
ftdm_status_t sngisdn_show_l1_stats(ftdm_stream_handle_t *stream, ftdm_span_t *span)
{
L1Mngmt sts;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
@ -1172,11 +1236,11 @@ void sngisdn_print_phy_stats(ftdm_stream_handle_t *stream, ftdm_span_t *span)
stream->write_function(stream, " TX Errors Details");
stream->write_function(stream, "\n---------------------------------------------------------------------\n");
stream->write_function(stream, "Aborted:\t%u\tFifo:\t\t%u\tCarrier:\t%u\n", sts.t.sts.tx_aborted_errors, sts.t.sts.tx_fifo_errors, sts.t.sts.tx_carrier_errors);
return;
return FTDM_SUCCESS;
}
void sngisdn_print_span(ftdm_stream_handle_t *stream, ftdm_span_t *span)
ftdm_status_t sngisdn_show_span(ftdm_stream_handle_t *stream, ftdm_span_t *span)
{
ftdm_signaling_status_t sigstatus;
ftdm_alarm_flag_t alarmbits;
@ -1191,18 +1255,18 @@ void sngisdn_print_span(ftdm_stream_handle_t *stream, ftdm_span_t *span)
stream->write_function(stream, "span:%s physical:%s signalling:%s\n",
span->name, alarmbits ? "ALARMED" : "OK",
ftdm_signaling_status2str(sigstatus));
return;
return FTDM_SUCCESS;
}
void sngisdn_print_spans(ftdm_stream_handle_t *stream)
ftdm_status_t sngisdn_show_spans(ftdm_stream_handle_t *stream)
{
int i;
for(i=1;i<=MAX_L1_LINKS;i++) {
if (g_sngisdn_data.spans[i]) {
sngisdn_print_span(stream, g_sngisdn_data.spans[i]->ftdm_span);
sngisdn_show_span(stream, g_sngisdn_data.spans[i]->ftdm_span);
}
}
return;
return FTDM_SUCCESS;
}
ftdm_status_t sngisdn_add_var(sngisdn_chan_data_t *sngisdn_info, const char* var, const char* val)
@ -1265,10 +1329,13 @@ void sngisdn_send_signal(sngisdn_chan_data_t *sngisdn_info, ftdm_signal_event_t
sigev.raw.data = sngisdn_info->raw_data;
sigev.raw.len = sngisdn_info->raw_data_len;
sngisdn_info->raw_data = NULL;
sngisdn_info->raw_data_len = 0;
}
if (event_id == FTDM_SIGEVENT_TRANSFER_COMPLETED) {
sigev.ev_data.transfer_completed.response = sngisdn_info->transfer_data.response;
}
ftdm_span_send_signal(ftdmchan->span, &sigev);
}

View File

@ -334,11 +334,12 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
switch(ieId) {
case PROT_Q931_IE_BEARER_CAP:
{
uint8_t codingStandard, infTransferCap, transferMode, infTransferRate, usrL1Prot;
uint8_t codingStandard, infTransferCap, infTransferRate, usrL1Prot;
/*uint8_t transferMode;*/
codingStandard = get_bits(OCTET(3),6,7);
infTransferCap = get_bits(OCTET(3),1,5);
transferMode = get_bits(OCTET(4),6,7);
/*transferMode = get_bits(OCTET(4),6,7);*/
infTransferRate = get_bits(OCTET(4),1,5);
usrL1Prot = get_bits(OCTET(5),1,5);
@ -404,8 +405,9 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
uint8_t infoChannelSelection=0;
uint8_t prefExclusive=0;
uint8_t ifaceIdPresent=0;
uint8_t ifaceIdentifier = 0; /* octet_3_1 */
uint8_t chanType=0, numberMap=0, codingStandard=0;
/* uint8_t ifaceIdentifier = 0; */ /* octet_3_1 */
uint8_t chanType=0, numberMap=0;
/* uint8_t codingStandard=0; */
uint8_t channelNo = 0;
infoChannelSelection = get_bits(OCTET(3),1,2);
@ -413,15 +415,15 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
ifaceIdPresent = get_bits(OCTET(3),7,7);
if (ifaceIdPresent) {
ifaceIdentifier= get_bits(OCTET(4),1,7);
/*ifaceIdentifier= get_bits(OCTET(4),1,7);*/
chanType = get_bits(OCTET(5),1,4);
numberMap = get_bits(OCTET(5),5,5);
codingStandard = get_bits(OCTET(5),6,7);
/*codingStandard = get_bits(OCTET(5),6,7);*/
channelNo = get_bits(OCTET(6),1,7);
} else {
chanType = get_bits(OCTET(4),1,4);
numberMap = get_bits(OCTET(4),5,5);
codingStandard = get_bits(OCTET(4),6,7);
/*codingStandard = get_bits(OCTET(4),6,7);*/
channelNo = get_bits(OCTET(5),1,7);
}
@ -755,7 +757,7 @@ void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_
{
uint32_t k;
*str_len += sprintf(&str[*str_len], " [ ");
for(k=index_start; k <= index_end; k++) {
for(k=index_start; k < index_end; k++) {
if (k && !(k%32)) {
*str_len += sprintf(&str[*str_len], "\n ");
}
@ -915,7 +917,7 @@ static ftdm_status_t sngisdn_map_call(sngisdn_span_data_t *signal_data, sngisdn_
case PROT_Q931_MSGTYPE_USER_INFO:
case PROT_Q931_MSGTYPE_DISCONNECT:
case PROT_Q931_MSGTYPE_RELEASE:
case PROT_Q931_MSGTYPE_RELEASE_ACK:
case PROT_Q931_MSGTYPE_RESTART_ACK:
case PROT_Q931_MSGTYPE_RELEASE_COMPLETE:
case PROT_Q931_MSGTYPE_FACILITY:
case PROT_Q931_MSGTYPE_NOTIFY:

View File

@ -211,7 +211,7 @@ struct code2str dcodQ931CallRefLoTable[] = {
#define PROT_Q931_MSGTYPE_DISCONNECT 69
#define PROT_Q931_MSGTYPE_RESTART 70
#define PROT_Q931_MSGTYPE_RELEASE 77
#define PROT_Q931_MSGTYPE_RELEASE_ACK 78
#define PROT_Q931_MSGTYPE_RESTART_ACK 78
#define PROT_Q931_MSGTYPE_RELEASE_COMPLETE 90
#define PROT_Q931_MSGTYPE_SEGMENT 96
#define PROT_Q931_MSGTYPE_FACILITY 98
@ -240,7 +240,7 @@ struct code2str dcodQ931MsgTypeTable[] = {
{PROT_Q931_MSGTYPE_DISCONNECT, "DISCONNECT"},
{PROT_Q931_MSGTYPE_RESTART, "RESTART"},
{PROT_Q931_MSGTYPE_RELEASE, "RELEASE"},
{PROT_Q931_MSGTYPE_RELEASE_ACK, "RELEASR ACK"},
{PROT_Q931_MSGTYPE_RESTART_ACK, "RESTART ACK"},
{PROT_Q931_MSGTYPE_RELEASE_COMPLETE, "RELEASE COMPLETE"},
{PROT_Q931_MSGTYPE_SEGMENT, "SEGMENT"},
{PROT_Q931_MSGTYPE_FACILITY, "FACILITY"},

View File

@ -0,0 +1,281 @@
/*
* Copyright (c) 2011, Sangoma Technologies
* David Yat Sin <davidy@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.
*/
#include "ftmod_sangoma_isdn.h"
#define TRANSFER_FUNC(name) ftdm_status_t (name)(ftdm_channel_t *ftdmchan, sngisdn_transfer_type_t type, char* target)
#define SNGISDN_ATT_TRANSFER_RESPONSE_CP_DROP_OFF "**1"
#define SNGISDN_ATT_TRANSFER_RESPONSE_LIMITS_EXCEEDED "**5"
#define SNGISDN_ATT_TRANSFER_RESPONSE_OK "**6"
#define SNGISDN_ATT_TRANSFER_RESPONSE_INVALID_NUM "**7"
#define SNGISDN_ATT_TRANSFER_RESPONSE_INVALID_COMMAND "**8"
void att_courtesy_transfer_complete(sngisdn_chan_data_t *sngisdn_info, ftdm_transfer_response_t response);
void att_courtesy_transfer_timeout(void* p_sngisdn_info);
static ftdm_status_t att_courtesy_vru(ftdm_channel_t *ftdmchan, sngisdn_transfer_type_t type, char* target);
typedef struct transfer_interfaces {
const char *name;
sngisdn_transfer_type_t type;
TRANSFER_FUNC(*func);
}transfer_interface_t;
static transfer_interface_t transfer_interfaces[] = {
/* AT&T TR-50075 Courtesy Transfer - VRU -- No Data (Section 4.3) */
{ "ATT_COURTESY_TRANSFER_V", SNGISDN_TRANSFER_ATT_COURTESY_VRU, att_courtesy_vru},
/* AT&T TR-50075 Courtesy Transfer - VRU --Data (Section 4.4) */
{ "ATT_COURTESY_TRANSFER_V_DATA", SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA, att_courtesy_vru},
};
void att_courtesy_transfer_complete(sngisdn_chan_data_t *sngisdn_info, ftdm_transfer_response_t response)
{
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED);
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_DTMF_DETECT, NULL);
sngisdn_info->transfer_data.type = SNGISDN_TRANSFER_NONE;
sngisdn_info->transfer_data.response = response;
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Transfer Complete:%s\n", ftdm_transfer_response2str(sngisdn_info->transfer_data.response));
sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_TRANSFER_COMPLETED);
ftdm_channel_command(ftdmchan, FTDM_COMMAND_FLUSH_RX_BUFFERS, NULL);
return;
}
void att_courtesy_transfer_timeout(void* p_sngisdn_info)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
ftdm_mutex_lock(ftdmchan->mutex);
if (sngisdn_info->transfer_data.type == SNGISDN_TRANSFER_NONE) {
/* Call was already cleared */
ftdm_mutex_unlock(ftdmchan->mutex);
return;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "AT&T Courtesy Transfer timeout (%d)\n", signal_data->transfer_timeout);
att_courtesy_transfer_complete(sngisdn_info, FTDM_TRANSFER_RESPONSE_TIMEOUT);
ftdm_mutex_unlock(ftdmchan->mutex);
return;
}
static ftdm_status_t att_courtesy_vru(ftdm_channel_t *ftdmchan, sngisdn_transfer_type_t type, char* args)
{
char dtmf_digits[64];
ftdm_status_t status = FTDM_FAIL;
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
char *p = args;
uint8_t forced_answer = 0;
switch (signal_data->switchtype) {
case SNGISDN_SWITCH_5ESS:
case SNGISDN_SWITCH_4ESS:
break;
default:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "AT&T Courtesy Transfer not supported for switchtype\n");
return FTDM_FAIL;
}
while (!ftdm_strlen_zero(p)) {
if (!isdigit(*p) && *p != 'w' && *p != 'W') {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot transfer to non-numeric number:%s\n", args);
return FTDM_FAIL;
}
p++;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Performing AT&T Courtesy Transfer-VRU%s to %s\n", (type == SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA) ?"--data" : "", args);
sprintf(dtmf_digits, "*8w%s", args);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending digits %s\n", dtmf_digits);
switch (ftdmchan->last_state) {
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
/* Call has to be in answered state - so send a CONNECT message if we did not answer this call yet */
forced_answer++;
sngisdn_snd_connect(ftdmchan);
/* fall-through */
case FTDM_CHANNEL_STATE_UP:
memset(&sngisdn_info->transfer_data.tdata.att_courtesy_vru.dtmf_digits, 0, sizeof(sngisdn_info->transfer_data.tdata.att_courtesy_vru.dtmf_digits));
sngisdn_info->transfer_data.type = type;
/* We will be polling the channel for IO so that we can receive the DTMF events,
* Disable user RX otherwise it is a race between who calls channel_read */
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_RX_DISABLED);
ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_DTMF_DETECT, NULL);
ftdm_channel_command(ftdmchan, FTDM_COMMAND_SEND_DTMF, dtmf_digits);
if (type == SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA) {
/* We need to save transfer data, so we can send it in the disconnect msg */
const char *val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "transfer_data");
if (ftdm_strlen_zero(val)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Cannot perform data transfer because transfer_data variable is not set\n");
goto done;
}
if (strlen(val) > COURTESY_TRANSFER_MAX_DATA_SIZE) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Data exceeds max size (len:%d max:%d), cannot perform transfer\n", strlen(val), COURTESY_TRANSFER_MAX_DATA_SIZE);
goto done;
}
memcpy(sngisdn_info->transfer_data.tdata.att_courtesy_vru.data, val, strlen(val));
}
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
if (forced_answer) {
/* Notify the user that we answered the call */
sngisdn_send_signal(sngisdn_info, FTDM_SIGEVENT_UP);
}
if (signal_data->transfer_timeout) {
ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "courtesy_transfer_timeout", signal_data->transfer_timeout, att_courtesy_transfer_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_ATT_TRANSFER]);
}
status = FTDM_SUCCESS;
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot perform transfer in state %s\n", ftdm_channel_state2str(ftdmchan->state));
break;
}
done:
return status;
}
ftdm_status_t sngisdn_transfer(ftdm_channel_t *ftdmchan)
{
const char* args;
char *p;
char *type = NULL;
char *target = NULL;
ftdm_status_t status = FTDM_FAIL;
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
unsigned i;
args = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "transfer_arg");
if (ftdm_strlen_zero(args)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Cannot perform transfer because call_transfer_arg variable is not set\n");
goto done;
}
type = ftdm_strdup(args);
if ((p = strchr(type, '/'))) {
target = ftdm_strdup(p+1);
*p = '\0';
}
if (ftdm_strlen_zero(type) || ftdm_strlen_zero(target)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Invalid parameters for transfer %s, expected <type>/<target>\n", args);
goto done;
}
if (sngisdn_info->transfer_data.type != SNGISDN_TRANSFER_NONE) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Cannot perform transfer because an existing transfer transfer is pending (%s)\n", sngisdn_transfer_type2str(sngisdn_info->transfer_data.type));
goto done;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Transfer requested type:%s target:%s\n", type, target);
for (i = 0; i < ftdm_array_len(transfer_interfaces); i++ ) {
if (!strcasecmp(transfer_interfaces[i].name, type)) {
/* Depending on the transfer type, the transfer function may change the
* channel state to UP, or last_state, but the transfer function will always result in
* an immediate state change if FTDM_SUCCESS is returned */
status = transfer_interfaces[i].func(ftdmchan, transfer_interfaces[i].type, target);
goto done;
}
}
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Invalid transfer type:%s\n", type);
done:
if (status != FTDM_SUCCESS) {
ftdm_set_state(ftdmchan, ftdmchan->last_state);
}
ftdm_safe_free(type);
ftdm_safe_free(target);
return status;
}
ftdm_status_t sngisdn_att_transfer_process_dtmf(ftdm_channel_t *ftdmchan, const char* dtmf)
{
ftdm_status_t status = FTDM_SUCCESS;
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
char *dtmf_digits = sngisdn_info->transfer_data.tdata.att_courtesy_vru.dtmf_digits;
ftdm_size_t dtmf_digits_len = strlen(dtmf_digits);
dtmf_digits_len += sprintf(&dtmf_digits[dtmf_digits_len], "%s", dtmf);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Transfer response digits:%s\n", dtmf_digits);
if (dtmf_digits_len == 3) {
if (!strcmp(dtmf_digits, SNGISDN_ATT_TRANSFER_RESPONSE_CP_DROP_OFF)) {
sngisdn_info->transfer_data.response = FTDM_TRANSFER_RESPONSE_CP_DROP_OFF;
} else if (!strcmp(dtmf_digits, SNGISDN_ATT_TRANSFER_RESPONSE_LIMITS_EXCEEDED)) {
sngisdn_info->transfer_data.response = FTDM_TRANSFER_RESPONSE_LIMITS_EXCEEDED;
} else if (!strcmp(dtmf_digits, SNGISDN_ATT_TRANSFER_RESPONSE_OK)) {
sngisdn_info->transfer_data.response = FTDM_TRANSFER_RESPONSE_OK;
} else if (!strcmp(dtmf_digits, SNGISDN_ATT_TRANSFER_RESPONSE_INVALID_NUM)) {
sngisdn_info->transfer_data.response = FTDM_TRANSFER_RESPONSE_INVALID_NUM;
} else if (!strcmp(dtmf_digits, SNGISDN_ATT_TRANSFER_RESPONSE_INVALID_COMMAND)) {
sngisdn_info->transfer_data.response = FTDM_TRANSFER_RESPONSE_INVALID_COMMAND;
} else {
sngisdn_info->transfer_data.response = FTDM_TRANSFER_RESPONSE_INVALID;
}
if (signal_data->transfer_timeout) {
ftdm_sched_cancel_timer(signal_data->sched, sngisdn_info->timers[SNGISDN_TIMER_ATT_TRANSFER]);
}
if (sngisdn_info->transfer_data.response == FTDM_TRANSFER_RESPONSE_OK &&
sngisdn_info->transfer_data.type == SNGISDN_TRANSFER_ATT_COURTESY_VRU_DATA) {
sngisdn_set_flag(sngisdn_info, FLAG_SEND_DISC);
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING;
sngisdn_snd_disconnect(ftdmchan);
}
/* Network side will send disconnect in case of NO-DATA Transfer */
att_courtesy_transfer_complete(sngisdn_info, sngisdn_info->transfer_data.response);
}
if (signal_data->att_remove_dtmf) {
/* If we return FTDM_BREAK, dtmf event is not queue'ed to user */
status = FTDM_BREAK;
}
return status;
}

View File

@ -532,9 +532,9 @@ move_along:
/**************************************************************************/
default:
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != VOICE) {
SS7_ERROR("Rx %s on circuit that is not a voice CIC (%d)\n",
ftdm_log(FTDM_LOG_DEBUG, "Rx %s on circuit that is not a voice CIC (%d) (circuit:%d)\n",
DECODE_LCC_EVENT(evntType),
g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic);
g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, circuit);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}

View File

@ -60,6 +60,10 @@
#define MAX_SIZEOF_SUBADDR_IE 24 /* as per Q931 4.5.9 */
#define SNGSS7_SWITCHTYPE_ANSI(switchtype) (switchtype == LSI_SW_ANS88) || \
(switchtype == LSI_SW_ANS92) || \
(switchtype == LSI_SW_ANS95)
typedef struct ftdm2trillium
{
uint8_t ftdm_val;

View File

@ -92,8 +92,10 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
/* Transmission medium requirements */
copy_txMedReq_to_sngss7(ftdmchan, &iam.txMedReq);
/* User Service Info A */
copy_usrServInfoA_to_sngss7(ftdmchan, &iam.usrServInfoA);
if (SNGSS7_SWITCHTYPE_ANSI(g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType)) {
/* User Service Info A */
copy_usrServInfoA_to_sngss7(ftdmchan, &iam.usrServInfoA);
}
/* Called Number information */
copy_cdPtyNum_to_sngss7(ftdmchan, &iam.cdPtyNum);

View File

@ -641,39 +641,32 @@ ftdm_status_t copy_txMedReq_to_sngss7(ftdm_channel_t *ftdmchan, SiTxMedReq *txMe
ftdm_status_t copy_usrServInfoA_to_sngss7(ftdm_channel_t *ftdmchan, SiUsrServInfo *usrServInfoA)
{
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
if ((g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS88) ||
(g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS92) ||
(g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS95)) {
usrServInfoA->eh.pres = PRSNT_NODEF;
usrServInfoA->eh.pres = PRSNT_NODEF;
usrServInfoA->infoTranCap.pres = PRSNT_NODEF;
usrServInfoA->infoTranCap.pres = PRSNT_NODEF;
usrServInfoA->infoTranCap.val = get_trillium_val(bc_cap_codes, ftdmchan->caller_data.bearer_capability, ITC_SPEECH);
usrServInfoA->infoTranCap.val = get_trillium_val(bc_cap_codes, ftdmchan->caller_data.bearer_capability, ITC_SPEECH);
usrServInfoA->cdeStand.pres = PRSNT_NODEF;
usrServInfoA->cdeStand.val = 0x0; /* ITU-T standardized coding */
usrServInfoA->tranMode.pres = PRSNT_NODEF;
usrServInfoA->tranMode.val = 0x0; /* circuit mode */
usrServInfoA->infoTranRate0.pres = PRSNT_NODEF;
usrServInfoA->infoTranRate0.val = 0x10; /* 64kbps origination to destination */
usrServInfoA->infoTranRate1.pres = PRSNT_NODEF;
usrServInfoA->infoTranRate1.val = 0x10; /* 64kbps destination to origination */
usrServInfoA->chanStruct.pres = PRSNT_NODEF;
usrServInfoA->chanStruct.val = 0x1; /* 8kHz integrity */
usrServInfoA->config.pres = PRSNT_NODEF;
usrServInfoA->config.val = 0x0; /* point to point configuration */
usrServInfoA->establish.pres = PRSNT_NODEF;
usrServInfoA->establish.val = 0x0; /* on demand */
usrServInfoA->symmetry.pres = PRSNT_NODEF;
usrServInfoA->symmetry.val = 0x0; /* bi-directional symmetric */
usrServInfoA->usrInfLyr1Prot.pres = PRSNT_NODEF;
usrServInfoA->usrInfLyr1Prot.val = 0x2; /* G.711 ulaw */
usrServInfoA->rateMultiplier.pres = PRSNT_NODEF;
usrServInfoA->rateMultiplier.val = 0x1; /* 1x rate multipler */
} /* if ANSI */
usrServInfoA->cdeStand.pres = PRSNT_NODEF;
usrServInfoA->cdeStand.val = 0x0; /* ITU-T standardized coding */
usrServInfoA->tranMode.pres = PRSNT_NODEF;
usrServInfoA->tranMode.val = 0x0; /* circuit mode */
usrServInfoA->infoTranRate0.pres = PRSNT_NODEF;
usrServInfoA->infoTranRate0.val = 0x10; /* 64kbps origination to destination */
usrServInfoA->infoTranRate1.pres = PRSNT_NODEF;
usrServInfoA->infoTranRate1.val = 0x10; /* 64kbps destination to origination */
usrServInfoA->chanStruct.pres = PRSNT_NODEF;
usrServInfoA->chanStruct.val = 0x1; /* 8kHz integrity */
usrServInfoA->config.pres = PRSNT_NODEF;
usrServInfoA->config.val = 0x0; /* point to point configuration */
usrServInfoA->establish.pres = PRSNT_NODEF;
usrServInfoA->establish.val = 0x0; /* on demand */
usrServInfoA->symmetry.pres = PRSNT_NODEF;
usrServInfoA->symmetry.val = 0x0; /* bi-directional symmetric */
usrServInfoA->usrInfLyr1Prot.pres = PRSNT_NODEF;
usrServInfoA->usrInfLyr1Prot.val = 0x2; /* G.711 ulaw */
usrServInfoA->rateMultiplier.pres = PRSNT_NODEF;
usrServInfoA->rateMultiplier.val = 0x1; /* 1x rate multipler */
return FTDM_SUCCESS;
}
@ -780,10 +773,17 @@ ftdm_status_t copy_tknStr_to_sngss7(char* val, TknStr *tknStr, TknU8 *oddEven)
/* check if the digit is a number and that is not null */
while (!(isxdigit(tmp[0])) && (tmp[0] != '\0')) {
SS7_INFO("Dropping invalid digit: %c\n", tmp[0]);
/* move on to the next value */
k++;
tmp[0] = val[k];
if (tmp[0] == '*') {
/* Could not find a spec that specifies this , but on customer system, * was transmitted as 0x0b */
SS7_DEBUG("Replacing * with 0x0b");
k++;
tmp[0] = 0x0b;
} else {
SS7_INFO("Dropping invalid digit: %c\n", tmp[0]);
/* move on to the next value */
k++;
tmp[0] = val[k];
}
} /* while(!(isdigit(tmp))) */
/* check if tmp is null or a digit */
@ -1544,10 +1544,17 @@ ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int typ
/* confirm it is a hex digit */
while ((!isxdigit(tmp[0])) && (tmp[0] != '\0')) {
SS7_INFO("Dropping invalid digit: %c\n", tmp[0]);
/* move to the next character in subAddr */
x++;
tmp[0] = subAddr[x];
if (tmp[0] == '*') {
/* Could not find a spec that specifies this, but on customer system, * was transmitted as 0x0b */
SS7_DEBUG("Replacing * with 0x0b");
x++;
tmp[0] = 0x0b;
} else {
SS7_INFO("Dropping invalid digit: %c\n", tmp[0]);
/* move to the next character in subAddr */
x++;
tmp[0] = subAddr[x];
}
}
/* check if tmp is null or a digit */

View File

@ -2205,7 +2205,7 @@ static int ftmod_ss7_fill_in_mtp2_link(sng_mtp2_link_t *mtp2Link)
if ( mtp2Link->t7 != 0 ) {
g_ftdm_sngss7_data.cfg.mtp2Link[i].t7 = mtp2Link->t7;
}else {
g_ftdm_sngss7_data.cfg.mtp2Link[i].t7 = 40;
g_ftdm_sngss7_data.cfg.mtp2Link[i].t7 = 20;
}
return FTDM_SUCCESS;

View File

@ -950,7 +950,6 @@ static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx
static FIO_READ_FUNCTION(wanpipe_read)
{
int rx_len = 0;
int myerrno = 0;
wp_tdm_api_rx_hdr_t hdrframe;
memset(&hdrframe, 0, sizeof(hdrframe));
@ -964,7 +963,6 @@ static FIO_READ_FUNCTION(wanpipe_read)
}
if (rx_len < 0) {
myerrno = errno;
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;
@ -1195,12 +1193,26 @@ FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
#else
if (pfds[i-1].revents & POLLPRI) {
#endif
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_EVENT);
ftdm_set_io_flag(ftdmchan, FTDM_CHANNEL_IO_EVENT);
ftdmchan->last_event_time = ftdm_current_time_in_ms();
k++;
}
#ifdef LIBSANGOMA_VERSION
if (outflags[i-1] & POLLIN) {
#else
if (pfds[i-1].revents & POLLIN) {
#endif
ftdm_set_io_flag(ftdmchan, FTDM_CHANNEL_IO_READ);
}
#ifdef LIBSANGOMA_VERSION
if (outflags[i-1] & POLLOUT) {
#else
if (pfds[i-1].revents & POLLOUT) {
#endif
ftdm_set_io_flag(ftdmchan, FTDM_CHANNEL_IO_WRITE);
}
}
/* when k is 0 it might be that an async wanpipe device signal was delivered */
/* when k is 0 it might be that an async wanpipe device signal was delivered */
return FTDM_SUCCESS;
}
@ -1269,7 +1281,7 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms)
ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_LINK_STATUS, &sangoma_status);
ftdmchan->alarm_flags = sangoma_status == FTDM_HW_LINK_DISCONNECTED ? FTDM_ALARM_RED : FTDM_ALARM_NONE;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Link status is %d\n", sangoma_status);
}
}
}
if (alarms) {
@ -1293,6 +1305,7 @@ static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fc
switch(tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_type) {
case WP_API_EVENT_LINK_STATUS:
{
if (FTDM_IS_DIGITAL_CHANNEL(fchan)) {
switch(tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_link_status) {
case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED:
/* *event_id = FTDM_OOB_ALARM_CLEAR; */
@ -1305,6 +1318,22 @@ static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fc
};
/* The WP_API_EVENT_ALARM event should be used to clear alarms */
*event_id = FTDM_OOB_NOOP;
} else {
switch(tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_link_status) {
case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED:
/* *event_id = FTDM_OOB_ALARM_CLEAR; */
ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Using analog link connected event as alarm clear\n");
*event_id = FTDM_OOB_ALARM_CLEAR;
fchan->alarm_flags = FTDM_ALARM_NONE;
break;
default:
/* *event_id = FTDM_OOB_ALARM_TRAP; */
ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Using analog link disconnected event as alarm trap\n");
*event_id = FTDM_OOB_ALARM_TRAP;
fchan->alarm_flags = FTDM_ALARM_RED;
break;
};
}
}
break;
@ -1430,14 +1459,9 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(wanpipe_channel_next_event)
wanpipe_tdm_api_t tdm_api;
ftdm_span_t *span = ftdmchan->span;
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) {
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_EVENT);
}
memset(&tdm_api, 0, sizeof(tdm_api));
status = sangoma_tdm_read_event(ftdmchan->sockfd, &tdm_api);
if (status != FTDM_SUCCESS) {
snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno));
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to read event from channel: %s\n", strerror(errno));
return FTDM_FAIL;
}
@ -1473,7 +1497,7 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
for(i = 1; i <= span->chan_count; i++) {
/* as a hack for wink/flash detection, wanpipe_poll_event overrides the timeout parameter
* to force the user to call this function each 5ms or so to detect the timeout of our wink/flash */
if (span->channels[i]->last_event_time && !ftdm_test_flag(span->channels[i], FTDM_CHANNEL_EVENT)) {
if (span->channels[i]->last_event_time && !ftdm_test_io_flag(span->channels[i], FTDM_CHANNEL_IO_EVENT)) {
ftdm_time_t diff = ftdm_current_time_in_ms() - span->channels[i]->last_event_time;
/* XX printf("%u %u %u\n", diff, (unsigned)ftdm_current_time_in_ms(), (unsigned)span->channels[i]->last_event_time); */
if (ftdm_test_flag(span->channels[i], FTDM_CHANNEL_WINK)) {
@ -1505,13 +1529,13 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(wanpipe_span_next_event)
goto event;
}
}
}
if (ftdm_test_flag(span->channels[i], FTDM_CHANNEL_EVENT)) {
}
if (ftdm_test_io_flag(span->channels[i], FTDM_CHANNEL_IO_EVENT)) {
ftdm_status_t status;
wanpipe_tdm_api_t tdm_api;
ftdm_channel_t *ftdmchan = span->channels[i];
memset(&tdm_api, 0, sizeof(tdm_api));
ftdm_clear_flag(span->channels[i], FTDM_CHANNEL_EVENT);
ftdm_clear_io_flag(span->channels[i], FTDM_CHANNEL_IO_EVENT);
err = sangoma_tdm_read_event(ftdmchan->sockfd, &tdm_api);
if (err != FTDM_SUCCESS) {

View File

@ -976,13 +976,19 @@ FIO_SPAN_POLL_EVENT_FUNCTION(zt_poll_event)
snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno));
return FTDM_FAIL;
}
for(i = 1; i <= span->chan_count; i++) {
if (pfds[i-1].revents & POLLPRI) {
ftdm_set_flag(span->channels[i], FTDM_CHANNEL_EVENT);
ftdm_set_io_flag(span->channels[i], FTDM_CHANNEL_IO_EVENT);
span->channels[i]->last_event_time = ftdm_current_time_in_ms();
k++;
}
if (pfds[i-1].revents & POLLIN) {
ftdm_set_io_flag(span->channels[i], FTDM_CHANNEL_IO_READ);
}
if (pfds[i-1].revents & POLLOUT) {
ftdm_set_io_flag(span->channels[i], FTDM_CHANNEL_IO_WRITE);
}
}
if (!k) {
@ -1106,8 +1112,8 @@ FIO_CHANNEL_NEXT_EVENT_FUNCTION(zt_channel_next_event)
zt_event_t zt_event_id = 0;
ftdm_span_t *span = ftdmchan->span;
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_EVENT)) {
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_EVENT);
if (ftdm_test_io_flag(ftdmchan, FTDM_CHANNEL_IO_EVENT)) {
ftdm_clear_io_flag(ftdmchan, FTDM_CHANNEL_IO_EVENT);
}
if (ioctl(ftdmchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) {
@ -1143,8 +1149,8 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event)
for(i = 1; i <= span->chan_count; i++) {
ftdm_channel_t *fchan = span->channels[i];
if (ftdm_test_flag(fchan, FTDM_CHANNEL_EVENT)) {
ftdm_clear_flag(fchan, FTDM_CHANNEL_EVENT);
if (ftdm_test_io_flag(fchan, FTDM_CHANNEL_IO_EVENT)) {
ftdm_clear_io_flag(fchan, FTDM_CHANNEL_IO_EVENT);
if (ioctl(fchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) {
snprintf(span->last_error, sizeof(span->last_error), "%s", strerror(errno));
return FTDM_FAIL;

View File

@ -30,9 +30,10 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* Contributors:
*
* Moises Silva <moy@sangoma.com>
* David Yat Sin <dyatsin@sangoma.com>
*
*/
@ -241,12 +242,12 @@ FTDM_STR2ENUM_P(ftdm_str2ftdm_ton, ftdm_ton2str, ftdm_ton_t)
/*! Numbering Plan Identification (NPI) */
typedef enum {
FTDM_NPI_UNKNOWN = 0,
FTDM_NPI_ISDN = 1,
FTDM_NPI_DATA = 3,
FTDM_NPI_TELEX = 4,
FTDM_NPI_NATIONAL = 8,
FTDM_NPI_PRIVATE = 9,
FTDM_NPI_RESERVED = 10,
FTDM_NPI_ISDN,
FTDM_NPI_DATA,
FTDM_NPI_TELEX,
FTDM_NPI_NATIONAL,
FTDM_NPI_PRIVATE,
FTDM_NPI_RESERVED,
FTDM_NPI_INVALID
} ftdm_npi_t;
#define NPI_STRINGS "unknown", "ISDN", "data", "telex", "national", "private", "reserved", "invalid"
@ -317,9 +318,24 @@ typedef enum {
#define CALLING_PARTY_CATEGORY_STRINGS "unknown", "operator", "operator-french", "operator-english", "operator-german", "operator-russian", "operator-spanish", "ordinary", "priority", "data-call", "test-call", "payphone", "invalid"
FTDM_STR2ENUM_P(ftdm_str2ftdm_calling_party_category, ftdm_calling_party_category2str, ftdm_calling_party_category_t)
/*! Network responses to transfer requests */
typedef enum {
FTDM_TRANSFER_RESPONSE_OK, /* Call is being transferred */
FTDM_TRANSFER_RESPONSE_CP_DROP_OFF, /* Calling Party drop off */
FTDM_TRANSFER_RESPONSE_LIMITS_EXCEEDED, /* Cannot redirect, limits exceeded */
FTDM_TRANSFER_RESPONSE_INVALID_NUM, /* Network did not receive or recognize dialed number */
FTDM_TRANSFER_RESPONSE_INVALID_COMMAND, /* Network received an invalid command */
FTDM_TRANSFER_RESPONSE_TIMEOUT, /* We did not receive a response from Network */
FTDM_TRANSFER_RESPONSE_INVALID,
} ftdm_transfer_response_t;
#define TRANSFER_RESPONSE_STRINGS "transfer-ok", "cp-drop-off", "limits-exceeded", "invalid-num", "invalid-command", "timeout", "invalid"
FTDM_STR2ENUM_P(ftdm_str2ftdm_transfer_response, ftdm_transfer_response2str, ftdm_transfer_response_t)
/*! \brief Digit limit used in DNIS/ANI */
#define FTDM_DIGITS_LIMIT 25
#define FTDM_SILENCE_VALUE(fchan) (fchan)->native_codec == FTDM_CODEC_ULAW ? 255 : (fchan)->native_codec == FTDM_CODEC_ALAW ? 0xD5 : 0x00
/*! \brief Number abstraction */
typedef struct {
char digits[FTDM_DIGITS_LIMIT];
@ -434,13 +450,14 @@ typedef enum {
FTDM_SIGEVENT_TRACE, /*!<Interpreted trace event */
FTDM_SIGEVENT_TRACE_RAW, /*!<Raw trace event */
FTDM_SIGEVENT_INDICATION_COMPLETED, /*!< Last requested indication was completed */
FTDM_SIGEVENT_DIALING, /* Outgoing call just started */
FTDM_SIGEVENT_DIALING, /*!< Outgoing call just started */
FTDM_SIGEVENT_TRANSFER_COMPLETED, /*!< Transfer request is completed */
FTDM_SIGEVENT_INVALID, /*!<Invalid */
} ftdm_signal_event_t;
#define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROCEED", "RINGING", "PROGRESS", \
"PROGRESS_MEDIA", "ALARM_TRAP", "ALARM_CLEAR", \
"COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "FACILITY", \
"TRACE", "TRACE_RAW", "INDICATION_COMPLETED", "DIALING", "INVALID"
"TRACE", "TRACE_RAW", "INDICATION_COMPLETED", "DIALING", "TRANSFER_COMPLETED", "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)
@ -543,12 +560,13 @@ typedef enum {
/* Using this indication is equivalent to call ftdm_channel_call_answer API */
FTDM_CHANNEL_INDICATE_ANSWER,
FTDM_CHANNEL_INDICATE_FACILITY,
FTDM_CHANNEL_INDICATE_TRANSFER,
FTDM_CHANNEL_INDICATE_INVALID,
} ftdm_channel_indication_t;
#define INDICATION_STRINGS "NONE", "RINGING", "PROCEED", "PROGRESS", "PROGRESS_MEDIA", "BUSY", "ANSWER", "FACILITY", "INVALID"
#define INDICATION_STRINGS "NONE", "RINGING", "PROCEED", "PROGRESS", "PROGRESS_MEDIA", "BUSY", "ANSWER", "FACILITY", "TRANSFER", "INVALID"
/*! \brief Move from string to ftdm_channel_indication_t and viceversa */
FTDM_STR2ENUM_P(ftdm_str2channel_indication, ftdm_channel_indication2str, ftdm_channel_indication_t)
FTDM_STR2ENUM_P(ftdm_str2ftdm_channel_indication, ftdm_channel_indication2str, ftdm_channel_indication_t)
typedef struct {
/* The indication that was completed */
@ -557,6 +575,10 @@ typedef struct {
ftdm_status_t status;
} ftdm_event_indication_completed_t;
typedef struct {
ftdm_transfer_response_t response;
} ftdm_event_transfer_completed_t;
typedef void * ftdm_variable_container_t;
typedef struct {
@ -578,6 +600,7 @@ struct ftdm_sigmsg {
ftdm_event_trace_t trace; /*!< valid if event_id is FTDM_SIGEVENT_TRACE or FTDM_SIGEVENT_TRACE_RAW */
ftdm_event_collected_t collected; /*!< valid if event_id is FTDM_SIGEVENT_COLLECTED_DIGIT */
ftdm_event_indication_completed_t indication_completed; /*!< valid if the event_id is FTDM_SIGEVENT_INDICATION_COMPLETED */
ftdm_event_transfer_completed_t transfer_completed;
} ev_data;
ftdm_raw_data_t raw;
};
@ -911,7 +934,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char
#define ftdm_channel_call_place(ftdmchan) _ftdm_channel_call_place(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), NULL)
#define ftdm_channel_call_place_ex(ftdmchan, usrmsg) _ftdm_channel_call_place_ex(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (usrmsg))
/*! \brief Place an outgoing call recording the source code point where it was called (see ftdm_channel_call_place for an easy to use macro)
/*! \brief Place an outgoing call recording the source code point where it was called (see ftdm_channel_call_place for an easy to use macro)
* \deprecated This function is deprecated since leaves the door open to glare issues, use ftdm_call_place instead
*/
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg);
@ -970,6 +993,20 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup(const char *file, const char
/*! \brief Hangup the call with cause recording the source code point where it was called (see ftdm_channel_call_hangup_with_cause for an easy to use macro) */
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup_with_cause(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_call_cause_t, ftdm_usrmsg_t *usrmsg);
/*! \brief Transfer call. This can also be accomplished by ftdm_channel_call_indicate with FTDM_CHANNEL_INDICATE_TRANSFER, in both
* cases you will get a FTDM_SIGEVENT_INDICATION_COMPLETED when the indication is sent (or an error occurs).
* Just as with ftdm_channel_call_indicate you won't receive FTDM_SIGEVENT_INDICATION_COMPLETED when this function
* returns anything else than FTDM_SUCCESS
* \note Although this API may result in FTDM_SIGEVENT_INDICATION_COMPLETED event being delivered,
* there is no guarantee of whether the event will arrive after or before your execution thread returns
* from ftdm_channel_call_transfer
*/
#define ftdm_channel_call_transfer(ftdmchan, arg) _ftdm_channel_call_transfer(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (arg), NULL)
#define ftdm_channel_call_transfer_ex(ftdmchan, arg, usrmsg) _ftdm_channel_call_transfer(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (arg), (usrmsg))
/*! \brief Answer call recording the source code point where the it was called (see ftdm_channel_call_tranasfer for an easy to use macro) */
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_transfer(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, const char* arg, ftdm_usrmsg_t *usrmsg);
/*! \brief Reset the channel */
#define ftdm_channel_reset(ftdmchan) _ftdm_channel_reset(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), NULL)
#define ftdm_channel_reset_ex(ftdmchan, usrmsg) _ftdm_channel_reset(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), usrmsg)
@ -1240,7 +1277,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_add_to_group(const char* name, ftdm_chann
/*! \brief Remove the channel from a hunt group */
FT_DECLARE(ftdm_status_t) ftdm_channel_remove_from_group(ftdm_group_t* group, ftdm_channel_t* ftdmchan);
/*!
/*!
* \brief Retrieves an event from the span
*
* \note

View File

@ -155,6 +155,10 @@ extern "C" {
#define ftdm_clear_alarm_flag(obj, flag) (obj)->alarm_flags &= ~(flag)
#define ftdm_test_alarm_flag(obj, flag) ((obj)->alarm_flags & flag)
#define ftdm_set_io_flag(obj, flag) (obj)->io_flags |= (flag)
#define ftdm_clear_io_flag(obj, flag) (obj)->io_flags &= ~(flag)
#define ftdm_test_io_flag(obj, flag) ((obj)->io_flags & flag)
/*!
\brief Set a flag on an arbitrary object
\command obj the object to set the flags on
@ -399,6 +403,7 @@ struct ftdm_channel {
uint64_t flags;
uint32_t pflags;
uint32_t sflags;
uint8_t io_flags;
ftdm_alarm_flag_t alarm_flags;
ftdm_channel_feature_t features;
ftdm_codec_t effective_codec;
@ -503,6 +508,7 @@ struct ftdm_span {
ftdm_span_stop_t stop;
ftdm_channel_sig_read_t sig_read;
ftdm_channel_sig_write_t sig_write;
ftdm_channel_sig_dtmf_t sig_dtmf;
ftdm_channel_state_processor_t state_processor; /*!< This guy is called whenever state processing is required */
void *io_data; /*!< Private I/O data per span. Do not touch unless you are an I/O module */
char *type;
@ -591,6 +597,10 @@ FT_DECLARE(void) ftdm_ack_indication(ftdm_channel_t *ftdmchan, ftdm_channel_indi
FT_DECLARE(ftdm_iterator_t *) ftdm_get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t *iter);
FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen);
FIO_WRITE_FUNCTION(ftdm_raw_write);
FIO_READ_FUNCTION(ftdm_raw_read);
/*!
* \brief Retrieves an event from the span

View File

@ -67,6 +67,7 @@ typedef enum {
FTDM_CHANNEL_STATE_PROGRESS,
FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
FTDM_CHANNEL_STATE_UP,
FTDM_CHANNEL_STATE_TRANSFER,
FTDM_CHANNEL_STATE_IDLE,
FTDM_CHANNEL_STATE_TERMINATING,
FTDM_CHANNEL_STATE_CANCEL,
@ -78,7 +79,7 @@ typedef enum {
} ftdm_channel_state_t;
#define CHANNEL_STATE_STRINGS "DOWN", "HOLD", "SUSPENDED", "DIALTONE", "COLLECT", \
"RING", "RINGING", "BUSY", "ATTN", "GENRING", "DIALING", "GET_CALLERID", "CALLWAITING", \
"RESTART", "PROCEED", "PROGRESS", "PROGRESS_MEDIA", "UP", "IDLE", "TERMINATING", "CANCEL", \
"RESTART", "PROCEED", "PROGRESS", "PROGRESS_MEDIA", "UP", "TRANSFER", "IDLE", "TERMINATING", "CANCEL", \
"HANGUP", "HANGUP_COMPLETE", "IN_LOOP", "RESET", "INVALID"
FTDM_STR2ENUM_P(ftdm_str2ftdm_channel_state, ftdm_channel_state2str, ftdm_channel_state_t)

View File

@ -189,6 +189,8 @@ typedef enum {
/* If this flag is set, then this span cannot be stopped individually, it can only be stopped
on freetdm unload */
FTDM_SPAN_NON_STOPPABLE = (1 << 13),
/* If this flag is set, then this span supports TRANSFER state */
FTDM_SPAN_USE_TRANSFER = (1 << 14),
} ftdm_span_flag_t;
/*! \brief Channel supported features */
@ -206,6 +208,13 @@ typedef enum {
FTDM_CHANNEL_FEATURE_MF_GENERATE = (1<<10), /*!< Channel can generate R2 MF tones (read-only) */
} ftdm_channel_feature_t;
/*! \brief Channel IO pending flags */
typedef enum {
FTDM_CHANNEL_IO_EVENT = (1 << 0),
FTDM_CHANNEL_IO_READ = (1 << 1),
FTDM_CHANNEL_IO_WRITE = (1 << 2),
} ftdm_channel_io_flags_t;
/*!< Channel flags. This used to be an enum but we reached the 32bit limit for enums, is safer this way */
#define FTDM_CHANNEL_CONFIGURED (1ULL << 0)
#define FTDM_CHANNEL_READY (1ULL << 1)
@ -214,7 +223,6 @@ typedef enum {
#define FTDM_CHANNEL_SUPRESS_DTMF (1ULL << 4)
#define FTDM_CHANNEL_TRANSCODE (1ULL << 5)
#define FTDM_CHANNEL_BUFFER (1ULL << 6)
#define FTDM_CHANNEL_EVENT (1ULL << 7)
#define FTDM_CHANNEL_INTHREAD (1ULL << 8)
#define FTDM_CHANNEL_WINK (1ULL << 9)
#define FTDM_CHANNEL_FLASH (1ULL << 10)
@ -249,6 +257,8 @@ typedef enum {
#define FTDM_CHANNEL_IND_ACK_PENDING (1ULL << 34)
/*!< There is someone blocking in the channel waiting for state completion */
#define FTDM_CHANNEL_BLOCKING (1ULL << 35)
/*!< Media is digital */
#define FTDM_CHANNEL_DIGITAL_MEDIA (1ULL << 36)
#include "ftdm_state.h"
@ -329,10 +339,11 @@ typedef ftdm_status_t (*ftdm_span_start_t)(ftdm_span_t *span);
typedef ftdm_status_t (*ftdm_span_stop_t)(ftdm_span_t *span);
typedef ftdm_status_t (*ftdm_channel_sig_read_t)(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t size);
typedef ftdm_status_t (*ftdm_channel_sig_write_t)(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t size);
typedef ftdm_status_t (*ftdm_channel_sig_dtmf_t)(ftdm_channel_t *ftdmchan, const char *dtmf);
typedef enum {
FTDM_ITERATOR_VARS = 1,
FTDM_ITERATOR_CHANS,
FTDM_ITERATOR_CHANS,
} ftdm_iterator_type_t;
struct ftdm_iterator {

View File

@ -273,7 +273,7 @@ TELETONE_API(int) teletone_mux_tones(teletone_generation_session_t *ts, teletone
TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cmd)
{
char *data = NULL, *cur = NULL, *end = NULL;
int var = 0, LOOPING = 0;
int LOOPING = 0;
if (!cmd) {
return -1;
@ -287,7 +287,6 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm
cur = data;
while (*cur) {
var = 0;
if (*cur == ' ' || *cur == '\r' || *cur == '\n') {
cur++;
continue;
@ -298,7 +297,6 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm
}
if (*(cur + 1) == '=') {
var = 1;
switch(*cur) {
case 'c':
ts->channels = atoi(cur + 2);

View File

@ -242,7 +242,7 @@ static void default_logger(char *file, const char *func, int line, int level, ch
vsnprintf(data, sizeof(data), fmt, ap);
fprintf(globals.log_stream, "%s:%d %s() %s", file, line, func, data);
fprintf(globals.log_stream, "%s:%d %s() %s", fp, line, func, data);
va_end(ap);
@ -997,9 +997,9 @@ static int on_commands(void *user_data, ikspak *pak)
uint8_t is_result = strcasecmp(type, "result") ? 0 : 1;
uint8_t is_error = strcasecmp(type, "error") ? 0 : 1;
iks *xml, *xsession, *xerror = NULL, *xredir = NULL;
struct iks_tag* tmp;
xml = iks_child (pak->x);
tmp = (struct iks_tag*) xml;
if (is_error) {
if ((xerror = working_find(xml, "error"))) {
char *code = iks_find_attrib(xerror, "code");

View File

@ -321,7 +321,7 @@ static char *my_strdup (const char *s)
TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cmd)
{
char *data = NULL, *cur = NULL, *end = NULL;
int var = 0, LOOPING = 0;
int LOOPING = 0;
if (!cmd) {
return -1;
@ -335,7 +335,6 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm
cur = data;
while (*cur) {
var = 0;
if (*cur == ' ' || *cur == '\r' || *cur == '\n') {
cur++;
continue;
@ -346,7 +345,6 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm
}
if (*(cur + 1) == '=') {
var = 1;
switch(*cur) {
case 'c':
ts->channels = atoi(cur + 2);

View File

@ -1 +1 @@
Tue Mar 22 15:01:49 CDT 2011
Wed Apr 27 11:49:37 CDT 2011

View File

@ -182,7 +182,7 @@ int time_d(char const **ss,
issize_t msg_date_d(char const **ss, msg_time_t *date)
{
char const *s = *ss;
char const *wkday;
//char const *wkday;
char const *tz;
unsigned long day, year, hour, min, sec;
int mon;
@ -190,7 +190,8 @@ issize_t msg_date_d(char const **ss, msg_time_t *date)
if (!IS_TOKEN(*s) || !date)
return -1;
wkday = s; skip_token(&s); if (*s == ',') s++;
//wkday = s;
skip_token(&s); if (*s == ',') s++;
while (IS_LWS(*s)) s++;
if (is_digit(*s)) {

View File

@ -550,7 +550,7 @@ int nea_server_shutdown(nea_server_t *nes,
int retry_after)
{
nea_sub_t *s;
int status = 200;
// int status = 200;
int in_callback;
if (nes == NULL)
@ -576,8 +576,8 @@ int nea_server_shutdown(nea_server_t *nes,
TAG_IF(!retry_after, NEATAG_REASON("deactivated")),
TAG_IF(retry_after, NEATAG_RETRY_AFTER(retry_after)),
TAG_END());
else
status = 180;
//else
//status = 180;
}
nes->nes_in_callback = in_callback;

View File

@ -2307,7 +2307,7 @@ int agent_init_via(nta_agent_t *self, tport_t *primaries, int use_maddr)
/* Set via fields for the tports */
for (tp = primaries; tp; tp = tport_next(tp)) {
int maddr, first_via;
int maddr;
tp_name_t tpn[1];
char const *comp = NULL;
@ -2339,8 +2339,6 @@ int agent_init_via(nta_agent_t *self, tport_t *primaries, int use_maddr)
if (tport_has_tls(tp)) self->sa_tport_tls = 1;
first_via = 1;
ai = tport_get_address(tp);
for (; ai; ai = ai->ai_next) {

View File

@ -1879,14 +1879,14 @@ int nua_registration_process_request(nua_registration_t *list,
nta_incoming_t *irq,
sip_t const *sip)
{
sip_call_id_t *i;
//sip_call_id_t *i;
nua_registration_t *nr;
if (!outbound_targeted_request(sip))
return 0;
/* Process by outbound... */
i = sip->sip_call_id;
//i = sip->sip_call_id;
for (nr = list; nr; nr = nr->nr_next) {
outbound_t *ob = nr->nr_ob;

View File

@ -1743,7 +1743,7 @@ static int nua_prack_client_request(nua_client_request_t *cr,
nua_client_request_t *cri;
int offer_sent = 0, answer_sent = 0, retval;
int status = 0; char const *phrase = "PRACK Sent";
uint32_t rseq = 0;
//uint32_t rseq = 0;
if (du == NULL) /* Call terminated */
return nua_client_return(cr, SIP_481_NO_TRANSACTION, msg);
@ -1754,8 +1754,8 @@ static int nua_prack_client_request(nua_client_request_t *cr,
cri = du->du_cr;
if (sip->sip_rack)
rseq = sip->sip_rack->ra_response;
// if (sip->sip_rack)
// rseq = sip->sip_rack->ra_response;
if (cri->cr_offer_recv && !cri->cr_answer_sent) {
if (nh->nh_soa == NULL)

View File

@ -1883,12 +1883,11 @@ static char *next(char **message, const char *sep, const char *strip)
static int parsing_error(sdp_parser_t *p, char const *fmt, ...)
{
int n;
va_list ap;
va_start(ap, fmt);
memset(p->pr_error, 0, sizeof(p->pr_error));
n = vsnprintf(p->pr_error, sizeof(p->pr_error), fmt, ap);
vsnprintf(p->pr_error, sizeof(p->pr_error), fmt, ap);
va_end(ap);
p->pr_ok = 0;

View File

@ -685,9 +685,8 @@ static void printing_error(sdp_printer_t *p, const char *fmt, ...)
va_list ap;
if (p->pr_ok) {
int n;
va_start(ap, fmt);
n = vsnprintf(p->pr_buffer, p->pr_bsiz, fmt, ap);
vsnprintf(p->pr_buffer, p->pr_bsiz, fmt, ap);
va_end(ap);
}

View File

@ -1010,7 +1010,6 @@ int soa_sdp_mode_set(sdp_session_t const *user,
int retval = 0, i, j;
int hold_all;
int inactive_all;
int inactive = 0;
char const *hold_media = NULL;
sdp_mode_t send_mode, recv_mode;
@ -1029,7 +1028,6 @@ int soa_sdp_mode_set(sdp_session_t const *user,
for (sm = session->sdp_media; sm; sm = sm->m_next, rm = rm_next, i++) {
rm_next = rm ? rm->m_next : NULL;
inactive = 0;
if (sm->m_rejected)
continue;

View File

@ -3636,6 +3636,10 @@ sres_decode_msg(sres_resolver_t *res,
m_get_domain(name, sizeof(name), m, 0); /* Query domain */
qtype = m_get_uint16(m); /* Query type */
qclass = m_get_uint16(m); /* Query class */
if (qtype && qclass) {
/* XXX: never mind these useless check, this is done to make compiler happy about unused value */
}
}
if (m->m_error) {

View File

@ -673,12 +673,12 @@ static stun_request_t *stun_request_create(stun_discovery_t *sd)
void stun_request_destroy(stun_request_t *req)
{
stun_handle_t *sh;
//stun_handle_t *sh;
assert(req);
enter;
sh = req->sr_handle;
//sh = req->sr_handle;
if (x_is_inserted(req, sr))
x_remove(req, sr);
@ -1140,14 +1140,14 @@ static stun_discovery_t *stun_discovery_create(stun_handle_t *sh,
static int stun_discovery_destroy(stun_discovery_t *sd)
{
stun_handle_t *sh;
//stun_handle_t *sh;
enter;
if (!sd)
return errno = EFAULT, -1;
sh = sd->sd_handle;
//sh = sd->sd_handle;
if (sd->sd_timer)
su_timer_destroy(sd->sd_timer), sd->sd_timer = NULL;
@ -1883,7 +1883,7 @@ static int process_test_lifetime(stun_request_t *req, stun_msg_t *binding_respon
stun_discovery_t *sd = req->sr_discovery;
stun_request_t *new;
stun_handle_t *sh = req->sr_handle;
su_localinfo_t *li;
//su_localinfo_t *li;
su_sockaddr_t *sa;
su_timer_t *sockfdy_timer = NULL;
su_socket_t sockfdy = sd->sd_socket2;
@ -1954,7 +1954,7 @@ static int process_test_lifetime(stun_request_t *req, stun_msg_t *binding_respon
/* Rock, we come from sockfdx */
process_binding_request(req, binding_response);
li = &req->sr_localinfo;
//li = &req->sr_localinfo;
sa = req->sr_local_addr;
stun_free_message(binding_response);
@ -1981,7 +1981,7 @@ static int process_test_lifetime(stun_request_t *req, stun_msg_t *binding_respon
static int action_bind(stun_request_t *req, stun_msg_t *binding_response)
{
su_localinfo_t *li = NULL;
//su_localinfo_t *li = NULL;
su_sockaddr_t *sa = NULL;
stun_discovery_t *sd = req->sr_discovery;
stun_handle_t *sh = req->sr_handle;
@ -1992,7 +1992,7 @@ static int action_bind(stun_request_t *req, stun_msg_t *binding_response)
process_binding_request(req, binding_response);
li = &req->sr_localinfo;
//li = &req->sr_localinfo;
sa = req->sr_local_addr;
memcpy(sd->sd_addr_seen_outside, sa, sizeof(su_sockaddr_t));
@ -3039,7 +3039,7 @@ int stun_process_request(su_socket_t s, stun_msg_t *req,
su_sockaddr_t mod_addr[1] = {{ 0 }}, src_addr[1] = {{ 0 }}, chg_addr[1] = {{ 0 }};
stun_attr_t *tmp, m_attr[1], s_attr[1], c_attr[1], **p;
su_sockaddr_t to_addr;
int c, i;
int i;
tmp = stun_get_attr(req->stun_attr, RESPONSE_ADDRESS);
@ -3071,20 +3071,20 @@ int stun_process_request(su_socket_t s, stun_msg_t *req,
/* SOURCE-ADDRESS depends on CHANGE_REQUEST */
tmp = stun_get_attr(req->stun_attr, CHANGE_REQUEST);
if (!tmp) {
c = 0;
//c = 0;
}
else {
switch (((stun_attr_changerequest_t *) tmp->pattr)->value) {
case STUN_CR_CHANGE_IP:
c = 1;
//c = 1;
break;
case STUN_CR_CHANGE_PORT:
c = 2;
//c = 2;
break;
case STUN_CR_CHANGE_IP | STUN_CR_CHANGE_PORT: /* bitwise or */
c = 3;
//c = 3;
break;
default:

View File

@ -163,7 +163,10 @@ stun_dns_lookup_t *stun_dns_lookup(stun_magic_t *magic,
query = sres_query(self->stun_sres, priv_sres_cb, self,
sres_type_srv,
srvname);
}
if (query) {
/* TODO Just so compiler doesn't give error */
}
}
else {
su_free(NULL, self), self = NULL;
}

View File

@ -429,13 +429,13 @@ void *sub_alloc(su_home_t *home,
if (sub == NULL || 3 * sub->sub_used > 2 * sub->sub_n) {
/* Resize the hash table */
size_t i, n, n2, used;
size_t i, n, n2;
su_block_t *b2;
if (sub)
n = home->suh_blocks->sub_n, n2 = 4 * n + 3, used = sub->sub_used;
n = home->suh_blocks->sub_n, n2 = 4 * n + 3; //, used = sub->sub_used;
else
n = 0, n2 = SUB_N, used = 0;
n = 0, n2 = SUB_N; //, used = 0;
#if 0
printf("su_alloc(home = %p): realloc block hash of size %d\n", home, n2);

View File

@ -194,7 +194,8 @@ static void li_sort(su_localinfo_t *i, su_localinfo_t **rresult);
int su_getlocalinfo(su_localinfo_t const *hints,
su_localinfo_t **return_localinfo)
{
int error = 0, ip4 = 0, ip6 = 0;
int error = 0, ip4 = 0;
int ip6 = 0;
su_localinfo_t *result = NULL, **rr = &result;
su_localinfo_t hh[1] = {{ 0 }};
@ -231,7 +232,11 @@ int su_getlocalinfo(su_localinfo_t const *hints,
break;
case 0:
ip6 = ip4 = 1;
ip4 = 1;
#if SU_HAVE_IN6
ip6 = 1;
#endif
break;
default:
@ -260,6 +265,9 @@ int su_getlocalinfo(su_localinfo_t const *hints,
}
#endif
if (ip6) {
/* Required to make compiler happy */
}
if (!result)
error = ELI_NOADDRESS;

View File

@ -478,7 +478,7 @@ size_t su_memspn(const void *mem, size_t memlen,
* of bytes not in @a reject.
*
* @param mem pointer to memory area
* @param memlen size of @a mem in bytes
* @param memlen size of @a mem in bytes
* @param reject pointer to table containing bytes to reject
* @param rejectlen size of @a reject table
*

View File

@ -1595,7 +1595,7 @@ int tport_bind_server(tport_master_t *mr,
{
char hostname[TPORT_HOSTPORTSIZE];
char const *canon = NULL, *host, *service;
int error = 0, not_supported, family = 0;
int error = 0, family = 0;
tport_primary_t *pri = NULL, **tbf;
su_addrinfo_t *ai, *res = NULL;
unsigned port, port0, port1, old;
@ -1691,8 +1691,6 @@ int tport_bind_server(tport_master_t *mr,
break;
}
not_supported = 0;
if (port0 == 0 && port == 0) {
port = port1 = ntohs(su->su_port);
assert(public != tport_type_server || port != 0);

View File

@ -170,10 +170,10 @@ void tport_stun_bind_cb(tport_primary_t *pri,
stun_action_t action,
stun_state_t event)
{
tport_master_t *mr;
//tport_master_t *mr;
SU_DEBUG_3(("%s: %s\n", __func__, stun_str_state(event)));
mr = pri->pri_master;
//mr = pri->pri_master;
if (event == stun_discovery_done) {
tport_stun_bind_done(pri, sh, sd);

View File

@ -567,7 +567,7 @@ static
int _url_d(url_t *url, char *s)
{
size_t n, p;
char *s0, rest_c, *host, *user;
char rest_c, *host, *user;
int have_authority = 1;
memset(url, 0, sizeof(*url));
@ -578,8 +578,6 @@ int _url_d(url_t *url, char *s)
return 0;
}
s0 = s;
n = strcspn(s, ":/?#");
if (n && s[n] == ':') {

View File

@ -1 +1 @@
Mon Jun 7 20:09:38 EDT 2010
Wed May 4 10:03:23 CDT 2011

View File

@ -165,10 +165,10 @@ SPAN_DECLARE(int) plc_fillin(plc_state_t *s, int16_t amp[], int len)
float old_weight;
float new_weight;
float gain;
int16_t *orig_amp;
//int16_t *orig_amp;
int orig_len;
orig_amp = amp;
//orig_amp = amp;
orig_len = len;
if (s->missing_samples == 0)
{

View File

@ -799,7 +799,11 @@ SPAN_DECLARE(int) t38_core_send_indicator(t38_core_state_t *s, int indicator)
return len;
}
span_log(&s->logging, SPAN_LOG_FLOW, "Tx %5d: indicator %s\n", s->tx_seq_no, t38_indicator_to_str(indicator));
s->tx_packet_handler(s, s->tx_packet_user_data, buf, len, transmissions);
if (s->tx_packet_handler(s, s->tx_packet_user_data, buf, len, transmissions) < 0)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Tx Packet Handler Failure\n");
return -1;
}
s->tx_seq_no = (s->tx_seq_no + 1) & 0xFFFF;
delay = modem_startup_time[indicator].training;
if (s->allow_for_tep)
@ -837,7 +841,11 @@ SPAN_DECLARE(int) t38_core_send_data(t38_core_state_t *s, int data_type, int fie
span_log(&s->logging, SPAN_LOG_FLOW, "T.38 data len is %d\n", len);
return len;
}
s->tx_packet_handler(s, s->tx_packet_user_data, buf, len, s->category_control[category]);
if (s->tx_packet_handler(s, s->tx_packet_user_data, buf, len, s->category_control[category]) < 0)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Tx Packet Handler Failure\n");
return -1;
}
s->tx_seq_no = (s->tx_seq_no + 1) & 0xFFFF;
return 0;
}
@ -853,7 +861,11 @@ SPAN_DECLARE(int) t38_core_send_data_multi_field(t38_core_state_t *s, int data_t
span_log(&s->logging, SPAN_LOG_FLOW, "T.38 data len is %d\n", len);
return len;
}
s->tx_packet_handler(s, s->tx_packet_user_data, buf, len, s->category_control[category]);
if (s->tx_packet_handler(s, s->tx_packet_user_data, buf, len, s->category_control[category]) < 0)
{
span_log(&s->logging, SPAN_LOG_PROTOCOL_WARNING, "Tx Packet Handler Failure\n");
return -1;
}
s->tx_seq_no = (s->tx_seq_no + 1) & 0xFFFF;
return 0;
}

View File

@ -63,10 +63,18 @@
#include "spandsp/v17rx.h"
#include "spandsp/t4_rx.h"
#include "spandsp/t4_tx.h"
#if defined(SPANDSP_SUPPORT_T85)
#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85)
#include "spandsp/t81_t82_arith_coding.h"
#endif
#if defined(SPANDSP_SUPPORT_T85)
#include "spandsp/t85.h"
#endif
#if defined(SPANDSP_SUPPORT_T42)
#include "spandsp/t42.h"
#endif
#if defined(SPANDSP_SUPPORT_T43)
#include "spandsp/t43.h"
#endif
#include "spandsp/t4_t6_decode.h"
#include "spandsp/t4_t6_encode.h"
#include "spandsp/t30_fcf.h"
@ -78,10 +86,18 @@
#include "spandsp/t38_terminal.h"
#include "spandsp/private/logging.h"
#if defined(SPANDSP_SUPPORT_T85)
#if defined(SPANDSP_SUPPORT_T42) || defined(SPANDSP_SUPPORT_T43) | defined(SPANDSP_SUPPORT_T85)
#include "spandsp/private/t81_t82_arith_coding.h"
#endif
#if defined(SPANDSP_SUPPORT_T85)
#include "spandsp/private/t85.h"
#endif
#if defined(SPANDSP_SUPPORT_T42)
#include "spandsp/private/t42.h"
#endif
#if defined(SPANDSP_SUPPORT_T43)
#include "spandsp/private/t43.h"
#endif
#include "spandsp/private/t4_t6_decode.h"
#include "spandsp/private/t4_t6_encode.h"
#include "spandsp/private/t4_rx.h"
@ -629,7 +645,9 @@ static int set_no_signal(t38_terminal_state_t *s)
if ((s->t38_fe.chunking_modes & T38_CHUNKING_SEND_REGULAR_INDICATORS))
{
t38_core_send_indicator(&s->t38_fe.t38, 0x100 | T38_IND_NO_SIGNAL);
if ((delay = t38_core_send_indicator(&s->t38_fe.t38, 0x100 | T38_IND_NO_SIGNAL)) < 0)
return delay;
/*endif*/
s->t38_fe.timed_step = T38_TIMED_STEP_NO_SIGNAL;
#if 0
if ((s->t38_fe.chunking_modes & T38_CHUNKING_SEND_2S_REGULAR_INDICATORS))
@ -641,7 +659,9 @@ static int set_no_signal(t38_terminal_state_t *s)
return s->t38_fe.ms_per_tx_chunk*1000;
}
/*endif*/
delay = t38_core_send_indicator(&s->t38_fe.t38, T38_IND_NO_SIGNAL);
if ((delay = t38_core_send_indicator(&s->t38_fe.t38, T38_IND_NO_SIGNAL)) < 0)
return delay;
/*endif*/
s->t38_fe.timed_step = T38_TIMED_STEP_NONE;
return delay;
}
@ -649,7 +669,11 @@ static int set_no_signal(t38_terminal_state_t *s)
static int stream_no_signal(t38_terminal_state_t *s)
{
t38_core_send_indicator(&s->t38_fe.t38, 0x100 | T38_IND_NO_SIGNAL);
int delay;
if ((delay = t38_core_send_indicator(&s->t38_fe.t38, 0x100 | T38_IND_NO_SIGNAL)) < 0)
return delay;
/*endif*/
#if 0
if (s->t38_fe.timeout_tx_samples && s->t38_fe.next_tx_samples >= s->t38_fe.timeout_tx_samples)
s->t38_fe.timed_step = T38_TIMED_STEP_NONE;
@ -663,6 +687,7 @@ static int stream_non_ecm(t38_terminal_state_t *s)
{
t38_terminal_front_end_state_t *fe;
uint8_t buf[MAX_OCTETS_PER_UNPACED_CHUNK + 50];
int res;
int delay;
int len;
@ -674,9 +699,15 @@ static int stream_non_ecm(t38_terminal_state_t *s)
case T38_TIMED_STEP_NON_ECM_MODEM:
/* Create a 75ms silence */
if (fe->t38.current_tx_indicator != T38_IND_NO_SIGNAL)
delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL);
{
if ((delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL)) < 0)
return delay;
/*endif*/
}
else
{
delay = 75000;
}
/*endif*/
fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_2;
#if 0
@ -690,7 +721,9 @@ static int stream_non_ecm(t38_terminal_state_t *s)
#if 0
if ((s->t38_fe.chunking_modes & T38_CHUNKING_SEND_REGULAR_INDICATORS))
{
delay = t38_core_send_indicator(&fe->t38, 0x100 | fe->next_tx_indicator);
if ((delay = t38_core_send_indicator(&fe->t38, 0x100 | fe->next_tx_indicator)) < 0)
return delay;
/*endif*/
if (fe->next_tx_samples >= fe->timeout_tx_samples)
fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_3;
/*endif*/
@ -698,7 +731,9 @@ static int stream_non_ecm(t38_terminal_state_t *s)
}
/*endif*/
#endif
delay = t38_core_send_indicator(&fe->t38, fe->next_tx_indicator);
if ((delay = t38_core_send_indicator(&fe->t38, fe->next_tx_indicator)) < 0)
return delay;
/*endif*/
fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_3;
break;
case T38_TIMED_STEP_NON_ECM_MODEM_3:
@ -731,7 +766,9 @@ static int stream_non_ecm(t38_terminal_state_t *s)
else
{
/* If we are sending quickly there seems no point in doing any padding */
t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_SIG_END, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA_END);
if ((res = t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_SIG_END, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA_END)) < 0)
return res;
/*endif*/
fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_5;
delay = 0;
break;
@ -739,7 +776,9 @@ static int stream_non_ecm(t38_terminal_state_t *s)
/*endif*/
}
/*endif*/
t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA);
if ((res = t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA)) < 0)
return res;
/*endif*/
delay = bits_to_us(s, 8*len);
break;
case T38_TIMED_STEP_NON_ECM_MODEM_4:
@ -750,7 +789,9 @@ static int stream_non_ecm(t38_terminal_state_t *s)
{
len += fe->non_ecm_trailer_bytes;
memset(buf, 0, len);
t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_SIG_END, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA_END);
if ((res = t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_SIG_END, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA_END)) < 0)
return res;
/*endif*/
fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_5;
/* Allow a bit more time than the data will take to play out, to ensure the far ATA does not
cut things short. */
@ -763,7 +804,9 @@ static int stream_non_ecm(t38_terminal_state_t *s)
}
/*endif*/
memset(buf, 0, len);
t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA);
if ((res = t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA)) < 0)
return res;
/*endif*/
delay = bits_to_us(s, 8*len);
break;
case T38_TIMED_STEP_NON_ECM_MODEM_5:
@ -785,6 +828,7 @@ static int stream_hdlc(t38_terminal_state_t *s)
t38_data_field_t data_fields[2];
int category;
int previous;
int res;
int delay;
int i;
@ -796,9 +840,15 @@ static int stream_hdlc(t38_terminal_state_t *s)
case T38_TIMED_STEP_HDLC_MODEM:
/* Create a 75ms silence */
if (fe->t38.current_tx_indicator != T38_IND_NO_SIGNAL)
delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL);
{
if ((delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL)) < 0)
return delay;
/*endif*/
}
else
{
delay = 75000;
}
/*endif*/
fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_2;
#if 0
@ -814,7 +864,9 @@ static int stream_hdlc(t38_terminal_state_t *s)
#if 0
if ((s->t38_fe.chunking_modes & T38_CHUNKING_SEND_REGULAR_INDICATORS))
{
delay = t38_core_send_indicator(&fe->t38, 0x100 | fe->next_tx_indicator);
if ((delay = t38_core_send_indicator(&fe->t38, 0x100 | fe->next_tx_indicator)) < 0)
return delay;
/*endif*/
if (fe->next_tx_samples >= fe->timeout_tx_samples)
fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3;
/*endif*/
@ -822,8 +874,10 @@ static int stream_hdlc(t38_terminal_state_t *s)
}
/*endif*/
#endif
delay = t38_core_send_indicator(&fe->t38, fe->next_tx_indicator)
+ t38_core_send_flags_delay(&fe->t38, fe->next_tx_indicator);
if ((delay = t38_core_send_indicator(&fe->t38, fe->next_tx_indicator)) < 0)
return delay;
/*endif*/
delay += t38_core_send_flags_delay(&fe->t38, fe->next_tx_indicator);
fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3;
break;
case T38_TIMED_STEP_HDLC_MODEM_3:
@ -852,7 +906,9 @@ static int stream_hdlc(t38_terminal_state_t *s)
data_fields[1].field = NULL;
data_fields[1].field_len = 0;
category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA_END : T38_PACKET_CATEGORY_IMAGE_DATA_END;
t38_core_send_data_multi_field(&fe->t38, fe->current_tx_data_type, data_fields, 2, category);
if ((res = t38_core_send_data_multi_field(&fe->t38, fe->current_tx_data_type, data_fields, 2, category)) < 0)
return res;
/*endif*/
fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_5;
/* We add a bit of extra time here, as with some implementations
the carrier falling too abruptly causes data loss. */
@ -868,7 +924,9 @@ static int stream_hdlc(t38_terminal_state_t *s)
data_fields[1].field = NULL;
data_fields[1].field_len = 0;
category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA;
t38_core_send_data_multi_field(&fe->t38, fe->current_tx_data_type, data_fields, 2, category);
if ((res = t38_core_send_data_multi_field(&fe->t38, fe->current_tx_data_type, data_fields, 2, category)) < 0)
return res;
/*endif*/
fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3;
delay = bits_to_us(s, i*8 + fe->hdlc_tx.extra_bits);
}
@ -877,14 +935,18 @@ static int stream_hdlc(t38_terminal_state_t *s)
}
/*endif*/
category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA;
t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_HDLC_DATA, &fe->hdlc_tx.buf[fe->hdlc_tx.ptr], i, category);
if ((res = t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_HDLC_DATA, &fe->hdlc_tx.buf[fe->hdlc_tx.ptr], i, category)) < 0)
return res;
/*endif*/
fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_4;
}
else
{
i = fe->octets_per_data_packet;
category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA;
t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_HDLC_DATA, &fe->hdlc_tx.buf[fe->hdlc_tx.ptr], i, category);
if ((res = t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_HDLC_DATA, &fe->hdlc_tx.buf[fe->hdlc_tx.ptr], i, category)) < 0)
return res;
/*endif*/
fe->hdlc_tx.ptr += i;
}
/*endif*/
@ -901,7 +963,9 @@ static int stream_hdlc(t38_terminal_state_t *s)
{
/* End of transmission */
category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA_END : T38_PACKET_CATEGORY_IMAGE_DATA_END;
t38_core_send_data(&fe->t38, previous, T38_FIELD_HDLC_FCS_OK_SIG_END, NULL, 0, category);
if ((res = t38_core_send_data(&fe->t38, previous, T38_FIELD_HDLC_FCS_OK_SIG_END, NULL, 0, category)) < 0)
return res;
/*endif*/
fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_5;
/* We add a bit of extra time here, as with some implementations
the carrier falling too abruptly causes data loss. */
@ -922,7 +986,9 @@ static int stream_hdlc(t38_terminal_state_t *s)
/*endif*/
/* Finish the current frame off, and prepare for the next one. */
category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA;
t38_core_send_data(&fe->t38, previous, T38_FIELD_HDLC_FCS_OK, NULL, 0, category);
if ((res = t38_core_send_data(&fe->t38, previous, T38_FIELD_HDLC_FCS_OK, NULL, 0, category)) < 0)
return res;
/*endif*/
fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3;
/* We should now wait enough time for everything to clear through an analogue modem at the far end. */
delay = bits_to_us(s, fe->hdlc_tx.extra_bits);
@ -955,14 +1021,18 @@ static int stream_ced(t38_terminal_state_t *s)
of silence, starting the delay with a no signal indication makes sense.
We do need a 200ms delay, as that is a specification requirement. */
fe->timed_step = T38_TIMED_STEP_CED_2;
delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL);
if ((delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL)) < 0)
return delay;
/*endif*/
delay = 200000;
fe->next_tx_samples = fe->samples;
break;
case T38_TIMED_STEP_CED_2:
/* Initial 200ms delay over. Send the CED indicator */
fe->timed_step = T38_TIMED_STEP_CED_3;
delay = t38_core_send_indicator(&fe->t38, T38_IND_CED);
if ((delay = t38_core_send_indicator(&fe->t38, T38_IND_CED)) < 0)
return delay;
/*endif*/
fe->current_tx_data_type = T38_DATA_NONE;
break;
case T38_TIMED_STEP_CED_3:
@ -994,7 +1064,9 @@ static int stream_cng(t38_terminal_state_t *s)
be sending 200ms of silence, according to T.30, starting that delay with
a no signal indication makes sense. */
fe->timed_step = T38_TIMED_STEP_CNG_2;
delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL);
if ((delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL)) < 0)
return delay;
/*endif*/
delay = 200000;
fe->next_tx_samples = fe->samples;
break;
@ -1003,7 +1075,9 @@ static int stream_cng(t38_terminal_state_t *s)
coming the other way interrupts it, or a long timeout controlled by the T.30 engine
expires. */
fe->timed_step = T38_TIMED_STEP_NONE;
delay = t38_core_send_indicator(&fe->t38, T38_IND_CNG);
if ((delay = t38_core_send_indicator(&fe->t38, T38_IND_CNG)) < 0)
return delay;
/*endif*/
fe->current_tx_data_type = T38_DATA_NONE;
return delay;
}
@ -1067,6 +1141,12 @@ SPAN_DECLARE(int) t38_terminal_send_timeout(t38_terminal_state_t *s, int samples
break;
}
/*endswitch*/
if (delay < 0)
{
t30_terminate(&s->t30);
return TRUE;
}
/*endif*/
fe->next_tx_samples += us_to_samples(delay);
return FALSE;
}

View File

@ -297,7 +297,7 @@ static inline char *strndup_lite(const char *s, size_t n)
#define sqliteMalloc(x) zmalloc(x)//sqlite3Malloc(x,1)
#define sqliteMallocRaw(x) malloc(x)//sqlite3MallocRaw(x,1)
#define sqliteRealloc(x,y) realloc(x, y)//sqlite3Realloc(x,y)
#define sqliteStrDup(x) strdup(x)//sqlite3StrDup(x)
#define sqliteStrDup(x) (x?strdup(x):NULL)//sqlite3StrDup(x)
#define sqliteStrNDup(x,y) strndup_lite(x,y) //sqlite3StrNDup(x,y)
#define sqliteReallocOrFree(x,y) sqlite3ReallocOrFree(x,y)

View File

@ -76,6 +76,7 @@ struct stfu_instance {
uint32_t miss_count;
uint32_t max_plc;
uint32_t qlen;
uint32_t most_qlen;
uint32_t max_qlen;
uint32_t orig_qlen;
uint32_t packet_count;
@ -136,6 +137,11 @@ int32_t stfu_n_get_drift(stfu_instance_t *i)
return i->ts_drift;
}
int32_t stfu_n_get_most_qlen(stfu_instance_t *i)
{
return i->most_qlen;
}
void stfu_global_set_logger(stfu_logger_t logger)
{
if (logger) {
@ -253,6 +259,10 @@ stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen)
s = stfu_n_resize_aqueue(&i->b_queue, qlen);
s = stfu_n_resize_aqueue(&i->c_queue, qlen);
if (qlen > i->most_qlen) {
i->most_qlen = qlen;
}
i->qlen = qlen;
i->max_plc = 5;
i->last_frame = NULL;
@ -506,9 +516,9 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void
i->diff_total += i->diff;
if ((i->period_packet_in_count > i->period_time)) {
uint32_t avg;
//uint32_t avg;
avg = i->diff_total / least1(i->period_packet_in_count);
//avg = i->diff_total / least1(i->period_packet_in_count);
i->period_packet_in_count = 0;
@ -904,7 +914,7 @@ static void default_logger(const char *file, const char *func, int line, int lev
ret = stfu_vasprintf(&data, fmt, ap);
if (ret != -1) {
fprintf(stderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], file, line, func, data);
fprintf(stderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], fp, line, func, data);
free(data);
}

View File

@ -188,6 +188,7 @@ stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets);
void stfu_n_call_me(stfu_instance_t *i, stfu_n_call_me_t callback, void *udata);
void stfu_n_debug(stfu_instance_t *i, const char *name);
int32_t stfu_n_get_drift(stfu_instance_t *i);
int32_t stfu_n_get_most_qlen(stfu_instance_t *i);
#define stfu_im_done(i) stfu_n_add_data(i, 0, NULL, 0, 0, 1)
#define stfu_n_eat(i,t,p,d,l,tt) stfu_n_add_data(i, t, p, d, l, tt, 0)

View File

@ -0,0 +1,74 @@
--
-- sound_test.lua
--
-- accepts two args and then rolls through the sound files
-- arg 1: type
-- arg 2: rate
--
--[[ Use a dialplan entry like this:
<extension name="sound file tester">
<condition field="destination_number" expression="^((8|16|32|48)000)(.*)$">
<action application="lua" data="sound_test.lua $3 $1"/>
<action application="hangup"/>
</condition>
</extension>
Note the syntax of the destination number: <rate><type>
Rate can be 8000, 16000, 32000, or 48000
Type can be ivr, conference, voicemail, misc, digits, etc.
Using the extension listed above you could call it with mod_portaudio from fs_cli:
pa call 16000ivr
pa call 8000conference
pa call 32000conference
etc.
]]
-- Create tables that hold our rates and types
tbl_types = {
['ascii'] = 1,
['base256'] = 1,
['conference'] = 1,
['currency'] = 1,
['digits'] = 1,
['directory'] = 1,
['ivr'] = 1,
['misc'] = 1,
['phonetic-ascii'] = 1,
['time'] = 1,
['voicemail'] = 1,
['zrtp'] = 1
};
tbl_rates = {['8000'] = 1 ,['16000'] = 1, ['32000'] = 1, ['48000'] = 1};
stype = argv[1];
srate = argv[2];
freeswitch.consoleLog("INFO","Args: Type = " .. argv[1] .. ', Rate = ' .. argv[2] .. "\n");
if ( tbl_types[stype] == nil ) then
freeswitch.consoleLog("ERR","Type '" .. stype .. "' is not valid.\n");
elseif ( tbl_rates[srate] == nil ) then
freeswitch.consoleLog("ERR","Rate '" .. srate .. "' is not valid.\n");
else
-- Looks good, let's play some sound files
sound_base = session:getVariable('sounds_dir') .. '/en/us/callie/' .. stype .. '/' .. srate;
input_file = '/tmp/filez.txt';
res = os.execute('ls -1 ' .. sound_base .. ' > ' .. input_file);
freeswitch.consoleLog("INFO","Result of system call: " .. res .. "\n");
if ( res == 0 ) then
for fname in io.lines(input_file) do
freeswitch.consoleLog("NOTICE","Playing file: " .. fname .. "\n");
session:streamFile(sound_base .. '/' .. fname);
session:sleep(100);
end
else
freeswitch.consoleLog("ERR","Result of system call: " .. res .. "\n");
end
end

View File

@ -240,6 +240,7 @@ struct switch_runtime {
uint32_t debug_level;
uint32_t runlevel;
uint32_t tipping_point;
uint32_t microseconds_per_tick;
int32_t timer_affinity;
switch_profile_timer_t *profile_timer;
double profile_time;
@ -248,9 +249,12 @@ struct switch_runtime {
int max_sql_buffer_len;
switch_dbtype_t odbc_dbtype;
char hostname[256];
char *switchname;
int multiple_registrations;
uint32_t max_db_handles;
uint32_t db_handle_timeout;
int curl_count;
int ssl_count;
};
extern struct switch_runtime runtime;

View File

@ -725,12 +725,99 @@ SWITCH_DECLARE(switch_status_t) switch_queue_trypush(switch_queue_t *queue, void
* @{
*/
/** File types. */
typedef enum {
SWITCH_NOFILE = 0, /**< no file type determined */
SWITCH_REG, /**< a regular file */
SWITCH_DIR, /**< a directory */
SWITCH_CHR, /**< a character device */
SWITCH_BLK, /**< a block device */
SWITCH_PIPE, /**< a FIFO / pipe */
SWITCH_LNK, /**< a symbolic link */
SWITCH_SOCK, /**< a [unix domain] socket */
SWITCH_UNKFILE = 127 /**< a file of some other unknown type */
} switch_filetype_e;
/** Structure for referencing files. */
typedef struct apr_file_t switch_file_t;
typedef int32_t switch_fileperms_t;
typedef int switch_seek_where_t;
/**
* Structure for determining user ownership.
*/
#ifdef WIN32
typedef PSID switch_uid_t;
#else
typedef uid_t switch_uid_t;
#endif
/**
* Structure for determining group ownership.
*/
#ifdef WIN32
typedef PSID switch_gid_t;
#else
typedef gid_t switch_gid_t;
#endif
#ifdef WIN32
typedef uint32_t switch_dev_t;
typedef uint64_t switch_ino_t;
#else
typedef ino_t switch_ino_t;
typedef dev_t switch_dev_t;
#endif
typedef off64_t switch_off_t;
/**
* Structure for referencing file information
*/
//typedef struct apr_stat_t switch_finfo_t;
typedef struct {
/** Allocates memory and closes lingering handles in the specified pool */
switch_memory_pool_t *pool;
/** The bitmask describing valid fields of this switch_finfo_t structure
* including all available 'wanted' fields and potentially more */
int32_t valid;
/** The access permissions of the file. Mimics Unix access rights. */
switch_fileperms_t protection;
/** The type of file. One of APR_REG, APR_DIR, APR_CHR, APR_BLK, APR_PIPE,
* APR_LNK or APR_SOCK. If the type is undetermined, the value is APR_NOFILE.
* If the type cannot be determined, the value is APR_UNKFILE.
*/
switch_filetype_e filetype;
/** The user id that owns the file */
switch_uid_t user;
/** The group id that owns the file */
switch_gid_t group;
/** The inode of the file. */
switch_ino_t inode;
/** The id of the device the file is on. */
switch_dev_t device;
/** The number of hard links to the file. */
int32_t nlink;
/** The size of the file */
switch_off_t size;
/** The storage size consumed by the file */
switch_off_t csize;
/** The time the file was last accessed */
switch_time_t atime;
/** The time the file was last modified */
switch_time_t mtime;
/** The time the file was created, or the inode was last changed */
switch_time_t ctime;
/** The pathname of the file (possibly unrooted) */
const char *fname;
/** The file's name (no path) in filesystem case */
const char *name;
/** The file's handle, if accessed (can be submitted to apr_duphandle) */
switch_file_t *filehand;
} switch_finfo_t;
/**
* @defgroup apr_file_seek_flags File Seek Flags
* @{
@ -817,6 +904,37 @@ SWITCH_DECLARE(switch_status_t) switch_queue_trypush(switch_queue_t *queue, void
#define SWITCH_FOPEN_LARGEFILE 0x04000 /**< Platform dependent flag to enable large file support */
/** @} */
/**
* @defgroup switch_file_stat flags
* @ingroup switch_file_io
* @{
*/
#define SWITCH_FINFO_LINK 0x00000001 /**< Stat the link not the file itself if it is a link */
#define SWITCH_FINFO_MTIME 0x00000010 /**< Modification Time */
#define SWITCH_FINFO_CTIME 0x00000020 /**< Creation or inode-changed time */
#define SWITCH_FINFO_ATIME 0x00000040 /**< Access Time */
#define SWITCH_FINFO_SIZE 0x00000100 /**< Size of the file */
#define SWITCH_FINFO_CSIZE 0x00000200 /**< Storage size consumed by the file */
#define SWITCH_FINFO_DEV 0x00001000 /**< Device */
#define SWITCH_FINFO_INODE 0x00002000 /**< Inode */
#define SWITCH_FINFO_NLINK 0x00004000 /**< Number of links */
#define SWITCH_FINFO_TYPE 0x00008000 /**< Type */
#define SWITCH_FINFO_USER 0x00010000 /**< User */
#define SWITCH_FINFO_GROUP 0x00020000 /**< Group */
#define SWITCH_FINFO_UPROT 0x00100000 /**< User protection bits */
#define SWITCH_FINFO_GPROT 0x00200000 /**< Group protection bits */
#define SWITCH_FINFO_WPROT 0x00400000 /**< World protection bits */
#define SWITCH_FINFO_ICASE 0x01000000 /**< if dev is case insensitive */
#define SWITCH_FINFO_NAME 0x02000000 /**< ->name in proper case */
#define SWITCH_FINFO_MIN 0x00008170 /**< type, mtime, ctime, atime, size */
#define SWITCH_FINFO_IDENT 0x00003000 /**< dev and inode */
#define SWITCH_FINFO_OWNER 0x00030000 /**< user and group */
#define SWITCH_FINFO_PROT 0x00700000 /**< all protections */
#define SWITCH_FINFO_NORM 0x0073b170 /**< an atomic unix apr_stat() */
#define SWITCH_FINFO_DIRENT 0x02000000 /**< an atomic unix apr_dir_read() */
/** @} */
/**
* Open the specified file.
* @param newf The opened file descriptor.
@ -861,6 +979,8 @@ SWITCH_DECLARE(switch_status_t) switch_file_seek(switch_file_t *thefile, switch_
SWITCH_DECLARE(switch_status_t) switch_file_copy(const char *from_path, const char *to_path, switch_fileperms_t perms, switch_memory_pool_t *pool);
SWITCH_DECLARE(switch_status_t) switch_file_stat(switch_finfo_t *finfo, const char *fname, int32_t wanted, switch_memory_pool_t *pool);
/**
* Close the specified file.
* @param thefile The file descriptor to close.

View File

@ -56,6 +56,15 @@
#include <switch.h>
SWITCH_BEGIN_EXTERN_C
typedef struct profile_node_s {
char *var;
char *val;
struct profile_node_s *next;
} profile_node_t;
/*! \brief Call Specific Data
*/
struct switch_caller_profile {
@ -110,6 +119,7 @@ SWITCH_BEGIN_EXTERN_C
switch_memory_pool_t *pool;
struct switch_caller_profile *next;
switch_call_direction_t direction;
profile_node_t *soft;
};
/*! \brief An Abstract Representation of a dialplan Application */

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