Merge branch 'master' into arnaldo.zt_chan_next_event

This commit is contained in:
Arnaldo Pereira 2010-12-21 14:16:45 -02:00
commit 7732a67598
132 changed files with 10229 additions and 1269 deletions

View File

@ -1,6 +1,6 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchConsole", "w32\Console\FreeSwitchConsole.2008.vcproj", "{1AF3A893-F7BE-43DD-B697-8AB2397C0D67}"
ProjectSection(ProjectDependencies) = postProject
{202D7A4E-760D-4D0E-AFA1-D7459CED30FF} = {202D7A4E-760D-4D0E-AFA1-D7459CED30FF}
@ -11,6 +11,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchCoreLib", "w32\Li
ProjectSection(ProjectDependencies) = postProject
{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}

View File

@ -381,6 +381,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FreeSwitchCoreLib", "w32\Li
ProjectSection(ProjectDependencies) = postProject
{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}

View File

@ -707,6 +707,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_distributor", "src\mod\
EndProject
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Setup", "w32\Setup\Setup.wixproj", "{47213370-B933-487D-9F45-BCA26D7E2B6F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_say_pt", "src\mod\say\mod_say_pt\mod_say_pt.2010.vcxproj", "{7C22BDFF-CC09-400C-8A09-660733980028}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
All|Win32 = All|Win32
@ -3619,6 +3621,23 @@ Global
{47213370-B933-487D-9F45-BCA26D7E2B6F}.Release|x64 Setup.Build.0 = Release|x64
{47213370-B933-487D-9F45-BCA26D7E2B6F}.Release|x86 Setup.ActiveCfg = Release|x86
{47213370-B933-487D-9F45-BCA26D7E2B6F}.Release|x86 Setup.Build.0 = Release|x86
{7C22BDFF-CC09-400C-8A09-660733980028}.All|Win32.ActiveCfg = Release|x64
{7C22BDFF-CC09-400C-8A09-660733980028}.All|x64.ActiveCfg = Release|x64
{7C22BDFF-CC09-400C-8A09-660733980028}.All|x64.Build.0 = Release|x64
{7C22BDFF-CC09-400C-8A09-660733980028}.All|x64 Setup.ActiveCfg = Release|x64
{7C22BDFF-CC09-400C-8A09-660733980028}.All|x86 Setup.ActiveCfg = Release|x64
{7C22BDFF-CC09-400C-8A09-660733980028}.Debug|Win32.ActiveCfg = Debug|Win32
{7C22BDFF-CC09-400C-8A09-660733980028}.Debug|Win32.Build.0 = Debug|Win32
{7C22BDFF-CC09-400C-8A09-660733980028}.Debug|x64.ActiveCfg = Debug|x64
{7C22BDFF-CC09-400C-8A09-660733980028}.Debug|x64.Build.0 = Debug|x64
{7C22BDFF-CC09-400C-8A09-660733980028}.Debug|x64 Setup.ActiveCfg = Debug|x64
{7C22BDFF-CC09-400C-8A09-660733980028}.Debug|x86 Setup.ActiveCfg = Debug|x64
{7C22BDFF-CC09-400C-8A09-660733980028}.Release|Win32.ActiveCfg = Release|Win32
{7C22BDFF-CC09-400C-8A09-660733980028}.Release|Win32.Build.0 = Release|Win32
{7C22BDFF-CC09-400C-8A09-660733980028}.Release|x64.ActiveCfg = Release|x64
{7C22BDFF-CC09-400C-8A09-660733980028}.Release|x64.Build.0 = Release|x64
{7C22BDFF-CC09-400C-8A09-660733980028}.Release|x64 Setup.ActiveCfg = Release|x64
{7C22BDFF-CC09-400C-8A09-660733980028}.Release|x86 Setup.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -3769,6 +3788,7 @@ Global
{A4B122CF-5196-476B-8C0E-D8BD59AC3C14} = {6CD61A1D-797C-470A-BE08-8C31B68BB336}
{B6A9FB7A-1CC4-442B-812D-EC33E4E4A36E} = {6CD61A1D-797C-470A-BE08-8C31B68BB336}
{0382E8FD-CFDC-41C0-8B03-792C7C84FC31} = {6CD61A1D-797C-470A-BE08-8C31B68BB336}
{7C22BDFF-CC09-400C-8A09-660733980028} = {6CD61A1D-797C-470A-BE08-8C31B68BB336}
{3B08FEFD-4D3D-4C16-BA94-EE83509E32A0} = {57D119DC-484F-420F-B9E9-8589FD9A8DF8}
{7BFD517E-7F8F-4A40-A78E-8D3632738227} = {57D119DC-484F-420F-B9E9-8589FD9A8DF8}
{6374D55C-FABE-4A02-9CF1-4145308A56C5} = {57D119DC-484F-420F-B9E9-8589FD9A8DF8}

View File

@ -90,6 +90,8 @@ $(RECURSIVE_TARGETS):
fi; \
if test -z "$$fail" ; then \
cd $(top_builddir)/build && $(MAKE) $(AM_MAKEFLAGS) $$target || exit 1; \
else \
exit 1; \
fi ;
CORE_CFLAGS = `$(switch_builddir)/libs/apr/apr-1-config --cflags --cppflags --includes`
@ -100,6 +102,7 @@ CORE_CFLAGS += -I$(switch_srcdir)/libs/pcre
CORE_CFLAGS += -I$(switch_srcdir)/libs/speex/include -Ilibs/speex/include
CORE_CFLAGS += -I$(switch_srcdir)/libs/srtp/include
CORE_CFLAGS += -I$(switch_srcdir)/libs/srtp/crypto/include -Ilibs/srtp/crypto/include
CORE_CFLAGS += -I$(switch_srcdir)/libs/spandsp/src -I$(switch_srcdir)/libs/tiff-3.8.2/libtiff
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
@ -247,7 +250,8 @@ libfreeswitch_la_SOURCES = \
libs/miniupnpc/minissdpc.c \
libs/miniupnpc/upnperrors.c \
libs/libnatpmp/natpmp.c \
libs/libnatpmp/getgateway.c
libs/libnatpmp/getgateway.c\
libs/spandsp/src/plc.c
if ENABLE_CPP
libfreeswitch_la_SOURCES += src/switch_cpp.cpp
@ -272,7 +276,8 @@ bin_PROGRAMS = freeswitch fs_cli fs_ivrd tone2wav fs_encode
##
## fs_cli ()
##
fs_cli_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c libs/esl/src/esl_threadmutex.c libs/esl/fs_cli.c libs/esl/src/esl_json.c
fs_cli_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c \
libs/esl/src/esl_threadmutex.c libs/esl/fs_cli.c libs/esl/src/esl_json.c libs/esl/src/esl_buffer.c
fs_cli_CFLAGS = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include
fs_cli_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS) -lm
@ -300,7 +305,8 @@ tone2wav_LDADD = libfreeswitch.la
##
## fs_ivrd ()
##
fs_ivrd_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c libs/esl/src/esl_threadmutex.c libs/esl/ivrd.c libs/esl/src/esl_json.c
fs_ivrd_SOURCES = libs/esl/src/esl.c libs/esl/src/esl_config.c libs/esl/src/esl_event.c \
libs/esl/src/esl_threadmutex.c libs/esl/ivrd.c libs/esl/src/esl_json.c libs/esl/src/esl_buffer.c
fs_ivrd_CFLAGS = $(AM_CFLAGS) -I$(switch_srcdir)/libs/esl/src/include
fs_ivrd_LDFLAGS = $(AM_LDFLAGS) -lpthread $(ESL_LDFLAGS) -lm

View File

@ -100,6 +100,7 @@ say/mod_say_en
#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

View File

@ -205,10 +205,14 @@ if test "x${ax_cv_c_compiler_vendor}" = "xsun" ; then
APR_ADDTO(SWITCH_AM_CFLAGS, -DPIC)
APR_ADDTO(SWITCH_AM_CFLAGS, -erroff=E_END_OF_LOOP_CODE_NOT_REACHED)
APR_ADDTO(SWITCH_AM_CFLAGS, -errtags=yes)
APR_ADDTO(SWITCH_AM_CFLAGS, -D__FUNCTION__=__func__ )
APR_ADDTO(SWITCH_AM_CFLAGS, -mt)
APR_ADDTO(SWITCH_AM_CXXFLAGS, -errtags=yes)
APR_ADDTO(SWITCH_AM_CXXFLAGS, -KPIC)
APR_ADDTO(SWITCH_AM_CXXFLAGS, -DPIC)
APR_ADDTO(SWITCH_AM_CXXFLAGS, "-features=extensions")
APR_ADDTO(SWITCH_AM_CXXFLAGS, -D__FUNCTION__=__func__)
APR_ADDTO(SWITCH_AM_CXXFLAGS, -mt)
APR_ADDTO(SWITCH_AM_LDFLAGS, -R${prefix}/lib)
if test "${enable_64}" = "yes"; then

View File

@ -20,6 +20,7 @@ freeswitch (1.0.7)
build: Remove mod_spidermonkey from windows 2008 x64 builds - does not work (r:280e894d)
build: fix warnings on windows x64 builds src and mods projects - only libsofia included on the libs side (r:45ecbc2f)
build: Patch debian init.d script to set ulimit values (r:0eb33e57/FS-2844)
build: add plc to core (r:b7c80a84)
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
@ -32,6 +33,8 @@ freeswitch (1.0.7)
config: default example to resolve some issues with SCA in cases where host and ip are mixed causing the phone to be confused. (r:0279261b)
config: Fix phrase files, still missing a sound file (r:6741f350/FS-2742)
config: Disallow global-intercept and group-intercept can intercept an outbound call in default dialplan (r:890871ba/FS-2777)
config: fix single domain assumption in default config to be more portable *cough* bkw *cough* (r:f987903e)
config: Bump Doxygen.conf version to 1.0.6... belatedly (r:cfeae1ba)
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
@ -134,6 +137,25 @@ freeswitch (1.0.7)
core: Better handling of progress and answering to prevent sip profile from locking up at higher volumes (r:04e57577/FS-2801)
core: ACL for IPv6 address and swigall to boot (r:db91f0e8/FS-2842)
core: add intercept_unanswered_only var akin to intercept_unbridged_only (r:68f18efe)
core: switch_odbc_handle_exec_string duplication SQLExecute (r:8b0e7d24/FS-2880)
core: Fix timeout while bridge is waiting for CF_BRIDGED flag (r:2572621b/FS-2368)
core: don't parse events for b legs from a leg thread in case they are using a monolothic python script as a group_confirm exec over socket to send it messages while the call is ringing (r:ed5266d3)
core: add new function to check when messages need parsing to improve performance on parsing messages during originate (r:8b0421ff)
core: run execute_on_answer on_media _on_ring apps async (r:ef4a4ed0)
core: add switch_ivr_insert_file to insert one file into another at an arbitrary sample point (r:82394b37)
core: Slow reload cause calls to hang (r:1ba98b02/FS-2852)
core: Application intercept causes FS to stop processing calls (r:12fc65f7/FS-2872)
core: fix edge cases for endless loop in sql thread (r:5d7c09ed)
core: prevent race while changing codecs mid call (r:7aa72b67)
core: Fix crash in ODBC when SQL Server kills TCP connection (r:5aba96e3/FS-2910)
core: Fix fallback to CORE_DB when MSSQL fails init (r:3406d05b)
core: add new function to init an empty switch_sockaddr_t to avoid an unnecessary dns lookup on 0.0.0.0 (r:009c41d4)
core: fix endless RTP loop in Windows (r:cb2d0736/FS-2924)
core: play_and_get_digits should actually timeout, not last forever... (r:28cab5ed/FS-2923)
core: Fix crash w/o core dump (r:00046ee0/FS-2933)
core: normalize tests for outbound channels to use switch_channel_direction instead of testing for CF_OUTBOUND (r:93cc3dc5)
core: add CF_DIALPLAN (r:3ff07445)
core: tweak on calle[re] id (r:9db4a826)
lang: Improve French phrase files (FSCONFIG-23)
libapr: Fix issue where after a bridge with a member, uuid of Agent is set to single quote character ' (r:3fee704d/FS-2738)
libdingaling: fix race on shutdown causing crash (FSMOD-47)
@ -151,6 +173,9 @@ freeswitch (1.0.7)
libesl: Fix SEGV when using serialize function without any arguments (r:910729b5/ESL-44)
libesl: fix leak-on-error in esl_connect_timeout() (r:4263d60e)
libesl: Call close on connection handle if the connection fails (r:413dcc4c/ESL-50)
libesl: allow fs_cli -x to have args up to 1024 chars (was 256) (r:7039ba47)
libesl: Make last_event pointer last longer (r:a15f51d5/ESL-37)
libesl: use a packet buffer for ESL (r:2081bf97)
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)
@ -189,7 +214,8 @@ freeswitch (1.0.7)
mod_callcenter: Fix invalid update of agent field (r:426a448f/FS-2738)
mod_callcenter: Allow to get queue info via api (r:70d592ae)
mod_callcenter: Fix bad return type so it compile on archlinux, thx bougyman (r:3a475986)
mod_callcenter: Make callcenter_config agent get return the value of the item requested. Also added queue param max-wait-time-with-no-agent-time-reached: If the max-wai-time-with-no-agent is already reached for the queue, then new caller can wait for x ammount of second before it kicked out of the queue rather than get rejected automaticly. (r:81a03869)
mod_callcenter: Make callcenter_config agent get return the value of the item requested. Also added queue param max-wait-time-with-no-agent-time-reached: If the max-wai-time-with-no-agent is already reached for the queue, then new caller can wait for x amount of second before it kicked out of the queue rather than get rejected automatically. (r:81a03869)
mod_callcenter: Add new event socket agent-offering. Plus some documentation and better handling of bad agent type -- FS-2869 (r:80174cf3/FS-2869)
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
@ -205,6 +231,10 @@ freeswitch (1.0.7)
mod_commands: ***BEHAVIOUR CHANGE*** reloadacl, load <module>, reload <module> will now explicitly call reloadxml (r:42c9df72)
mod_commands: add nat_map usage (r:7577b8aa)
mod_commands: add escaping empty strings to sql_escape (r:7bd0a5a6/FS-2833)
mod_commands: add uuid_fileman <uuid> <cmd>:<val> <-- same vals as the callbacks in js and lua to control the currently playing file of a channel from the cli or ESL (for the people who were ignoring me on the conference call so I decided to implement it instead of try to explain it ) (r:c4369fc8)
mod_commands: FS-2210 Add support for auto completion for uuid_simplify (r:72bcc01b/FS-2210)
mod_commands: allow epoch in strftime_tz (r:bbf1cd1f)
mod_commands: Dramatic jitterbuffer changes (r:d5470961)
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
@ -214,6 +244,7 @@ freeswitch (1.0.7)
mod_conference: Fix floor change events not always firing (r:8f1767d3/MODAPP-424)
mod_conference: refactor conference to use switch_ivr_dmachine for the digit parsing controls are now bound to each member separately based on conference_controls channel var, then the caller-controls param in the profile or a default to "default" (r:ac19f73c)
mod_conference: Fix crash on dtmf action (r:4d5389bd/FS-2781)
mod_conference: revert to the last transfered conference on recover (r:d11c83b1)
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)
@ -221,6 +252,8 @@ freeswitch (1.0.7)
mod_dingaling: make dingaling work with google voice inbound too (r:4ee68141)
mod_dingaling: Fix crash when testing the new gv-dingaling with around 24 concurrent calls (r:73e1ec5e/FSCORE-667)
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_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)
@ -279,8 +312,10 @@ freeswitch (1.0.7)
mod_freetdm: lock the channel when placing call (r:705dd237)
mod_freetdm: created cmake files for freetdm (r:fc55997b)
mod_freetdm: ss7 - added support to control mtp2, mtp3, and isup timers via freetdm.conf.xml (r:4455d581)
mod_freetdm: made ftmod_r2 use FTDM_SPAN_USE_SIGNALS_QUEUE and properly send FTDM_SIGEVENT_SIGSTATUS_CHANGED (r:af5f0a4a)
mod_gsmopen: copy from branch
mod_gsmopen: fix FS-2793, compilation stops (r:355c0dbb/FS-2793)
mod_gsmopen: retry serial initialization if failed, zeroing audio buffers, slower retry on soundcard busy (EAGAIN) (r:c7aefe93)
mod_hash: free all hashtables on shutdown (r:e76d7d92)
mod_hash: remove unneeded initializer (r:10d468a6)
mod_hash: begin working on remote support (r:c5ad49da)
@ -324,6 +359,7 @@ freeswitch (1.0.7)
mod_lua: Added SAF_ROUTING_EXEC flag to lua app, so it can be run inline (r:7d5ca1c0)
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)
mod_mp4v: MP4V-ES passthru for washibechi on IRC
mod_mp4: New module. Supports playback of MP4 files. Depends on libmp4v2 <http://code.google.com/p/mp4v2/> (originally compiled against v1.6.1)
mod_nibblebill: free allocated mem at shutdown; free properly if using custom_sql
@ -472,6 +508,19 @@ freeswitch (1.0.7)
mod_sofia: fix missing name and potential segfault in gateway status (r:40ac860a)
mod_sofia: Add missing RTP info for early SDP in bypass media (r:10119e9e/FS-2824)
mod_sofia: add manual_rtp_bugs to profile and chan var and 3 new RTP bugs SEND_LINEAR_TIMESTAMPS|START_SEQ_AT_ZERO|NEVER_SEND_MARKER (r:b278dd23)
mod_sofia: apparently some sip device vendors did not read the RFC (who knew?) adding verbose_sdp=true var to add needless a= lines for standard iana codecs that explicitly do not require them (r:6c4f49a8)
mod_sofia: Fix registering a gateway, sofia always places a Via header with ext-sip-ip, even if this gateway is local (r:cf398e1a/FS-535)
mod_sofia: add presence-probe-on-register sofia param to send a probe on register instead of presence to deal with some broken phones and add some general improvements to allow multi homed presence (r:14394994)
mod_sofia: Fix issue when fs_path is used so we pick the correct media IP in our outbound invite this was soemthing that wouldn't work correctly over ATT on the iphone. (r:a669f76f)
mod_sofia: Default T38 Options (r:92f43440/FS-2892)
mod_sofia: Fix wrong IP in VIA and contact HEADER for MESSAGE method while fs run in private network (r:59ea4a1b/FS-2886)
mod_sofia: SIP-header History-Info might exist multiple times, but only last header is exposed as a channel variable (r:8cf15012/FS-2881)
mod_sofia: Add support to reboot Yealink phone remotely (r:fdc31908/FS-2897)
mod_sofia: Add reuse-connections sofia profile param to allow users to turn off TPTAG_REUSE, thus not re-using TCP connections (r:98ed05cc)
mod_sofia: Make sofia recover also work on custom uuid (r:3a645dee/FS-2913)
mod_sofia: remove check for va_list completely in sofia since i don't even think it happens ever (r:dfecc914)
mod_sofia: have mod_sofia always elect to be the session refresher so we know it will work, also make the session-expires set to 0 imply 100% disabled session timers (r:321013ef)
mod_sofia: Do not set nat mode when the device's network_ip is within the acl also so if your FS is behind nat and your phone is too then it will still make the right decisions (r:6c6eab8c)
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)
@ -487,6 +536,7 @@ freeswitch (1.0.7)
mod_spidermonkey: fix seg in js hangup (r:7d554c11)
mod_spidermonkey: Fix mod_spidermonkey build on FreeBSD, (Undefined symbol PR_LocalTimeParameters). (r:3edb8419)
mod_spy: add support for loopback endpoint (MODAPP-416)
mod_spy: fix crash when session can't be located (r:c4154633/FS-2929)
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_valet_parking: add event data to valet parking hold event
@ -508,6 +558,8 @@ freeswitch (1.0.7)
mod_xml_cdr: fix minor memory leaks and config bug (r:19253d83/MODEVENT-62)
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)
tools: Add fs_encode tool (r:89b17601)

View File

@ -31,7 +31,7 @@ PROJECT_NAME = FreeSWITCH
# This could be handy for archiving the generated documentation or
# if some version control system is used.
PROJECT_NUMBER = 1.0.4
PROJECT_NUMBER = 1.0.6
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.

View File

@ -221,6 +221,7 @@
<prompt phrase="Welcome to your new voicemail. To listen to a tutorial and setup your voice mail box, press 1. To skip, press 2." filename="vm-tutorial_yes_no.wav"/>
<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"/>
</voicemail>
<directory>
<prompt phrase="Please enter the first few letters of the persons" filename="dir-enter_person.wav"/>
@ -241,6 +242,8 @@
<prompt phrase="...letters of the person's name." filename="dir-letters_of_person_name.wav"/>
<prompt phrase="Please try again." filename="dir-please_try_again.wav"/>
<prompt phrase="press" filename="dir-press.wav" info="we can copy vm/vm-press.wav"/>
<prompt phrase="For the next entry..." filename="dir-for_next.wav" note="re-recorded because original was wrong"/>
<prompt phrase="Please enter the first few letters of the person's first or last name" filename="dir-enter_person_first_or_last.wav"/>
</directory>
<conference>
<prompt phrase="NULL" filename="conf-ack.wav" type="tone"/>
@ -259,6 +262,12 @@
<prompt phrase="Invalid pin number, try again." filename="conf-bad-pin.wav"/>
<prompt phrase="goodbye" filename="conf-goodbye.wav"/>
<prompt phrase="Welcome to the conference." filename="conf-welcome.wav"/>
<prompt phrase="Please enter the conference number, followed by the pound key" filename="conf-enter_conf_number.wav"/>
<prompt phrase="Enter the conference PIN number, followed by the pound key." filename="conf-enter_conf_pin.wav"/>
<prompt phrase="...has entered the conference." filename="conf-has_joined.wav"/>
<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"/>
</conference>
<ivr>
<prompt phrase="Account number" filename="ivr-account_number.wav"/>
@ -362,8 +371,6 @@
<prompt phrase="Thank you for calling. If you know your party's extension, please enter it now. For a directory, press..." filename="ivr-generic_greeting.wav"/>
<prompt phrase="...file..." filename="ivr-file.wav"/>
<prompt phrase="...files..." filename="ivr-files-.wav"/>
<!-- The following phrases still need to be recorded -->
<prompt phrase="For a wakeup call..." filename="ivr-for_a_wakeup_call.wav"/>
<prompt phrase="This is your wakeup call." filename="ivr-this_is_your_wakeup_call.wav"/>
<prompt phrase="To request a wakeup call..." filename="ivr-request_wakeup_call.wav"/>
@ -390,15 +397,10 @@
<prompt phrase="You are the..." filename="ivr-you_are_the.wav"/>
<prompt phrase="One moment please." filename="ivr-one_moment_please.wav"/>
<prompt phrase="Your call will be answered in the order it was received." filename="ivr-call_answered_order_received.wav"/>
<prompt phrase="Please enter the conference number, followed by the pound key" filename="conf-enter_conf_number.wav"/>
<prompt phrase="Enter the conference PIN number, followed by the pound key." filename="conf-enter_conf_pin.wav"/>
<prompt phrase="...has entered the conference." filename="conf-has_joined.wav"/>
<prompt phrase="...has left the conference." filename="conf-has_left.wav"/>
<prompt phrase="You entered..." filename="ivr-you_entered.wav"/>
<prompt phrase="Extension number..." filename="ivr-extension_number.wav"/>
<prompt phrase="Please hold while your party is being contacted." filename="ivr-please_hold_while_party_contacted.wav"/>
<prompt phrase="Please enjoy the music while your party is being reached." filename="ivr-please_enjoy_music_while_party_reached.wav"/>
<prompt phrase="For the next entry..." filename="dir-for_next.wav" note="re-record because original is wrong"/>
<prompt phrase="Thank you for calling. If you know your party's extension, please enter it now, or dial nine for a directory." filename="ivr-generic_greeting.wav"/>
<prompt phrase="If this is correct, press 1. If not, press 2." filename="ivr-if_correct_one_if_not_two.wav"/>
<prompt phrase="To repeat this information..." filename="ivr-repeat_this_information.wav"/>
@ -409,10 +411,7 @@
<prompt phrase="That's it! One more mistake and I WILL hang up on your ass." filename="ivr-one_more_mistake.wav"/>
<prompt phrase="Congratulations, you pressed star. This does not mean you ARE a star. It simply means that you can press buttons and probably have fingers." filename="ivr-congratulations_you_pressed_star.wav"/>
<prompt phrase="All of our engineers are busy assisting other sales guys with demonstrating how cool the CudaTel is." filename="ivr-engineers_busy_assisting_other_sales.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="This message will self-destruct in 5, 4, 3, 2, 1..." filename="ivr-message_self_destruct.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="All your call are belong to us." filename="ivr-all_your_call_are_belong_to_us.wav"/>
<prompt phrase="I just love the way you press those touch tones!" filename="ivr-love_those_touch_tones.wav"/>
<prompt phrase="Yes, we have no bananas." filename="ivr-yes_we_have_no_bananas.wav"/>
@ -425,20 +424,10 @@
<prompt phrase="Please contact the system administrator for assistance." filename="ivr-contact_system_administrator.wav"/>
<prompt phrase="Barracuda Networks" filename="ivr-barracuda_networks.wav"/>
<prompt phrase="CudaTel Communication Server" filename="ivr-cudatel_communication_server.wav"/>
<prompt phrase="Please enter the first few letters of the person's first or last name" filename="dir-enter_person_first_or_last.wav"/>
<prompt phrase="There are no calls waiting in this queue." filename="ivr-no_calls_waiting_in_queue.wav"/>
<prompt phrase="Brian West" filename="misc-Brian_West.wav"/>
<prompt phrase="Anthony Minessale" filename="misc-Anthony_Minessale.wav"/>
<prompt phrase="Michael Jerris" filename="misc-Michael_Jerris.wav"/>
<prompt phrase="Raymond Chandler" filename="misc-Raymond_Chandler.wav"/>
<prompt phrase="Michael Collins" filename="misc-Michael_Collins.wav"/>
<prompt phrase="Mark Mann" filename="misc-Mark_Mann.wav"/>
<prompt phrase="William King" filename="misc-William_King.wav"/>
<prompt phrase="Rudy Fleminger" filename="misc-Rudy_Fleminger.wav"/>
<prompt phrase="Andrew Thompson" filename="misc-Andrew_Thompson.wav"/>
<prompt phrase="Graham Saathoff" filename="misc-Graham_Saathoff.wav"/>
<prompt phrase="Nicholaus Belluni" filename="misc-Nicholaus_Belluni.wav"/>
<prompt phrase="Sean Heiney" filename="misc-Sean_Heiney.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"/>
</ivr>
<misc>
<prompt phrase="This call has been secured" filename="call_secured.wav"/>

View File

@ -0,0 +1,994 @@
<language>
<es_ES>
<ascii>
<prompt phrase="Espacio" filename="32.wav"/>
<prompt phrase="Almohadilla" filename="35.wav"/>
<prompt phrase="Asterisco" filename="42.wav"/>
<prompt phrase="Punto" filename="46.wav"/>
<prompt phrase="A" filename="97.wav"/>
<prompt phrase="B" filename="98.wav"/>
<prompt phrase="C" filename="99.wav"/>
<prompt phrase="D" filename="100.wav"/>
<prompt phrase="E" filename="101.wav"/>
<prompt phrase="F" filename="102.wav"/>
<prompt phrase="G" filename="103.wav"/>
<prompt phrase="H" filename="104.wav"/>
<prompt phrase="I" filename="105.wav"/>
<prompt phrase="J" filename="106.wav"/>
<prompt phrase="K" filename="107.wav"/>
<prompt phrase="L" filename="108.wav"/>
<prompt phrase="M" filename="109.wav"/>
<prompt phrase="N" filename="110.wav"/>
<prompt phrase="Ñ" filename="Ñ.wav"/>
<prompt phrase="O" filename="111.wav"/>
<prompt phrase="P" filename="112.wav"/>
<prompt phrase="Q" filename="113.wav"/>
<prompt phrase="R" filename="114.wav"/>
<prompt phrase="S" filename="115.wav"/>
<prompt phrase="T" filename="116.wav"/>
<prompt phrase="U" filename="117.wav"/>
<prompt phrase="V" filename="118.wav"/>
<prompt phrase="W" filename="119.wav"/>
<prompt phrase="X" filename="120.wav"/>
<prompt phrase="Y" filename="121.wav"/>
<prompt phrase="Z" filename="122.wav"/>
</ascii>
<phonetic-ascii>
<prompt phrase="Espacio" filename="32.wav"/>
<prompt phrase="Punto" filename="46.wav"/>
<prompt phrase="Alpha" filename="97.wav"/>
<prompt phrase="Bravo" filename="98.wav"/>
<prompt phrase="Charlie" filename="99.wav"/>
<prompt phrase="Delta" filename="100.wav"/>
<prompt phrase="Echo" filename="101.wav"/>
<prompt phrase="Foxtrot" filename="102.wav"/>
<prompt phrase="Golf" filename="103.wav"/>
<prompt phrase="Hotel" filename="104.wav"/>
<prompt phrase="India" filename="105.wav"/>
<prompt phrase="Juliet" filename="106.wav"/>
<prompt phrase="Kilo" filename="107.wav"/>
<prompt phrase="Lima" filename="108.wav"/>
<prompt phrase="Mike" filename="109.wav"/>
<prompt phrase="November" filename="110.wav"/>
<prompt phrase="Oscar" filename="111.wav"/>
<prompt phrase="Papa" filename="112.wav"/>
<prompt phrase="Quebec" filename="113.wav"/>
<prompt phrase="Romeo" filename="114.wav"/>
<prompt phrase="Sierra" filename="115.wav"/>
<prompt phrase="Tango" filename="116.wav"/>
<prompt phrase="Unifor" filename="117.wav"/>
<prompt phrase="Victor" filename="118.wav"/>
<prompt phrase="Whiskey" filename="119.wav"/>
<prompt phrase="Xray" filename="120.wav"/>
<prompt phrase="Yankee" filename="121.wav"/>
<prompt phrase="Zulu" filename="122.wav"/>
</phonetic-ascii>
<digits>
<prompt phrase="Cero" filename="0.wav"/>
<prompt phrase="Uno" filename="1.wav"/>
<prompt phrase="Dos" filename="2.wav"/>
<prompt phrase="Tres" filename="3.wav"/>
<prompt phrase="Cuatro" filename="4.wav"/>
<prompt phrase="Cinco" filename="5.wav"/>
<prompt phrase="Seis" filename="6.wav"/>
<prompt phrase="Siete" filename="7.wav"/>
<prompt phrase="Ocho" filename="8.wav"/>
<prompt phrase="Nueve" filename="9.wav"/>
<prompt phrase="Diez" filename="10.wav"/>
<prompt phrase="Once" filename="11.wav"/>
<prompt phrase="Doce" filename="12.wav"/>
<prompt phrase="Trece" filename="13.wav"/>
<prompt phrase="Catorce" filename="14.wav"/>
<prompt phrase="Quince" filename="15.wav"/>
<prompt phrase="Dieciséis" filename="16.wav"/>
<prompt phrase="Diecisiete" filename="17.wav"/>
<prompt phrase="Dieciocho" filename="18.wav"/>
<prompt phrase="Diecinueve" filename="19.wav"/>
<prompt phrase="Veinte" filename="20.wav"/>
<prompt phrase="Veinti" filename="veinti.wav"/>
<prompt phrase="Treinta" filename="30.wav"/>
<prompt phrase="Cuarenta" filename="40.wav"/>
<prompt phrase="Cincuenta" filename="50.wav"/>
<prompt phrase="Sesenta" filename="60.wav"/>
<prompt phrase="Setenta" filename="70.wav"/>
<prompt phrase="Ochenta" filename="80.wav"/>
<prompt phrase="Noventa" filename="90.wav"/>
<prompt phrase="Cien" filename="100.wav"/>
<prompt phrase="Quinientos" filename="500.wav"/>
<prompt phrase="Setecientos" filename="700.wav"/>
<prompt phrase="Novecientos" filename="900.wav"/>
<prompt phrase="Punto" filename="dot.wav"/>
<prompt phrase="Primero" filename="h-1.wav"/>
<prompt phrase="Segundo" filename="h-2.wav"/>
<prompt phrase="Tercero" filename="h-3.wav"/>
<prompt phrase="Cuarto" filename="h-4.wav"/>
<prompt phrase="Quinto" filename="h-5.wav"/>
<prompt phrase="Sexto" filename="h-6.wav"/>
<prompt phrase="Séptimo" filename="h-7.wav"/>
<prompt phrase="Octavo" filename="h-8.wav"/>
<prompt phrase="Noveno" filename="h-9.wav"/>
<prompt phrase="Décimo" filename="h-10.wav"/>
<prompt phrase="Undécimo" filename="h-11.wav"/>
<prompt phrase="Duodécimo" filename="h-12.wav"/>
<prompt phrase="Decimotercero" filename="h-13.wav"/>
<prompt phrase="Decimocuarto" filename="h-14.wav"/>
<prompt phrase="Decimoquinto" filename="h-15.wav"/>
<prompt phrase="Decimosexto" filename="h-16.wav"/>
<prompt phrase="Decimoséptimo" filename="h-17.wav"/>
<prompt phrase="Decimoctavo" filename="h-18.wav"/>
<prompt phrase="Decimonoveno" filename="h-19.wav"/>
<prompt phrase="Vigésimo" filename="h-20.wav"/>
<prompt phrase="Trigésimo" filename="h-30.wav"/>
<prompt phrase="Un" filename="un.wav"/>
<prompt phrase="Ciento" filename="hundred.wav"/>
<prompt phrase="Cientos" filename="hundreds.wav"/>
<prompt phrase="Mil" filename="thousand.wav"/>
<prompt phrase="Millón" filename="million.wav"/>
<prompt phrase="Millones" filename="millions.wav"/>
<prompt phrase="Período" filename="period.wav"/>
<prompt phrase="Punto" filename="point.wav"/>
<prompt phrase="Almohadilla" filename="pound.wav"/>
<prompt phrase="Asterisco" filename="star.wav"/>
</digits>
<currency>
<prompt phrase="Y" filename="and.wav"/>
<prompt phrase="Céntimo" filename="cent.wav"/>
<prompt phrase="Central" filename="central.wav"/>
<prompt phrase="Céntimos por minuto" filename="cents-per-minute.wav"/>
<prompt phrase="Céntimos" filename="cents.wav"/>
<prompt phrase="Dólar" filename="dollar.wav"/>
<prompt phrase="Dólares" filename="dollars.wav"/>
<prompt phrase="Menos" filename="minus.wav"/>
<prompt phrase="Negativo" filename="negative.wav"/>
</currency>
<time>
<prompt phrase="A.M." filename="a-m.wav"/>
<prompt phrase="A la..." filename="at.wav"/>
<prompt phrase="A las..." filename="ats.wav"/>
<prompt phrase="Domingo" filename="day-0.wav"/>
<prompt phrase="Lunes" filename="day-1.wav"/>
<prompt phrase="Martes" filename="day-2.wav"/>
<prompt phrase="Miércoles" filename="day-3.wav"/>
<prompt phrase="Jueves" filename="day-4.wav"/>
<prompt phrase="Viernes" filename="day-5.wav"/>
<prompt phrase="Sábado" filename="day-6.wav"/>
<prompt phrase="Hora" filename="hour.wav"/>
<prompt phrase="Horas" filename="hours.wav"/>
<prompt phrase="Minuto" filename="minute.wav"/>
<prompt phrase="Minutos" filename="minutes.wav"/>
<prompt phrase="Enero" filename="mon-0.wav"/>
<prompt phrase="Febrero" filename="mon-1.wav"/>
<prompt phrase="Marzo" filename="mon-2.wav"/>
<prompt phrase="Abril" filename="mon-3.wav"/>
<prompt phrase="Mayo" filename="mon-4.wav"/>
<prompt phrase="Junio" filename="mon-5.wav"/>
<prompt phrase="Julio" filename="mon-6.wav"/>
<prompt phrase="Agosto" filename="mon-7.wav"/>
<prompt phrase="Septiembre" filename="mon-8.wav"/>
<prompt phrase="Octubre" filename="mon-9.wav"/>
<prompt phrase="Noviembre" filename="mon-10.wav"/>
<prompt phrase="Diciembre" filename="mon-11.wav"/>
<prompt phrase="En punto" filename="oclock.wav"/>
<prompt phrase="P.M." filename="p-m.wav"/>
<prompt phrase="Segundo" filename="second.wav"/>
<prompt phrase="Segundos" filename="seconds.wav"/>
<prompt phrase="Hoy" filename="today.wav"/>
<prompt phrase="Mañana" filename="tomorrow.wav"/>
<prompt phrase="Ayer" filename="yesterday.wav"/>
</time>
<voicemail>
<prompt phrase="La persona en la extensión..." filename="vm-person.wav"/>
<prompt phrase="Marcado urgente." filename="vm-marked-urgent.wav"/>
<prompt phrase="Enviado por correo electrónico." filename="vm-emailed.wav"/>
<prompt phrase="Usted tiene..." filename="vm-you_have.wav"/>
<prompt phrase="Por favor introduzca su número de usuario, seguido por..." filename="vm-enter_id.wav"/>
<prompt phrase="Por favor introduzca su contraseña, seguido por..." filename="vm-enter_pass.wav"/>
<prompt phrase="Inicio de sesión incorrecto." filename="vm-fail_auth.wav"/>
<prompt phrase="Bienvenido a su buzón de voz." filename="vm-hello.wav"/>
<prompt phrase="Adiós" filename="vm-goodbye.wav"/>
<prompt phrase="Por favor grabe su nombre después de la señal, pulse cualquier tecla o deje de hablar para poner fin a la grabación." filename="vm-record_name1.wav"/>
<prompt phrase="Elija un saludo entre 1 y 9." filename="vm-choose_greeting_choose.wav"/>
<prompt phrase="Valor inválido." filename="vm-choose_greeting_fail.wav"/>
<prompt phrase="Demasiados intentos fallidos." filename="vm-abort.wav"/>
<prompt phrase="Para cambiar su contraseña..." filename="vm-change_password.wav"/>
<prompt phrase="Grabe su saludo después de la señal, pulse cualquier tecla o deje de hablar para poner fin a la grabación." filename="vm-record_greeting.wav"/>
<prompt phrase="Grabe su mensaje después de la señal, pulse cualquier tecla o deje de hablar para poner fin a la grabación." filename="vm-record_message.wav"/>
<prompt phrase="...no está disponible." filename="vm-play_greeting.wav"/>
<prompt phrase="Urgente nuevo." filename="vm-urgent-new.wav"/>
<prompt phrase="Nuevo" filename="vm-new.wav"/>
<prompt phrase="Urgente guardado" filename="vm-urgent-saved.wav"/>
<prompt phrase="Guardado" filename="vm-saved.wav"/>
<prompt phrase="Mensaje" filename="vm-message.wav"/>
<prompt phrase="Mensajes" filename="vm-messages.wav"/>
<prompt phrase="Pulse" filename="vm-press.wav"/>
<prompt phrase="Para escuchar mensajes nuevos..." filename="vm-listen_new.wav"/>
<prompt phrase="Para escuchar mensajes guardados..." filename="vm-listen_saved.wav"/>
<prompt phrase="Para opciones avanzadas..." filename="vm-advanced.wav"/>
<prompt phrase="Para salir..." filename="vm-to_exit.wav"/>
<prompt phrase="Para grabar un saludo..." filename="vm-record_greeting.wav"/>
<prompt phrase="Para elegir un saludo..." filename="vm-choose_greeting.wav"/>
<prompt phrase="Para grabar su nombre..." filename="vm-record_name2.wav"/>
<prompt phrase="Para el menú principal..." filename="vm-main_menu.wav"/>
<prompt phrase="Para escuchar la grabación..." filename="vm-listen_to_recording.wav"/>
<prompt phrase="Para guardar la grabación..." filename="vm-save_recording.wav"/>
<prompt phrase="Para regrabar..." filename="vm-rerecord.wav"/>
<prompt phrase="Para marcar este mensaje como urgente..." filename="vm-mark-urgent.wav"/>
<prompt phrase="Para continuar..." filename="vm-continue.wav"/>
<prompt phrase="Para escuchar la grabación de nuevo..." filename="vm-listen_to_recording_again.wav"/>
<prompt phrase="Para eliminar la grabación..." filename="vm-delete_recording.wav"/>
<prompt phrase="Para enviar la grabación a su correo electrónico..." filename="vm-forward_to_email.wav"/>
<prompt phrase="Saludo" filename="vm-greeting.wav"/>
<prompt phrase="Seleccionado" filename="vm-selected.wav"/>
<prompt phrase="...no está disponible." filename="vm-not_available.wav"/>
<prompt phrase="Mensaje número..." filename="vm-message_number.wav"/>
<prompt phrase="Eliminado" filename="vm-deleted.wav"/>
<prompt phrase="Su grabación es demasiado corta, por favor intente de nuevo." filename="vm-too-small.wav"/>
<prompt phrase="...en la bandeja de entrada." filename="vm-in_folder.wav"/>
<prompt phrase="Para devolver la llamada..." filename="vm-return_call.wav"/>
<prompt phrase="Urgente" filename="vm-urgent.wav"/>
<prompt phrase="Este buzón está lleno. Por favor intente llamar mas tarde." filename="vm-mailbox_full.wav"/>
<prompt phrase="Bienvenido a su nuevo buzón de voz. Para escuchar el tutorial y configurar su buzón, pulse 1. Para saltarlo pulse 2." filename="vm-tutorial_yes_no.wav"/>
<prompt phrase="Necesito grabar su nombre y apellido. Esta grabación se usará entre otros en el servicio de directorio." filename="vm-tutorial_record_name.wav"/>
<prompt phrase="Su número de identificación personal o PIN sirve para impedir a terceros el acceso a sus mensajes. Desea cambiar su PIN ahora?" filename="vm-tutorial_change_pin.wav"/>
</voicemail>
<directory>
<prompt phrase="Por favor introduzca las primeras letras del nombre buscado." filename="dir-enter_person.wav"/>
<prompt phrase="...apellido..." filename="dir-last_name.wav"/>
<prompt phrase="Para buscar por..." filename="dir-to_search_by.wav"/>
<prompt phrase="...nombre..." filename="dir-first_name.wav"/>
<prompt phrase="No hay resultados que coincidan con su busqueda." filename="dir-no_matching_results.wav"/>
<prompt phrase="...resultados coinciden con su busqueda." filename="dir-result_match.wav"/>
<prompt phrase="Su busqueda genera demasiados resultados." filename="dir-too_many_result.wav"/>
<prompt phrase="No hay más resultados." filename="dir-no_more_results.wav"/>
<prompt phrase="Resultado número..." filename="dir-result_number.wav"/>
<prompt phrase="...en la extensión..." filename="dir-at_extension.wav"/>
<prompt phrase="Para seleccionar este resultado..." filename="dir-to_select_entry.wav"/>
<prompt phrase="Para el resultado siguiente..." filename="dir-for_next.wav"/>
<prompt phrase="Para el resultado previo..." filename="dir-for_prev.wav"/>
<prompt phrase="Para empezar una nueva busqueda..." filename="dir-start_new_search.wav"/>
<prompt phrase="Necesita especificar un mínimo de..." filename="dir-specify_mininum.wav"/>
<prompt phrase="...letras del nombre buscado." filename="dir-letters_of_person_name.wav"/>
<prompt phrase="Por favor intente de nuevo." filename="dir-please_try_again.wav"/>
<prompt phrase="Pulse..." filename="dir-press.wav" info="we can copy vm/vm-press.wav"/>
</directory>
<conference>
<prompt phrase="NULL" filename="conf-ack.wav" type="tone"/>
<prompt phrase="NULL" filename="conf-nack.wav" type="tone"/>
<prompt phrase="Su voz ha sido silenciada." filename="conf-muted.wav"/>
<prompt phrase="Su voz ha sido habilitada." filename="conf-unmuted.wav"/>
<prompt phrase="En este momento usted es la única persona en la conferencia." filename="conf-alone.wav"/>
<prompt phrase="NULL" filename="conf-perpetual.wav" type="music"/>
<prompt phrase="NULL" filename="conf-enter.wav" type="tone"/>
<prompt phrase="NULL" filename="conf-exit.wav" type="tone"/>
<prompt phrase="Usted ha sido expulsado de la conferencia." filename="conf-kicked.wav"/>
<prompt phrase="Esta conferencia está bloqueada." filename="conf-locked.wav"/>
<prompt phrase="La conferencia está ahora bloqueada." filename="conf-is-locked.wav"/>
<prompt phrase="La conferencia está ahora desbloqueada." filename="conf-is-unlocked.wav"/>
<prompt phrase="Por favor ingrese el PIN de la conferencia." filename="conf-pin.wav"/>
<prompt phrase="PIN inválido, intente de nuevo." filename="conf-bad-pin.wav"/>
<prompt phrase="Hasta luego." filename="conf-goodbye.wav"/>
<prompt phrase="Bienvenido a la conferencia." filename="conf-welcome.wav"/>
</conference>
<ivr>
<prompt phrase="Número de cuenta" filename="ivr-account_number.wav"/>
<prompt phrase="Conectar con el llamante" filename="ivr-connect_to_caller.wav"/>
<prompt phrase="Si conoce la extensión de su destino, por favor marquela ahora." filename="ivr-enter_ext_pound.wav"/>
<prompt phrase="Por favor ingrese un número de extensión seguido por la tecla almohadilla." filename="ivr-enter_ext.wav"/>
<prompt phrase="Para esta persona..." filename="ivr-for_this_person.wav"/>
<prompt phrase="Por favor espere mientras se conecta su llamada." filename="ivr-hold_connect_call.wav"/>
<prompt phrase="Lo siento..." filename="ivr-im_sorry.wav"/>
<prompt phrase="Por favor..." filename="ivr-please.wav"/>
<prompt phrase="Por favor devuelva nuestra llamada al..." filename="ivr-please_return_our_call_at.wav"/>
<prompt phrase="Acerca del número de referencia..." filename="ivr-regarding_reference_number.wav"/>
<prompt phrase="Este es un ejemplo de un submenú." filename="ivr-sample_submenu.wav"/>
<prompt phrase="Por favor diga su nombre después del tono." filename="ivr-say_name.wav"/>
<prompt phrase="Enviar a este llamante al buzón de voz." filename="ivr-send_to_voicemail.wav"/>
<prompt phrase="Para hablar con un representante del servicio de atención al cliente..." filename="ivr-speak_to_a_customer_service_representative.wav"/>
<prompt phrase="Tomar un mensaje" filename="ivr-take_a_message.wav"/>
<prompt phrase="Gracias" filename="ivr-thank_you.wav"/>
<prompt phrase="Esa fue una entrada inválida." filename="ivr-that_was_an_invalid_entry.wav"/>
<prompt phrase="Esta es una llamada de..." filename="ivr-this_is_a_call_from.wav"/>
<prompt phrase="Este menú de voz le permitirá probar algunas de las funciones..." filename="ivr-this_ivr_will_let_you_test_features.wav"/>
<prompt phrase="Para llamar a la conferencia de FreeSWITCH..." filename="ivr-to_call_the_freeswitch_conference.wav"/>
<prompt phrase="Para hacer una prueba de eco de FreeSWITCH..." filename="ivr-to_do_a_freeswitch_echo_test.wav"/>
<prompt phrase="Para hacer una prueba de eco de FWD..." filename="ivr-to_do_a_fwd_echo_test.wav"/>
<prompt phrase="Para escuchar un ejemplo de un submenú..." filename="ivr-to_hear_sample_submenu.wav"/>
<prompt phrase="Para escuchar simios gritando..." filename="ivr-to_hear_screaming_monkeys.wav"/>
<prompt phrase="Para escuchar música de llamada en espera..." filename="ivr-to_listen_to_moh.wav"/>
<prompt phrase="Para repetir estas opciones..." filename="ivr-to_repeat_these_options.wav"/>
<prompt phrase="Para volver al menú anterior..." filename="ivr-to_return_to_previous_menu.wav"/>
<prompt phrase="Para hablar con una operadora..." filename="ivr-to_speak_with_an_operator.wav"/>
<prompt phrase="Bienvenido a FreeSWITCH, el futuro de la telefonía." filename="ivr-welcome_to_freeswitch.wav"/>
<prompt phrase="Usted puede colgar en cualquier momento para salir." filename="ivr-you_may_exit_by_hanging_up.wav"/>
<prompt phrase="O" filename="ivr-or.wav"/>
<prompt phrase="No" filename="ivr-not.wav"/>
<prompt phrase="Llamar" filename="ivr-call.wav"/>
<prompt phrase="Usted puede..." filename="ivr-you_may.wav"/>
<prompt phrase="Hola" filename="ivr-hello.wav"/>
<prompt phrase="Usando el teclado de su teléfono..." filename="ivr-use_telephone_keypad.wav"/>
<prompt phrase="Por favor deletree el nombre de la persona con la cual está intentando contactar." filename="ivr-spell_name.wav"/>
<prompt phrase="Primero el apellido" filename="ivr-last_name_first.wav"/>
<prompt phrase="Primero el nombre" filename="ivr-first_name_first.wav"/>
<prompt phrase="Pulse 1 para Q ó Z." filename="ivr-press_one_q_or_z.wav"/>
<prompt phrase="Ventas" filename="ivr-sales.wav"/>
<prompt phrase="Servicio de atención al cliente" filename="ivr-customer_service.wav"/>
<prompt phrase="Soporte técnico" filename="ivr-technical_support.wav"/>
<prompt phrase="Operador" filename="ivr-operator.wav"/>
<prompt phrase="Usted marcó una extensión inválida." filename="ivr-you_have_dialed_an_invalid_extension.wav"/>
<prompt phrase="Por favor introduzca su número de extensión, seguido de la tecla almohadilla." filename="ivr-please_enter_extension_followed_by_pound.wav"/>
<prompt phrase="Por favor introduzca su contraseña, seguido de la tecla almohadilla." filename="ivr-please_enter_pin_followed_by_pound.wav"/>
<prompt phrase="Su contraseña o extensión es inválida." filename="ivr-pin_or_extension_is-invalid.wav"/>
<prompt phrase="Usted esta a punto de asociar este teléfono a su cuenta..." filename="ivr-you_are_about_to_provision_this_phone.wav"/>
<prompt phrase="Por favor vuelva a introducir su contraseña para confirmar." filename="ivr-please_reenter_your_pin.wav"/>
<prompt phrase="Para registrarse en ClueCon, por favor pulse..." filename="ivr-register_for_cluecon.wav"/>
<prompt phrase="Para conectarse..." filename="ivr-to_log_in.wav"/>
<prompt phrase="Para desconectarse..." filename="ivr-to_log_out.wav"/>
<prompt phrase="Usted está ahora conectado." filename="ivr-you_are_now_logged_in.wav"/>
<prompt phrase="Usted está ahora desconectado." filename="ivr-you_are_now_logged_out.wav"/>
<prompt phrase="Por favor intente de nuevo." filename="ivr-please_try_again.wav"/>
<prompt phrase="Usted está a punto de asociar este teléfono a su cuenta de forma permanente." filename="ivr-provision_phone_permanently_to_extension.wav"/>
<prompt phrase="Por favor introduzca su número de extensión con la cual desea asociar su teléfono, seguido de la tecla almohadilla." filename="ivr-extension_to_provision_this_phone.wav"/>
<prompt phrase="Gracias, este teléfono va a reiniciarse ahora." filename="ivr-this_phone_will_now_reboot.wav"/>
<prompt phrase="Gracias, su grabación ha sido guardada." filename="ivr-recording_saved.wav"/>
<prompt phrase="Pulse 1 para guardar su grabación. Pulse 2 para escuchar su grabación. Pulse 3 para volver a grabar." filename="ivr-save_review_record.wav"/>
<prompt phrase="En este momento, el sistema no puede guardar su fichero de audio. Por favor intente de nuevo." filename="ivr-unable_save.wav"/>
<prompt phrase="Usted está en la posición..." filename="ivr-you_are_number.wav"/>
<prompt phrase="...en la cola de espera." filename="ivr-in_line.wav"/>
<prompt phrase="Gracias por permanecer en espera." filename="ivr-thank_you_for_holding.wav"/>
<prompt phrase="El tiempo estimado de espera es..." filename="ivr-estimated_hold_time.wav"/>
<prompt phrase="Más de..." filename="ivr-more_than.wav"/>
<prompt phrase="Menos de..." filename="ivr-less_than.wav"/>
<prompt phrase="Empieze a grabar." filename="ivr-begin_recording.wav "/>
<prompt phrase="El desvío de llamada ha sido desactivado." filename="ivr-call_forwarding_has_been_cancelled.wav"/>
<prompt phrase="El desvío de llamada ha sido activado." filename="ivr-call_forwarding_has_been_set.wav"/>
<prompt phrase="Por favor introduzca el número de teléfono." filename="ivr-please_enter_the_phone_number.wav"/>
<prompt phrase="Por favor diga su nombre, y la razón de la llamada." filename="ivr-please_state_your_name_and_reason_for_calling.wav"/>
<prompt phrase="Para aceptar, pulse 1. Para rechazar, pulse 2. Para enviar al buzón de voz, pulse 3." filename="ivr-accept_reject_voicemail.wav"/>
<prompt phrase="Llamada entrante." filename="ivr-incoming_call.wav"/>
<prompt phrase="Gracias por llamar." filename="ivr-thank_you_for_calling.wav"/>
<prompt phrase="Por favor mentengase a la espera. Su llamada será atendida en un momento." filename="ivr-stay_on_line_call_answered_momentarily.wav"/>
<prompt phrase="Su llamada está siendo procesada." filename="ivr-call_being_transferred.wav"/>
<prompt phrase="Por favor disfrute de la música mientras su llamada está siendo procesada..." filename="ivr-enjoy_music_while_transfer.wav"/>
<prompt phrase="Usted tiene una llamada de..." filename="ivr-call_from.wav"/>
<prompt phrase="Este menú no tiene entradas. Por favor contacte con el administrador." filename="ivr-no_menu_items.wav"/>
<prompt phrase="Para el servicio de directorio, pulse..." filename="ivr-for_directory_press.wav"/>
<prompt phrase="Usando las teclas de su teléfono..." filename="ivr-using_telephone_keypad.wav"/>
<prompt phrase="Introduzca las primeras letras del apellido de la persona." filename="ivr-enter_letters_last_name.wav"/>
<prompt phrase="Introduzca las primeras letras del nombre de la persona." filename="ivr-enter_letters_first_name.wav"/>
<prompt phrase="Introduzca las primeras letras del nombre o apellido de la persona." filename="ivr-enter_letters_first_or_last_name.wav"/>
<prompt phrase="Si es correcto, pulse..." filename="ivr-if_correct_press.wav"/>
<prompt phrase="Sino, pulse..." filename="ivr-if_not_press.wav"/>
<prompt phrase="Cuando termine, pulse la tecla almohadilla." filename="ivr-finished_pound_hash_key.wav"/>
<prompt phrase="La función de No Molestar ha sido activada." filename="ivr-dnd_activated.wav"/>
<prompt phrase="La función de No Molestar ha sido desactivada." filename="ivr-dnd_cancelled.wav"/>
<prompt phrase="Pulse cualquier otro dígito..." filename="ivr-any_other_digit.wav"/>
<prompt phrase="Pulse uno si su respuesta es sí. Pulse dos si su respuesta es no." filename="ivr-one_yes_two_no.wav"/>
<prompt phrase="Por favor introduzca el número de la cola, seguido de la tecla almohadilla." filename="ivr-enter_queue_number.wav"/>
<prompt phrase="Por favor introduzca el..." filename="ivr-please_enter_the.wav"/>
<prompt phrase="Número." filename="ivr-number.wav"/>
<prompt phrase="...seguido de la tecla almohadilla." filename="ivr-followed_by_pound.wav"/>
<prompt phrase="El balance de la cuenta es..." filename="ivr-account_balance_is.wav"/>
<prompt phrase="Gracias por llamar. Si conoce la extensión de su destino, por favor marquela ahora. Para acceder al directorio, pulse..." filename="ivr-generic_greeting.wav"/>
<prompt phrase="...fichero..." filename="ivr-file.wav"/>
<prompt phrase="...ficheros..." filename="ivr-files-.wav"/>
<prompt phrase="Para una llamada de despertador..." filename="ivr-for_a_wakeup_call.wav"/>
<prompt phrase="Este es el servicio de despertador." filename="ivr-this_is_your_wakeup_call.wav"/>
<prompt phrase="Para solicitar una llamada de despertador..." filename="ivr-request_wakeup_call.wav"/>
<prompt phrase="Para confirmar la llamada de despertador..." filename="ivr-confirm_wakeup_call.wav"/>
<prompt phrase="Para anular la llamada de despertador..." filename="ivr-cancel_wakeup_call.wav"/>
<prompt phrase="Usted ha solicitado una llamada de despertador para..." filename="ivr-requested_wakeup_call_for.wav"/>
<prompt phrase="Usted no ha solicitado llamadas de despertador." filename="ivr-not_requested_wakeup_call.wav"/>
<prompt phrase="Su llamada de despertador ha sido anulada." filename="ivr-wakeup_call_cancelled.wav"/>
<prompt phrase="Para una llamada diaria de despertador..." filename="ivr-for_daily_wakeup_call.wav"/>
<prompt phrase="Llamada diaria de despertador..." filename="ivr-daily_wakeup_call.wav"/>
<prompt phrase="Para llamadas diarias de despertador..." filename="ivr-for_daily_wakeup_calls.wav"/>
<prompt phrase="Para una llamada de despertador única..." filename="ivr-for_one_time_wakeup_call.wav"/>
<prompt phrase="Llamada de despertador única..." filename="ivr-one_time_wakeup_call.wav"/>
<prompt phrase="...llamada de despertador..." filename="ivr-wakeup_call.wav"/>
<prompt phrase="¡Vamos despierta cielo!" filename="ivr-wakey_wakey_sunshine.wav"/>
<prompt phrase="Bienvenido." filename="ivr-welcome.wav"/>
<prompt phrase="Bienvenido a..." filename="ivr-welcome_to.wav"/>
<prompt phrase="Buenos días." filename="ivr-good_morning.wav"/>
<prompt phrase="Buenas tardes." filename="ivr-good_afternoon.wav"/>
<prompt phrase="Buenas noches." filename="ivr-good_evening.wav"/>
<prompt phrase="Gracias." filename="ivr-Thank_you.wav"/>
<prompt phrase="Para..." filename="ivr-for.wav"/>
<prompt phrase="El tiempo de espera esta siendo anormalmente elevado." filename="ivr-longer_than_usual_hold_times.wav"/>
<prompt phrase="Usted es el..." filename="ivr-you_are_the.wav"/>
<prompt phrase="Un momento por favor." filename="ivr-one_moment_please.wav"/>
<prompt phrase="Su llamada será atendida según el orden de entrada." filename="ivr-call_answered_order_received.wav"/>
<prompt phrase="Por favor introduzca el número de conferencia, seguido de la tecla almohadilla." filename="conf-enter_conf_number.wav"/>
<prompt phrase="Introduzca el PIN de la conferencia, seguido de la tecla almohadilla." filename="conf-enter_conf_pin.wav"/>
<prompt phrase="...se incorporó a la conferencia." filename="conf-has_joined.wav"/>
<prompt phrase="...ha abandonado la conferencia." filename="conf-has_left.wav"/>
<prompt phrase="Usted entró..." filename="ivr-you_entered.wav"/>
<prompt phrase="Número de extensión..." filename="ivr-extension_number.wav"/>
<prompt phrase="Por favor mantengase a la espera mientras contactamos con su destino." filename="ivr-please_hold_while_party_contacted.wav"/>
<prompt phrase="Por favor disfrute de la música mientras le conectamos con su destino." filename="ivr-please_enjoy_music_while_party_reached.wav"/>
<prompt phrase="Gracias por llamar. Si conoce la extensión de su destino, por favor marquela ahora, o marque nueve para el servicio de directorio." filename="ivr-generic_greeting.wav"/>
<prompt phrase="Si es correcto, pulse 1. Sino, pulse 2." filename="ivr-if_correct_one_if_not_two.wav"/>
<prompt phrase="Para repetir esta información..." filename="ivr-repeat_this_information.wav"/>
<prompt phrase="No no no!" filename="ivr-no_no_no.wav"/>
<prompt phrase="Era su intención pulsar esta tecla?" filename="ivr-did_you_mean_to_press_key.wav"/>
<prompt phrase="Pensaba Usted DE VERDAD pulsar esta tecla?" filename="ivr-seriously_mean_to_press_key.wav"/>
<prompt phrase="Oh DA IGUAL." filename="ivr-oh_whatever.wav"/>
<prompt phrase="Se acabó! Un error más y le colgaré a la cara." filename="ivr-one_more_mistake.wav"/>
<prompt phrase="Felicitaciones. Ha pulsado estrella. Esto no significa que ES una estrella. Tan solo significa que puede pulsar teclas y probablemente tiene dedos." filename="ivr-congratulations_you_pressed_star.wav"/>
<prompt phrase="Todos nuestros ingenieros están ocupados en demostrar lo impresionante que es el CudaTel." filename="ivr-engineers_busy_assisting_other_sales.wav"/>
<prompt phrase="La persona con la que intenta hablar no está disponible y no tiene buzón de voz." filename="vm-not_available_no_voicemail.wav"/>
<prompt phrase="Este mensaje se auto-destruira en 5, 4, 3, 2, 1..." filename="ivr-message_self_destruct.wav"/>
<prompt phrase="Su llamada ya está silenciada." filename="conf-you_are_already_muted.wav"/>
<prompt phrase="Su llamada ha sido silenciada en ambos sentidos." filename="conf-you_are_now_bidirectionally_muted.wav"/>
<prompt phrase="Todas sus llamadas nos pertenecen." filename="ivr-all_your_call_are_belong_to_us.wav"/>
<prompt phrase="Me encanta como está pulsando estas teclas!" filename="ivr-love_those_touch_tones.wav"/>
<prompt phrase="No, no tenemos bananas." filename="ivr-yes_we_have_no_bananas.wav"/>
<prompt phrase="Está haciendo el ridículo!" filename="ivr-dude_you_suck.wav"/>
<prompt phrase="Su llamada es muy importante para nosotros, pero su bienestar mental no lo es, así que estamos felices mantenerle a la espera, torturándole indefinidamente con nuestra pésima música en espera." filename="ivr-on_hold_indefinitely.wav"/>
<prompt phrase="...ha abandonado el edificio." filename="ivr-has_left_the_building.wav"/>
<prompt phrase="Este teléfono no está asignado y no puede ser usado para realizar llamadas externas." filename="ivr-phone_is_unassigned.wav"/>
<prompt phrase="Este teléfono no está configurado correctamente." filename="ivr-phone_not_configured.wav"/>
<prompt phrase="Felicitaciones! Este teléfono está configurado correctamente y puede ahora ser asociado a un usuario." filename="ivr-phone_is_configured_properly.wav"/>
<prompt phrase="Por favor contacte con el administrador del sistema para obtener asistencia." filename="ivr-contact_system_administrator.wav"/>
<prompt phrase="Barracuda Networks" filename="ivr-barracuda_networks.wav"/>
<prompt phrase="CudaTel Communication Server" filename="ivr-cudatel_communication_server.wav"/>
<prompt phrase="Por favor introduzca las primeras letras del nombre o apellido de la persona." filename="dir-enter_person_first_or_last.wav"/>
<prompt phrase="No hay llamadas en espera en esta cola." filename="ivr-no_calls_waiting_in_queue.wav"/>
<prompt phrase="Brian West" filename="misc-Brian_West.wav"/>
<prompt phrase="Anthony Minessale" filename="misc-Anthony_Minessale.wav"/>
<prompt phrase="Michael Jerris" filename="misc-Michael_Jerris.wav"/>
<prompt phrase="Raymond Chandler" filename="misc-Raymond_Chandler.wav"/>
<prompt phrase="Michael Collins" filename="misc-Michael_Collins.wav"/>
<prompt phrase="Mark Mann" filename="misc-Mark_Mann.wav"/>
<prompt phrase="William King" filename="misc-William_King.wav"/>
<prompt phrase="Rudy Fleminger" filename="misc-Rudy_Fleminger.wav"/>
<prompt phrase="Andrew Thompson" filename="misc-Andrew_Thompson.wav"/>
<prompt phrase="Graham Saathoff" filename="misc-Graham_Saathoff.wav"/>
<prompt phrase="Nicholaus Belluni" filename="misc-Nicholaus_Belluni.wav"/>
<prompt phrase="Sean Heiney" filename="misc-Sean_Heiney.wav"/>
</ivr>
<misc>
<prompt phrase="Esta llamada está ahora protegida." filename="call_secured.wav"/>
<prompt phrase="...seguido de la tecla almohadilla." filename="followed.wav"/>
<prompt phrase="Si usted es esta persona..." filename="if_you_are_this_person.wav"/>
<prompt phrase="Si usted desea..." filename="if_you_would_like_to.wav"/>
<prompt phrase="Por favor, introduzca el número de referencia." filename="provide_reference_number.wav"/>
<prompt phrase="Por favor, marque la extensión a la cual desea transferir." filename="transfer1.wav"/>
<prompt phrase="Transferir" filename="transfer2.wav"/>
<prompt phrase="Estamos tratando de contactar..." filename="we_are_trying_to_reach.wav"/>
<prompt phrase="Ha ocurrido un error, por favor contacte con el administrador." filename="error.wav"/>
<prompt phrase="Su llamada será terminada en..." filename="misc-your_call_will_be_terminated_in.wav"/>
<prompt phrase="Su llamada ha sido terminada." filename="misc-your_call_has_been_terminated.wav"/>
</misc>
<zrtp>
<!-- base256 prompts for SAS -->
<prompt phrase="Algol" filename="Algol.wav"/>
<prompt phrase="Apollo" filename="Apollo.wav"/>
<prompt phrase="Athens" filename="Athens.wav"/>
<prompt phrase="Atlantic" filename="Atlantic.wav"/>
<prompt phrase="Aztec" filename="Aztec.wav"/>
<prompt phrase="Babylon" filename="Babylon.wav"/>
<prompt phrase="Belfast" filename="Belfast.wav"/>
<prompt phrase="Bradbury" filename="Bradbury.wav"/>
<prompt phrase="Brazilian" filename="Brazilian.wav"/>
<prompt phrase="Burbank" filename="Burbank.wav"/>
<prompt phrase="Burlington" filename="Burlington.wav"/>
<prompt phrase="Camelot" filename="Camelot.wav"/>
<prompt phrase="Capricorn" filename="Capricorn.wav"/>
<prompt phrase="Cherokee" filename="Cherokee.wav"/>
<prompt phrase="Chicago" filename="Chicago.wav"/>
<prompt phrase="Christmas" filename="Christmas.wav"/>
<prompt phrase="Dakota" filename="Dakota.wav"/>
<prompt phrase="December" filename="December.wav"/>
<prompt phrase="Dupont" filename="Dupont.wav"/>
<prompt phrase="Eskimo" filename="Eskimo.wav"/>
<prompt phrase="Galveston" filename="Galveston.wav"/>
<prompt phrase="Geiger" filename="Geiger.wav"/>
<prompt phrase="Hamilton" filename="Hamilton.wav"/>
<prompt phrase="Istanbul" filename="Istanbul.wav"/>
<prompt phrase="Jamaica" filename="Jamaica.wav"/>
<prompt phrase="Jupiter" filename="Jupiter.wav"/>
<prompt phrase="Medusa" filename="Medusa.wav"/>
<prompt phrase="Mohawk" filename="Mohawk.wav"/>
<prompt phrase="Montana" filename="Montana.wav"/>
<prompt phrase="Neptune" filename="Neptune.wav"/>
<prompt phrase="Norwegian" filename="Norwegian.wav"/>
<prompt phrase="Oakland" filename="Oakland.wav"/>
<prompt phrase="October" filename="October.wav"/>
<prompt phrase="Ohio" filename="Ohio.wav"/>
<prompt phrase="Orlando" filename="Orlando.wav"/>
<prompt phrase="Pacific" filename="Pacific.wav"/>
<prompt phrase="Pandora" filename="Pandora.wav"/>
<prompt phrase="Pegasus" filename="Pegasus.wav"/>
<prompt phrase="Pluto" filename="Pluto.wav"/>
<prompt phrase="Saturday" filename="Saturday.wav"/>
<prompt phrase="Scotland" filename="Scotland.wav"/>
<prompt phrase="Trojan" filename="Trojan.wav"/>
<prompt phrase="Virginia" filename="Virginia.wav"/>
<prompt phrase="Vulcan" filename="Vulcan.wav"/>
<prompt phrase="Waterloo" filename="Waterloo.wav"/>
<prompt phrase="Wichita" filename="Wichita.wav"/>
<prompt phrase="Wilmington" filename="Wilmington.wav"/>
<prompt phrase="Wyoming" filename="Wyoming.wav"/>
<prompt phrase="Yucatan" filename="Yucatan.wav"/>
<prompt phrase="Zulu" filename="Zulu.wav"/>
<prompt phrase="aardvark" filename="aardvark.wav"/>
<prompt phrase="absurd" filename="absurd.wav"/>
<prompt phrase="accrue" filename="accrue.wav"/>
<prompt phrase="acme" filename="acme.wav"/>
<prompt phrase="adrift" filename="adrift.wav"/>
<prompt phrase="adroitness" filename="adroitness.wav"/>
<prompt phrase="adult" filename="adult.wav"/>
<prompt phrase="adviser" filename="adviser.wav"/>
<prompt phrase="afflict" filename="afflict.wav"/>
<prompt phrase="aftermath" filename="aftermath.wav"/>
<prompt phrase="aggregate" filename="aggregate.wav"/>
<prompt phrase="ahead" filename="ahead.wav"/>
<prompt phrase="aimless" filename="aimless.wav"/>
<prompt phrase="alkali" filename="alkali.wav"/>
<prompt phrase="allow" filename="allow.wav"/>
<prompt phrase="almighty" filename="almighty.wav"/>
<prompt phrase="alone" filename="alone.wav"/>
<prompt phrase="ammo" filename="ammo.wav"/>
<prompt phrase="amulet" filename="amulet.wav"/>
<prompt phrase="amusement" filename="amusement.wav"/>
<prompt phrase="ancient" filename="ancient.wav"/>
<prompt phrase="antenna" filename="antenna.wav"/>
<prompt phrase="apple" filename="apple.wav"/>
<prompt phrase="applicant" filename="applicant.wav"/>
<prompt phrase="armistice" filename="armistice.wav"/>
<prompt phrase="article" filename="article.wav"/>
<prompt phrase="artist" filename="artist.wav"/>
<prompt phrase="assume" filename="assume.wav"/>
<prompt phrase="asteroid" filename="asteroid.wav"/>
<prompt phrase="atlas" filename="atlas.wav"/>
<prompt phrase="atmosphere" filename="atmosphere.wav"/>
<prompt phrase="autopsy" filename="autopsy.wav"/>
<prompt phrase="baboon" filename="baboon.wav"/>
<prompt phrase="backfield" filename="backfield.wav"/>
<prompt phrase="backward" filename="backward.wav"/>
<prompt phrase="backwater" filename="backwater.wav"/>
<prompt phrase="banjo" filename="banjo.wav"/>
<prompt phrase="barbecue" filename="barbecue.wav"/>
<prompt phrase="beaming" filename="beaming.wav"/>
<prompt phrase="bedlamp" filename="bedlamp.wav"/>
<prompt phrase="beehive" filename="beehive.wav"/>
<prompt phrase="beeswax" filename="beeswax.wav"/>
<prompt phrase="befriend" filename="befriend.wav"/>
<prompt phrase="belowground" filename="belowground.wav"/>
<prompt phrase="berserk" filename="berserk.wav"/>
<prompt phrase="bifocals" filename="bifocals.wav"/>
<prompt phrase="billiard" filename="billiard.wav"/>
<prompt phrase="bison" filename="bison.wav"/>
<prompt phrase="blackjack" filename="blackjack.wav"/>
<prompt phrase="blockade" filename="blockade.wav"/>
<prompt phrase="blowtorch" filename="blowtorch.wav"/>
<prompt phrase="bluebird" filename="bluebird.wav"/>
<prompt phrase="bodyguard" filename="bodyguard.wav"/>
<prompt phrase="bombast" filename="bombast.wav"/>
<prompt phrase="bookseller" filename="bookseller.wav"/>
<prompt phrase="bookshelf" filename="bookshelf.wav"/>
<prompt phrase="borderline" filename="borderline.wav"/>
<prompt phrase="bottomless" filename="bottomless.wav"/>
<prompt phrase="brackish" filename="brackish.wav"/>
<prompt phrase="bravado" filename="bravado.wav"/>
<prompt phrase="breadline" filename="breadline.wav"/>
<prompt phrase="breakaway" filename="breakaway.wav"/>
<prompt phrase="breakup" filename="breakup.wav"/>
<prompt phrase="brickyard" filename="brickyard.wav"/>
<prompt phrase="briefcase" filename="briefcase.wav"/>
<prompt phrase="businessman" filename="businessman.wav"/>
<prompt phrase="butterfat" filename="butterfat.wav"/>
<prompt phrase="button" filename="button.wav"/>
<prompt phrase="buzzard" filename="buzzard.wav"/>
<prompt phrase="candidate" filename="candidate.wav"/>
<prompt phrase="cannonball" filename="cannonball.wav"/>
<prompt phrase="caravan" filename="caravan.wav"/>
<prompt phrase="caretaker" filename="caretaker.wav"/>
<prompt phrase="celebrate" filename="celebrate.wav"/>
<prompt phrase="cellulose" filename="cellulose.wav"/>
<prompt phrase="cement" filename="cement.wav"/>
<prompt phrase="certify" filename="certify.wav"/>
<prompt phrase="chairlift" filename="chairlift.wav"/>
<prompt phrase="chambermaid" filename="chambermaid.wav"/>
<prompt phrase="chatter" filename="chatter.wav"/>
<prompt phrase="checkup" filename="checkup.wav"/>
<prompt phrase="chisel" filename="chisel.wav"/>
<prompt phrase="choking" filename="choking.wav"/>
<prompt phrase="chopper" filename="chopper.wav"/>
<prompt phrase="clamshell" filename="clamshell.wav"/>
<prompt phrase="classic" filename="classic.wav"/>
<prompt phrase="classroom" filename="classroom.wav"/>
<prompt phrase="cleanup" filename="cleanup.wav"/>
<prompt phrase="clergyman" filename="clergyman.wav"/>
<prompt phrase="clockwork" filename="clockwork.wav"/>
<prompt phrase="cobra" filename="cobra.wav"/>
<prompt phrase="coherence" filename="coherence.wav"/>
<prompt phrase="combustion" filename="combustion.wav"/>
<prompt phrase="commando" filename="commando.wav"/>
<prompt phrase="commence" filename="commence.wav"/>
<prompt phrase="company" filename="company.wav"/>
<prompt phrase="component" filename="component.wav"/>
<prompt phrase="concert" filename="concert.wav"/>
<prompt phrase="concurrent" filename="concurrent.wav"/>
<prompt phrase="confidence" filename="confidence.wav"/>
<prompt phrase="conformist" filename="conformist.wav"/>
<prompt phrase="congregate" filename="congregate.wav"/>
<prompt phrase="consensus" filename="consensus.wav"/>
<prompt phrase="consulting" filename="consulting.wav"/>
<prompt phrase="corporate" filename="corporate.wav"/>
<prompt phrase="corrosion" filename="corrosion.wav"/>
<prompt phrase="councilman" filename="councilman.wav"/>
<prompt phrase="cowbell" filename="cowbell.wav"/>
<prompt phrase="crackdown" filename="crackdown.wav"/>
<prompt phrase="cranky" filename="cranky.wav"/>
<prompt phrase="crossover" filename="crossover.wav"/>
<prompt phrase="crowfoot" filename="crowfoot.wav"/>
<prompt phrase="crucial" filename="crucial.wav"/>
<prompt phrase="crucifix" filename="crucifix.wav"/>
<prompt phrase="crumpled" filename="crumpled.wav"/>
<prompt phrase="crusade" filename="crusade.wav"/>
<prompt phrase="cubic" filename="cubic.wav"/>
<prompt phrase="cumbersome" filename="cumbersome.wav"/>
<prompt phrase="customer" filename="customer.wav"/>
<prompt phrase="dashboard" filename="dashboard.wav"/>
<prompt phrase="deadbolt" filename="deadbolt.wav"/>
<prompt phrase="decadence" filename="decadence.wav"/>
<prompt phrase="decimal" filename="decimal.wav"/>
<prompt phrase="deckhand" filename="deckhand.wav"/>
<prompt phrase="designing" filename="designing.wav"/>
<prompt phrase="detector" filename="detector.wav"/>
<prompt phrase="detergent" filename="detergent.wav"/>
<prompt phrase="determine" filename="determine.wav"/>
<prompt phrase="dictator" filename="dictator.wav"/>
<prompt phrase="dinosaur" filename="dinosaur.wav"/>
<prompt phrase="direction" filename="direction.wav"/>
<prompt phrase="disable" filename="disable.wav"/>
<prompt phrase="disbelief" filename="disbelief.wav"/>
<prompt phrase="disruptive" filename="disruptive.wav"/>
<prompt phrase="distortion" filename="distortion.wav"/>
<prompt phrase="document" filename="document.wav"/>
<prompt phrase="dogsled" filename="dogsled.wav"/>
<prompt phrase="dragnet" filename="dragnet.wav"/>
<prompt phrase="drainage" filename="drainage.wav"/>
<prompt phrase="dreadful" filename="dreadful.wav"/>
<prompt phrase="drifter" filename="drifter.wav"/>
<prompt phrase="dropper" filename="dropper.wav"/>
<prompt phrase="drumbeat" filename="drumbeat.wav"/>
<prompt phrase="drunken" filename="drunken.wav"/>
<prompt phrase="dwelling" filename="dwelling.wav"/>
<prompt phrase="eating" filename="eating.wav"/>
<prompt phrase="edict" filename="edict.wav"/>
<prompt phrase="egghead" filename="egghead.wav"/>
<prompt phrase="eightball" filename="eightball.wav"/>
<prompt phrase="embezzle" filename="embezzle.wav"/>
<prompt phrase="enchanting" filename="enchanting.wav"/>
<prompt phrase="endorse" filename="endorse.wav"/>
<prompt phrase="endow" filename="endow.wav"/>
<prompt phrase="enlist" filename="enlist.wav"/>
<prompt phrase="enrollment" filename="enrollment.wav"/>
<prompt phrase="enterprise" filename="enterprise.wav"/>
<prompt phrase="equation" filename="equation.wav"/>
<prompt phrase="equipment" filename="equipment.wav"/>
<prompt phrase="erase" filename="erase.wav"/>
<prompt phrase="escapade" filename="escapade.wav"/>
<prompt phrase="escape" filename="escape.wav"/>
<prompt phrase="everyday" filename="everyday.wav"/>
<prompt phrase="examine" filename="examine.wav"/>
<prompt phrase="exceed" filename="exceed.wav"/>
<prompt phrase="existence" filename="existence.wav"/>
<prompt phrase="exodus" filename="exodus.wav"/>
<prompt phrase="eyeglass" filename="eyeglass.wav"/>
<prompt phrase="eyetooth" filename="eyetooth.wav"/>
<prompt phrase="facial" filename="facial.wav"/>
<prompt phrase="fallout" filename="fallout.wav"/>
<prompt phrase="fascinate" filename="fascinate.wav"/>
<prompt phrase="filament" filename="filament.wav"/>
<prompt phrase="finicky" filename="finicky.wav"/>
<prompt phrase="flagpole" filename="flagpole.wav"/>
<prompt phrase="flatfoot" filename="flatfoot.wav"/>
<prompt phrase="flytrap" filename="flytrap.wav"/>
<prompt phrase="forever" filename="forever.wav"/>
<prompt phrase="fortitude" filename="fortitude.wav"/>
<prompt phrase="fracture" filename="fracture.wav"/>
<prompt phrase="framework" filename="framework.wav"/>
<prompt phrase="freedom" filename="freedom.wav"/>
<prompt phrase="frequency" filename="frequency.wav"/>
<prompt phrase="frighten" filename="frighten.wav"/>
<prompt phrase="gadgetry" filename="gadgetry.wav"/>
<prompt phrase="gazelle" filename="gazelle.wav"/>
<prompt phrase="getaway" filename="getaway.wav"/>
<prompt phrase="glitter" filename="glitter.wav"/>
<prompt phrase="glossary" filename="glossary.wav"/>
<prompt phrase="glucose" filename="glucose.wav"/>
<prompt phrase="goggles" filename="goggles.wav"/>
<prompt phrase="goldfish" filename="goldfish.wav"/>
<prompt phrase="gossamer" filename="gossamer.wav"/>
<prompt phrase="graduate" filename="graduate.wav"/>
<prompt phrase="gravity" filename="gravity.wav"/>
<prompt phrase="gremlin" filename="gremlin.wav"/>
<prompt phrase="guidance" filename="guidance.wav"/>
<prompt phrase="guitarist" filename="guitarist.wav"/>
<prompt phrase="hamburger" filename="hamburger.wav"/>
<prompt phrase="hamlet" filename="hamlet.wav"/>
<prompt phrase="handiwork" filename="handiwork.wav"/>
<prompt phrase="hazardous" filename="hazardous.wav"/>
<prompt phrase="headwaters" filename="headwaters.wav"/>
<prompt phrase="hemisphere" filename="hemisphere.wav"/>
<prompt phrase="hesitate" filename="hesitate.wav"/>
<prompt phrase="hideaway" filename="hideaway.wav"/>
<prompt phrase="highchair" filename="highchair.wav"/>
<prompt phrase="hockey" filename="hockey.wav"/>
<prompt phrase="holiness" filename="holiness.wav"/>
<prompt phrase="hurricane" filename="hurricane.wav"/>
<prompt phrase="hydraulic" filename="hydraulic.wav"/>
<prompt phrase="impartial" filename="impartial.wav"/>
<prompt phrase="impetus" filename="impetus.wav"/>
<prompt phrase="inception" filename="inception.wav"/>
<prompt phrase="indigo" filename="indigo.wav"/>
<prompt phrase="indoors" filename="indoors.wav"/>
<prompt phrase="indulge" filename="indulge.wav"/>
<prompt phrase="inertia" filename="inertia.wav"/>
<prompt phrase="infancy" filename="infancy.wav"/>
<prompt phrase="inferno" filename="inferno.wav"/>
<prompt phrase="informant" filename="informant.wav"/>
<prompt phrase="insincere" filename="insincere.wav"/>
<prompt phrase="insurgent" filename="insurgent.wav"/>
<prompt phrase="integrate" filename="integrate.wav"/>
<prompt phrase="intention" filename="intention.wav"/>
<prompt phrase="inventive" filename="inventive.wav"/>
<prompt phrase="inverse" filename="inverse.wav"/>
<prompt phrase="involve" filename="involve.wav"/>
<prompt phrase="island" filename="island.wav"/>
<prompt phrase="jawbone" filename="jawbone.wav"/>
<prompt phrase="keyboard" filename="keyboard.wav"/>
<prompt phrase="kickoff" filename="kickoff.wav"/>
<prompt phrase="kiwi" filename="kiwi.wav"/>
<prompt phrase="klaxon" filename="klaxon.wav"/>
<prompt phrase="leprosy" filename="leprosy.wav"/>
<prompt phrase="letterhead" filename="letterhead.wav"/>
<prompt phrase="liberty" filename="liberty.wav"/>
<prompt phrase="locale" filename="locale.wav"/>
<prompt phrase="lockup" filename="lockup.wav"/>
<prompt phrase="maritime" filename="maritime.wav"/>
<prompt phrase="matchmaker" filename="matchmaker.wav"/>
<prompt phrase="maverick" filename="maverick.wav"/>
<prompt phrase="megaton" filename="megaton.wav"/>
<prompt phrase="merit" filename="merit.wav"/>
<prompt phrase="microscope" filename="microscope.wav"/>
<prompt phrase="microwave" filename="microwave.wav"/>
<prompt phrase="midsummer" filename="midsummer.wav"/>
<prompt phrase="millionaire" filename="millionaire.wav"/>
<prompt phrase="minnow" filename="minnow.wav"/>
<prompt phrase="miracle" filename="miracle.wav"/>
<prompt phrase="miser" filename="miser.wav"/>
<prompt phrase="misnomer" filename="misnomer.wav"/>
<prompt phrase="molasses" filename="molasses.wav"/>
<prompt phrase="molecule" filename="molecule.wav"/>
<prompt phrase="monument" filename="monument.wav"/>
<prompt phrase="mosquito" filename="mosquito.wav"/>
<prompt phrase="mural" filename="mural.wav"/>
<prompt phrase="music" filename="music.wav"/>
<prompt phrase="narrative" filename="narrative.wav"/>
<prompt phrase="nebula" filename="nebula.wav"/>
<prompt phrase="necklace" filename="necklace.wav"/>
<prompt phrase="newborn" filename="newborn.wav"/>
<prompt phrase="newsletter" filename="newsletter.wav"/>
<prompt phrase="nightbird" filename="nightbird.wav"/>
<prompt phrase="obtuse" filename="obtuse.wav"/>
<prompt phrase="offload" filename="offload.wav"/>
<prompt phrase="onlooker" filename="onlooker.wav"/>
<prompt phrase="optic" filename="optic.wav"/>
<prompt phrase="opulent" filename="opulent.wav"/>
<prompt phrase="orca" filename="orca.wav"/>
<prompt phrase="outfielder" filename="outfielder.wav"/>
<prompt phrase="pandemic" filename="pandemic.wav"/>
<prompt phrase="paperweight" filename="paperweight.wav"/>
<prompt phrase="paragon" filename="paragon.wav"/>
<prompt phrase="paragraph" filename="paragraph.wav"/>
<prompt phrase="paramount" filename="paramount.wav"/>
<prompt phrase="passenger" filename="passenger.wav"/>
<prompt phrase="payday" filename="payday.wav"/>
<prompt phrase="peachy" filename="peachy.wav"/>
<prompt phrase="pedigree" filename="pedigree.wav"/>
<prompt phrase="penetrate" filename="penetrate.wav"/>
<prompt phrase="perceptive" filename="perceptive.wav"/>
<prompt phrase="performance" filename="performance.wav"/>
<prompt phrase="pharmacy" filename="pharmacy.wav"/>
<prompt phrase="pheasant" filename="pheasant.wav"/>
<prompt phrase="phonetic" filename="phonetic.wav"/>
<prompt phrase="photograph" filename="photograph.wav"/>
<prompt phrase="physique" filename="physique.wav"/>
<prompt phrase="pioneer" filename="pioneer.wav"/>
<prompt phrase="playhouse" filename="playhouse.wav"/>
<prompt phrase="pocketful" filename="pocketful.wav"/>
<prompt phrase="politeness" filename="politeness.wav"/>
<prompt phrase="positive" filename="positive.wav"/>
<prompt phrase="potato" filename="potato.wav"/>
<prompt phrase="preclude" filename="preclude.wav"/>
<prompt phrase="prefer" filename="prefer.wav"/>
<prompt phrase="preshrunk" filename="preshrunk.wav"/>
<prompt phrase="printer" filename="printer.wav"/>
<prompt phrase="processor" filename="processor.wav"/>
<prompt phrase="provincial" filename="provincial.wav"/>
<prompt phrase="prowler" filename="prowler.wav"/>
<prompt phrase="proximate" filename="proximate.wav"/>
<prompt phrase="puberty" filename="puberty.wav"/>
<prompt phrase="publisher" filename="publisher.wav"/>
<prompt phrase="pupil" filename="pupil.wav"/>
<prompt phrase="puppy" filename="puppy.wav"/>
<prompt phrase="pyramid" filename="pyramid.wav"/>
<prompt phrase="python" filename="python.wav"/>
<prompt phrase="quadrant" filename="quadrant.wav"/>
<prompt phrase="quantity" filename="quantity.wav"/>
<prompt phrase="quiver" filename="quiver.wav"/>
<prompt phrase="quota" filename="quota.wav"/>
<prompt phrase="racketeer" filename="racketeer.wav"/>
<prompt phrase="ragtime" filename="ragtime.wav"/>
<prompt phrase="ratchet" filename="ratchet.wav"/>
<prompt phrase="rebellion" filename="rebellion.wav"/>
<prompt phrase="rebirth" filename="rebirth.wav"/>
<prompt phrase="recipe" filename="recipe.wav"/>
<prompt phrase="recover" filename="recover.wav"/>
<prompt phrase="reform" filename="reform.wav"/>
<prompt phrase="regain" filename="regain.wav"/>
<prompt phrase="reindeer" filename="reindeer.wav"/>
<prompt phrase="rematch" filename="rematch.wav"/>
<prompt phrase="repay" filename="repay.wav"/>
<prompt phrase="repellent" filename="repellent.wav"/>
<prompt phrase="replica" filename="replica.wav"/>
<prompt phrase="reproduce" filename="reproduce.wav"/>
<prompt phrase="resistor" filename="resistor.wav"/>
<prompt phrase="responsive" filename="responsive.wav"/>
<prompt phrase="retouch" filename="retouch.wav"/>
<prompt phrase="retraction" filename="retraction.wav"/>
<prompt phrase="retrieval" filename="retrieval.wav"/>
<prompt phrase="retrospect" filename="retrospect.wav"/>
<prompt phrase="revenge" filename="revenge.wav"/>
<prompt phrase="revenue" filename="revenue.wav"/>
<prompt phrase="revival" filename="revival.wav"/>
<prompt phrase="revolver" filename="revolver.wav"/>
<prompt phrase="reward" filename="reward.wav"/>
<prompt phrase="rhythm" filename="rhythm.wav"/>
<prompt phrase="ribcage" filename="ribcage.wav"/>
<prompt phrase="ringbolt" filename="ringbolt.wav"/>
<prompt phrase="robust" filename="robust.wav"/>
<prompt phrase="rocker" filename="rocker.wav"/>
<prompt phrase="ruffled" filename="ruffled.wav"/>
<prompt phrase="sailboat" filename="sailboat.wav"/>
<prompt phrase="sandalwood" filename="sandalwood.wav"/>
<prompt phrase="sardonic" filename="sardonic.wav"/>
<prompt phrase="savagery" filename="savagery.wav"/>
<prompt phrase="sawdust" filename="sawdust.wav"/>
<prompt phrase="scallion" filename="scallion.wav"/>
<prompt phrase="scavenger" filename="scavenger.wav"/>
<prompt phrase="scenic" filename="scenic.wav"/>
<prompt phrase="scorecard" filename="scorecard.wav"/>
<prompt phrase="seabird" filename="seabird.wav"/>
<prompt phrase="select" filename="select.wav"/>
<prompt phrase="sensation" filename="sensation.wav"/>
<prompt phrase="sentence" filename="sentence.wav"/>
<prompt phrase="shadow" filename="shadow.wav"/>
<prompt phrase="shamrock" filename="shamrock.wav"/>
<prompt phrase="showgirl" filename="showgirl.wav"/>
<prompt phrase="skullcap" filename="skullcap.wav"/>
<prompt phrase="skydive" filename="skydive.wav"/>
<prompt phrase="slingshot" filename="slingshot.wav"/>
<prompt phrase="slowdown" filename="slowdown.wav"/>
<prompt phrase="snapline" filename="snapline.wav"/>
<prompt phrase="snapshot" filename="snapshot.wav"/>
<prompt phrase="snowcap" filename="snowcap.wav"/>
<prompt phrase="snowslide" filename="snowslide.wav"/>
<prompt phrase="sociable" filename="sociable.wav"/>
<prompt phrase="solo" filename="solo.wav"/>
<prompt phrase="southward" filename="southward.wav"/>
<prompt phrase="souvenir" filename="souvenir.wav"/>
<prompt phrase="soybean" filename="soybean.wav"/>
<prompt phrase="spaniel" filename="spaniel.wav"/>
<prompt phrase="spearhead" filename="spearhead.wav"/>
<prompt phrase="specialist" filename="specialist.wav"/>
<prompt phrase="speculate" filename="speculate.wav"/>
<prompt phrase="spellbind" filename="spellbind.wav"/>
<prompt phrase="spheroid" filename="spheroid.wav"/>
<prompt phrase="spigot" filename="spigot.wav"/>
<prompt phrase="spindle" filename="spindle.wav"/>
<prompt phrase="spyglass" filename="spyglass.wav"/>
<prompt phrase="stagehand" filename="stagehand.wav"/>
<prompt phrase="stagnate" filename="stagnate.wav"/>
<prompt phrase="stairway" filename="stairway.wav"/>
<prompt phrase="standard" filename="standard.wav"/>
<prompt phrase="stapler" filename="stapler.wav"/>
<prompt phrase="steamship" filename="steamship.wav"/>
<prompt phrase="sterling" filename="sterling.wav"/>
<prompt phrase="stethoscope" filename="stethoscope.wav"/>
<prompt phrase="stockman" filename="stockman.wav"/>
<prompt phrase="stopwatch" filename="stopwatch.wav"/>
<prompt phrase="stormy" filename="stormy.wav"/>
<prompt phrase="stupendous" filename="stupendous.wav"/>
<prompt phrase="sugar" filename="sugar.wav"/>
<prompt phrase="supportive" filename="supportive.wav"/>
<prompt phrase="surmount" filename="surmount.wav"/>
<prompt phrase="surrender" filename="surrender.wav"/>
<prompt phrase="suspense" filename="suspense.wav"/>
<prompt phrase="suspicious" filename="suspicious.wav"/>
<prompt phrase="sweatband" filename="sweatband.wav"/>
<prompt phrase="swelter" filename="swelter.wav"/>
<prompt phrase="sympathy" filename="sympathy.wav"/>
<prompt phrase="tactics" filename="tactics.wav"/>
<prompt phrase="talon" filename="talon.wav"/>
<prompt phrase="tambourine" filename="tambourine.wav"/>
<prompt phrase="tapeworm" filename="tapeworm.wav"/>
<prompt phrase="telephone" filename="telephone.wav"/>
<prompt phrase="tempest" filename="tempest.wav"/>
<prompt phrase="therapist" filename="therapist.wav"/>
<prompt phrase="tiger" filename="tiger.wav"/>
<prompt phrase="tissue" filename="tissue.wav"/>
<prompt phrase="tobacco" filename="tobacco.wav"/>
<prompt phrase="tolerance" filename="tolerance.wav"/>
<prompt phrase="tomorrow" filename="tomorrow.wav"/>
<prompt phrase="tonic" filename="tonic.wav"/>
<prompt phrase="topmost" filename="topmost.wav"/>
<prompt phrase="torpedo" filename="torpedo.wav"/>
<prompt phrase="tracker" filename="tracker.wav"/>
<prompt phrase="tradition" filename="tradition.wav"/>
<prompt phrase="transit" filename="transit.wav"/>
<prompt phrase="trauma" filename="trauma.wav"/>
<prompt phrase="travesty" filename="travesty.wav"/>
<prompt phrase="treadmill" filename="treadmill.wav"/>
<prompt phrase="trombonist" filename="trombonist.wav"/>
<prompt phrase="trouble" filename="trouble.wav"/>
<prompt phrase="truncated" filename="truncated.wav"/>
<prompt phrase="tumor" filename="tumor.wav"/>
<prompt phrase="tunnel" filename="tunnel.wav"/>
<prompt phrase="tycoon" filename="tycoon.wav"/>
<prompt phrase="typewriter" filename="typewriter.wav"/>
<prompt phrase="ultimate" filename="ultimate.wav"/>
<prompt phrase="uncut" filename="uncut.wav"/>
<prompt phrase="undaunted" filename="undaunted.wav"/>
<prompt phrase="underfoot" filename="underfoot.wav"/>
<prompt phrase="unearth" filename="unearth.wav"/>
<prompt phrase="unicorn" filename="unicorn.wav"/>
<prompt phrase="unify" filename="unify.wav"/>
<prompt phrase="universe" filename="universe.wav"/>
<prompt phrase="unravel" filename="unravel.wav"/>
<prompt phrase="unwind" filename="unwind.wav"/>
<prompt phrase="upcoming" filename="upcoming.wav"/>
<prompt phrase="uproot" filename="uproot.wav"/>
<prompt phrase="upset" filename="upset.wav"/>
<prompt phrase="upshot" filename="upshot.wav"/>
<prompt phrase="vacancy" filename="vacancy.wav"/>
<prompt phrase="vagabond" filename="vagabond.wav"/>
<prompt phrase="vapor" filename="vapor.wav"/>
<prompt phrase="vertigo" filename="vertigo.wav"/>
<prompt phrase="village" filename="village.wav"/>
<prompt phrase="virus" filename="virus.wav"/>
<prompt phrase="visitor" filename="visitor.wav"/>
<prompt phrase="vocalist" filename="vocalist.wav"/>
<prompt phrase="voyager" filename="voyager.wav"/>
<prompt phrase="waffle" filename="waffle.wav"/>
<prompt phrase="wallet" filename="wallet.wav"/>
<prompt phrase="warranty" filename="warranty.wav"/>
<prompt phrase="watchword" filename="watchword.wav"/>
<prompt phrase="wayside" filename="wayside.wav"/>
<prompt phrase="whimsical" filename="whimsical.wav"/>
<prompt phrase="willow" filename="willow.wav"/>
<prompt phrase="woodlark" filename="woodlark.wav"/>
<prompt phrase="yesteryear" filename="yesteryear.wav"/>
<!-- Event prompts -->
<prompt phrase="Bienvenidos al servicio de inscripción ZRTP." filename="zrtp-enroll_welcome.wav"/>
<prompt phrase="Usted debe verificar la cadena de carácteres con su destino. Si no coincide, indica la presencia de una escucha telefónica." filename="zrtp-check_sas.wav"/>
<prompt phrase="Solo teléfonos autenticados pueden confiar en llamadas securizadas con ZRTP. Su teléfono no está autenticado con este sistema, por lo que esta llamada no estará securizada." filename="zrtp-enroll_not_sip_registered.wav"/>
<prompt phrase="Su teléfono indica que confia en este sistema para realizar llamadas seguras con ZRTP, no necesita hacer nada más." filename="zrtp-enroll_already_enrolled.wav"/>
<prompt phrase="Solo teléfonos soportando el protócolo ZRTP pueden usar esta extensión. Su teléfono no tiene ZRTP habilitado, por lo que esta llamada no estará securizada." filename="zrtp-enroll_notzrtp.wav"/>
<prompt phrase="Este sistema esta configurado para manejar llamadas cifradas con ZRTP. Decida si permite al sistema tener la posibilidad de interceptar o monitorizar su llamada. Puede colgar una vez confirmado." filename="zrtp-enroll_confirmed.wav"/>
<prompt phrase="Compara verbalmente este código de autenticación con su destino." filename="zrtp-is_secure.wav"/>
<prompt phrase="El código de autenticación no está verificado." filename="zrtp-is_unverified.wav"/>
<prompt phrase="El código de autenticación está verificado." filename="zrtp-is_verified.wav"/>
<prompt phrase="Gracias por llamar. Adiós." filename="zrtp-thankyou_goodbye.wav"/>
<prompt phrase="Algún error ha ocurrido." filename="zrtp-somethings_wrong.wav"/>
<prompt phrase="Error." filename="zrtp-status_error.wav"/>
<prompt phrase="Esta llamada no está protegida." filename="zrtp-status_notsecure.wav"/>
<prompt phrase="Esta llamada está protegida." filename="zrtp-status_secure.wav"/>
<prompt phrase="Securizando su llamada." filename="zrtp-status_securing.wav"/>
</zrtp>
</es_ES>
<language>

View File

@ -0,0 +1,993 @@
<language>
<es_MX>
<ascii>
<prompt phrase="Espacio" filename="32.wav"/>
<prompt phrase="Signo de número" filename="35.wav"/>
<prompt phrase="Asterisco" filename="42.wav"/>
<prompt phrase="Punto" filename="46.wav"/>
<prompt phrase="A" filename="97.wav"/>
<prompt phrase="B" filename="98.wav"/>
<prompt phrase="C" filename="99.wav"/>
<prompt phrase="D" filename="100.wav"/>
<prompt phrase="E" filename="101.wav"/>
<prompt phrase="F" filename="102.wav"/>
<prompt phrase="G" filename="103.wav"/>
<prompt phrase="H" filename="104.wav"/>
<prompt phrase="I" filename="105.wav"/>
<prompt phrase="J" filename="106.wav"/>
<prompt phrase="K" filename="107.wav"/>
<prompt phrase="L" filename="108.wav"/>
<prompt phrase="M" filename="109.wav"/>
<prompt phrase="N" filename="110.wav"/>
<prompt phrase="Ñ" filename="Ñ.wav"/>
<prompt phrase="O" filename="111.wav"/>
<prompt phrase="P" filename="112.wav"/>
<prompt phrase="Q" filename="113.wav"/>
<prompt phrase="R" filename="114.wav"/>
<prompt phrase="S" filename="115.wav"/>
<prompt phrase="T" filename="116.wav"/>
<prompt phrase="U" filename="117.wav"/>
<prompt phrase="V" filename="118.wav"/>
<prompt phrase="W" filename="119.wav"/>
<prompt phrase="X" filename="120.wav"/>
<prompt phrase="Y" filename="121.wav"/>
<prompt phrase="Z" filename="122.wav"/>
</ascii>
<phonetic-ascii>
<prompt phrase="Espacio" filename="32.wav"/>
<prompt phrase="Punto" filename="46.wav"/>
<prompt phrase="Alpha" filename="97.wav"/>
<prompt phrase="Bravo" filename="98.wav"/>
<prompt phrase="Charlie" filename="99.wav"/>
<prompt phrase="Delta" filename="100.wav"/>
<prompt phrase="Echo" filename="101.wav"/>
<prompt phrase="Foxtrot" filename="102.wav"/>
<prompt phrase="Golf" filename="103.wav"/>
<prompt phrase="Hotel" filename="104.wav"/>
<prompt phrase="India" filename="105.wav"/>
<prompt phrase="Juliet" filename="106.wav"/>
<prompt phrase="Kilo" filename="107.wav"/>
<prompt phrase="Lima" filename="108.wav"/>
<prompt phrase="Mike" filename="109.wav"/>
<prompt phrase="November" filename="110.wav"/>
<prompt phrase="Oscar" filename="111.wav"/>
<prompt phrase="Papa" filename="112.wav"/>
<prompt phrase="Quebec" filename="113.wav"/>
<prompt phrase="Romeo" filename="114.wav"/>
<prompt phrase="Sierra" filename="115.wav"/>
<prompt phrase="Tango" filename="116.wav"/>
<prompt phrase="Unifor" filename="117.wav"/>
<prompt phrase="Victor" filename="118.wav"/>
<prompt phrase="Whiskey" filename="119.wav"/>
<prompt phrase="Xray" filename="120.wav"/>
<prompt phrase="Yankee" filename="121.wav"/>
<prompt phrase="Zulu" filename="122.wav"/>
</phonetic-ascii>
<digits>
<prompt phrase="Cero" filename="0.wav"/>
<prompt phrase="Uno" filename="1.wav"/>
<prompt phrase="Dos" filename="2.wav"/>
<prompt phrase="Tres" filename="3.wav"/>
<prompt phrase="Cuatro" filename="4.wav"/>
<prompt phrase="Cinco" filename="5.wav"/>
<prompt phrase="Seis" filename="6.wav"/>
<prompt phrase="Siete" filename="7.wav"/>
<prompt phrase="Ocho" filename="8.wav"/>
<prompt phrase="Nueve" filename="9.wav"/>
<prompt phrase="Diez" filename="10.wav"/>
<prompt phrase="Once" filename="11.wav"/>
<prompt phrase="Doce" filename="12.wav"/>
<prompt phrase="Trece" filename="13.wav"/>
<prompt phrase="Catorce" filename="14.wav"/>
<prompt phrase="Quince" filename="15.wav"/>
<prompt phrase="Dieciséis" filename="16.wav"/>
<prompt phrase="Diecisiete" filename="17.wav"/>
<prompt phrase="Dieciocho" filename="18.wav"/>
<prompt phrase="Diecinueve" filename="19.wav"/>
<prompt phrase="Veinte" filename="20.wav"/>
<prompt phrase="Veinti" filename="veinti.wav"/>
<prompt phrase="Treinta" filename="30.wav"/>
<prompt phrase="Cuarenta" filename="40.wav"/>
<prompt phrase="Cincuenta" filename="50.wav"/>
<prompt phrase="Sesenta" filename="60.wav"/>
<prompt phrase="Setenta" filename="70.wav"/>
<prompt phrase="Ochenta" filename="80.wav"/>
<prompt phrase="Noventa" filename="90.wav"/>
<prompt phrase="Cien" filename="100.wav"/>
<prompt phrase="Quinientos" filename="500.wav"/>
<prompt phrase="Setecientos" filename="700.wav"/>
<prompt phrase="Novecientos" filename="900.wav"/>
<prompt phrase="Punto" filename="dot.wav"/>
<prompt phrase="Primero" filename="h-1.wav"/>
<prompt phrase="Segundo" filename="h-2.wav"/>
<prompt phrase="Tercero" filename="h-3.wav"/>
<prompt phrase="Cuarto" filename="h-4.wav"/>
<prompt phrase="Quinto" filename="h-5.wav"/>
<prompt phrase="Sexto" filename="h-6.wav"/>
<prompt phrase="Séptimo" filename="h-7.wav"/>
<prompt phrase="Octavo" filename="h-8.wav"/>
<prompt phrase="Noveno" filename="h-9.wav"/>
<prompt phrase="Décimo" filename="h-10.wav"/>
<prompt phrase="Undécimo" filename="h-11.wav"/>
<prompt phrase="Duodécimo" filename="h-12.wav"/>
<prompt phrase="Decimotercero" filename="h-13.wav"/>
<prompt phrase="Decimocuarto" filename="h-14.wav"/>
<prompt phrase="Decimoquinto" filename="h-15.wav"/>
<prompt phrase="Decimosexto" filename="h-16.wav"/>
<prompt phrase="Decimoséptimo" filename="h-17.wav"/>
<prompt phrase="Decimoctavo" filename="h-18.wav"/>
<prompt phrase="Decimonoveno" filename="h-19.wav"/>
<prompt phrase="Vigésimo" filename="h-20.wav"/>
<prompt phrase="Trigésimo" filename="h-30.wav"/>
<prompt phrase="Un" filename="un.wav"/>
<prompt phrase="Ciento" filename="hundred.wav"/>
<prompt phrase="Cientos" filename="hundreds.wav"/>
<prompt phrase="Mil" filename="thousand.wav"/>
<prompt phrase="Millón" filename="million.wav"/>
<prompt phrase="Millones" filename="millions.wav"/>
<prompt phrase="Período" filename="period.wav"/>
<prompt phrase="Punto" filename="point.wav"/>
<prompt phrase="Signo de número" filename="pound.wav"/>
<prompt phrase="Asterisco" filename="star.wav"/>
</digits>
<currency>
<prompt phrase="Y" filename="and.wav"/>
<prompt phrase="Centavo" filename="cent.wav"/>
<prompt phrase="Central" filename="central.wav"/>
<prompt phrase="Centavos por minuto" filename="cents-per-minute.wav"/>
<prompt phrase="Centavos" filename="cents.wav"/>
<prompt phrase="Dólar" filename="dollar.wav"/>
<prompt phrase="Dólares" filename="dollars.wav"/>
<prompt phrase="Menos" filename="minus.wav"/>
<prompt phrase="Negativo" filename="negative.wav"/>
</currency>
<time>
<prompt phrase="A.M." filename="a-m.wav"/>
<prompt phrase="A" filename="at.wav"/>
<prompt phrase="Domingo" filename="day-0.wav"/>
<prompt phrase="Lunes" filename="day-1.wav"/>
<prompt phrase="Martes" filename="day-2.wav"/>
<prompt phrase="Miércoles" filename="day-3.wav"/>
<prompt phrase="Jueves" filename="day-4.wav"/>
<prompt phrase="Viernes" filename="day-5.wav"/>
<prompt phrase="Sábado" filename="day-6.wav"/>
<prompt phrase="Hora" filename="hour.wav"/>
<prompt phrase="Horas" filename="hours.wav"/>
<prompt phrase="Minuto" filename="minute.wav"/>
<prompt phrase="Minutos" filename="minutes.wav"/>
<prompt phrase="Enero" filename="mon-0.wav"/>
<prompt phrase="Febrero" filename="mon-1.wav"/>
<prompt phrase="Marzo" filename="mon-2.wav"/>
<prompt phrase="Abril" filename="mon-3.wav"/>
<prompt phrase="Mayo" filename="mon-4.wav"/>
<prompt phrase="Junio" filename="mon-5.wav"/>
<prompt phrase="Julio" filename="mon-6.wav"/>
<prompt phrase="Agosto" filename="mon-7.wav"/>
<prompt phrase="Septiembre" filename="mon-8.wav"/>
<prompt phrase="Octubre" filename="mon-9.wav"/>
<prompt phrase="Noviembre" filename="mon-10.wav"/>
<prompt phrase="Diciembre" filename="mon-11.wav"/>
<prompt phrase="En punto" filename="oclock.wav"/>
<prompt phrase="P.M." filename="p-m.wav"/>
<prompt phrase="Segundo" filename="second.wav"/>
<prompt phrase="Segundos" filename="seconds.wav"/>
<prompt phrase="Hoy" filename="today.wav"/>
<prompt phrase="Mañana" filename="tomorrow.wav"/>
<prompt phrase="Ayer" filename="yesterday.wav"/>
</time>
<voicemail>
<prompt phrase="La persona en la extensión..." filename="vm-person.wav"/>
<prompt phrase="Marcado urgente." filename="vm-marked-urgent.wav"/>
<prompt phrase="Mandado por correo electrónico." filename="vm-emailed.wav"/>
<prompt phrase="Usted tiene..." filename="vm-you_have.wav"/>
<prompt phrase="Por favor ingrese su número de usuario, seguido por..." filename="vm-enter_id.wav"/>
<prompt phrase="Por favor ingrese su contraseña, seguido por..." filename="vm-enter_pass.wav"/>
<prompt phrase="Inicio de sesión incorrectos." filename="vm-fail_auth.wav"/>
<prompt phrase="Bienvenido a su buzon de voz." filename="vm-hello.wav"/>
<prompt phrase="Adiós." filename="vm-goodbye.wav"/>
<prompt phrase="Después del tono, por favor anote su nombre, pulse cualquier tecla o deje de hablar para poner fin a la grabación." filename="vm-record_name1.wav"/>
<prompt phrase="Elija un saludo entre 1 y 9." filename="vm-choose_greeting_choose.wav"/>
<prompt phrase="Valor inválido." filename="vm-choose_greeting_fail.wav"/>
<prompt phrase="Demasiados intentos fallidos." filename="vm-abort.wav"/>
<prompt phrase="Para cambiar su clave." filename="vm-change_password.wav"/>
<prompt phrase="Grabe su saludo después del tono, pulse cualquier tecla o deje de hablar para poner fin a la grabación" filename="vm-record_greeting.wav"/>
<prompt phrase="Grabe su mensaje después del tono, pulse cualquier tecla o deje de hablar para poner fin a la grabación" filename="vm-record_message.wav"/>
<prompt phrase="...no está disponible." filename="vm-play_greeting.wav"/>
<prompt phrase="Urgente nuevo" filename="vm-urgent-new.wav"/>
<prompt phrase="Nuevo" filename="vm-new.wav"/>
<prompt phrase="Urgente guardado" filename="vm-urgent-saved.wav"/>
<prompt phrase="Guardado" filename="vm-saved.wav"/>
<prompt phrase="Mensaje" filename="vm-message.wav"/>
<prompt phrase="Mensajes" filename="vm-messages.wav"/>
<prompt phrase="Presione" filename="vm-press.wav"/>
<prompt phrase="Para escuchar mensajes nuevos..." filename="vm-listen_new.wav"/>
<prompt phrase="Para escuchar mensajes guardados..." filename="vm-listen_saved.wav"/>
<prompt phrase="Para opciones avanzadas..." filename="vm-advanced.wav"/>
<prompt phrase="Para salir..." filename="vm-to_exit.wav"/>
<prompt phrase="Para guardar un saludo..." filename="vm-record_greeting.wav"/>
<prompt phrase="Para elegir un saludo..." filename="vm-choose_greeting.wav"/>
<prompt phrase="Para grabar su nombre..." filename="vm-record_name2.wav"/>
<prompt phrase="Para el menú principal..." filename="vm-main_menu.wav"/>
<prompt phrase="Para escuchar la grabación..." filename="vm-listen_to_recording.wav"/>
<prompt phrase="Para guardar la grabación..." filename="vm-save_recording.wav"/>
<prompt phrase="Para regrabar..." filename="vm-rerecord.wav"/>
<prompt phrase="Para marcar este mensaje como urgente..." filename="vm-mark-urgent.wav"/>
<prompt phrase="Para continuar..." filename="vm-continue.wav"/>
<prompt phrase="Para escuchar la grabación de nuevo..." filename="vm-listen_to_recording_again.wav"/>
<prompt phrase="Para eliminar la grabación..." filename="vm-delete_recording.wav"/>
<prompt phrase="Para enviar la grabación a su e-mail..." filename="vm-forward_to_email.wav"/>
<prompt phrase="Saludo" filename="vm-greeting.wav"/>
<prompt phrase="Seleccionado" filename="vm-selected.wav"/>
<prompt phrase="...no está disponible." filename="vm-not_available.wav"/>
<prompt phrase="Mensaje número..." filename="vm-message_number.wav"/>
<prompt phrase="Eliminado" filename="vm-deleted.wav"/>
<prompt phrase="Su grabación es demasiado corta, por favor intente de nuevo." filename="vm-too-small.wav"/>
<prompt phrase="...en la bandeja de entrada." filename="vm-in_folder.wav"/>
<prompt phrase="Para devolver la llamada..." filename="vm-return_call.wav"/>
<prompt phrase="Urgente" filename="vm-urgent.wav"/>
<prompt phrase="Este buzón está lleno. Por favor intente llamar mas tarde." filename="vm-mailbox_full.wav"/>
<prompt phrase="Bienvenido a su nuevo buzón de voz. Para escuchar el tutorial y configurar su buzón, pulse 1. Para saltarlo pulse 2." filename="vm-tutorial_yes_no.wav"/>
<prompt phrase="Necesito grabar su nombre y apellido. Esta grabación se usará entre otros en el servicio de directorio." filename="vm-tutorial_record_name.wav"/>
<prompt phrase="Su número de identificación personal o PIN sirve para impedir a terceros el acceso a sus mensajes. Desea cambiar su PIN ahora?" filename="vm-tutorial_change_pin.wav"/>
</voicemail>
<directory>
<prompt phrase="Por favor introduzca las primeras letras del nombre buscado." filename="dir-enter_person.wav"/>
<prompt phrase="...apellido..." filename="dir-last_name.wav"/>
<prompt phrase="Para buscar por..." filename="dir-to_search_by.wav"/>
<prompt phrase="...nombre..." filename="dir-first_name.wav"/>
<prompt phrase="No hay resultados que coincidan con su busqueda." filename="dir-no_matching_results.wav"/>
<prompt phrase="...resultados coinciden con su busqueda." filename="dir-result_match.wav"/>
<prompt phrase="Su busqueda genera demasiados resultados." filename="dir-too_many_result.wav"/>
<prompt phrase="No hay más resultados." filename="dir-no_more_results.wav"/>
<prompt phrase="Resultado número..." filename="dir-result_number.wav"/>
<prompt phrase="...en la extensión..." filename="dir-at_extension.wav"/>
<prompt phrase="Para seleccionar este resultado..." filename="dir-to_select_entry.wav"/>
<prompt phrase="Para el resultado siguiente..." filename="dir-for_next.wav"/>
<prompt phrase="Para el resultado previo..." filename="dir-for_prev.wav"/>
<prompt phrase="Para empezar una nueva busqueda..." filename="dir-start_new_search.wav"/>
<prompt phrase="Necesita especificar un mínimo de..." filename="dir-specify_mininum.wav"/>
<prompt phrase="...letras del nombre buscado." filename="dir-letters_of_person_name.wav"/>
<prompt phrase="Por favor intentelo de nuevo." filename="dir-please_try_again.wav"/>
<prompt phrase="Pulse..." filename="dir-press.wav" info="we can copy vm/vm-press.wav"/>
</directory>
<conference>
<prompt phrase="NULL" filename="conf-ack.wav" type="tone"/>
<prompt phrase="NULL" filename="conf-nack.wav" type="tone"/>
<prompt phrase="Usted ahora está silenciado." filename="conf-muted.wav"/>
<prompt phrase="Usted ya no está silenciado." filename="conf-unmuted.wav"/>
<prompt phrase="En este momento usted es la única persona en la conferencia." filename="conf-alone.wav"/>
<prompt phrase="NULL" filename="conf-perpetual.wav" type="music"/>
<prompt phrase="NULL" filename="conf-enter.wav" type="tone"/>
<prompt phrase="NULL" filename="conf-exit.wav" type="tone"/>
<prompt phrase="Usted ha sido expulsado de la conferencia." filename="conf-kicked.wav"/>
<prompt phrase="Esta conferencia está bloqueada." filename="conf-locked.wav"/>
<prompt phrase="La conferencia está ahora bloqueada." filename="conf-is-locked.wav"/>
<prompt phrase="La conferencia está ahora desbloqueada." filename="conf-is-unlocked.wav"/>
<prompt phrase="Por favor ingrese el PIN de la conferencia." filename="conf-pin.wav"/>
<prompt phrase="PIN inválido, intente de nuevo." filename="conf-bad-pin.wav"/>
<prompt phrase="Hasta luego." filename="conf-goodbye.wav"/>
<prompt phrase="Bienvenido a la conferencia." filename="conf-welcome.wav"/>
</conference>
<ivr>
<prompt phrase="Número de cuenta" filename="ivr-account_number.wav"/>
<prompt phrase="Conectar con quien llama" filename="ivr-connect_to_caller.wav"/>
<prompt phrase="Si conoce la extensión, por favor ingrésela ahora" filename="ivr-enter_ext_pound.wav"/>
<prompt phrase="por favor ingrese el número de una extensión seguido del signo de número" filename="ivr-enter_ext.wav"/>
<prompt phrase="Para esta persona..." filename="ivr-for_this_person.wav"/>
<prompt phrase="Por favor espere mientras conecto su llamada." filename="ivr-hold_connect_call.wav"/>
<prompt phrase="Lo siento..." filename="ivr-im_sorry.wav"/>
<prompt phrase="Por favor..." filename="ivr-please.wav"/>
<prompt phrase="Por favor devuelva nuestra llamada al..." filename="ivr-please_return_our_call_at.wav"/>
<prompt phrase="Acerca del número de referencia" filename="ivr-regarding_reference_number.wav"/>
<prompt phrase="Este es un ejemplo de un submenú de audio respuesta..." filename="ivr-sample_submenu.wav"/>
<prompt phrase="Por favor diga su nombre después del tono." filename="ivr-say_name.wav"/>
<prompt phrase="Enviar a esta persona que llama al buzón de voz." filename="ivr-send_to_voicemail.wav"/>
<prompt phrase="Para hablar con un representante de servicio al cliente..." filename="ivr-speak_to_a_customer_service_representative.wav"/>
<prompt phrase="Tomar un mensaje" filename="ivr-take_a_message.wav"/>
<prompt phrase="Gracias" filename="ivr-thank_you.wav"/>
<prompt phrase="Esa fue una entrada inválida." filename="ivr-that_was_an_invalid_entry.wav"/>
<prompt phrase="Esta es una llamada de..." filename="ivr-this_is_a_call_from.wav"/>
<prompt phrase="Este menú de audiorrespuesta le permitirá probar algunas de las características..." filename="ivr-this_ivr_will_let_you_test_features.wav"/>
<prompt phrase="Para llamar a la conferencia de FreeSWITCH..." filename="ivr-to_call_the_freeswitch_conference.wav"/>
<prompt phrase="Para hacer una prueba de eco de FreeSWITCH..." filename="ivr-to_do_a_freeswitch_echo_test.wav"/>
<prompt phrase="Para hacer una prueba de eco de FWD..." filename="ivr-to_do_a_fwd_echo_test.wav"/>
<prompt phrase="Para escuchar un ejemplo de un submenú de audio respuesta..." filename="ivr-to_hear_sample_submenu.wav"/>
<prompt phrase="Para escuchar simios gritando..." filename="ivr-to_hear_screaming_monkeys.wav"/>
<prompt phrase="Para escuchar música de llamada en espera..." filename="ivr-to_listen_to_moh.wav"/>
<prompt phrase="Para repetir estas opciones..." filename="ivr-to_repeat_these_options.wav"/>
<prompt phrase="Para regresar al menú anterior..." filename="ivr-to_return_to_previous_menu.wav"/>
<prompt phrase="Para hablar con un operador..." filename="ivr-to_speak_with_an_operator.wav"/>
<prompt phrase="Bienvenido a FreeSWITCH, el futuro de la telefonía." filename="ivr-welcome_to_freeswitch.wav"/>
<prompt phrase="Usted puede colgar en cualquier momento para salir." filename="ivr-you_may_exit_by_hanging_up.wav"/>
<prompt phrase="O" filename="ivr-or.wav"/>
<prompt phrase="No" filename="ivr-not.wav"/>
<prompt phrase="Llamar" filename="ivr-call.wav"/>
<prompt phrase="Usted puede..." filename="ivr-you_may.wav"/>
<prompt phrase="Hola" filename="ivr-hello.wav"/>
<prompt phrase="Usando el teclado de su teléfono..." filename="ivr-use_telephone_keypad.wav"/>
<prompt phrase="por favor deletree el nombre de la persona a la cual está intentando contactar." filename="ivr-spell_name.wav"/>
<prompt phrase="Primero el apellido" filename="ivr-last_name_first.wav"/>
<prompt phrase="Primero el nombre" filename="ivr-first_name_first.wav"/>
<prompt phrase="Presione 1 para Q ó Z." filename="ivr-press_one_q_or_z.wav"/>
<prompt phrase="Ventas" filename="ivr-sales.wav"/>
<prompt phrase="Servicio al cliente" filename="ivr-customer_service.wav"/>
<prompt phrase="Soporte técnico" filename="ivr-technical_support.wav"/>
<prompt phrase="Operador" filename="ivr-operator.wav"/>
<prompt phrase="Usted marcó una extensión inválida." filename="ivr-you_have_dialed_an_invalid_extension.wav"/>
<prompt phrase="Por favor introduzca su número de extensión, seguido de la tecla almohadilla." filename="ivr-please_enter_extension_followed_by_pound.wav"/>
<prompt phrase="Por favor introduzca su contraseña, seguido de la tecla almohadilla." filename="ivr-please_enter_pin_followed_by_pound.wav"/>
<prompt phrase="Su contraseña o extensión es inválida." filename="ivr-pin_or_extension_is-invalid.wav"/>
<prompt phrase="Usted esta a punto de asociar este teléfono a su cuenta..." filename="ivr-you_are_about_to_provision_this_phone.wav"/>
<prompt phrase="Por favor vuelva a introducir su contraseña para confirmar." filename="ivr-please_reenter_your_pin.wav"/>
<prompt phrase="Para registrarse en ClueCon, por favor pulse..." filename="ivr-register_for_cluecon.wav"/>
<prompt phrase="Para conectarse..." filename="ivr-to_log_in.wav"/>
<prompt phrase="Para desconectarse..." filename="ivr-to_log_out.wav"/>
<prompt phrase="Usted está ahora conectado." filename="ivr-you_are_now_logged_in.wav"/>
<prompt phrase="Usted está ahora desconectado." filename="ivr-you_are_now_logged_out.wav"/>
<prompt phrase="Por favor intentelo de nuevo." filename="ivr-please_try_again.wav"/>
<prompt phrase="Usted está a punto de asociar este teléfono a su cuenta de forma permanente." filename="ivr-provision_phone_permanently_to_extension.wav"/>
<prompt phrase="Por favor introduzca su número de extensión con la cual desea asociar su teléfono, seguido de la tecla almohadilla." filename="ivr-extension_to_provision_this_phone.wav"/>
<prompt phrase="Gracias, este teléfono va a reiniciarse ahora." filename="ivr-this_phone_will_now_reboot.wav"/>
<prompt phrase="Gracias, su grabación ha sido guardada." filename="ivr-recording_saved.wav"/>
<prompt phrase="Pulse 1 para guardar su grabación. Pulse 2 para escuchar su grabación. Pulse 3 para volver a grabar." filename="ivr-save_review_record.wav"/>
<prompt phrase="En este momento, el sistema no puede guardar su fichero de audio. Por favor intentelo de nuevo." filename="ivr-unable_save.wav"/>
<prompt phrase="Usted está en la posición..." filename="ivr-you_are_number.wav"/>
<prompt phrase="...en la cola de espera." filename="ivr-in_line.wav"/>
<prompt phrase="Gracias por permanecer en espera." filename="ivr-thank_you_for_holding.wav"/>
<prompt phrase="El tiempo estimado de espera es..." filename="ivr-estimated_hold_time.wav"/>
<prompt phrase="Más de..." filename="ivr-more_than.wav"/>
<prompt phrase="Menos de..." filename="ivr-less_than.wav"/>
<prompt phrase="Empieze a grabar." filename="ivr-begin_recording.wav "/>
<prompt phrase="El desvío de llamada ha sido desactivado." filename="ivr-call_forwarding_has_been_cancelled.wav"/>
<prompt phrase="El desvío de llamada ha sido activado." filename="ivr-call_forwarding_has_been_set.wav"/>
<prompt phrase="Por favor introduzca el número de teléfono." filename="ivr-please_enter_the_phone_number.wav"/>
<prompt phrase="Por favor diga su nombre, y la razón de la llamada." filename="ivr-please_state_your_name_and_reason_for_calling.wav"/>
<prompt phrase="Para aceptar, pulse 1. Para rechazar, pulse 2. Para mandar a buzón de voz, pulse 3." filename="ivr-accept_reject_voicemail.wav"/>
<prompt phrase="Llamada entrante." filename="ivr-incoming_call.wav"/>
<prompt phrase="Gracias por llamar." filename="ivr-thank_you_for_calling.wav"/>
<prompt phrase="Por favor mentengase a la espera. Su llamada será atendida en un momento." filename="ivr-stay_on_line_call_answered_momentarily.wav"/>
<prompt phrase="Su llamada está siendo procesada." filename="ivr-call_being_transferred.wav"/>
<prompt phrase="Por favor disfrute de la música mientras su llamada está siendo procesada..." filename="ivr-enjoy_music_while_transfer.wav"/>
<prompt phrase="Usted tiene una llamada de..." filename="ivr-call_from.wav"/>
<prompt phrase="Este menú no tiene entradas. Por favor contacte con el administrador." filename="ivr-no_menu_items.wav"/>
<prompt phrase="Para el servicio de directorio, pulse..." filename="ivr-for_directory_press.wav"/>
<prompt phrase="Usando las teclas de su teléfono..." filename="ivr-using_telephone_keypad.wav"/>
<prompt phrase="Introduzca las primeras letras del apellido de la persona." filename="ivr-enter_letters_last_name.wav"/>
<prompt phrase="Introduzca las primeras letras del nombre de la persona." filename="ivr-enter_letters_first_name.wav"/>
<prompt phrase="Introduzca las primeras letras del nombre o apellido de la persona." filename="ivr-enter_letters_first_or_last_name.wav"/>
<prompt phrase="Si es correcto, pulse..." filename="ivr-if_correct_press.wav"/>
<prompt phrase="Sino, pulse..." filename="ivr-if_not_press.wav"/>
<prompt phrase="Cuando termine, pulse la tecla almohadilla." filename="ivr-finished_pound_hash_key.wav"/>
<prompt phrase="La función de No Molestar ha sido activada." filename="ivr-dnd_activated.wav"/>
<prompt phrase="La función de No Molestar ha sido desactivada." filename="ivr-dnd_cancelled.wav"/>
<prompt phrase="Pulse cualquier otro dígito..." filename="ivr-any_other_digit.wav"/>
<prompt phrase="Pulse uno si su respuesta es sí. Pulse dos si su respuesta es no." filename="ivr-one_yes_two_no.wav"/>
<prompt phrase="Por favor introduzca el número de la cola, seguido de la tecla almohadilla." filename="ivr-enter_queue_number.wav"/>
<prompt phrase="Por favor introduzca el..." filename="ivr-please_enter_the.wav"/>
<prompt phrase="Número." filename="ivr-number.wav"/>
<prompt phrase="...seguido de la tecla almohadilla." filename="ivr-followed_by_pound.wav"/>
<prompt phrase="El balance de la cuenta es..." filename="ivr-account_balance_is.wav"/>
<prompt phrase="Gracias por llamar. Si conoce la extensión de su destino, por favor marquela ahora. Para acceder al directorio, pulse..." filename="ivr-generic_greeting.wav"/>
<prompt phrase="...fichero..." filename="ivr-file.wav"/>
<prompt phrase="...ficheros..." filename="ivr-files-.wav"/>
<prompt phrase="Para una llamada de despertador..." filename="ivr-for_a_wakeup_call.wav"/>
<prompt phrase="Este es el servicio de despertador." filename="ivr-this_is_your_wakeup_call.wav"/>
<prompt phrase="Para solicitar una llamada de despertador..." filename="ivr-request_wakeup_call.wav"/>
<prompt phrase="Para confirmar la llamada de despertador..." filename="ivr-confirm_wakeup_call.wav"/>
<prompt phrase="Para anular la llamada de despertador..." filename="ivr-cancel_wakeup_call.wav"/>
<prompt phrase="Usted ha solicitado una llamada de despertador para..." filename="ivr-requested_wakeup_call_for.wav"/>
<prompt phrase="Usted no ha solicitado llamadas de despertador." filename="ivr-not_requested_wakeup_call.wav"/>
<prompt phrase="Su llamada de despertador ha sido anulada." filename="ivr-wakeup_call_cancelled.wav"/>
<prompt phrase="Para una llamada diaria de despertador..." filename="ivr-for_daily_wakeup_call.wav"/>
<prompt phrase="Llamada diaria de despertador..." filename="ivr-daily_wakeup_call.wav"/>
<prompt phrase="Para llamadas diarias de despertador..." filename="ivr-for_daily_wakeup_calls.wav"/>
<prompt phrase="Para una llamada de despertador única..." filename="ivr-for_one_time_wakeup_call.wav"/>
<prompt phrase="Llamada de despertador única..." filename="ivr-one_time_wakeup_call.wav"/>
<prompt phrase="...llamada de despertador..." filename="ivr-wakeup_call.wav"/>
<prompt phrase="¡Vamos despierta cielo!" filename="ivr-wakey_wakey_sunshine.wav"/>
<prompt phrase="Bienvenido." filename="ivr-welcome.wav"/>
<prompt phrase="Bienvenido a..." filename="ivr-welcome_to.wav"/>
<prompt phrase="Buenos días." filename="ivr-good_morning.wav"/>
<prompt phrase="Buenas tardes." filename="ivr-good_afternoon.wav"/>
<prompt phrase="Buenas noches." filename="ivr-good_evening.wav"/>
<prompt phrase="Gracias." filename="ivr-Thank_you.wav"/>
<prompt phrase="Para..." filename="ivr-for.wav"/>
<prompt phrase="El tiempo de espera esta siendo anormalmente elevado." filename="ivr-longer_than_usual_hold_times.wav"/>
<prompt phrase="Usted es el..." filename="ivr-you_are_the.wav"/>
<prompt phrase="Un momento por favor." filename="ivr-one_moment_please.wav"/>
<prompt phrase="Su llamada será atendida según el orden de entrada." filename="ivr-call_answered_order_received.wav"/>
<prompt phrase="Por favor introduzca el número de conferencia, seguido de la tecla almohadilla." filename="conf-enter_conf_number.wav"/>
<prompt phrase="Introduzca el PIN de la conferencia, seguido de la tecla almohadilla." filename="conf-enter_conf_pin.wav"/>
<prompt phrase="...se incorporó a la conferencia." filename="conf-has_joined.wav"/>
<prompt phrase="...ha abandonado la conferencia." filename="conf-has_left.wav"/>
<prompt phrase="Usted entró..." filename="ivr-you_entered.wav"/>
<prompt phrase="Número de extensión..." filename="ivr-extension_number.wav"/>
<prompt phrase="Por favor mantengase a la espera mientras contactamos con su destino." filename="ivr-please_hold_while_party_contacted.wav"/>
<prompt phrase="Por favor disfrute de la música mientras le conectamos con su destino." filename="ivr-please_enjoy_music_while_party_reached.wav"/>
<prompt phrase="Gracias por llamar. Si conoce la extensión de su destino, por favor marquela ahora, o marque nueve para el servicio de directorio." filename="ivr-generic_greeting.wav"/>
<prompt phrase="Si es correcto, pulse 1. Sino, pulse 2." filename="ivr-if_correct_one_if_not_two.wav"/>
<prompt phrase="Para repetir esta información..." filename="ivr-repeat_this_information.wav"/>
<prompt phrase="No no no!" filename="ivr-no_no_no.wav"/>
<prompt phrase="Era su intención pulsar esta tecla?" filename="ivr-did_you_mean_to_press_key.wav"/>
<prompt phrase="Pensaba Usted DE VERDAD pulsar esta tecla?" filename="ivr-seriously_mean_to_press_key.wav"/>
<prompt phrase="Oh DA IGUAL." filename="ivr-oh_whatever.wav"/>
<prompt phrase="No más! Un error más y le colgaré a la cara." filename="ivr-one_more_mistake.wav"/>
<prompt phrase="Felicitaciones. Ha pulsado estrella. Esto no significa que ES una estrella. Tan solo significa que puede pulsar teclas y probablemente tiene dedos." filename="ivr-congratulations_you_pressed_star.wav"/>
<prompt phrase="Todos nuestros ingenieros están ocupados en demostrar lo impresionante que es el CudaTel." filename="ivr-engineers_busy_assisting_other_sales.wav"/>
<prompt phrase="La persona con la que intenta hablar no está disponible y no tiene buzón de voz." filename="vm-not_available_no_voicemail.wav"/>
<prompt phrase="Este mensaje se auto-destruira en 5, 4, 3, 2, 1..." filename="ivr-message_self_destruct.wav"/>
<prompt phrase="Su llamada ya está silenciada." filename="conf-you_are_already_muted.wav"/>
<prompt phrase="Su llamada ha sido silenciada en ambos sentidos." filename="conf-you_are_now_bidirectionally_muted.wav"/>
<prompt phrase="Todas sus llamadas nos pertenecen." filename="ivr-all_your_call_are_belong_to_us.wav"/>
<prompt phrase="Me encanta como está pulsando estas teclas!" filename="ivr-love_those_touch_tones.wav"/>
<prompt phrase="No, no tenemos bananas." filename="ivr-yes_we_have_no_bananas.wav"/>
<prompt phrase="Hombre, estas siendo ridículo!" filename="ivr-dude_you_suck.wav"/>
<prompt phrase="Su llamada es muy importante para nosotros, pero su bienestar mental no lo es, asi que estamos felices mantenerle a la espera, torturandole indefinidamente con nuestra péssima música en espera." filename="ivr-on_hold_indefinitely.wav"/>
<prompt phrase="...ha dejado el edificio." filename="ivr-has_left_the_building.wav"/>
<prompt phrase="Este teléfono no está asignado y no puede ser usado para realizar llamadas externas." filename="ivr-phone_is_unassigned.wav"/>
<prompt phrase="Este teléfono no está configurado correctamente." filename="ivr-phone_not_configured.wav"/>
<prompt phrase="Felicitaciones! Este teléfono está configurado correctamente y puede ahora ser asociado a un usuario." filename="ivr-phone_is_configured_properly.wav"/>
<prompt phrase="Por favor contacte con el administrador del sistema para obtener asistencia." filename="ivr-contact_system_administrator.wav"/>
<prompt phrase="Barracuda Networks" filename="ivr-barracuda_networks.wav"/>
<prompt phrase="CudaTel Communication Server" filename="ivr-cudatel_communication_server.wav"/>
<prompt phrase="Por favor introduzca las primeras letras del nombre o apellido de la persona." filename="dir-enter_person_first_or_last.wav"/>
<prompt phrase="No hay llamadas en espera en esta cola." filename="ivr-no_calls_waiting_in_queue.wav"/>
<prompt phrase="Brian West" filename="misc-Brian_West.wav"/>
<prompt phrase="Anthony Minessale" filename="misc-Anthony_Minessale.wav"/>
<prompt phrase="Michael Jerris" filename="misc-Michael_Jerris.wav"/>
<prompt phrase="Raymond Chandler" filename="misc-Raymond_Chandler.wav"/>
<prompt phrase="Michael Collins" filename="misc-Michael_Collins.wav"/>
<prompt phrase="Mark Mann" filename="misc-Mark_Mann.wav"/>
<prompt phrase="William King" filename="misc-William_King.wav"/>
<prompt phrase="Rudy Fleminger" filename="misc-Rudy_Fleminger.wav"/>
<prompt phrase="Andrew Thompson" filename="misc-Andrew_Thompson.wav"/>
<prompt phrase="Graham Saathoff" filename="misc-Graham_Saathoff.wav"/>
<prompt phrase="Nicholaus Belluni" filename="misc-Nicholaus_Belluni.wav"/>
<prompt phrase="Sean Heiney" filename="misc-Sean_Heiney.wav"/>
</ivr>
<misc>
<prompt phrase="Esta llamada ha sido asegurada." filename="call_secured.wav"/>
<prompt phrase="...seguido del signo de número." filename="followed.wav"/>
<prompt phrase="Si usted es esta persona..." filename="if_you_are_this_person.wav"/>
<prompt phrase="Si usted desea..." filename="if_you_would_like_to.wav"/>
<prompt phrase="Diga el número de referencia..." filename="provide_reference_number.wav"/>
<prompt phrase="Por favor pulse la extensión a la cual desea transferir." filename="transfer1.wav"/>
<prompt phrase="Transferir" filename="transfer2.wav"/>
<prompt phrase="Estamos tratando de contactar..." filename="we_are_trying_to_reach.wav"/>
<prompt phrase="Un error ha ocurrido, por favor contacte al administrador." filename="error.wav"/>
<prompt phrase="Su llamada será terminada en..." filename="misc-your_call_will_be_terminated_in.wav"/>
<prompt phrase="Su llamada ha sido terminada." filename="misc-your_call_has_been_terminated.wav"/>
</misc>
<zrtp>
<!-- base256 prompts for SAS -->
<prompt phrase="Algol" filename="Algol.wav"/>
<prompt phrase="Apollo" filename="Apollo.wav"/>
<prompt phrase="Athens" filename="Athens.wav"/>
<prompt phrase="Atlantic" filename="Atlantic.wav"/>
<prompt phrase="Aztec" filename="Aztec.wav"/>
<prompt phrase="Babylon" filename="Babylon.wav"/>
<prompt phrase="Belfast" filename="Belfast.wav"/>
<prompt phrase="Bradbury" filename="Bradbury.wav"/>
<prompt phrase="Brazilian" filename="Brazilian.wav"/>
<prompt phrase="Burbank" filename="Burbank.wav"/>
<prompt phrase="Burlington" filename="Burlington.wav"/>
<prompt phrase="Camelot" filename="Camelot.wav"/>
<prompt phrase="Capricorn" filename="Capricorn.wav"/>
<prompt phrase="Cherokee" filename="Cherokee.wav"/>
<prompt phrase="Chicago" filename="Chicago.wav"/>
<prompt phrase="Christmas" filename="Christmas.wav"/>
<prompt phrase="Dakota" filename="Dakota.wav"/>
<prompt phrase="December" filename="December.wav"/>
<prompt phrase="Dupont" filename="Dupont.wav"/>
<prompt phrase="Eskimo" filename="Eskimo.wav"/>
<prompt phrase="Galveston" filename="Galveston.wav"/>
<prompt phrase="Geiger" filename="Geiger.wav"/>
<prompt phrase="Hamilton" filename="Hamilton.wav"/>
<prompt phrase="Istanbul" filename="Istanbul.wav"/>
<prompt phrase="Jamaica" filename="Jamaica.wav"/>
<prompt phrase="Jupiter" filename="Jupiter.wav"/>
<prompt phrase="Medusa" filename="Medusa.wav"/>
<prompt phrase="Mohawk" filename="Mohawk.wav"/>
<prompt phrase="Montana" filename="Montana.wav"/>
<prompt phrase="Neptune" filename="Neptune.wav"/>
<prompt phrase="Norwegian" filename="Norwegian.wav"/>
<prompt phrase="Oakland" filename="Oakland.wav"/>
<prompt phrase="October" filename="October.wav"/>
<prompt phrase="Ohio" filename="Ohio.wav"/>
<prompt phrase="Orlando" filename="Orlando.wav"/>
<prompt phrase="Pacific" filename="Pacific.wav"/>
<prompt phrase="Pandora" filename="Pandora.wav"/>
<prompt phrase="Pegasus" filename="Pegasus.wav"/>
<prompt phrase="Pluto" filename="Pluto.wav"/>
<prompt phrase="Saturday" filename="Saturday.wav"/>
<prompt phrase="Scotland" filename="Scotland.wav"/>
<prompt phrase="Trojan" filename="Trojan.wav"/>
<prompt phrase="Virginia" filename="Virginia.wav"/>
<prompt phrase="Vulcan" filename="Vulcan.wav"/>
<prompt phrase="Waterloo" filename="Waterloo.wav"/>
<prompt phrase="Wichita" filename="Wichita.wav"/>
<prompt phrase="Wilmington" filename="Wilmington.wav"/>
<prompt phrase="Wyoming" filename="Wyoming.wav"/>
<prompt phrase="Yucatan" filename="Yucatan.wav"/>
<prompt phrase="Zulu" filename="Zulu.wav"/>
<prompt phrase="aardvark" filename="aardvark.wav"/>
<prompt phrase="absurd" filename="absurd.wav"/>
<prompt phrase="accrue" filename="accrue.wav"/>
<prompt phrase="acme" filename="acme.wav"/>
<prompt phrase="adrift" filename="adrift.wav"/>
<prompt phrase="adroitness" filename="adroitness.wav"/>
<prompt phrase="adult" filename="adult.wav"/>
<prompt phrase="adviser" filename="adviser.wav"/>
<prompt phrase="afflict" filename="afflict.wav"/>
<prompt phrase="aftermath" filename="aftermath.wav"/>
<prompt phrase="aggregate" filename="aggregate.wav"/>
<prompt phrase="ahead" filename="ahead.wav"/>
<prompt phrase="aimless" filename="aimless.wav"/>
<prompt phrase="alkali" filename="alkali.wav"/>
<prompt phrase="allow" filename="allow.wav"/>
<prompt phrase="almighty" filename="almighty.wav"/>
<prompt phrase="alone" filename="alone.wav"/>
<prompt phrase="ammo" filename="ammo.wav"/>
<prompt phrase="amulet" filename="amulet.wav"/>
<prompt phrase="amusement" filename="amusement.wav"/>
<prompt phrase="ancient" filename="ancient.wav"/>
<prompt phrase="antenna" filename="antenna.wav"/>
<prompt phrase="apple" filename="apple.wav"/>
<prompt phrase="applicant" filename="applicant.wav"/>
<prompt phrase="armistice" filename="armistice.wav"/>
<prompt phrase="article" filename="article.wav"/>
<prompt phrase="artist" filename="artist.wav"/>
<prompt phrase="assume" filename="assume.wav"/>
<prompt phrase="asteroid" filename="asteroid.wav"/>
<prompt phrase="atlas" filename="atlas.wav"/>
<prompt phrase="atmosphere" filename="atmosphere.wav"/>
<prompt phrase="autopsy" filename="autopsy.wav"/>
<prompt phrase="baboon" filename="baboon.wav"/>
<prompt phrase="backfield" filename="backfield.wav"/>
<prompt phrase="backward" filename="backward.wav"/>
<prompt phrase="backwater" filename="backwater.wav"/>
<prompt phrase="banjo" filename="banjo.wav"/>
<prompt phrase="barbecue" filename="barbecue.wav"/>
<prompt phrase="beaming" filename="beaming.wav"/>
<prompt phrase="bedlamp" filename="bedlamp.wav"/>
<prompt phrase="beehive" filename="beehive.wav"/>
<prompt phrase="beeswax" filename="beeswax.wav"/>
<prompt phrase="befriend" filename="befriend.wav"/>
<prompt phrase="belowground" filename="belowground.wav"/>
<prompt phrase="berserk" filename="berserk.wav"/>
<prompt phrase="bifocals" filename="bifocals.wav"/>
<prompt phrase="billiard" filename="billiard.wav"/>
<prompt phrase="bison" filename="bison.wav"/>
<prompt phrase="blackjack" filename="blackjack.wav"/>
<prompt phrase="blockade" filename="blockade.wav"/>
<prompt phrase="blowtorch" filename="blowtorch.wav"/>
<prompt phrase="bluebird" filename="bluebird.wav"/>
<prompt phrase="bodyguard" filename="bodyguard.wav"/>
<prompt phrase="bombast" filename="bombast.wav"/>
<prompt phrase="bookseller" filename="bookseller.wav"/>
<prompt phrase="bookshelf" filename="bookshelf.wav"/>
<prompt phrase="borderline" filename="borderline.wav"/>
<prompt phrase="bottomless" filename="bottomless.wav"/>
<prompt phrase="brackish" filename="brackish.wav"/>
<prompt phrase="bravado" filename="bravado.wav"/>
<prompt phrase="breadline" filename="breadline.wav"/>
<prompt phrase="breakaway" filename="breakaway.wav"/>
<prompt phrase="breakup" filename="breakup.wav"/>
<prompt phrase="brickyard" filename="brickyard.wav"/>
<prompt phrase="briefcase" filename="briefcase.wav"/>
<prompt phrase="businessman" filename="businessman.wav"/>
<prompt phrase="butterfat" filename="butterfat.wav"/>
<prompt phrase="button" filename="button.wav"/>
<prompt phrase="buzzard" filename="buzzard.wav"/>
<prompt phrase="candidate" filename="candidate.wav"/>
<prompt phrase="cannonball" filename="cannonball.wav"/>
<prompt phrase="caravan" filename="caravan.wav"/>
<prompt phrase="caretaker" filename="caretaker.wav"/>
<prompt phrase="celebrate" filename="celebrate.wav"/>
<prompt phrase="cellulose" filename="cellulose.wav"/>
<prompt phrase="cement" filename="cement.wav"/>
<prompt phrase="certify" filename="certify.wav"/>
<prompt phrase="chairlift" filename="chairlift.wav"/>
<prompt phrase="chambermaid" filename="chambermaid.wav"/>
<prompt phrase="chatter" filename="chatter.wav"/>
<prompt phrase="checkup" filename="checkup.wav"/>
<prompt phrase="chisel" filename="chisel.wav"/>
<prompt phrase="choking" filename="choking.wav"/>
<prompt phrase="chopper" filename="chopper.wav"/>
<prompt phrase="clamshell" filename="clamshell.wav"/>
<prompt phrase="classic" filename="classic.wav"/>
<prompt phrase="classroom" filename="classroom.wav"/>
<prompt phrase="cleanup" filename="cleanup.wav"/>
<prompt phrase="clergyman" filename="clergyman.wav"/>
<prompt phrase="clockwork" filename="clockwork.wav"/>
<prompt phrase="cobra" filename="cobra.wav"/>
<prompt phrase="coherence" filename="coherence.wav"/>
<prompt phrase="combustion" filename="combustion.wav"/>
<prompt phrase="commando" filename="commando.wav"/>
<prompt phrase="commence" filename="commence.wav"/>
<prompt phrase="company" filename="company.wav"/>
<prompt phrase="component" filename="component.wav"/>
<prompt phrase="concert" filename="concert.wav"/>
<prompt phrase="concurrent" filename="concurrent.wav"/>
<prompt phrase="confidence" filename="confidence.wav"/>
<prompt phrase="conformist" filename="conformist.wav"/>
<prompt phrase="congregate" filename="congregate.wav"/>
<prompt phrase="consensus" filename="consensus.wav"/>
<prompt phrase="consulting" filename="consulting.wav"/>
<prompt phrase="corporate" filename="corporate.wav"/>
<prompt phrase="corrosion" filename="corrosion.wav"/>
<prompt phrase="councilman" filename="councilman.wav"/>
<prompt phrase="cowbell" filename="cowbell.wav"/>
<prompt phrase="crackdown" filename="crackdown.wav"/>
<prompt phrase="cranky" filename="cranky.wav"/>
<prompt phrase="crossover" filename="crossover.wav"/>
<prompt phrase="crowfoot" filename="crowfoot.wav"/>
<prompt phrase="crucial" filename="crucial.wav"/>
<prompt phrase="crucifix" filename="crucifix.wav"/>
<prompt phrase="crumpled" filename="crumpled.wav"/>
<prompt phrase="crusade" filename="crusade.wav"/>
<prompt phrase="cubic" filename="cubic.wav"/>
<prompt phrase="cumbersome" filename="cumbersome.wav"/>
<prompt phrase="customer" filename="customer.wav"/>
<prompt phrase="dashboard" filename="dashboard.wav"/>
<prompt phrase="deadbolt" filename="deadbolt.wav"/>
<prompt phrase="decadence" filename="decadence.wav"/>
<prompt phrase="decimal" filename="decimal.wav"/>
<prompt phrase="deckhand" filename="deckhand.wav"/>
<prompt phrase="designing" filename="designing.wav"/>
<prompt phrase="detector" filename="detector.wav"/>
<prompt phrase="detergent" filename="detergent.wav"/>
<prompt phrase="determine" filename="determine.wav"/>
<prompt phrase="dictator" filename="dictator.wav"/>
<prompt phrase="dinosaur" filename="dinosaur.wav"/>
<prompt phrase="direction" filename="direction.wav"/>
<prompt phrase="disable" filename="disable.wav"/>
<prompt phrase="disbelief" filename="disbelief.wav"/>
<prompt phrase="disruptive" filename="disruptive.wav"/>
<prompt phrase="distortion" filename="distortion.wav"/>
<prompt phrase="document" filename="document.wav"/>
<prompt phrase="dogsled" filename="dogsled.wav"/>
<prompt phrase="dragnet" filename="dragnet.wav"/>
<prompt phrase="drainage" filename="drainage.wav"/>
<prompt phrase="dreadful" filename="dreadful.wav"/>
<prompt phrase="drifter" filename="drifter.wav"/>
<prompt phrase="dropper" filename="dropper.wav"/>
<prompt phrase="drumbeat" filename="drumbeat.wav"/>
<prompt phrase="drunken" filename="drunken.wav"/>
<prompt phrase="dwelling" filename="dwelling.wav"/>
<prompt phrase="eating" filename="eating.wav"/>
<prompt phrase="edict" filename="edict.wav"/>
<prompt phrase="egghead" filename="egghead.wav"/>
<prompt phrase="eightball" filename="eightball.wav"/>
<prompt phrase="embezzle" filename="embezzle.wav"/>
<prompt phrase="enchanting" filename="enchanting.wav"/>
<prompt phrase="endorse" filename="endorse.wav"/>
<prompt phrase="endow" filename="endow.wav"/>
<prompt phrase="enlist" filename="enlist.wav"/>
<prompt phrase="enrollment" filename="enrollment.wav"/>
<prompt phrase="enterprise" filename="enterprise.wav"/>
<prompt phrase="equation" filename="equation.wav"/>
<prompt phrase="equipment" filename="equipment.wav"/>
<prompt phrase="erase" filename="erase.wav"/>
<prompt phrase="escapade" filename="escapade.wav"/>
<prompt phrase="escape" filename="escape.wav"/>
<prompt phrase="everyday" filename="everyday.wav"/>
<prompt phrase="examine" filename="examine.wav"/>
<prompt phrase="exceed" filename="exceed.wav"/>
<prompt phrase="existence" filename="existence.wav"/>
<prompt phrase="exodus" filename="exodus.wav"/>
<prompt phrase="eyeglass" filename="eyeglass.wav"/>
<prompt phrase="eyetooth" filename="eyetooth.wav"/>
<prompt phrase="facial" filename="facial.wav"/>
<prompt phrase="fallout" filename="fallout.wav"/>
<prompt phrase="fascinate" filename="fascinate.wav"/>
<prompt phrase="filament" filename="filament.wav"/>
<prompt phrase="finicky" filename="finicky.wav"/>
<prompt phrase="flagpole" filename="flagpole.wav"/>
<prompt phrase="flatfoot" filename="flatfoot.wav"/>
<prompt phrase="flytrap" filename="flytrap.wav"/>
<prompt phrase="forever" filename="forever.wav"/>
<prompt phrase="fortitude" filename="fortitude.wav"/>
<prompt phrase="fracture" filename="fracture.wav"/>
<prompt phrase="framework" filename="framework.wav"/>
<prompt phrase="freedom" filename="freedom.wav"/>
<prompt phrase="frequency" filename="frequency.wav"/>
<prompt phrase="frighten" filename="frighten.wav"/>
<prompt phrase="gadgetry" filename="gadgetry.wav"/>
<prompt phrase="gazelle" filename="gazelle.wav"/>
<prompt phrase="getaway" filename="getaway.wav"/>
<prompt phrase="glitter" filename="glitter.wav"/>
<prompt phrase="glossary" filename="glossary.wav"/>
<prompt phrase="glucose" filename="glucose.wav"/>
<prompt phrase="goggles" filename="goggles.wav"/>
<prompt phrase="goldfish" filename="goldfish.wav"/>
<prompt phrase="gossamer" filename="gossamer.wav"/>
<prompt phrase="graduate" filename="graduate.wav"/>
<prompt phrase="gravity" filename="gravity.wav"/>
<prompt phrase="gremlin" filename="gremlin.wav"/>
<prompt phrase="guidance" filename="guidance.wav"/>
<prompt phrase="guitarist" filename="guitarist.wav"/>
<prompt phrase="hamburger" filename="hamburger.wav"/>
<prompt phrase="hamlet" filename="hamlet.wav"/>
<prompt phrase="handiwork" filename="handiwork.wav"/>
<prompt phrase="hazardous" filename="hazardous.wav"/>
<prompt phrase="headwaters" filename="headwaters.wav"/>
<prompt phrase="hemisphere" filename="hemisphere.wav"/>
<prompt phrase="hesitate" filename="hesitate.wav"/>
<prompt phrase="hideaway" filename="hideaway.wav"/>
<prompt phrase="highchair" filename="highchair.wav"/>
<prompt phrase="hockey" filename="hockey.wav"/>
<prompt phrase="holiness" filename="holiness.wav"/>
<prompt phrase="hurricane" filename="hurricane.wav"/>
<prompt phrase="hydraulic" filename="hydraulic.wav"/>
<prompt phrase="impartial" filename="impartial.wav"/>
<prompt phrase="impetus" filename="impetus.wav"/>
<prompt phrase="inception" filename="inception.wav"/>
<prompt phrase="indigo" filename="indigo.wav"/>
<prompt phrase="indoors" filename="indoors.wav"/>
<prompt phrase="indulge" filename="indulge.wav"/>
<prompt phrase="inertia" filename="inertia.wav"/>
<prompt phrase="infancy" filename="infancy.wav"/>
<prompt phrase="inferno" filename="inferno.wav"/>
<prompt phrase="informant" filename="informant.wav"/>
<prompt phrase="insincere" filename="insincere.wav"/>
<prompt phrase="insurgent" filename="insurgent.wav"/>
<prompt phrase="integrate" filename="integrate.wav"/>
<prompt phrase="intention" filename="intention.wav"/>
<prompt phrase="inventive" filename="inventive.wav"/>
<prompt phrase="inverse" filename="inverse.wav"/>
<prompt phrase="involve" filename="involve.wav"/>
<prompt phrase="island" filename="island.wav"/>
<prompt phrase="jawbone" filename="jawbone.wav"/>
<prompt phrase="keyboard" filename="keyboard.wav"/>
<prompt phrase="kickoff" filename="kickoff.wav"/>
<prompt phrase="kiwi" filename="kiwi.wav"/>
<prompt phrase="klaxon" filename="klaxon.wav"/>
<prompt phrase="leprosy" filename="leprosy.wav"/>
<prompt phrase="letterhead" filename="letterhead.wav"/>
<prompt phrase="liberty" filename="liberty.wav"/>
<prompt phrase="locale" filename="locale.wav"/>
<prompt phrase="lockup" filename="lockup.wav"/>
<prompt phrase="maritime" filename="maritime.wav"/>
<prompt phrase="matchmaker" filename="matchmaker.wav"/>
<prompt phrase="maverick" filename="maverick.wav"/>
<prompt phrase="megaton" filename="megaton.wav"/>
<prompt phrase="merit" filename="merit.wav"/>
<prompt phrase="microscope" filename="microscope.wav"/>
<prompt phrase="microwave" filename="microwave.wav"/>
<prompt phrase="midsummer" filename="midsummer.wav"/>
<prompt phrase="millionaire" filename="millionaire.wav"/>
<prompt phrase="minnow" filename="minnow.wav"/>
<prompt phrase="miracle" filename="miracle.wav"/>
<prompt phrase="miser" filename="miser.wav"/>
<prompt phrase="misnomer" filename="misnomer.wav"/>
<prompt phrase="molasses" filename="molasses.wav"/>
<prompt phrase="molecule" filename="molecule.wav"/>
<prompt phrase="monument" filename="monument.wav"/>
<prompt phrase="mosquito" filename="mosquito.wav"/>
<prompt phrase="mural" filename="mural.wav"/>
<prompt phrase="music" filename="music.wav"/>
<prompt phrase="narrative" filename="narrative.wav"/>
<prompt phrase="nebula" filename="nebula.wav"/>
<prompt phrase="necklace" filename="necklace.wav"/>
<prompt phrase="newborn" filename="newborn.wav"/>
<prompt phrase="newsletter" filename="newsletter.wav"/>
<prompt phrase="nightbird" filename="nightbird.wav"/>
<prompt phrase="obtuse" filename="obtuse.wav"/>
<prompt phrase="offload" filename="offload.wav"/>
<prompt phrase="onlooker" filename="onlooker.wav"/>
<prompt phrase="optic" filename="optic.wav"/>
<prompt phrase="opulent" filename="opulent.wav"/>
<prompt phrase="orca" filename="orca.wav"/>
<prompt phrase="outfielder" filename="outfielder.wav"/>
<prompt phrase="pandemic" filename="pandemic.wav"/>
<prompt phrase="paperweight" filename="paperweight.wav"/>
<prompt phrase="paragon" filename="paragon.wav"/>
<prompt phrase="paragraph" filename="paragraph.wav"/>
<prompt phrase="paramount" filename="paramount.wav"/>
<prompt phrase="passenger" filename="passenger.wav"/>
<prompt phrase="payday" filename="payday.wav"/>
<prompt phrase="peachy" filename="peachy.wav"/>
<prompt phrase="pedigree" filename="pedigree.wav"/>
<prompt phrase="penetrate" filename="penetrate.wav"/>
<prompt phrase="perceptive" filename="perceptive.wav"/>
<prompt phrase="performance" filename="performance.wav"/>
<prompt phrase="pharmacy" filename="pharmacy.wav"/>
<prompt phrase="pheasant" filename="pheasant.wav"/>
<prompt phrase="phonetic" filename="phonetic.wav"/>
<prompt phrase="photograph" filename="photograph.wav"/>
<prompt phrase="physique" filename="physique.wav"/>
<prompt phrase="pioneer" filename="pioneer.wav"/>
<prompt phrase="playhouse" filename="playhouse.wav"/>
<prompt phrase="pocketful" filename="pocketful.wav"/>
<prompt phrase="politeness" filename="politeness.wav"/>
<prompt phrase="positive" filename="positive.wav"/>
<prompt phrase="potato" filename="potato.wav"/>
<prompt phrase="preclude" filename="preclude.wav"/>
<prompt phrase="prefer" filename="prefer.wav"/>
<prompt phrase="preshrunk" filename="preshrunk.wav"/>
<prompt phrase="printer" filename="printer.wav"/>
<prompt phrase="processor" filename="processor.wav"/>
<prompt phrase="provincial" filename="provincial.wav"/>
<prompt phrase="prowler" filename="prowler.wav"/>
<prompt phrase="proximate" filename="proximate.wav"/>
<prompt phrase="puberty" filename="puberty.wav"/>
<prompt phrase="publisher" filename="publisher.wav"/>
<prompt phrase="pupil" filename="pupil.wav"/>
<prompt phrase="puppy" filename="puppy.wav"/>
<prompt phrase="pyramid" filename="pyramid.wav"/>
<prompt phrase="python" filename="python.wav"/>
<prompt phrase="quadrant" filename="quadrant.wav"/>
<prompt phrase="quantity" filename="quantity.wav"/>
<prompt phrase="quiver" filename="quiver.wav"/>
<prompt phrase="quota" filename="quota.wav"/>
<prompt phrase="racketeer" filename="racketeer.wav"/>
<prompt phrase="ragtime" filename="ragtime.wav"/>
<prompt phrase="ratchet" filename="ratchet.wav"/>
<prompt phrase="rebellion" filename="rebellion.wav"/>
<prompt phrase="rebirth" filename="rebirth.wav"/>
<prompt phrase="recipe" filename="recipe.wav"/>
<prompt phrase="recover" filename="recover.wav"/>
<prompt phrase="reform" filename="reform.wav"/>
<prompt phrase="regain" filename="regain.wav"/>
<prompt phrase="reindeer" filename="reindeer.wav"/>
<prompt phrase="rematch" filename="rematch.wav"/>
<prompt phrase="repay" filename="repay.wav"/>
<prompt phrase="repellent" filename="repellent.wav"/>
<prompt phrase="replica" filename="replica.wav"/>
<prompt phrase="reproduce" filename="reproduce.wav"/>
<prompt phrase="resistor" filename="resistor.wav"/>
<prompt phrase="responsive" filename="responsive.wav"/>
<prompt phrase="retouch" filename="retouch.wav"/>
<prompt phrase="retraction" filename="retraction.wav"/>
<prompt phrase="retrieval" filename="retrieval.wav"/>
<prompt phrase="retrospect" filename="retrospect.wav"/>
<prompt phrase="revenge" filename="revenge.wav"/>
<prompt phrase="revenue" filename="revenue.wav"/>
<prompt phrase="revival" filename="revival.wav"/>
<prompt phrase="revolver" filename="revolver.wav"/>
<prompt phrase="reward" filename="reward.wav"/>
<prompt phrase="rhythm" filename="rhythm.wav"/>
<prompt phrase="ribcage" filename="ribcage.wav"/>
<prompt phrase="ringbolt" filename="ringbolt.wav"/>
<prompt phrase="robust" filename="robust.wav"/>
<prompt phrase="rocker" filename="rocker.wav"/>
<prompt phrase="ruffled" filename="ruffled.wav"/>
<prompt phrase="sailboat" filename="sailboat.wav"/>
<prompt phrase="sandalwood" filename="sandalwood.wav"/>
<prompt phrase="sardonic" filename="sardonic.wav"/>
<prompt phrase="savagery" filename="savagery.wav"/>
<prompt phrase="sawdust" filename="sawdust.wav"/>
<prompt phrase="scallion" filename="scallion.wav"/>
<prompt phrase="scavenger" filename="scavenger.wav"/>
<prompt phrase="scenic" filename="scenic.wav"/>
<prompt phrase="scorecard" filename="scorecard.wav"/>
<prompt phrase="seabird" filename="seabird.wav"/>
<prompt phrase="select" filename="select.wav"/>
<prompt phrase="sensation" filename="sensation.wav"/>
<prompt phrase="sentence" filename="sentence.wav"/>
<prompt phrase="shadow" filename="shadow.wav"/>
<prompt phrase="shamrock" filename="shamrock.wav"/>
<prompt phrase="showgirl" filename="showgirl.wav"/>
<prompt phrase="skullcap" filename="skullcap.wav"/>
<prompt phrase="skydive" filename="skydive.wav"/>
<prompt phrase="slingshot" filename="slingshot.wav"/>
<prompt phrase="slowdown" filename="slowdown.wav"/>
<prompt phrase="snapline" filename="snapline.wav"/>
<prompt phrase="snapshot" filename="snapshot.wav"/>
<prompt phrase="snowcap" filename="snowcap.wav"/>
<prompt phrase="snowslide" filename="snowslide.wav"/>
<prompt phrase="sociable" filename="sociable.wav"/>
<prompt phrase="solo" filename="solo.wav"/>
<prompt phrase="southward" filename="southward.wav"/>
<prompt phrase="souvenir" filename="souvenir.wav"/>
<prompt phrase="soybean" filename="soybean.wav"/>
<prompt phrase="spaniel" filename="spaniel.wav"/>
<prompt phrase="spearhead" filename="spearhead.wav"/>
<prompt phrase="specialist" filename="specialist.wav"/>
<prompt phrase="speculate" filename="speculate.wav"/>
<prompt phrase="spellbind" filename="spellbind.wav"/>
<prompt phrase="spheroid" filename="spheroid.wav"/>
<prompt phrase="spigot" filename="spigot.wav"/>
<prompt phrase="spindle" filename="spindle.wav"/>
<prompt phrase="spyglass" filename="spyglass.wav"/>
<prompt phrase="stagehand" filename="stagehand.wav"/>
<prompt phrase="stagnate" filename="stagnate.wav"/>
<prompt phrase="stairway" filename="stairway.wav"/>
<prompt phrase="standard" filename="standard.wav"/>
<prompt phrase="stapler" filename="stapler.wav"/>
<prompt phrase="steamship" filename="steamship.wav"/>
<prompt phrase="sterling" filename="sterling.wav"/>
<prompt phrase="stethoscope" filename="stethoscope.wav"/>
<prompt phrase="stockman" filename="stockman.wav"/>
<prompt phrase="stopwatch" filename="stopwatch.wav"/>
<prompt phrase="stormy" filename="stormy.wav"/>
<prompt phrase="stupendous" filename="stupendous.wav"/>
<prompt phrase="sugar" filename="sugar.wav"/>
<prompt phrase="supportive" filename="supportive.wav"/>
<prompt phrase="surmount" filename="surmount.wav"/>
<prompt phrase="surrender" filename="surrender.wav"/>
<prompt phrase="suspense" filename="suspense.wav"/>
<prompt phrase="suspicious" filename="suspicious.wav"/>
<prompt phrase="sweatband" filename="sweatband.wav"/>
<prompt phrase="swelter" filename="swelter.wav"/>
<prompt phrase="sympathy" filename="sympathy.wav"/>
<prompt phrase="tactics" filename="tactics.wav"/>
<prompt phrase="talon" filename="talon.wav"/>
<prompt phrase="tambourine" filename="tambourine.wav"/>
<prompt phrase="tapeworm" filename="tapeworm.wav"/>
<prompt phrase="telephone" filename="telephone.wav"/>
<prompt phrase="tempest" filename="tempest.wav"/>
<prompt phrase="therapist" filename="therapist.wav"/>
<prompt phrase="tiger" filename="tiger.wav"/>
<prompt phrase="tissue" filename="tissue.wav"/>
<prompt phrase="tobacco" filename="tobacco.wav"/>
<prompt phrase="tolerance" filename="tolerance.wav"/>
<prompt phrase="tomorrow" filename="tomorrow.wav"/>
<prompt phrase="tonic" filename="tonic.wav"/>
<prompt phrase="topmost" filename="topmost.wav"/>
<prompt phrase="torpedo" filename="torpedo.wav"/>
<prompt phrase="tracker" filename="tracker.wav"/>
<prompt phrase="tradition" filename="tradition.wav"/>
<prompt phrase="transit" filename="transit.wav"/>
<prompt phrase="trauma" filename="trauma.wav"/>
<prompt phrase="travesty" filename="travesty.wav"/>
<prompt phrase="treadmill" filename="treadmill.wav"/>
<prompt phrase="trombonist" filename="trombonist.wav"/>
<prompt phrase="trouble" filename="trouble.wav"/>
<prompt phrase="truncated" filename="truncated.wav"/>
<prompt phrase="tumor" filename="tumor.wav"/>
<prompt phrase="tunnel" filename="tunnel.wav"/>
<prompt phrase="tycoon" filename="tycoon.wav"/>
<prompt phrase="typewriter" filename="typewriter.wav"/>
<prompt phrase="ultimate" filename="ultimate.wav"/>
<prompt phrase="uncut" filename="uncut.wav"/>
<prompt phrase="undaunted" filename="undaunted.wav"/>
<prompt phrase="underfoot" filename="underfoot.wav"/>
<prompt phrase="unearth" filename="unearth.wav"/>
<prompt phrase="unicorn" filename="unicorn.wav"/>
<prompt phrase="unify" filename="unify.wav"/>
<prompt phrase="universe" filename="universe.wav"/>
<prompt phrase="unravel" filename="unravel.wav"/>
<prompt phrase="unwind" filename="unwind.wav"/>
<prompt phrase="upcoming" filename="upcoming.wav"/>
<prompt phrase="uproot" filename="uproot.wav"/>
<prompt phrase="upset" filename="upset.wav"/>
<prompt phrase="upshot" filename="upshot.wav"/>
<prompt phrase="vacancy" filename="vacancy.wav"/>
<prompt phrase="vagabond" filename="vagabond.wav"/>
<prompt phrase="vapor" filename="vapor.wav"/>
<prompt phrase="vertigo" filename="vertigo.wav"/>
<prompt phrase="village" filename="village.wav"/>
<prompt phrase="virus" filename="virus.wav"/>
<prompt phrase="visitor" filename="visitor.wav"/>
<prompt phrase="vocalist" filename="vocalist.wav"/>
<prompt phrase="voyager" filename="voyager.wav"/>
<prompt phrase="waffle" filename="waffle.wav"/>
<prompt phrase="wallet" filename="wallet.wav"/>
<prompt phrase="warranty" filename="warranty.wav"/>
<prompt phrase="watchword" filename="watchword.wav"/>
<prompt phrase="wayside" filename="wayside.wav"/>
<prompt phrase="whimsical" filename="whimsical.wav"/>
<prompt phrase="willow" filename="willow.wav"/>
<prompt phrase="woodlark" filename="woodlark.wav"/>
<prompt phrase="yesteryear" filename="yesteryear.wav"/>
<!-- Event prompts -->
<prompt phrase="Bienvenidos al servicio de inscripción ZRTP." filename="zrtp-enroll_welcome.wav"/>
<prompt phrase="Usted debe verificar la cadena de carácteres con su destino. Si no coincide, indica la presencia de una escucha telefónica." filename="zrtp-check_sas.wav"/>
<prompt phrase="Solo teléfonos autenticados pueden confiar en llamadas seguras con ZRTP. Su teléfono no está autenticado con este sistema, su llamada no estará securizada." filename="zrtp-enroll_not_sip_registered.wav"/>
<prompt phrase="Su teléfono indica que confia en este sistema para realizar llamadas seguras con ZRTP, no necesita hacer nada más." filename="zrtp-enroll_already_enrolled.wav"/>
<prompt phrase="Solo teléfonos soportando el protócolo ZRTP pueden usar esta extensión. Su teléfono no tiene ZRTP habilitado, y está llamada no será securizada." filename="zrtp-enroll_notzrtp.wav"/>
<prompt phrase="Este sistema esta configurado para manejar llamadas cifradas con ZRTP. Decida si permite al sistema tener la posibilidad de interceptar o monitorizar su llamada. Puede colgar una vez confirmado." filename="zrtp-enroll_confirmed.wav"/>
<prompt phrase="Compara verbalmente este código de autenticación con su destino." filename="zrtp-is_secure.wav"/>
<prompt phrase="El código de autenticación no está verificado." filename="zrtp-is_unverified.wav"/>
<prompt phrase="El código de autenticación está verificado." filename="zrtp-is_verified.wav"/>
<prompt phrase="Gracias por llamar. Adiós." filename="zrtp-thankyou_goodbye.wav"/>
<prompt phrase="Algún error ha ocurrido." filename="zrtp-somethings_wrong.wav"/>
<prompt phrase="Error." filename="zrtp-status_error.wav"/>
<prompt phrase="Esta llamada no está protegida." filename="zrtp-status_notsecure.wav"/>
<prompt phrase="Esta llamada está protegida." filename="zrtp-status_secure.wav"/>
<prompt phrase="Securizando su llamada." filename="zrtp-status_securing.wav"/>
</zrtp>
</es_MX>
</language>

View File

@ -0,0 +1,987 @@
<language>
<pt_BR>
<ascii>
<prompt phrase="Espaço" filename="32.wav"/>
<prompt phrase="Sustenido" filename="35.wav"/>
<prompt phrase="Asterisco" filename="42.wav"/>
<prompt phrase="Ponto" filename="46.wav"/>
<prompt phrase="A" filename="97.wav"/>
<prompt phrase="B" filename="98.wav"/>
<prompt phrase="C" filename="99.wav"/>
<prompt phrase="D" filename="100.wav"/>
<prompt phrase="E" filename="101.wav"/>
<prompt phrase="F" filename="102.wav"/>
<prompt phrase="G" filename="103.wav"/>
<prompt phrase="H" filename="104.wav"/>
<prompt phrase="I" filename="105.wav"/>
<prompt phrase="J" filename="106.wav"/>
<prompt phrase="K" filename="107.wav"/>
<prompt phrase="L" filename="108.wav"/>
<prompt phrase="M" filename="109.wav"/>
<prompt phrase="N" filename="110.wav"/>
<prompt phrase="O" filename="111.wav"/>
<prompt phrase="P" filename="112.wav"/>
<prompt phrase="Q" filename="113.wav"/>
<prompt phrase="R" filename="114.wav"/>
<prompt phrase="S" filename="115.wav"/>
<prompt phrase="T" filename="116.wav"/>
<prompt phrase="U" filename="117.wav"/>
<prompt phrase="V" filename="118.wav"/>
<prompt phrase="W" filename="119.wav"/>
<prompt phrase="X" filename="120.wav"/>
<prompt phrase="Y" filename="121.wav"/>
<prompt phrase="Z" filename="122.wav"/>
</ascii>
<phonetic-ascii>
<prompt phrase="Espaço" filename="32.wav"/>
<prompt phrase="Ponto" filename="46.wav"/>
<prompt phrase="Alpha" filename="97.wav"/>
<prompt phrase="Bravo" filename="98.wav"/>
<prompt phrase="Charlie" filename="99.wav"/>
<prompt phrase="Delta" filename="100.wav"/>
<prompt phrase="Echo" filename="101.wav"/>
<prompt phrase="Foxtrot" filename="102.wav"/>
<prompt phrase="Golf" filename="103.wav"/>
<prompt phrase="Hotel" filename="104.wav"/>
<prompt phrase="India" filename="105.wav"/>
<prompt phrase="Juliet" filename="106.wav"/>
<prompt phrase="Kilo" filename="107.wav"/>
<prompt phrase="Lima" filename="108.wav"/>
<prompt phrase="Mike" filename="109.wav"/>
<prompt phrase="November" filename="110.wav"/>
<prompt phrase="Oscar" filename="111.wav"/>
<prompt phrase="Papa" filename="112.wav"/>
<prompt phrase="Quebec" filename="113.wav"/>
<prompt phrase="Romeo" filename="114.wav"/>
<prompt phrase="Sierra" filename="115.wav"/>
<prompt phrase="Tango" filename="116.wav"/>
<prompt phrase="Unifor" filename="117.wav"/>
<prompt phrase="Victor" filename="118.wav"/>
<prompt phrase="Whiskey" filename="119.wav"/>
<prompt phrase="Xray" filename="120.wav"/>
<prompt phrase="Yankee" filename="121.wav"/>
<prompt phrase="Zulu" filename="122.wav"/>
</phonetic-ascii>
<digits>
<prompt phrase="Zero" filename="0.wav"/>
<prompt phrase="Um" filename="1.wav"/>
<prompt phrase="Dois" filename="2.wav"/>
<prompt phrase="Tręs" filename="3.wav"/>
<prompt phrase="Quatro" filename="4.wav"/>
<prompt phrase="Cinco" filename="5.wav"/>
<prompt phrase="Seis" filename="6.wav"/>
<prompt phrase="Sete" filename="7.wav"/>
<prompt phrase="Oito" filename="8.wav"/>
<prompt phrase="Nove" filename="9.wav"/>
<prompt phrase="Dez" filename="10.wav"/>
<prompt phrase="Onze" filename="11.wav"/>
<prompt phrase="Doze" filename="12.wav"/>
<prompt phrase="Treze" filename="13.wav"/>
<prompt phrase="Catorze" filename="14.wav"/>
<prompt phrase="Quinze" filename="15.wav"/>
<prompt phrase="Dezesseis" filename="16.wav"/>
<prompt phrase="Dezessete" filename="17.wav"/>
<prompt phrase="Dezoito" filename="18.wav"/>
<prompt phrase="Dezenove" filename="19.wav"/>
<prompt phrase="Vinte" filename="20.wav"/>
<prompt phrase="Trinta" filename="30.wav"/>
<prompt phrase="Quarenta" filename="40.wav"/>
<prompt phrase="Cinquenta" filename="50.wav"/>
<prompt phrase="Sessenta" filename="60.wav"/>
<prompt phrase="Setenta" filename="70.wav"/>
<prompt phrase="Oitenta" filename="80.wav"/>
<prompt phrase="Noventa" filename="90.wav"/>
<prompt phrase="Cem" filename="100.wav"/>
<prompt phrase="Duzentos" filename="200.wav"/>
<prompt phrase="Trezentos" filename="300.wav"/>
<prompt phrase="Quinhentos" filename="500.wav"/>
<prompt phrase="Ponto" filename="dot.wav"/>
<prompt phrase="Primeiro" filename="h-1.wav"/>
<prompt phrase="Segundo" filename="h-2.wav"/>
<prompt phrase="Terceiro" filename="h-3.wav"/>
<prompt phrase="Quarto" filename="h-4.wav"/>
<prompt phrase="Quinto" filename="h-5.wav"/>
<prompt phrase="Sexto" filename="h-6.wav"/>
<prompt phrase="Sétimo" filename="h-7.wav"/>
<prompt phrase="Oitavo" filename="h-8.wav"/>
<prompt phrase="Nono" filename="h-9.wav"/>
<prompt phrase="Décimo" filename="h-10.wav"/>
<prompt phrase="Vigésimo" filename="h-20.wav"/>
<prompt phrase="Trigésimo" filename="h-30.wav"/>
<prompt phrase="Quadragésimo" filename="h-40.wav"/>
<prompt phrase="Quinquagésimo" filename="h-50.wav"/>
<prompt phrase="Sexagésimo" filename="h-60.wav"/>
<prompt phrase="Septuagésimo" filename="h-70.wav"/>
<prompt phrase="Octogésimo" filename="h-80.wav"/>
<prompt phrase="Nonagésimo" filename="h-90.wav"/>
<prompt phrase="Cento" filename="hundred.wav"/>
<prompt phrase="Centos" filename="hundreds.wav"/>
<prompt phrase="Mil" filename="thousand.wav"/>
<prompt phrase="Milhăo" filename="million.wav"/>
<prompt phrase="Milhőes" filename="millions.wav"/>
<prompt phrase="Período" filename="period.wav"/>
<prompt phrase="Ponto" filename="point.wav"/>
<prompt phrase="Sustenido" filename="pound.wav"/>
<prompt phrase="Asterisco" filename="star.wav"/>
</digits>
<currency>
<prompt phrase="E" filename="and.wav"/>
<prompt phrase="Centavo" filename="cent.wav"/>
<prompt phrase="Central" filename="central.wav"/>
<prompt phrase="Centavos por minuto" filename="cents-per-minute.wav"/>
<prompt phrase="Centavos" filename="cents.wav"/>
<prompt phrase="Dólar" filename="dollar.wav"/>
<prompt phrase="Dólares" filename="dollars.wav"/>
<prompt phrase="Menos" filename="minus.wav"/>
<prompt phrase="Negativo" filename="negative.wav"/>
</currency>
<time>
<prompt phrase="A.M." filename="a-m.wav"/>
<prompt phrase="a" filename="at.wav"/>
<prompt phrase="ŕs" filename="ats.wav"/>
<prompt phrase="Domingo" filename="day-0.wav"/>
<prompt phrase="Segunda-feira" filename="day-1.wav"/>
<prompt phrase="Terça-feira" filename="day-2.wav"/>
<prompt phrase="Quarta-feira" filename="day-3.wav"/>
<prompt phrase="Quinta-feira" filename="day-4.wav"/>
<prompt phrase="Sexta-feira" filename="day-5.wav"/>
<prompt phrase="Sábado" filename="day-6.wav"/>
<prompt phrase="Hora" filename="hour.wav"/>
<prompt phrase="Horas" filename="hours.wav"/>
<prompt phrase="Minuto" filename="minute.wav"/>
<prompt phrase="Minutos" filename="minutes.wav"/>
<prompt phrase="Janeiro" filename="mon-0.wav"/>
<prompt phrase="Fevereiro" filename="mon-1.wav"/>
<prompt phrase="Março" filename="mon-2.wav"/>
<prompt phrase="Abril" filename="mon-3.wav"/>
<prompt phrase="Maio" filename="mon-4.wav"/>
<prompt phrase="Junho" filename="mon-5.wav"/>
<prompt phrase="Julho" filename="mon-6.wav"/>
<prompt phrase="Agosto" filename="mon-7.wav"/>
<prompt phrase="Setembro" filename="mon-8.wav"/>
<prompt phrase="Outubro" filename="mon-9.wav"/>
<prompt phrase="Novembro" filename="mon-10.wav"/>
<prompt phrase="Dezembro" filename="mon-11.wav"/>
<prompt phrase="Em ponto" filename="oclock.wav"/>
<prompt phrase="P.M." filename="p-m.wav"/>
<prompt phrase="Segundo" filename="second.wav"/>
<prompt phrase="Segundos" filename="seconds.wav"/>
<prompt phrase="Hoje" filename="today.wav"/>
<prompt phrase="Amanhă" filename="tomorrow.wav"/>
<prompt phrase="Ontem" filename="yesterday.wav"/>
</time>
<voicemail>
<prompt phrase="A pessoa na extensăo..." filename="vm-person.wav"/>
<prompt phrase="marcada como urgente" filename="vm-marked-urgent.wav"/>
<prompt phrase="email enviado" filename="vm-emailed.wav"/>
<prompt phrase="Vocę tem..." filename="vm-you_have.wav"/>
<prompt phrase="Por favor digite o seu número de usuario, e depois..." filename="vm-enter_id.wav"/>
<prompt phrase="Por favor digite a sua contrasenha, e depois..." filename="vm-enter_pass.wav"/>
<prompt phrase="Inicio incorreto da sessao." filename="vm-fail_auth.wav"/>
<prompt phrase="Bem-vindo ao seu correio de voz." filename="vm-hello.wav"/>
<prompt phrase="Até logo." filename="vm-goodbye.wav"/>
<prompt phrase="Grave a sua mensagem depois de ouvir o sinal, diga o seu nome e pressione qualquer tecla ou pare de falar para finalizar a gravaçăo." filename="vm-record_name1.wav"/>
<prompt phrase="Escolha uma saudaçao entre as opçőes 1 e 9" filename="vm-choose_greeting_choose.wav"/>
<prompt phrase="Número invalido." filename="vm-choose_greeting_fail.wav"/>
<prompt phrase="Muitas tentativas fracassadas." filename="vm-abort.wav"/>
<prompt phrase="Para mudar a sua senha..." filename="vm-change_password.wav"/>
<prompt phrase="Apos o sinal grave a sua saudaçăo, digite qualquer tecla ou deixe de falar para finalizar a gravaçăo." filename="vm-record_greeting.wav"/>
<prompt phrase="Apos o sinal grave a sua mensagem, digite qualquer tecla ou deixe de falar para finalizar a gravaçăo." filename="vm-record_message.wav"/>
<prompt phrase="Năo está disponível." filename="vm-play_greeting.wav"/>
<prompt phrase="nova e urgente" filename="vm-urgent-new.wav"/>
<prompt phrase="nova" filename="vm-new.wav"/>
<prompt phrase="guardada e urgente" filename="vm-urgent-saved.wav"/>
<prompt phrase="guardada" filename="vm-saved.wav"/>
<prompt phrase="mensagem" filename="vm-message.wav"/>
<prompt phrase="mensagens" filename="vm-messages.wav"/>
<prompt phrase="marque" filename="vm-press.wav"/>
<prompt phrase="Para ouvir as mensagens novas..." filename="vm-listen_new.wav"/>
<prompt phrase="Para ouvir as mensagens armazenadas..." filename="vm-listen_saved.wav"/>
<prompt phrase="Para opçőes avançadas..." filename="vm-advanced.wav"/>
<prompt phrase="Para sair..." filename="vm-to_exit.wav"/>
<prompt phrase="Para gravar a sua saudaçăo..." filename="vm-record_greeting.wav"/>
<prompt phrase="Para escolher a sua saudaçăo..." filename="vm-choose_greeting.wav"/>
<prompt phrase="Para gravar o seu nome..." filename="vm-record_name2.wav"/>
<prompt phrase="Para o menu principal..." filename="vm-main_menu.wav"/>
<prompt phrase="Para ouvir a gravaçao..." filename="vm-listen_to_recording.wav"/>
<prompt phrase="Para guardar a gravaçao..." filename="vm-save_recording.wav"/>
<prompt phrase="Para gravar novamente..." filename="vm-rerecord.wav"/>
<prompt phrase="Para marcar esta mensagem como urgente..." filename="vm-mark_urgent.wav"/>
<prompt phrase="Para continuar..." filename="vm-continue.wav"/>
<prompt phrase="Para ouvir a gravaçăo novamente..." filename="vm-listen_to_recording_again.wav"/>
<prompt phrase="Para borrar a gravaçăo..." filename="vm-delete_recording.wav"/>
<prompt phrase="Para enviar a gravaçăo para o seu email..." filename="vm-forward_to_email.wav"/>
<prompt phrase="saudaçăo" filename="vm-greeting.wav"/>
<prompt phrase="selecionada" filename="vm-selected.wav"/>
<prompt phrase="Năo está disponível." filename="vm-not_available.wav"/>
<prompt phrase="Mensagem número..." filename="vm-message_number.wav"/>
<prompt phrase="apagada" filename="vm-deleted.wav"/>
<prompt phrase="A sua gravaçăo é muito curta, por favor tente novamente." filename="vm-too-small.wav"/>
<prompt phrase="na caixa de mensagens" filename="vm-in_folder.wav"/>
<prompt phrase="Para devolver a ligaçăo agora..." filename="vm-return_call.wav"/>
<prompt phrase="urgente" filename="vm-urgent.wav"/>
<prompt phrase="Esta caixa de mensagens está lotada, por favor tente mais tarde." filename="vm-mailbox_full.wav"/>
<prompt phrase="Bem-vindo a sua caixa de mensagens. Para escutar o menu e configurar a sua caixa de mensagens, digite um. Para năo considera-lo, digite dois." filename="vm-tutorial_yes_no.wav"/>
<prompt phrase="Vocę precisa gravar o seu nome e sobrenome. Esta gravaçăo é usada entre outras, no serviço de diretório." filename="vm-tutorial_record_name.wav"/>
<prompt phrase="O número de identificaçăo pessoal ou PIN serve para impedir o acesso de terceiros as suas mensagens. Vocę deseja mudar o seu PIN agora?" filename="vm-tutorial_change_pin.wav"/>
</voicemail>
<directory>
<prompt phrase="Por favor marque as primeiras letras do nome da pessoa." filename="dir-enter-person.wav"/>
<prompt phrase="...último nome..." filename="dir-last_name.wav"/>
<prompt phrase="Para procurar por..." filename="dir-to_search_by.wav"/>
<prompt phrase="...primeiro nome..." filename="dir-first_name.wav"/>
<prompt phrase="Năo foram encontradas as respostas, tente novamente." filename="dir-no_match_entry.wav"/>
<prompt phrase="...respostas encontradas para a sua pergunta." filename="dir-result_match.wav"/>
<prompt phrase="A sua pergunta devolveu muitas respostas, por favor tente novamente." filename="dir-to_many_result.wav"/>
<prompt phrase="Năo há mais opçőes." filename="dir-no_more_results.wav"/>
<prompt phrase="Opçăo número..." filename="dir-result_number.wav"/>
<prompt phrase="...no ramal..." filename="dir-at_extension.wav"/>
<prompt phrase="Para escolher essa opçăo..." filename="dir-to_select_entry.wav"/>
<prompt phrase="Para a opçăo seguinte..." filename="dir-for_next.wav"/>
<prompt phrase="Para a opçăo anterior..." filename="dir-for_prev.wav"/>
<prompt phrase="Para uma nova busca..." filename="dir-start_new_search.wav"/>
<prompt phrase="Vocę precisa dizer um mínimo de..." filename="dir-specify_mininum_first.wav"/>
<prompt phrase="...letras do nome da pessoa, tente novamente." filename="dir-letters_of_person_name.wav"/>
<prompt phrase="marque" filename="dir-press.wav"/>
</directory>
<conference>
<prompt phrase="NULL" filename="conf-ack.wav" type="tone"/>
<prompt phrase="NULL" filename="conf-nack.wav" type="tone"/>
<prompt phrase="Vocę agora está mudo." filename="conf-muted.wav"/>
<prompt phrase="Vocę năo está mais mudo." filename="conf-unmuted.wav"/>
<prompt phrase="Neste momento vocę é a única pessoa na conferęncia." filename="conf-alone.wav"/>
<prompt phrase="NULL" filename="conf-perpetual.wav" type="music"/>
<prompt phrase="NULL" filename="conf-enter.wav" type="tone"/>
<prompt phrase="NULL" filename="conf-exit.wav" type="tone"/>
<prompt phrase="Vocę foi retirado da conferęncia." filename="conf-kicked.wav"/>
<prompt phrase="Esta confęrencia está bloqueada." filename="conf-locked.wav"/>
<prompt phrase="A conferęncia está bloqueada." filename="conf-is-locked.wav"/>
<prompt phrase="A conferęncia está liberada." filename="conf-is-unlocked.wav"/>
<prompt phrase="Por favor insira o PIN da conferęncia." filename="conf-pin.wav"/>
<prompt phrase="Este PIN năo e válido, tente novamente." filename="conf-bad-pin.wav"/>
<prompt phrase="Até logo." filename="conf-goodbye.wav"/>
<prompt phrase="Bem-vindo a conferęncia." filename="conf-welcome.wav"/>
</conference>
<ivr>
<prompt phrase="Número da conta" filename="ivr-account_number.wav"/>
<prompt phrase="Contatar com a pessoa que telefona" filename="ivr-connect_to_caller.wav"/>
<prompt phrase="Se conhece o ramal da pessoa com quem deseja falar, por favor digite agora." filename="ivr-enter_ext_pound.wav"/>
<prompt phrase="Por favor digite o ramal e a continuaçăo a tecla sustenido." filename="ivr-enter_ext.wav"/>
<prompt phrase="Para a pessoa..." filename="ivr-for_this_person.wav"/>
<prompt phrase="Por favor aguarde enquanto realizamos a sua chamada." filename="ivr-hold_connect_call.wav"/>
<prompt phrase="Desculpe" filename="ivr-im_sorry.wav"/>
<prompt phrase="Por favor" filename="ivr-please.wav"/>
<prompt phrase="Por favor devolva a nossa ligaçăo ŕ..." filename="ivr-please_return_our_call_at.wav"/>
<prompt phrase="De acordo com o número de referęncia." filename="ivr-regarding_reference_number.wav"/>
<prompt phrase="Este é um exemplo de um submenu IVR..." filename="ivr-sample_submenu.wav"/>
<prompt phrase="Por favor diga o seu nome depois do sinal." filename="ivr-say_name.wav"/>
<prompt phrase="Enviar esta ligaçăo para a caixa de mensagens de voz." filename="ivr-send_to_voicemail.wav"/>
<prompt phrase="Para falar com o responsavel do atençao a clientes..." filename="ivr-speak_to_a_customer_service_representative.wav"/>
<prompt phrase="Deixe uma mensagem" filename="ivr-take_a_message.wav"/>
<prompt phrase="Obrigado" filename="ivr-thank_you.wav"/>
<prompt phrase="Essa opçăo nao é valida." filename="ivr-that_was_an_invalid_entry.wav"/>
<prompt phrase="Esta é uma ligaçăo de..." filename="ivr-this_is_a_call_from.wav"/>
<prompt phrase="Este IVR lher permite testar algumas das opçőes..." filename="ivr-this_ivr_will_let_you_test_features.wav"/>
<prompt phrase="Para ligar ŕ conferencia FreeSWITCH..." filename="ivr-to_call_the_freeswitch_conference.wav"/>
<prompt phrase="Para realizar um teste FreeSWITCH eco..." filename="ivr-to_do_a_freeswitch_echo_test.wav"/>
<prompt phrase="Para realizar um teste FWD eco..." filename="ivr-to_do_a_fwd_echo_test.wav"/>
<prompt phrase="Para ouvir o exemplo de um submenu IVR..." filename="ivr-to_hear_sample_submenu.wav"/>
<prompt phrase="Para ouvir gritos de macacos..." filename="ivr-to_hear_screaming_monkeys.wav"/>
<prompt phrase="Para ouvir música de espera..." filename="ivr-to_listen_to_moh.wav"/>
<prompt phrase="Para ouvir novamente estas opçőes..." filename="ivr-to_repeat_these_options.wav"/>
<prompt phrase="Para voltar ao menu anterior..." filename="ivr-to_return_to_previous_menu.wav"/>
<prompt phrase="Para falar com um atendente..." filename="ivr-to_speak_with_an_operator.wav"/>
<prompt phrase="Bem-vindo a FreeSWITCH, o futuro da telefonia." filename="ivr-welcome_to_freeswitch.wav"/>
<prompt phrase="Vocę pode sair a qualquer momento, simplesmente terminando a ligaçăo." filename="ivr-you_may_exit_by_hanging_up.wav"/>
<prompt phrase="ou" filename="ivr-or.wav"/>
<prompt phrase="năo" filename="ivr-not.wav"/>
<prompt phrase="ligaçăo" filename="ivr-call.wav"/>
<prompt phrase="Vocę pode" filename="ivr-you_may.wav"/>
<prompt phrase="Oi?" filename="ivr-hello.wav"/>
<prompt phrase="Usando as teclas do seu telefone..." filename="ivr-use_telephone_keypad.wav"/>
<prompt phrase="Por favor soletre o nome da pessoa que vocę deseja contatar." filename="ivr-spell_name.wav"/>
<prompt phrase="Sobrenome primeiro" filename="ivr-last_name_first.wav"/>
<prompt phrase="Primeiro nome primeiro" filename="ivr-first_name_first.wav"/>
<prompt phrase="Marque 1 para Q ou Z." filename="ivr-press_one_q_or_z.wav"/>
<prompt phrase="Vendas" filename="ivr-sales.wav"/>
<prompt phrase="Atençăo a clientes" filename="ivr-customer_service.wav"/>
<prompt phrase="Suporte tecnico" filename="ivr-technical_support.wav"/>
<prompt phrase="Atendente" filename="ivr-operator.wav"/>
<prompt phrase="Vocę teclou um ramal inválido." filename="ivr-you_have_dialed_an_invalid_extension.wav"/>
<prompt phrase="Por favor digite o seu ramal, depois a tecla sustenido." filename="ivr-please_enter_extension_followed_by_pound.wav"/>
<prompt phrase="Por favor digite o seu número PIN, depois a tecla sustenido." filename="ivr-please_enter_pin_followed_by_pound.wav"/>
<prompt phrase="O seu número PIN ou ramal năo é válido." filename="ivr-pin_or_extension_is-invalid.wav"/>
<prompt phrase="Vocę está a ponto de associar este telefone ŕ sua conta..." filename="ivr-you_are_about_to_provision_this_phone.wav"/>
<prompt phrase="Por favor digite novamente o seu número PIN para confirmar." filename="ivr-please_reenter_your_pin.wav"/>
<prompt phrase="Para registar em ClueCon, por favor digite..." filename="ivr-register_for_cluecon.wav"/>
<prompt phrase="Para contatar..." filename="ivr-to_log_in.wav"/>
<prompt phrase="Para desligar..." filename="ivr-to_log_out.wav"/>
<prompt phrase="Vocę agora está conetado." filename="ivr-you_are_now_logged_in.wav"/>
<prompt phrase="Vocę agora está desconetado." filename="ivr-you_are_now_logged_out.wav"/>
<prompt phrase="Por favor tente novamente." filename="ivr-please_try_again.wav"/>
<prompt phrase="Vocę está a ponto de associar permanentemente este telefone ao seu ramal." filename="ivr-provision_phone_permanently_to_extension.wav"/>
<prompt phrase="Por favor digite o numero do ramal que vocę pretende associar a este telefone, logo digite sustenido." filename="ivr-extension_to_provision_this_phone.wav"/>
<prompt phrase="Obrigado, este telefone vai ser reiniciado." filename="ivr-this_phone_will_now_reboot.wav"/>
<prompt phrase="Obrigado. A sua gravaçăo foi guardada." filename="ivr-recording_saved.wav"/>
<prompt phrase="Digite 1 para guardar a sua gravaçăo. Digite 2 para ouvir á sua gravaçăo. Digite 3 para gravar novamente." filename="ivr-save_review_record.wav"/>
<prompt phrase="Neste momento o sistema é incapaz de guardar a sua gravaçăo. Por favor tente novamente mais tarde." filename="ivr-unable_save.wav"/>
<prompt phrase="Vocę é o número" filename="ivr-you_are_number.wav"/>
<prompt phrase="...em linha" filename="ivr-in_line.wav"/>
<prompt phrase="Obrigado por esperar." filename="ivr-thank_you_for_holding.wav"/>
<prompt phrase="O seu tempo estimado de espera é..." filename="ivr-estimated_hold_time.wav"/>
<prompt phrase="Mais de..." filename="ivr-more_than.wav"/>
<prompt phrase="Menos de..." filename="ivr-less_than.wav"/>
<prompt phrase="Iniciar a gravaçăo." filename="ivr-begin_recording.wav "/>
<prompt phrase="O encaminhamento da ligaçăo foi cancelada." filename="ivr-call_forwarding_has_been_cancelled.wav"/>
<prompt phrase="O encaminhamento da ligaçăo foi ativada." filename="ivr-call_forwarding_has_been_set.wav"/>
<prompt phrase="Por favor, introduza o número de telefone." filename="ivr-please_enter_the_phone_number.wav"/>
<prompt phrase="Por favor, diga o seu nome e o motivo da sua ligaçăo." filename="ivr-please_state_your_name_and_reason_for_calling.wav"/>
<prompt phrase="Para aceitar, digite 1. Para rejeitar, digite 2. Para enviar para o correio de voz, digite 3." filename="ivr-accept_reject_voicemail.wav"/>
<prompt phrase="Entrada da ligaçăo." filename="ivr-incoming_call.wav"/>
<prompt phrase="Obrigado pela sua ligaçăo." filename="ivr-thank_you_for_calling.wav"/>
<prompt phrase="Por favor permaneça em linha. A sua ligaçăo será atendida brevemente." filename="ivr-stay_on_line_call_answered_momentarily.wav"/>
<prompt phrase="A sua ligaçăo está sendo transferida." filename="ivr-call_being_transferred.wav"/>
<prompt phrase="Por favor, desfrute da música enquanto a sua ligaçăo é transferida." filename="ivr-enjoy_music_while_transfer.wav"/>
<prompt phrase="Vocę tem uma ligaçăo de..." filename="ivr-call_from.wav"/>
<prompt phrase="Este menú năo tem opçőes. Por favor entre em contato com o administrador." filename="ivr-no_menu_items.wav"/>
<prompt phrase="Para diretório, digite..." filename="ivr-for_directory_press.wav"/>
<prompt phrase="Usando o teclado do seu telefone..." filename="ivr-using_telephone_keypad.wav"/>
<prompt phrase="Introduza as primeiras letras do último nome da pessoa." filename="ivr-enter_letters_last_name.wav"/>
<prompt phrase="Introduza as primeiras letras do primeiro nome da pessoa." filename="ivr-enter_letters_first_name.wav"/>
<prompt phrase="Introduza as primeiras letras do primeiro ou último nome da pessoa." filename="ivr-enter_letters_first_or_last_name.wav"/>
<prompt phrase="Se isso é correcto, digite..." filename="ivr-if_correct_press.wav"/>
<prompt phrase="Se năo, digite..." filename="ivr-if_not_press.wav"/>
<prompt phrase="Quando terminar, digite sustenido." filename="ivr-finished_pound_hash_key.wav"/>
<prompt phrase="O modo Năo Incomodar agora está ativado." filename="ivr-dnd_activated.wav"/>
<prompt phrase="O modo Năo Incomodar foi desativado." filename="ivr-dnd_cancelled.wav"/>
<prompt phrase="Marque qualquer outro dígito..." filename="ivr-any_other_digit.wav"/>
<prompt phrase="Digite um para sim. Digite dois para năo." filename="ivr-one_yes_two_no.wav"/>
<prompt phrase="Por favor digite o número da fila, e logo a tecla sustenido." filename="ivr-enter_queue_number.wav"/>
<prompt phrase="Por favor digite o..." filename="ivr-please_enter_the.wav"/>
<prompt phrase="Número." filename="ivr-number.wav"/>
<prompt phrase="...e depois sustenido." filename="ivr-followed_by_pound.wav"/>
<prompt phrase="O saldo da conta é..." filename="ivr-account_balance_is.wav"/>
<prompt phrase="Obrigado por telefonar. Se conhece a ramal do destinatário, por favor digite-o agora. Para ir para o diretório, digite..." filename="ivr-generic_greeting.wav"/>
<prompt phrase="...ficheiro..." filename="ivr-file.wav"/>
<prompt phrase="...ficheiros..." filename="ivr-files-.wav"/>
<prompt phrase="Para uma ligaçăo de despertar..." filename="ivr-for_a_wakeup_call.wav"/>
<prompt phrase="Esta é a sua ligaçăo de despertar." filename="ivr-this_is_your_wakeup_call.wav"/>
<prompt phrase="Para solicitar uma ligaçăo de despertar..." filename="ivr-request_wakeup_call.wav"/>
<prompt phrase="Para confirmar uma ligaçăo de despertar..." filename="ivr-confirm_wakeup_call.wav"/>
<prompt phrase="Para cancelar uma ligaçăo de despertar..." filename="ivr-cancel_wakeup_call.wav"/>
<prompt phrase="Vocę solicitou uma ligaçăo de despertar..." filename="ivr-requested_wakeup_call_for.wav"/>
<prompt phrase="Vocę năo solicitou uma ligaçăo de despertar." filename="ivr-not_requested_wakeup_call.wav"/>
<prompt phrase="A sua ligaçăo de despertar foi cancelada." filename="ivr-wakeup_call_cancelled.wav"/>
<prompt phrase="Para uma ligaçăo de despertar por dia..." filename="ivr-for_daily_wakeup_call.wav"/>
<prompt phrase="ligaçăo de despertar diária..." filename="ivr-daily_wakeup_call.wav"/>
<prompt phrase="Para ligaçőes de despertar diárias..." filename="ivr-for_daily_wakeup_calls.wav"/>
<prompt phrase="Para apenas uma ligaçăo de despertar..." filename="ivr-for_one_time_wakeup_call.wav"/>
<prompt phrase="Apenas uma ligaçăo de despertar..." filename="ivr-one_time_wakeup_call.wav"/>
<prompt phrase="...ligaçăo de despertar..." filename="ivr-wakeup_call.wav"/>
<prompt phrase="Acorda! Acorda raio de sol!!" filename="ivr-wakey_wakey_sunshine.wav"/>
<prompt phrase="Bem-vindo." filename="ivr-welcome.wav"/>
<prompt phrase="Bem-vindo a..." filename="ivr-welcome_to.wav"/>
<prompt phrase="Bom dia." filename="ivr-good_morning.wav"/>
<prompt phrase="Boa tarde." filename="ivr-good_afternoon.wav"/>
<prompt phrase="Boa noite." filename="ivr-good_evening.wav"/>
<prompt phrase="Obrigado." filename="ivr-Thank_you.wav"/>
<prompt phrase="Para..." filename="ivr-for.wav"/>
<prompt phrase="Estamos a observar tempos de espera superiores ao normal." filename="ivr-longer_than_usual_hold_times.wav"/>
<prompt phrase="Vocę é o..." filename="ivr-you_are_the.wav"/>
<prompt phrase="Um momento por favor." filename="ivr-one_moment_please.wav"/>
<prompt phrase="A sua ligaçăo será atendida pela ordem que foi recebida." filename="ivr-call_answered_order_received.wav"/>
<prompt phrase="Por favor digite o número da conferęncia, seguido de sustenido." filename="conf-enter_conf_number.wav"/>
<prompt phrase="Introduza o número PIN da conferęncia, seguido de sustenido." filename="conf-enter_conf_pin.wav"/>
<prompt phrase="...entrou na conferęncia." filename="conf-has_joined.wav"/>
<prompt phrase="...abandonou a conferęncia." filename="conf-has_left.wav"/>
<prompt phrase="Vocę entrou..." filename="ivr-you_entered.wav"/>
<prompt phrase="Número do ramal..." filename="ivr-extension_number.wav"/>
<prompt phrase="Por favor aguarde enquanto contatamos com o destinatário." filename="ivr-please_hold_while_party_contacted.wav"/>
<prompt phrase="Por favor desfrute da música enquanto contatamos com o destinatário." filename="ivr-please_enjoy_music_while_party_reached.wav"/>
<prompt phrase="Obrigado por telefonar. Se conhece a ramal do destinatário, digite-o agora, ou digite nove para ir para o diretório." filename="ivr-generic_greeting.wav"/>
<prompt phrase="Se isto é correcto, digite 1. Se năo é correcto, digite 2." filename="ivr-if_correct_one_if_not_two.wav"/>
<prompt phrase="Para ouvir novamente esta informaçăo.." filename="ivr-repeat_this_information.wav"/>
<prompt phrase="Năo năo năo!" filename="ivr-no_no_no.wav"/>
<prompt phrase="Vocę pretendia marcar esta tecla?" filename="ivr-did_you_mean_to_press_key.wav"/>
<prompt phrase="É sério? Pretendia MESMO marcar esta tecla?" filename="ivr-seriously_mean_to_press_key.wav"/>
<prompt phrase="Oh, tanto faz." filename="ivr-oh_whatever.wav"/>
<prompt phrase="Já chega! Um erro mais e corto a ligaçăo." filename="ivr-one_more_mistake.wav"/>
<prompt phrase="Felicidades, vocę pressionou estrela. Isto năo significa que vocę é uma estrela. Apenas significa que pode pressionar teclas e que provavelmente tens dedos." filename="ivr-congratulations_you_pressed_star.wav"/>
<prompt phrase="Todos os nossos engenheiros estăo ocupados demonstrando como é impressionante CudaTel." filename="ivr-engineers_busy_assisting_other_sales.wav"/>
<prompt phrase="O destino que deseja contatar năo está disponível e năo tem correio de voz." filename="vm-not_available_no_voicemail.wav"/>
<prompt phrase="Esta mensagem vai se auto-destruir em 5, 4, 3, 2, 1..." filename="ivr-message_self_destruct.wav"/>
<prompt phrase="Vocę já está em silęncio." filename="conf-you_are_already_muted.wav"/>
<prompt phrase="Vocę está agora em silęncio em ambos sentidos." filename="conf-you_are_now_bidirectionally_muted.wav"/>
<prompt phrase="Todas as suas ligaçőes nos pertence." filename="ivr-all_your_call_are_belong_to_us.wav"/>
<prompt phrase="Adoro a forma como vocę pressiona as teclas!" filename="ivr-love_those_touch_tones.wav"/>
<prompt phrase="Sim, nós năo temos bananas." filename="ivr-yes_we_have_no_bananas.wav"/>
<prompt phrase="Homem, vocę está sendo ridículo!" filename="ivr-dude_you_suck.wav"/>
<prompt phrase="A sua ligaçăo é muito importante para nós, mas a sua saúde mental năo, por isso estamos felizes em fazę-lo esperar, torturando-o com a irritante música de espera." filename="ivr-on_hold_indefinitely.wav"/>
<prompt phrase="...deixou o edifício." filename="ivr-has_left_the_building.wav"/>
<prompt phrase="Este telefone năo está associado e năo pode realizar ligaçőes externas." filename="ivr-phone_is_unassigned.wav"/>
<prompt phrase="Este telefone năo está configurado corretamente." filename="ivr-phone_not_configured.wav"/>
<prompt phrase="Parabéns! Este telefone está configurado corretamente e agora pode ser associado a um utilizador." filename="ivr-phone_is_configured_properly.wav"/>
<prompt phrase="Por favor contate o administrador do sistema para assistęncia." filename="ivr-contact_system_administrator.wav"/>
<prompt phrase="Barracuda Networks" filename="ivr-barracuda_networks.wav"/>
<prompt phrase="CudaTel Communication Server" filename="ivr-cudatel_communication_server.wav"/>
<prompt phrase="Por favor, introduza as primeiras letras do primeiro ou último nome da pessoa" filename="dir-enter_person_first_or_last.wav"/>
<prompt phrase="Năo há mais ligaçőes em espera nesta fila." filename="ivr-no_calls_waiting_in_queue.wav"/>
<prompt phrase="Brian West" filename="misc-Brian_West.wav"/>
<prompt phrase="Anthony Minessale" filename="misc-Anthony_Minessale.wav"/>
<prompt phrase="Michael Jerris" filename="misc-Michael_Jerris.wav"/>
<prompt phrase="Raymond Chandler" filename="misc-Raymond_Chandler.wav"/>
<prompt phrase="Michael Collins" filename="misc-Michael_Collins.wav"/>
<prompt phrase="Mark Mann" filename="misc-Mark_Mann.wav"/>
<prompt phrase="William King" filename="misc-William_King.wav"/>
<prompt phrase="Rudy Fleminger" filename="misc-Rudy_Fleminger.wav"/>
<prompt phrase="Andrew Thompson" filename="misc-Andrew_Thompson.wav"/>
<prompt phrase="Graham Saathoff" filename="misc-Graham_Saathoff.wav"/>
<prompt phrase="Nicholaus Belluni" filename="misc-Nicholaus_Belluni.wav"/>
<prompt phrase="Sean Heiney" filename="misc-Sean_Heiney.wav"/>
</ivr>
<misc>
<prompt phrase="Foi ativada a segurança para esta ligaçăo." filename="call_secured.wav"/>
<prompt phrase="...depois a tecla sustenido." filename="followed.wav"/>
<prompt phrase="Se vocę é esta pessoa..." filename="if_you_are_this_person.wav"/>
<prompt phrase="Se vocę deseja..." filename="if_you_would_like_to.wav"/>
<prompt phrase="Indique o número de referęncia" filename="provide_reference_number.wav"/>
<prompt phrase="Por favor, digite o ramal que deseja transferir." filename="transfer1.wav"/>
<prompt phrase="Transferir" filename="transfer2.wav"/>
<prompt phrase="Estamos tentando contatar..." filename="we_are_trying_to_reach.wav"/>
<prompt phrase="Houve uma falha, por favor entre em contato com o administrador." filename="error.wav"/>
<prompt phrase="A sua ligaçăo vai terminar em..." filename="misc-your_call_will_be_terminated_in.wav"/>
<prompt phrase="A sua ligaçăo foi finalizada." filename="misc-your_call_has_been_terminated.wav"/>
</misc>
<zrtp>
<!-- base256 prompts for SAS -->
<prompt phrase="Algol" filename="Algol.wav"/>
<prompt phrase="Apollo" filename="Apollo.wav"/>
<prompt phrase="Athens" filename="Athens.wav"/>
<prompt phrase="Atlantic" filename="Atlantic.wav"/>
<prompt phrase="Aztec" filename="Aztec.wav"/>
<prompt phrase="Babylon" filename="Babylon.wav"/>
<prompt phrase="Belfast" filename="Belfast.wav"/>
<prompt phrase="Bradbury" filename="Bradbury.wav"/>
<prompt phrase="Brazilian" filename="Brazilian.wav"/>
<prompt phrase="Burbank" filename="Burbank.wav"/>
<prompt phrase="Burlington" filename="Burlington.wav"/>
<prompt phrase="Camelot" filename="Camelot.wav"/>
<prompt phrase="Capricorn" filename="Capricorn.wav"/>
<prompt phrase="Cherokee" filename="Cherokee.wav"/>
<prompt phrase="Chicago" filename="Chicago.wav"/>
<prompt phrase="Christmas" filename="Christmas.wav"/>
<prompt phrase="Dakota" filename="Dakota.wav"/>
<prompt phrase="December" filename="December.wav"/>
<prompt phrase="Dupont" filename="Dupont.wav"/>
<prompt phrase="Eskimo" filename="Eskimo.wav"/>
<prompt phrase="Galveston" filename="Galveston.wav"/>
<prompt phrase="Geiger" filename="Geiger.wav"/>
<prompt phrase="Hamilton" filename="Hamilton.wav"/>
<prompt phrase="Istanbul" filename="Istanbul.wav"/>
<prompt phrase="Jamaica" filename="Jamaica.wav"/>
<prompt phrase="Jupiter" filename="Jupiter.wav"/>
<prompt phrase="Medusa" filename="Medusa.wav"/>
<prompt phrase="Mohawk" filename="Mohawk.wav"/>
<prompt phrase="Montana" filename="Montana.wav"/>
<prompt phrase="Neptune" filename="Neptune.wav"/>
<prompt phrase="Norwegian" filename="Norwegian.wav"/>
<prompt phrase="Oakland" filename="Oakland.wav"/>
<prompt phrase="October" filename="October.wav"/>
<prompt phrase="Ohio" filename="Ohio.wav"/>
<prompt phrase="Orlando" filename="Orlando.wav"/>
<prompt phrase="Pacific" filename="Pacific.wav"/>
<prompt phrase="Pandora" filename="Pandora.wav"/>
<prompt phrase="Pegasus" filename="Pegasus.wav"/>
<prompt phrase="Pluto" filename="Pluto.wav"/>
<prompt phrase="Saturday" filename="Saturday.wav"/>
<prompt phrase="Scotland" filename="Scotland.wav"/>
<prompt phrase="Trojan" filename="Trojan.wav"/>
<prompt phrase="Virginia" filename="Virginia.wav"/>
<prompt phrase="Vulcan" filename="Vulcan.wav"/>
<prompt phrase="Waterloo" filename="Waterloo.wav"/>
<prompt phrase="Wichita" filename="Wichita.wav"/>
<prompt phrase="Wilmington" filename="Wilmington.wav"/>
<prompt phrase="Wyoming" filename="Wyoming.wav"/>
<prompt phrase="Yucatan" filename="Yucatan.wav"/>
<prompt phrase="Zulu" filename="Zulu.wav"/>
<prompt phrase="aardvark" filename="aardvark.wav"/>
<prompt phrase="absurd" filename="absurd.wav"/>
<prompt phrase="accrue" filename="accrue.wav"/>
<prompt phrase="acme" filename="acme.wav"/>
<prompt phrase="adrift" filename="adrift.wav"/>
<prompt phrase="adroitness" filename="adroitness.wav"/>
<prompt phrase="adult" filename="adult.wav"/>
<prompt phrase="adviser" filename="adviser.wav"/>
<prompt phrase="afflict" filename="afflict.wav"/>
<prompt phrase="aftermath" filename="aftermath.wav"/>
<prompt phrase="aggregate" filename="aggregate.wav"/>
<prompt phrase="ahead" filename="ahead.wav"/>
<prompt phrase="aimless" filename="aimless.wav"/>
<prompt phrase="alkali" filename="alkali.wav"/>
<prompt phrase="allow" filename="allow.wav"/>
<prompt phrase="almighty" filename="almighty.wav"/>
<prompt phrase="alone" filename="alone.wav"/>
<prompt phrase="ammo" filename="ammo.wav"/>
<prompt phrase="amulet" filename="amulet.wav"/>
<prompt phrase="amusement" filename="amusement.wav"/>
<prompt phrase="ancient" filename="ancient.wav"/>
<prompt phrase="antenna" filename="antenna.wav"/>
<prompt phrase="apple" filename="apple.wav"/>
<prompt phrase="applicant" filename="applicant.wav"/>
<prompt phrase="armistice" filename="armistice.wav"/>
<prompt phrase="article" filename="article.wav"/>
<prompt phrase="artist" filename="artist.wav"/>
<prompt phrase="assume" filename="assume.wav"/>
<prompt phrase="asteroid" filename="asteroid.wav"/>
<prompt phrase="atlas" filename="atlas.wav"/>
<prompt phrase="atmosphere" filename="atmosphere.wav"/>
<prompt phrase="autopsy" filename="autopsy.wav"/>
<prompt phrase="baboon" filename="baboon.wav"/>
<prompt phrase="backfield" filename="backfield.wav"/>
<prompt phrase="backward" filename="backward.wav"/>
<prompt phrase="backwater" filename="backwater.wav"/>
<prompt phrase="banjo" filename="banjo.wav"/>
<prompt phrase="barbecue" filename="barbecue.wav"/>
<prompt phrase="beaming" filename="beaming.wav"/>
<prompt phrase="bedlamp" filename="bedlamp.wav"/>
<prompt phrase="beehive" filename="beehive.wav"/>
<prompt phrase="beeswax" filename="beeswax.wav"/>
<prompt phrase="befriend" filename="befriend.wav"/>
<prompt phrase="belowground" filename="belowground.wav"/>
<prompt phrase="berserk" filename="berserk.wav"/>
<prompt phrase="bifocals" filename="bifocals.wav"/>
<prompt phrase="billiard" filename="billiard.wav"/>
<prompt phrase="bison" filename="bison.wav"/>
<prompt phrase="blackjack" filename="blackjack.wav"/>
<prompt phrase="blockade" filename="blockade.wav"/>
<prompt phrase="blowtorch" filename="blowtorch.wav"/>
<prompt phrase="bluebird" filename="bluebird.wav"/>
<prompt phrase="bodyguard" filename="bodyguard.wav"/>
<prompt phrase="bombast" filename="bombast.wav"/>
<prompt phrase="bookseller" filename="bookseller.wav"/>
<prompt phrase="bookshelf" filename="bookshelf.wav"/>
<prompt phrase="borderline" filename="borderline.wav"/>
<prompt phrase="bottomless" filename="bottomless.wav"/>
<prompt phrase="brackish" filename="brackish.wav"/>
<prompt phrase="bravado" filename="bravado.wav"/>
<prompt phrase="breadline" filename="breadline.wav"/>
<prompt phrase="breakaway" filename="breakaway.wav"/>
<prompt phrase="breakup" filename="breakup.wav"/>
<prompt phrase="brickyard" filename="brickyard.wav"/>
<prompt phrase="briefcase" filename="briefcase.wav"/>
<prompt phrase="businessman" filename="businessman.wav"/>
<prompt phrase="butterfat" filename="butterfat.wav"/>
<prompt phrase="button" filename="button.wav"/>
<prompt phrase="buzzard" filename="buzzard.wav"/>
<prompt phrase="candidate" filename="candidate.wav"/>
<prompt phrase="cannonball" filename="cannonball.wav"/>
<prompt phrase="caravan" filename="caravan.wav"/>
<prompt phrase="caretaker" filename="caretaker.wav"/>
<prompt phrase="celebrate" filename="celebrate.wav"/>
<prompt phrase="cellulose" filename="cellulose.wav"/>
<prompt phrase="cement" filename="cement.wav"/>
<prompt phrase="certify" filename="certify.wav"/>
<prompt phrase="chairlift" filename="chairlift.wav"/>
<prompt phrase="chambermaid" filename="chambermaid.wav"/>
<prompt phrase="chatter" filename="chatter.wav"/>
<prompt phrase="checkup" filename="checkup.wav"/>
<prompt phrase="chisel" filename="chisel.wav"/>
<prompt phrase="choking" filename="choking.wav"/>
<prompt phrase="chopper" filename="chopper.wav"/>
<prompt phrase="clamshell" filename="clamshell.wav"/>
<prompt phrase="classic" filename="classic.wav"/>
<prompt phrase="classroom" filename="classroom.wav"/>
<prompt phrase="cleanup" filename="cleanup.wav"/>
<prompt phrase="clergyman" filename="clergyman.wav"/>
<prompt phrase="clockwork" filename="clockwork.wav"/>
<prompt phrase="cobra" filename="cobra.wav"/>
<prompt phrase="coherence" filename="coherence.wav"/>
<prompt phrase="combustion" filename="combustion.wav"/>
<prompt phrase="commando" filename="commando.wav"/>
<prompt phrase="commence" filename="commence.wav"/>
<prompt phrase="company" filename="company.wav"/>
<prompt phrase="component" filename="component.wav"/>
<prompt phrase="concert" filename="concert.wav"/>
<prompt phrase="concurrent" filename="concurrent.wav"/>
<prompt phrase="confidence" filename="confidence.wav"/>
<prompt phrase="conformist" filename="conformist.wav"/>
<prompt phrase="congregate" filename="congregate.wav"/>
<prompt phrase="consensus" filename="consensus.wav"/>
<prompt phrase="consulting" filename="consulting.wav"/>
<prompt phrase="corporate" filename="corporate.wav"/>
<prompt phrase="corrosion" filename="corrosion.wav"/>
<prompt phrase="councilman" filename="councilman.wav"/>
<prompt phrase="cowbell" filename="cowbell.wav"/>
<prompt phrase="crackdown" filename="crackdown.wav"/>
<prompt phrase="cranky" filename="cranky.wav"/>
<prompt phrase="crossover" filename="crossover.wav"/>
<prompt phrase="crowfoot" filename="crowfoot.wav"/>
<prompt phrase="crucial" filename="crucial.wav"/>
<prompt phrase="crucifix" filename="crucifix.wav"/>
<prompt phrase="crumpled" filename="crumpled.wav"/>
<prompt phrase="crusade" filename="crusade.wav"/>
<prompt phrase="cubic" filename="cubic.wav"/>
<prompt phrase="cumbersome" filename="cumbersome.wav"/>
<prompt phrase="customer" filename="customer.wav"/>
<prompt phrase="dashboard" filename="dashboard.wav"/>
<prompt phrase="deadbolt" filename="deadbolt.wav"/>
<prompt phrase="decadence" filename="decadence.wav"/>
<prompt phrase="decimal" filename="decimal.wav"/>
<prompt phrase="deckhand" filename="deckhand.wav"/>
<prompt phrase="designing" filename="designing.wav"/>
<prompt phrase="detector" filename="detector.wav"/>
<prompt phrase="detergent" filename="detergent.wav"/>
<prompt phrase="determine" filename="determine.wav"/>
<prompt phrase="dictator" filename="dictator.wav"/>
<prompt phrase="dinosaur" filename="dinosaur.wav"/>
<prompt phrase="direction" filename="direction.wav"/>
<prompt phrase="disable" filename="disable.wav"/>
<prompt phrase="disbelief" filename="disbelief.wav"/>
<prompt phrase="disruptive" filename="disruptive.wav"/>
<prompt phrase="distortion" filename="distortion.wav"/>
<prompt phrase="document" filename="document.wav"/>
<prompt phrase="dogsled" filename="dogsled.wav"/>
<prompt phrase="dragnet" filename="dragnet.wav"/>
<prompt phrase="drainage" filename="drainage.wav"/>
<prompt phrase="dreadful" filename="dreadful.wav"/>
<prompt phrase="drifter" filename="drifter.wav"/>
<prompt phrase="dropper" filename="dropper.wav"/>
<prompt phrase="drumbeat" filename="drumbeat.wav"/>
<prompt phrase="drunken" filename="drunken.wav"/>
<prompt phrase="dwelling" filename="dwelling.wav"/>
<prompt phrase="eating" filename="eating.wav"/>
<prompt phrase="edict" filename="edict.wav"/>
<prompt phrase="egghead" filename="egghead.wav"/>
<prompt phrase="eightball" filename="eightball.wav"/>
<prompt phrase="embezzle" filename="embezzle.wav"/>
<prompt phrase="enchanting" filename="enchanting.wav"/>
<prompt phrase="endorse" filename="endorse.wav"/>
<prompt phrase="endow" filename="endow.wav"/>
<prompt phrase="enlist" filename="enlist.wav"/>
<prompt phrase="enrollment" filename="enrollment.wav"/>
<prompt phrase="enterprise" filename="enterprise.wav"/>
<prompt phrase="equation" filename="equation.wav"/>
<prompt phrase="equipment" filename="equipment.wav"/>
<prompt phrase="erase" filename="erase.wav"/>
<prompt phrase="escapade" filename="escapade.wav"/>
<prompt phrase="escape" filename="escape.wav"/>
<prompt phrase="everyday" filename="everyday.wav"/>
<prompt phrase="examine" filename="examine.wav"/>
<prompt phrase="exceed" filename="exceed.wav"/>
<prompt phrase="existence" filename="existence.wav"/>
<prompt phrase="exodus" filename="exodus.wav"/>
<prompt phrase="eyeglass" filename="eyeglass.wav"/>
<prompt phrase="eyetooth" filename="eyetooth.wav"/>
<prompt phrase="facial" filename="facial.wav"/>
<prompt phrase="fallout" filename="fallout.wav"/>
<prompt phrase="fascinate" filename="fascinate.wav"/>
<prompt phrase="filament" filename="filament.wav"/>
<prompt phrase="finicky" filename="finicky.wav"/>
<prompt phrase="flagpole" filename="flagpole.wav"/>
<prompt phrase="flatfoot" filename="flatfoot.wav"/>
<prompt phrase="flytrap" filename="flytrap.wav"/>
<prompt phrase="forever" filename="forever.wav"/>
<prompt phrase="fortitude" filename="fortitude.wav"/>
<prompt phrase="fracture" filename="fracture.wav"/>
<prompt phrase="framework" filename="framework.wav"/>
<prompt phrase="freedom" filename="freedom.wav"/>
<prompt phrase="frequency" filename="frequency.wav"/>
<prompt phrase="frighten" filename="frighten.wav"/>
<prompt phrase="gadgetry" filename="gadgetry.wav"/>
<prompt phrase="gazelle" filename="gazelle.wav"/>
<prompt phrase="getaway" filename="getaway.wav"/>
<prompt phrase="glitter" filename="glitter.wav"/>
<prompt phrase="glossary" filename="glossary.wav"/>
<prompt phrase="glucose" filename="glucose.wav"/>
<prompt phrase="goggles" filename="goggles.wav"/>
<prompt phrase="goldfish" filename="goldfish.wav"/>
<prompt phrase="gossamer" filename="gossamer.wav"/>
<prompt phrase="graduate" filename="graduate.wav"/>
<prompt phrase="gravity" filename="gravity.wav"/>
<prompt phrase="gremlin" filename="gremlin.wav"/>
<prompt phrase="guidance" filename="guidance.wav"/>
<prompt phrase="guitarist" filename="guitarist.wav"/>
<prompt phrase="hamburger" filename="hamburger.wav"/>
<prompt phrase="hamlet" filename="hamlet.wav"/>
<prompt phrase="handiwork" filename="handiwork.wav"/>
<prompt phrase="hazardous" filename="hazardous.wav"/>
<prompt phrase="headwaters" filename="headwaters.wav"/>
<prompt phrase="hemisphere" filename="hemisphere.wav"/>
<prompt phrase="hesitate" filename="hesitate.wav"/>
<prompt phrase="hideaway" filename="hideaway.wav"/>
<prompt phrase="highchair" filename="highchair.wav"/>
<prompt phrase="hockey" filename="hockey.wav"/>
<prompt phrase="holiness" filename="holiness.wav"/>
<prompt phrase="hurricane" filename="hurricane.wav"/>
<prompt phrase="hydraulic" filename="hydraulic.wav"/>
<prompt phrase="impartial" filename="impartial.wav"/>
<prompt phrase="impetus" filename="impetus.wav"/>
<prompt phrase="inception" filename="inception.wav"/>
<prompt phrase="indigo" filename="indigo.wav"/>
<prompt phrase="indoors" filename="indoors.wav"/>
<prompt phrase="indulge" filename="indulge.wav"/>
<prompt phrase="inertia" filename="inertia.wav"/>
<prompt phrase="infancy" filename="infancy.wav"/>
<prompt phrase="inferno" filename="inferno.wav"/>
<prompt phrase="informant" filename="informant.wav"/>
<prompt phrase="insincere" filename="insincere.wav"/>
<prompt phrase="insurgent" filename="insurgent.wav"/>
<prompt phrase="integrate" filename="integrate.wav"/>
<prompt phrase="intention" filename="intention.wav"/>
<prompt phrase="inventive" filename="inventive.wav"/>
<prompt phrase="inverse" filename="inverse.wav"/>
<prompt phrase="involve" filename="involve.wav"/>
<prompt phrase="island" filename="island.wav"/>
<prompt phrase="jawbone" filename="jawbone.wav"/>
<prompt phrase="keyboard" filename="keyboard.wav"/>
<prompt phrase="kickoff" filename="kickoff.wav"/>
<prompt phrase="kiwi" filename="kiwi.wav"/>
<prompt phrase="klaxon" filename="klaxon.wav"/>
<prompt phrase="leprosy" filename="leprosy.wav"/>
<prompt phrase="letterhead" filename="letterhead.wav"/>
<prompt phrase="liberty" filename="liberty.wav"/>
<prompt phrase="locale" filename="locale.wav"/>
<prompt phrase="lockup" filename="lockup.wav"/>
<prompt phrase="maritime" filename="maritime.wav"/>
<prompt phrase="matchmaker" filename="matchmaker.wav"/>
<prompt phrase="maverick" filename="maverick.wav"/>
<prompt phrase="megaton" filename="megaton.wav"/>
<prompt phrase="merit" filename="merit.wav"/>
<prompt phrase="microscope" filename="microscope.wav"/>
<prompt phrase="microwave" filename="microwave.wav"/>
<prompt phrase="midsummer" filename="midsummer.wav"/>
<prompt phrase="millionaire" filename="millionaire.wav"/>
<prompt phrase="minnow" filename="minnow.wav"/>
<prompt phrase="miracle" filename="miracle.wav"/>
<prompt phrase="miser" filename="miser.wav"/>
<prompt phrase="misnomer" filename="misnomer.wav"/>
<prompt phrase="molasses" filename="molasses.wav"/>
<prompt phrase="molecule" filename="molecule.wav"/>
<prompt phrase="monument" filename="monument.wav"/>
<prompt phrase="mosquito" filename="mosquito.wav"/>
<prompt phrase="mural" filename="mural.wav"/>
<prompt phrase="music" filename="music.wav"/>
<prompt phrase="narrative" filename="narrative.wav"/>
<prompt phrase="nebula" filename="nebula.wav"/>
<prompt phrase="necklace" filename="necklace.wav"/>
<prompt phrase="newborn" filename="newborn.wav"/>
<prompt phrase="newsletter" filename="newsletter.wav"/>
<prompt phrase="nightbird" filename="nightbird.wav"/>
<prompt phrase="obtuse" filename="obtuse.wav"/>
<prompt phrase="offload" filename="offload.wav"/>
<prompt phrase="onlooker" filename="onlooker.wav"/>
<prompt phrase="optic" filename="optic.wav"/>
<prompt phrase="opulent" filename="opulent.wav"/>
<prompt phrase="orca" filename="orca.wav"/>
<prompt phrase="outfielder" filename="outfielder.wav"/>
<prompt phrase="pandemic" filename="pandemic.wav"/>
<prompt phrase="paperweight" filename="paperweight.wav"/>
<prompt phrase="paragon" filename="paragon.wav"/>
<prompt phrase="paragraph" filename="paragraph.wav"/>
<prompt phrase="paramount" filename="paramount.wav"/>
<prompt phrase="passenger" filename="passenger.wav"/>
<prompt phrase="payday" filename="payday.wav"/>
<prompt phrase="peachy" filename="peachy.wav"/>
<prompt phrase="pedigree" filename="pedigree.wav"/>
<prompt phrase="penetrate" filename="penetrate.wav"/>
<prompt phrase="perceptive" filename="perceptive.wav"/>
<prompt phrase="performance" filename="performance.wav"/>
<prompt phrase="pharmacy" filename="pharmacy.wav"/>
<prompt phrase="pheasant" filename="pheasant.wav"/>
<prompt phrase="phonetic" filename="phonetic.wav"/>
<prompt phrase="photograph" filename="photograph.wav"/>
<prompt phrase="physique" filename="physique.wav"/>
<prompt phrase="pioneer" filename="pioneer.wav"/>
<prompt phrase="playhouse" filename="playhouse.wav"/>
<prompt phrase="pocketful" filename="pocketful.wav"/>
<prompt phrase="politeness" filename="politeness.wav"/>
<prompt phrase="positive" filename="positive.wav"/>
<prompt phrase="potato" filename="potato.wav"/>
<prompt phrase="preclude" filename="preclude.wav"/>
<prompt phrase="prefer" filename="prefer.wav"/>
<prompt phrase="preshrunk" filename="preshrunk.wav"/>
<prompt phrase="printer" filename="printer.wav"/>
<prompt phrase="processor" filename="processor.wav"/>
<prompt phrase="provincial" filename="provincial.wav"/>
<prompt phrase="prowler" filename="prowler.wav"/>
<prompt phrase="proximate" filename="proximate.wav"/>
<prompt phrase="puberty" filename="puberty.wav"/>
<prompt phrase="publisher" filename="publisher.wav"/>
<prompt phrase="pupil" filename="pupil.wav"/>
<prompt phrase="puppy" filename="puppy.wav"/>
<prompt phrase="pyramid" filename="pyramid.wav"/>
<prompt phrase="python" filename="python.wav"/>
<prompt phrase="quadrant" filename="quadrant.wav"/>
<prompt phrase="quantity" filename="quantity.wav"/>
<prompt phrase="quiver" filename="quiver.wav"/>
<prompt phrase="quota" filename="quota.wav"/>
<prompt phrase="racketeer" filename="racketeer.wav"/>
<prompt phrase="ragtime" filename="ragtime.wav"/>
<prompt phrase="ratchet" filename="ratchet.wav"/>
<prompt phrase="rebellion" filename="rebellion.wav"/>
<prompt phrase="rebirth" filename="rebirth.wav"/>
<prompt phrase="recipe" filename="recipe.wav"/>
<prompt phrase="recover" filename="recover.wav"/>
<prompt phrase="reform" filename="reform.wav"/>
<prompt phrase="regain" filename="regain.wav"/>
<prompt phrase="reindeer" filename="reindeer.wav"/>
<prompt phrase="rematch" filename="rematch.wav"/>
<prompt phrase="repay" filename="repay.wav"/>
<prompt phrase="repellent" filename="repellent.wav"/>
<prompt phrase="replica" filename="replica.wav"/>
<prompt phrase="reproduce" filename="reproduce.wav"/>
<prompt phrase="resistor" filename="resistor.wav"/>
<prompt phrase="responsive" filename="responsive.wav"/>
<prompt phrase="retouch" filename="retouch.wav"/>
<prompt phrase="retraction" filename="retraction.wav"/>
<prompt phrase="retrieval" filename="retrieval.wav"/>
<prompt phrase="retrospect" filename="retrospect.wav"/>
<prompt phrase="revenge" filename="revenge.wav"/>
<prompt phrase="revenue" filename="revenue.wav"/>
<prompt phrase="revival" filename="revival.wav"/>
<prompt phrase="revolver" filename="revolver.wav"/>
<prompt phrase="reward" filename="reward.wav"/>
<prompt phrase="rhythm" filename="rhythm.wav"/>
<prompt phrase="ribcage" filename="ribcage.wav"/>
<prompt phrase="ringbolt" filename="ringbolt.wav"/>
<prompt phrase="robust" filename="robust.wav"/>
<prompt phrase="rocker" filename="rocker.wav"/>
<prompt phrase="ruffled" filename="ruffled.wav"/>
<prompt phrase="sailboat" filename="sailboat.wav"/>
<prompt phrase="sandalwood" filename="sandalwood.wav"/>
<prompt phrase="sardonic" filename="sardonic.wav"/>
<prompt phrase="savagery" filename="savagery.wav"/>
<prompt phrase="sawdust" filename="sawdust.wav"/>
<prompt phrase="scallion" filename="scallion.wav"/>
<prompt phrase="scavenger" filename="scavenger.wav"/>
<prompt phrase="scenic" filename="scenic.wav"/>
<prompt phrase="scorecard" filename="scorecard.wav"/>
<prompt phrase="seabird" filename="seabird.wav"/>
<prompt phrase="select" filename="select.wav"/>
<prompt phrase="sensation" filename="sensation.wav"/>
<prompt phrase="sentence" filename="sentence.wav"/>
<prompt phrase="shadow" filename="shadow.wav"/>
<prompt phrase="shamrock" filename="shamrock.wav"/>
<prompt phrase="showgirl" filename="showgirl.wav"/>
<prompt phrase="skullcap" filename="skullcap.wav"/>
<prompt phrase="skydive" filename="skydive.wav"/>
<prompt phrase="slingshot" filename="slingshot.wav"/>
<prompt phrase="slowdown" filename="slowdown.wav"/>
<prompt phrase="snapline" filename="snapline.wav"/>
<prompt phrase="snapshot" filename="snapshot.wav"/>
<prompt phrase="snowcap" filename="snowcap.wav"/>
<prompt phrase="snowslide" filename="snowslide.wav"/>
<prompt phrase="sociable" filename="sociable.wav"/>
<prompt phrase="solo" filename="solo.wav"/>
<prompt phrase="southward" filename="southward.wav"/>
<prompt phrase="souvenir" filename="souvenir.wav"/>
<prompt phrase="soybean" filename="soybean.wav"/>
<prompt phrase="spaniel" filename="spaniel.wav"/>
<prompt phrase="spearhead" filename="spearhead.wav"/>
<prompt phrase="specialist" filename="specialist.wav"/>
<prompt phrase="speculate" filename="speculate.wav"/>
<prompt phrase="spellbind" filename="spellbind.wav"/>
<prompt phrase="spheroid" filename="spheroid.wav"/>
<prompt phrase="spigot" filename="spigot.wav"/>
<prompt phrase="spindle" filename="spindle.wav"/>
<prompt phrase="spyglass" filename="spyglass.wav"/>
<prompt phrase="stagehand" filename="stagehand.wav"/>
<prompt phrase="stagnate" filename="stagnate.wav"/>
<prompt phrase="stairway" filename="stairway.wav"/>
<prompt phrase="standard" filename="standard.wav"/>
<prompt phrase="stapler" filename="stapler.wav"/>
<prompt phrase="steamship" filename="steamship.wav"/>
<prompt phrase="sterling" filename="sterling.wav"/>
<prompt phrase="stethoscope" filename="stethoscope.wav"/>
<prompt phrase="stockman" filename="stockman.wav"/>
<prompt phrase="stopwatch" filename="stopwatch.wav"/>
<prompt phrase="stormy" filename="stormy.wav"/>
<prompt phrase="stupendous" filename="stupendous.wav"/>
<prompt phrase="sugar" filename="sugar.wav"/>
<prompt phrase="supportive" filename="supportive.wav"/>
<prompt phrase="surmount" filename="surmount.wav"/>
<prompt phrase="surrender" filename="surrender.wav"/>
<prompt phrase="suspense" filename="suspense.wav"/>
<prompt phrase="suspicious" filename="suspicious.wav"/>
<prompt phrase="sweatband" filename="sweatband.wav"/>
<prompt phrase="swelter" filename="swelter.wav"/>
<prompt phrase="sympathy" filename="sympathy.wav"/>
<prompt phrase="tactics" filename="tactics.wav"/>
<prompt phrase="talon" filename="talon.wav"/>
<prompt phrase="tambourine" filename="tambourine.wav"/>
<prompt phrase="tapeworm" filename="tapeworm.wav"/>
<prompt phrase="telephone" filename="telephone.wav"/>
<prompt phrase="tempest" filename="tempest.wav"/>
<prompt phrase="therapist" filename="therapist.wav"/>
<prompt phrase="tiger" filename="tiger.wav"/>
<prompt phrase="tissue" filename="tissue.wav"/>
<prompt phrase="tobacco" filename="tobacco.wav"/>
<prompt phrase="tolerance" filename="tolerance.wav"/>
<prompt phrase="tomorrow" filename="tomorrow.wav"/>
<prompt phrase="tonic" filename="tonic.wav"/>
<prompt phrase="topmost" filename="topmost.wav"/>
<prompt phrase="torpedo" filename="torpedo.wav"/>
<prompt phrase="tracker" filename="tracker.wav"/>
<prompt phrase="tradition" filename="tradition.wav"/>
<prompt phrase="transit" filename="transit.wav"/>
<prompt phrase="trauma" filename="trauma.wav"/>
<prompt phrase="travesty" filename="travesty.wav"/>
<prompt phrase="treadmill" filename="treadmill.wav"/>
<prompt phrase="trombonist" filename="trombonist.wav"/>
<prompt phrase="trouble" filename="trouble.wav"/>
<prompt phrase="truncated" filename="truncated.wav"/>
<prompt phrase="tumor" filename="tumor.wav"/>
<prompt phrase="tunnel" filename="tunnel.wav"/>
<prompt phrase="tycoon" filename="tycoon.wav"/>
<prompt phrase="typewriter" filename="typewriter.wav"/>
<prompt phrase="ultimate" filename="ultimate.wav"/>
<prompt phrase="uncut" filename="uncut.wav"/>
<prompt phrase="undaunted" filename="undaunted.wav"/>
<prompt phrase="underfoot" filename="underfoot.wav"/>
<prompt phrase="unearth" filename="unearth.wav"/>
<prompt phrase="unicorn" filename="unicorn.wav"/>
<prompt phrase="unify" filename="unify.wav"/>
<prompt phrase="universe" filename="universe.wav"/>
<prompt phrase="unravel" filename="unravel.wav"/>
<prompt phrase="unwind" filename="unwind.wav"/>
<prompt phrase="upcoming" filename="upcoming.wav"/>
<prompt phrase="uproot" filename="uproot.wav"/>
<prompt phrase="upset" filename="upset.wav"/>
<prompt phrase="upshot" filename="upshot.wav"/>
<prompt phrase="vacancy" filename="vacancy.wav"/>
<prompt phrase="vagabond" filename="vagabond.wav"/>
<prompt phrase="vapor" filename="vapor.wav"/>
<prompt phrase="vertigo" filename="vertigo.wav"/>
<prompt phrase="village" filename="village.wav"/>
<prompt phrase="virus" filename="virus.wav"/>
<prompt phrase="visitor" filename="visitor.wav"/>
<prompt phrase="vocalist" filename="vocalist.wav"/>
<prompt phrase="voyager" filename="voyager.wav"/>
<prompt phrase="waffle" filename="waffle.wav"/>
<prompt phrase="wallet" filename="wallet.wav"/>
<prompt phrase="warranty" filename="warranty.wav"/>
<prompt phrase="watchword" filename="watchword.wav"/>
<prompt phrase="wayside" filename="wayside.wav"/>
<prompt phrase="whimsical" filename="whimsical.wav"/>
<prompt phrase="willow" filename="willow.wav"/>
<prompt phrase="woodlark" filename="woodlark.wav"/>
<prompt phrase="yesteryear" filename="yesteryear.wav"/>
<!-- Event prompts -->
<prompt phrase="Bem-vindo ao agente de registro de segurança ZRTP." filename="zrtp-enroll_welcome.wav"/>
<prompt phrase="Vocę deve verificar a autentificaçăo com o seu destinatário. Se năo coincidir, isso indica presença de um dispositivo de escuta telefonica." filename="zrtp-check_sas.wav"/>
<prompt phrase="Somente aqueles telefones que estem autentificados podem ser configurados de maneira segura neste sistema para retransmitir as ligaçőes em ZRTP. O seu telefone nao esta autentificado com este sistema, esta ligaçăo năo sera realizada." filename="zrtp-enroll_not_sip_registered.wav"/>
<prompt phrase="O seu telefone indica que é seguro este sistema para realizar ligaçőes seguras em ZRTP, vocę năo precisa fazer nada mais." filename="zrtp-enroll_already_enrolled.wav"/>
<prompt phrase="Somente os telefones equipados com protocolo ZRTP podem usar este ramal.O seu telefone năo esta configurado para ZRTP, esta ligaçăo năo sera completada." filename="zrtp-enroll_notzrtp.wav"/>
<prompt phrase="Este sistema está configurado para realizar ligaçőes telefonicas encriptadas em ZRTP. Vocę deve decidir se permitira que este sistema possa interceptar e monitorizar as suas ligaçőes telefonicas seguras. Pode finalizar a ligaçăo depois disso." filename="zrtp-enroll_confirmed.wav"/>
<prompt phrase="Compare verbalmente este código de autentificaçăo com o seu destinatário." filename="zrtp-is_secure.wav"/>
<prompt phrase="O código de autentificaçăo năo foi verificado." filename="zrtp-is_unverified.wav"/>
<prompt phrase="O código de autentificaçăo foi verificado." filename="zrtp-is_verified.wav"/>
<prompt phrase="Obrigado pela sua ligaçăo. Até logo." filename="zrtp-thankyou_goodbye.wav"/>
<prompt phrase="Algo falha." filename="zrtp-somethings_wrong.wav"/>
<prompt phrase="Erro." filename="zrtp-status_error.wav"/>
<prompt phrase="A ligaçăo năo e segura." filename="zrtp-status_notsecure.wav"/>
<prompt phrase="A ligaçăo e segura." filename="zrtp-status_secure.wav"/>
<prompt phrase="Securizando a ligaçăo." filename="zrtp-status_securing.wav"/>
</zrtp>
</pt_BR>
</language>

View File

@ -0,0 +1,987 @@
<language>
<pt_PT>
<ascii>
<prompt phrase="Espaço" filename="32.wav"/>
<prompt phrase="Cardinal" filename="35.wav"/>
<prompt phrase="Asterisco" filename="42.wav"/>
<prompt phrase="Ponto" filename="46.wav"/>
<prompt phrase="A" filename="97.wav"/>
<prompt phrase="B" filename="98.wav"/>
<prompt phrase="C" filename="99.wav"/>
<prompt phrase="D" filename="100.wav"/>
<prompt phrase="E" filename="101.wav"/>
<prompt phrase="F" filename="102.wav"/>
<prompt phrase="G" filename="103.wav"/>
<prompt phrase="H" filename="104.wav"/>
<prompt phrase="I" filename="105.wav"/>
<prompt phrase="J" filename="106.wav"/>
<prompt phrase="K" filename="107.wav"/>
<prompt phrase="L" filename="108.wav"/>
<prompt phrase="M" filename="109.wav"/>
<prompt phrase="N" filename="110.wav"/>
<prompt phrase="O" filename="111.wav"/>
<prompt phrase="P" filename="112.wav"/>
<prompt phrase="Q" filename="113.wav"/>
<prompt phrase="R" filename="114.wav"/>
<prompt phrase="S" filename="115.wav"/>
<prompt phrase="T" filename="116.wav"/>
<prompt phrase="U" filename="117.wav"/>
<prompt phrase="V" filename="118.wav"/>
<prompt phrase="W" filename="119.wav"/>
<prompt phrase="X" filename="120.wav"/>
<prompt phrase="Y" filename="121.wav"/>
<prompt phrase="Z" filename="122.wav"/>
</ascii>
<phonetic-ascii>
<prompt phrase="Espaço" filename="32.wav"/>
<prompt phrase="Ponto" filename="46.wav"/>
<prompt phrase="Alpha" filename="97.wav"/>
<prompt phrase="Bravo" filename="98.wav"/>
<prompt phrase="Charlie" filename="99.wav"/>
<prompt phrase="Delta" filename="100.wav"/>
<prompt phrase="Echo" filename="101.wav"/>
<prompt phrase="Foxtrot" filename="102.wav"/>
<prompt phrase="Golf" filename="103.wav"/>
<prompt phrase="Hotel" filename="104.wav"/>
<prompt phrase="India" filename="105.wav"/>
<prompt phrase="Juliet" filename="106.wav"/>
<prompt phrase="Kilo" filename="107.wav"/>
<prompt phrase="Lima" filename="108.wav"/>
<prompt phrase="Mike" filename="109.wav"/>
<prompt phrase="November" filename="110.wav"/>
<prompt phrase="Oscar" filename="111.wav"/>
<prompt phrase="Papa" filename="112.wav"/>
<prompt phrase="Quebec" filename="113.wav"/>
<prompt phrase="Romeo" filename="114.wav"/>
<prompt phrase="Sierra" filename="115.wav"/>
<prompt phrase="Tango" filename="116.wav"/>
<prompt phrase="Unifor" filename="117.wav"/>
<prompt phrase="Victor" filename="118.wav"/>
<prompt phrase="Whiskey" filename="119.wav"/>
<prompt phrase="Xray" filename="120.wav"/>
<prompt phrase="Yankee" filename="121.wav"/>
<prompt phrase="Zulu" filename="122.wav"/>
</phonetic-ascii>
<digits>
<prompt phrase="Zero" filename="0.wav"/>
<prompt phrase="Um" filename="1.wav"/>
<prompt phrase="Dois" filename="2.wav"/>
<prompt phrase="Três" filename="3.wav"/>
<prompt phrase="Quatro" filename="4.wav"/>
<prompt phrase="Cinco" filename="5.wav"/>
<prompt phrase="Seis" filename="6.wav"/>
<prompt phrase="Sete" filename="7.wav"/>
<prompt phrase="Oito" filename="8.wav"/>
<prompt phrase="Nove" filename="9.wav"/>
<prompt phrase="Dez" filename="10.wav"/>
<prompt phrase="Onze" filename="11.wav"/>
<prompt phrase="Doze" filename="12.wav"/>
<prompt phrase="Treze" filename="13.wav"/>
<prompt phrase="Catorze" filename="14.wav"/>
<prompt phrase="Quinze" filename="15.wav"/>
<prompt phrase="Dezasseis" filename="16.wav"/>
<prompt phrase="Dezassete" filename="17.wav"/>
<prompt phrase="Dezoito" filename="18.wav"/>
<prompt phrase="Dezanove" filename="19.wav"/>
<prompt phrase="Vinte" filename="20.wav"/>
<prompt phrase="Trinta" filename="30.wav"/>
<prompt phrase="Quarenta" filename="40.wav"/>
<prompt phrase="Cinquenta" filename="50.wav"/>
<prompt phrase="Sessenta" filename="60.wav"/>
<prompt phrase="Setenta" filename="70.wav"/>
<prompt phrase="Oitenta" filename="80.wav"/>
<prompt phrase="Noventa" filename="90.wav"/>
<prompt phrase="Cem" filename="100.wav"/>
<prompt phrase="Duzentos" filename="200.wav"/>
<prompt phrase="Trezentos" filename="300.wav"/>
<prompt phrase="Quinhentos" filename="500.wav"/>
<prompt phrase="Ponto" filename="dot.wav"/>
<prompt phrase="Primeiro" filename="h-1.wav"/>
<prompt phrase="Segundo" filename="h-2.wav"/>
<prompt phrase="Terceiro" filename="h-3.wav"/>
<prompt phrase="Quarto" filename="h-4.wav"/>
<prompt phrase="Quinto" filename="h-5.wav"/>
<prompt phrase="Sexto" filename="h-6.wav"/>
<prompt phrase="Sétimo" filename="h-7.wav"/>
<prompt phrase="Oitavo" filename="h-8.wav"/>
<prompt phrase="Nono" filename="h-9.wav"/>
<prompt phrase="Décimo" filename="h-10.wav"/>
<prompt phrase="Vigésimo" filename="h-20.wav"/>
<prompt phrase="Trigésimo" filename="h-30.wav"/>
<prompt phrase="Quadragésimo" filename="h-40.wav"/>
<prompt phrase="Quinquagésimo" filename="h-50.wav"/>
<prompt phrase="Sexagésimo" filename="h-60.wav"/>
<prompt phrase="Septuagésimo" filename="h-70.wav"/>
<prompt phrase="Octogésimo" filename="h-80.wav"/>
<prompt phrase="Nonagésimo" filename="h-90.wav"/>
<prompt phrase="Cento" filename="hundred.wav"/>
<prompt phrase="Centos" filename="hundreds.wav"/>
<prompt phrase="Mil" filename="thousand.wav"/>
<prompt phrase="Milhão" filename="million.wav"/>
<prompt phrase="Milhões" filename="millions.wav"/>
<prompt phrase="Período" filename="period.wav"/>
<prompt phrase="Ponto" filename="point.wav"/>
<prompt phrase="Cardinal" filename="pound.wav"/>
<prompt phrase="Asterisco" filename="star.wav"/>
</digits>
<currency>
<prompt phrase="E" filename="and.wav"/>
<prompt phrase="Cêntimo" filename="cent.wav"/>
<prompt phrase="Central" filename="central.wav"/>
<prompt phrase="Cêntimos por minuto" filename="cents-per-minute.wav"/>
<prompt phrase="Cêntimos" filename="cents.wav"/>
<prompt phrase="Dólar" filename="dollar.wav"/>
<prompt phrase="Dólares" filename="dollars.wav"/>
<prompt phrase="Menos" filename="minus.wav"/>
<prompt phrase="Negativo" filename="negative.wav"/>
</currency>
<time>
<prompt phrase="A.M." filename="a-m.wav"/>
<prompt phrase="a" filename="at.wav"/>
<prompt phrase="às" filename="ats.wav"/>
<prompt phrase="Domingo" filename="day-0.wav"/>
<prompt phrase="Segunda-feira" filename="day-1.wav"/>
<prompt phrase="Terça-feira" filename="day-2.wav"/>
<prompt phrase="Quarta-feira" filename="day-3.wav"/>
<prompt phrase="Quinta-feira" filename="day-4.wav"/>
<prompt phrase="Sexta-feira" filename="day-5.wav"/>
<prompt phrase="Sábado" filename="day-6.wav"/>
<prompt phrase="Hora" filename="hour.wav"/>
<prompt phrase="Horas" filename="hours.wav"/>
<prompt phrase="Minuto" filename="minute.wav"/>
<prompt phrase="Minutos" filename="minutes.wav"/>
<prompt phrase="Janeiro" filename="mon-0.wav"/>
<prompt phrase="Fevereiro" filename="mon-1.wav"/>
<prompt phrase="Março" filename="mon-2.wav"/>
<prompt phrase="Abril" filename="mon-3.wav"/>
<prompt phrase="Maio" filename="mon-4.wav"/>
<prompt phrase="Junho" filename="mon-5.wav"/>
<prompt phrase="Julho" filename="mon-6.wav"/>
<prompt phrase="Agosto" filename="mon-7.wav"/>
<prompt phrase="Setembro" filename="mon-8.wav"/>
<prompt phrase="Outubro" filename="mon-9.wav"/>
<prompt phrase="Novembro" filename="mon-10.wav"/>
<prompt phrase="Dezembro" filename="mon-11.wav"/>
<prompt phrase="Em ponto" filename="oclock.wav"/>
<prompt phrase="P.M." filename="p-m.wav"/>
<prompt phrase="Segundo" filename="second.wav"/>
<prompt phrase="Segundos" filename="seconds.wav"/>
<prompt phrase="Hoje" filename="today.wav"/>
<prompt phrase="Amanhã" filename="tomorrow.wav"/>
<prompt phrase="Ontem" filename="yesterday.wav"/>
</time>
<voicemail>
<prompt phrase="A pessoa na extensão..." filename="vm-person.wav"/>
<prompt phrase="marcada como urgente" filename="vm-marked-urgent.wav"/>
<prompt phrase="email enviado" filename="vm-emailed.wav"/>
<prompt phrase="Você tem..." filename="vm-you_have.wav"/>
<prompt phrase="Por favor introduza o seu número de utilizador, seguido de..." filename="vm-enter_id.wav"/>
<prompt phrase="Por favor introduza a sua palavra passe, seguida de..." filename="vm-enter_pass.wav"/>
<prompt phrase="Falha na autenticação." filename="vm-fail_auth.wav"/>
<prompt phrase="Bem-vindo ao seu correio de voz." filename="vm-hello.wav"/>
<prompt phrase="Até breve." filename="vm-goodbye.wav"/>
<prompt phrase="Após o sinal por favor diga o seu nome, pressione qualquer tecla ou deixe de falar para parar a gravação." filename="vm-record_name1.wav"/>
<prompt phrase="Seleccione uma saudação entre 1 e 9" filename="vm-choose_greeting_choose.wav"/>
<prompt phrase="Valor inválido." filename="vm-choose_greeting_fail.wav"/>
<prompt phrase="Demasiadas tentativas falhadas." filename="vm-abort.wav"/>
<prompt phrase="Para alterar a sua palavra passe..." filename="vm-change_password.wav"/>
<prompt phrase="após o sinal grave a sua saudação, pressione qualquer tecla ou deixe de falar para parar a gravação." filename="vm-record_greeting.wav"/>
<prompt phrase="após o sinal grave a sua mensagem, pressione qualquer tecla ou deixe de falar para parar a gravação." filename="vm-record_message.wav"/>
<prompt phrase="Não está disponível." filename="vm-play_greeting.wav"/>
<prompt phrase="nova e urgente" filename="vm-urgent-new.wav"/>
<prompt phrase="nova" filename="vm-new.wav"/>
<prompt phrase="guardada e urgente" filename="vm-urgent-saved.wav"/>
<prompt phrase="guardada" filename="vm-saved.wav"/>
<prompt phrase="mensagem" filename="vm-message.wav"/>
<prompt phrase="mensagens" filename="vm-messages.wav"/>
<prompt phrase="marque" filename="vm-press.wav"/>
<prompt phrase="Para ouvir as mensagens novas..." filename="vm-listen_new.wav"/>
<prompt phrase="Para ouvir as mensagens guardadas..." filename="vm-listen_saved.wav"/>
<prompt phrase="Para opções avançadas..." filename="vm-advanced.wav"/>
<prompt phrase="Para sair..." filename="vm-to_exit.wav"/>
<prompt phrase="Para gravar a sua saudação..." filename="vm-record_greeting.wav"/>
<prompt phrase="Para escolher a sua saudação..." filename="vm-choose_greeting.wav"/>
<prompt phrase="Para gravar o seu nome..." filename="vm-record_name2.wav"/>
<prompt phrase="Para o menu principal..." filename="vm-main_menu.wav"/>
<prompt phrase="Para ouvir a gravação..." filename="vm-listen_to_recording.wav"/>
<prompt phrase="Para guardar a gravação..." filename="vm-save_recording.wav"/>
<prompt phrase="Para gravar novamente..." filename="vm-rerecord.wav"/>
<prompt phrase="Para marcar esta mensagem como urgente..." filename="vm-mark_urgent.wav"/>
<prompt phrase="Para continuar..." filename="vm-continue.wav"/>
<prompt phrase="Para ouvir a gravação novamente..." filename="vm-listen_to_recording_again.wav"/>
<prompt phrase="Para apagar a gravação..." filename="vm-delete_recording.wav"/>
<prompt phrase="Para encaminhar a gravação para o seu email..." filename="vm-forward_to_email.wav"/>
<prompt phrase="saudação" filename="vm-greeting.wav"/>
<prompt phrase="seleccionada" filename="vm-selected.wav"/>
<prompt phrase="Não está disponível." filename="vm-not_available.wav"/>
<prompt phrase="Mensagem número..." filename="vm-message_number.wav"/>
<prompt phrase="apagada" filename="vm-deleted.wav"/>
<prompt phrase="O tamanho da sua gravação é menor que o mínimo aceite, por favor tente novamente." filename="vm-too-small.wav"/>
<prompt phrase="na caixa de entrada" filename="vm-in_folder.wav"/>
<prompt phrase="Para devolver a chamada agora..." filename="vm-return_call.wav"/>
<prompt phrase="urgente" filename="vm-urgent.wav"/>
<prompt phrase="Esta caixa de correio está cheia, por favor tente mais tarde." filename="vm-mailbox_full.wav"/>
<prompt phrase="Bem-Vindo ao seu voicemail. Para ouvir o tutorial e configurar o seu voicemail, pressione um. Para saltar-lo pressione dois." filename="vm-tutorial_yes_no.wav"/>
<prompt phrase="Necessita gravar o seu nome e sobrenome. Esta gravação é usada entre outros, no serviço de directório." filename="vm-tutorial_record_name.wav"/>
<prompt phrase="O número de identificação pessoal ou PIN serve para impedir o acesso de terceiros às suas mensagens. Deseja alterar o seu PIN agora?" filename="vm-tutorial_change_pin.wav"/>
</voicemail>
<directory>
<prompt phrase="Por favor introduza as primeiras letras do nome da pessoa." filename="dir-enter-person.wav"/>
<prompt phrase="...último nome..." filename="dir-last_name.wav"/>
<prompt phrase="Para pesquisar por..." filename="dir-to_search_by.wav"/>
<prompt phrase="...primeiro nome..." filename="dir-first_name.wav"/>
<prompt phrase="Não foram encontrados resultados, tente novamente." filename="dir-no_match_entry.wav"/>
<prompt phrase="...resultados encontrados para a sua pesquisa." filename="dir-result_match.wav"/>
<prompt phrase="A sua pesquisa devolveu demasiados resultados, por favor tente novamente." filename="dir-too_many_result.wav"/>
<prompt phrase="Não há mais resultados." filename="dir-no_more_results.wav"/>
<prompt phrase="Resultado número" filename="dir-result_number.wav"/>
<prompt phrase="...na extensão..." filename="dir-at_extension.wav"/>
<prompt phrase="Para seleccionar este resultado..." filename="dir-to_select_entry.wav"/>
<prompt phrase="Para o resultado seguinte..." filename="dir-for_next.wav"/>
<prompt phrase="Para o resultado anterior..." filename="dir-for_prev.wav"/>
<prompt phrase="Para iniciar uma nova pesquisa..." filename="dir-start_new_search.wav"/>
<prompt phrase="Você necessita de especificar um mínimo de..." filename="dir-specify_mininum_first.wav"/>
<prompt phrase="...letras do nome da pessoa, tente novamente." filename="dir-letters_of_person_name.wav"/>
<prompt phrase="marque" filename="dir-press.wav"/>
</directory>
<conference>
<prompt phrase="NULL" filename="conf-ack.wav" type="tone"/>
<prompt phrase="NULL" filename="conf-nack.wav" type="tone"/>
<prompt phrase="Você agora está em silêncio." filename="conf-muted.wav"/>
<prompt phrase="Você já não está em silêncio." filename="conf-unmuted.wav"/>
<prompt phrase="Neste momento você é a única pessoa na conferência." filename="conf-alone.wav"/>
<prompt phrase="NULL" filename="conf-perpetual.wav" type="music"/>
<prompt phrase="NULL" filename="conf-enter.wav" type="tone"/>
<prompt phrase="NULL" filename="conf-exit.wav" type="tone"/>
<prompt phrase="Você foi excluído desta conferência." filename="conf-kicked.wav"/>
<prompt phrase="Esta conferência está bloqueada." filename="conf-locked.wav"/>
<prompt phrase="A conferência está agora bloqueada." filename="conf-is-locked.wav"/>
<prompt phrase="A conferência está agora desbloqueada." filename="conf-is-unlocked.wav"/>
<prompt phrase="Por favor introduza o PIN da conferência." filename="conf-pin.wav"/>
<prompt phrase="PIN inválido, tente novamente." filename="conf-bad-pin.wav"/>
<prompt phrase="Até breve." filename="conf-goodbye.wav"/>
<prompt phrase="Bem-vindo à conferência." filename="conf-welcome.wav"/>
</conference>
<ivr>
<prompt phrase="Número da conta" filename="ivr-account_number.wav"/>
<prompt phrase="Estabelecer contacto com a pessoa que telefona" filename="ivr-connect_to_caller.wav"/>
<prompt phrase="Se conhece a extensão do destinatário, por favor marque-a agora." filename="ivr-enter_ext_pound.wav"/>
<prompt phrase="Por favor introduza uma extensão seguida de cardinal." filename="ivr-enter_ext.wav"/>
<prompt phrase="Para esta pessoa..." filename="ivr-for_this_person.wav"/>
<prompt phrase="Por favor aguarde enquanto a sua chamada é estabelecida." filename="ivr-hold_connect_call.wav"/>
<prompt phrase="Desculpe" filename="ivr-im_sorry.wav"/>
<prompt phrase="Por favor" filename="ivr-please.wav"/>
<prompt phrase="Por favor devolva a nossa chamada às..." filename="ivr-please_return_our_call_at.wav"/>
<prompt phrase="De acordo com o número de referência" filename="ivr-regarding_reference_number.wav"/>
<prompt phrase="Este é um exemplo de um submenu IVR..." filename="ivr-sample_submenu.wav"/>
<prompt phrase="Por favor diga o seu nome depois do sinal." filename="ivr-say_name.wav"/>
<prompt phrase="Enviar esta chamada para o correio de voz." filename="ivr-send_to_voicemail.wav"/>
<prompt phrase="Para falar com um responsável do apoio a clientes..." filename="ivr-speak_to_a_customer_service_representative.wav"/>
<prompt phrase="Deixe uma mensagem" filename="ivr-take_a_message.wav"/>
<prompt phrase="Obrigado" filename="ivr-thank_you.wav"/>
<prompt phrase="Essa era uma entrada inválida." filename="ivr-that_was_an_invalid_entry.wav"/>
<prompt phrase="Esta é uma chamada de..." filename="ivr-this_is_a_call_from.wav"/>
<prompt phrase="Este IVR permite-lhe testar algumas das funções..." filename="ivr-this_ivr_will_let_you_test_features.wav"/>
<prompt phrase="Para ligar à conferência FreeSWITCH..." filename="ivr-to_call_the_freeswitch_conference.wav"/>
<prompt phrase="Para realizar um teste FreeSWITCH eco..." filename="ivr-to_do_a_freeswitch_echo_test.wav"/>
<prompt phrase="Para realizar um teste FWD eco..." filename="ivr-to_do_a_fwd_echo_test.wav"/>
<prompt phrase="Para ouvir o exemplo de um submenu IVR..." filename="ivr-to_hear_sample_submenu.wav"/>
<prompt phrase="Para ouvir gritaria de macacos..." filename="ivr-to_hear_screaming_monkeys.wav"/>
<prompt phrase="Para ouvir música em espera..." filename="ivr-to_listen_to_moh.wav"/>
<prompt phrase="Para ouvir novamente estas opções..." filename="ivr-to_repeat_these_options.wav"/>
<prompt phrase="Para voltar ao menu anterior..." filename="ivr-to_return_to_previous_menu.wav"/>
<prompt phrase="Para falar com um operador..." filename="ivr-to_speak_with_an_operator.wav"/>
<prompt phrase="Bem-vindo a FreeSWITCH, o futuro da telefonia." filename="ivr-welcome_to_freeswitch.wav"/>
<prompt phrase="Você pode sair a qualquer altura, simplesmente terminando a chamada." filename="ivr-you_may_exit_by_hanging_up.wav"/>
<prompt phrase="ou" filename ="ivr-or.wav"/>
<prompt phrase="não" filename ="ivr-not.wav"/>
<prompt phrase="chamada" filename ="ivr-call.wav"/>
<prompt phrase="Você pode" filename ="ivr-you_may.wav"/>
<prompt phrase="Olá" filename="ivr-hello.wav"/>
<prompt phrase="Usando as teclas do seu telefone..." filename="ivr-use_telephone_keypad.wav"/>
<prompt phrase="Por favor soletre o nome da pessoa que você pretente contactar." filename="ivr-spell_name.wav"/>
<prompt phrase="Último nome primeiro" filename="ivr-last_name_first.wav"/>
<prompt phrase="Primeiro nome primeiro" filename="ivr-first_name_first.wav"/>
<prompt phrase="Marque 1 para Q ou Z." filename="ivr-press_one_q_or_z.wav"/>
<prompt phrase="Vendas" filename="ivr-sales.wav"/>
<prompt phrase="Apoio a clientes" filename="ivr-customer_service.wav"/>
<prompt phrase="Suporte técnico" filename="ivr-technical_support.wav"/>
<prompt phrase="Operador" filename="ivr-operator.wav"/>
<prompt phrase="Você marcou uma extensão inválida." filename="ivr-you_have_dialed_an_invalid_extension.wav"/>
<prompt phrase="Por favor marque a sua extensão, seguida de cardinal." filename="ivr-please_enter_extension_followed_by_pound.wav"/>
<prompt phrase="Por favor marque o seu número PIN, seguido de cardinal." filename="ivr-please_enter_pin_followed_by_pound.wav"/>
<prompt phrase="O seu número PIN ou extensão é inválido." filename="ivr-pin_or_extension_is-invalid.wav"/>
<prompt phrase="Você está a ponto de associar este telefone à sua conta..." filename="ivr-you_are_about_to_provision_this_phone.wav"/>
<prompt phrase="Por favor marque novamente o seu número PIN para confirmar." filename="ivr-please_reenter_your_pin.wav"/>
<prompt phrase="Para registar em ClueCon, por favor marque..." filename="ivr-register_for_cluecon.wav"/>
<prompt phrase="Para conectar..." filename="ivr-to_log_in.wav"/>
<prompt phrase="Para desconectar..." filename="ivr-to_log_out.wav"/>
<prompt phrase="Você está agora conectado." filename="ivr-you_are_now_logged_in.wav"/>
<prompt phrase="Você está agora desconectado." filename="ivr-you_are_now_logged_out.wav"/>
<prompt phrase="Por favor tente novamente." filename="ivr-please_try_again.wav"/>
<prompt phrase="Você está a ponto de associar permanentemente este telefone à sua extensão." filename="ivr-provision_phone_permanently_to_extension.wav"/>
<prompt phrase="Por favor marque o número da extensão à qual pretende associar este telefone, seguido de cardinal." filename="ivr-extension_to_provision_this_phone.wav"/>
<prompt phrase="Obrigado, este telefone irá agora ser reiniciado." filename="ivr-this_phone_will_now_reboot.wav"/>
<prompt phrase="Obrigado. A sua gravação foi guardada." filename="ivr-recording_saved.wav"/>
<prompt phrase="Marque 1 para guardar a sua gravação. Marque 2 para ouvir a sua gravação. Marque 3 para gravar novamente." filename="ivr-save_review_record.wav"/>
<prompt phrase="Neste momento o sistema é incapaz de guardar o seu ficheiro de som. Por favor tente novamente mais tarde." filename="ivr-unable_save.wav"/>
<prompt phrase="Você é o número" filename="ivr-you_are_number.wav"/>
<prompt phrase="...em linha" filename="ivr-in_line.wav"/>
<prompt phrase="Obrigado por aguardar." filename="ivr-thank_you_for_holding.wav"/>
<prompt phrase="O seu tempo estimado de espera é..." filename="ivr-estimated_hold_time.wav"/>
<prompt phrase="Mais de..." filename="ivr-more_than.wav"/>
<prompt phrase="Menos de..." filename="ivr-less_than.wav"/>
<prompt phrase="Iniciar gravação." filename="ivr-begin_recording.wav "/>
<prompt phrase="O encaminhamento da chamada foi cancelado." filename="ivr-call_forwarding_has_been_cancelled.wav"/>
<prompt phrase="O encaminhamento da chamada foi activado." filename="ivr-call_forwarding_has_been_set.wav"/>
<prompt phrase="Por favor, introduza o número de telefone." filename="ivr-please_enter_the_phone_number.wav"/>
<prompt phrase="Por favor, deixe o seu nome e o motivo da sua chamada." filename="ivr-please_state_your_name_and_reason_for_calling.wav"/>
<prompt phrase="Para aceitar, marque 1. Para rejeitar, marque 2. Para enviar para o correio de voz, marque 3." filename="ivr-accept_reject_voicemail.wav"/>
<prompt phrase="Entrada de chamada." filename="ivr-incoming_call.wav"/>
<prompt phrase="Obrigado pela sua chamada." filename="ivr-thank_you_for_calling.wav"/>
<prompt phrase="Por favor permaneça em linha. A sua chamada será atendida brevemente." filename="ivr-stay_on_line_call_answered_momentarily.wav"/>
<prompt phrase="A sua chamada está a ser transferida." filename="ivr-call_being_transferred.wav"/>
<prompt phrase="Por favor, desfrute da música enquanto a sua chamada é transferida." filename="ivr-enjoy_music_while_transfer.wav"/>
<prompt phrase="Você tem uma chamada de..." filename="ivr-call_from.wav"/>
<prompt phrase="Este menú não tem opções. Por favor entre em contacto com o administrador." filename="ivr-no_menu_items.wav"/>
<prompt phrase="Para directório, marque..." filename="ivr-for_directory_press.wav"/>
<prompt phrase="Usando o teclado do seu telefone..." filename="ivr-using_telephone_keypad.wav"/>
<prompt phrase="Introduza as primeiras letras do último nome da pessoa." filename="ivr-enter_letters_last_name.wav"/>
<prompt phrase="Introduza as primeiras letras do primeiro nome da pessoa." filename="ivr-enter_letters_first_name.wav"/>
<prompt phrase="Introduza as primeiras letras do primeiro ou último nome da pessoa." filename="ivr-enter_letters_first_or_last_name.wav"/>
<prompt phrase="Se isto é correcto, marque..." filename="ivr-if_correct_press.wav"/>
<prompt phrase="Se não, marque..." filename="ivr-if_not_press.wav"/>
<prompt phrase="Quando terminar, marque cardinal." filename="ivr-finished_pound_hash_key.wav"/>
<prompt phrase="O modo Não Incomodar está agora activado." filename="ivr-dnd_activated.wav"/>
<prompt phrase="O modo Não Incomodar foi desactivado." filename="ivr-dnd_cancelled.wav"/>
<prompt phrase="Marque qualquer outro dígito..." filename="ivr-any_other_digit.wav"/>
<prompt phrase="Marque um para sim. Marque dois para não." filename="ivr-one_yes_two_no.wav"/>
<prompt phrase="Por favor marque o número da fila, seguido de cardinal." filename="ivr-enter_queue_number.wav"/>
<prompt phrase="Por favor marque o..." filename="ivr-please_enter_the.wav"/>
<prompt phrase="Número." filename="ivr-number.wav"/>
<prompt phrase="...seguido de cardinal." filename="ivr-followed_by_pound.wav"/>
<prompt phrase="O saldo da conta é..." filename="ivr-account_balance_is.wav"/>
<prompt phrase="Obrigado por telefonar. Se conhece a extensão do destinatário, por favor marque-a agora. Para ir para o directório, marque..." filename="ivr-generic_greeting.wav"/>
<prompt phrase="...ficheiro..." filename="ivr-file.wav"/>
<prompt phrase="...ficheiros..." filename="ivr-files-.wav"/>
<prompt phrase="Para uma chamada de despertar..." filename="ivr-for_a_wakeup_call.wav"/>
<prompt phrase="Esta é a sua chamada de despertar." filename="ivr-this_is_your_wakeup_call.wav"/>
<prompt phrase="Para solicitar uma chamada de despertar..." filename="ivr-request_wakeup_call.wav"/>
<prompt phrase="Para confirmar uma chamada de despertar..." filename="ivr-confirm_wakeup_call.wav"/>
<prompt phrase="Para cancelar uma chamada de despertar..." filename="ivr-cancel_wakeup_call.wav"/>
<prompt phrase="Você solicitou uma chamada de despertar..." filename="ivr-requested_wakeup_call_for.wav"/>
<prompt phrase="Você não solicitou uma chamada de despertar." filename="ivr-not_requested_wakeup_call.wav"/>
<prompt phrase="A sua chamada de despertar foi cancelada." filename="ivr-wakeup_call_cancelled.wav"/>
<prompt phrase="Para uma chamada de despertar por dia..." filename="ivr-for_daily_wakeup_call.wav"/>
<prompt phrase="Chamada de despertar diária..." filename="ivr-daily_wakeup_call.wav"/>
<prompt phrase="Para chamadas de despertar diárias..." filename="ivr-for_daily_wakeup_calls.wav"/>
<prompt phrase="Para apenas uma chamada de despertar..." filename="ivr-for_one_time_wakeup_call.wav"/>
<prompt phrase="Apenas uma chamada de despertar..." filename="ivr-one_time_wakeup_call.wav"/>
<prompt phrase="...chamada de despertar..." filename="ivr-wakeup_call.wav"/>
<prompt phrase="Acorda! Acorda raio de sol!!" filename="ivr-wakey_wakey_sunshine.wav"/>
<prompt phrase="Bem-vindo." filename="ivr-welcome.wav"/>
<prompt phrase="Bem-vindo a..." filename="ivr-welcome_to.wav"/>
<prompt phrase="Bom dia." filename="ivr-good_morning.wav"/>
<prompt phrase="Boa tarde." filename="ivr-good_afternoon.wav"/>
<prompt phrase="Boa noite." filename="ivr-good_evening.wav"/>
<prompt phrase="Obrigado." filename="ivr-Thank_you.wav"/>
<prompt phrase="Para..." filename="ivr-for.wav"/>
<prompt phrase="Estamos a observar tempos de espera superiores ao normal." filename="ivr-longer_than_usual_hold_times.wav"/>
<prompt phrase="Você é o..." filename="ivr-you_are_the.wav"/>
<prompt phrase="Um momento por favor." filename="ivr-one_moment_please.wav"/>
<prompt phrase="A sua chamada será atendida pela ordem que foi recebida." filename="ivr-call_answered_order_received.wav"/>
<prompt phrase="Por favor marque o número da conferência, seguido de cardinal" filename="conf-enter_conf_number.wav"/>
<prompt phrase="Introduza o número PIN da conferência, seguido de cardinal." filename="conf-enter_conf_pin.wav"/>
<prompt phrase="...entrou na conferência." filename="conf-has_joined.wav"/>
<prompt phrase="...abandonou a conferência." filename="conf-has_left.wav"/>
<prompt phrase="Você entrou..." filename="ivr-you_entered.wav"/>
<prompt phrase="Número da extensão..." filename="ivr-extension_number.wav"/>
<prompt phrase="Por favor aguarde enquanto contactamos com o destinatário." filename="ivr-please_hold_while_party_contacted.wav"/>
<prompt phrase="Por favor desfrute da música enquanto contactamos com o destinatário." filename="ivr-please_enjoy_music_while_party_reached.wav"/>
<prompt phrase="Obrigado por telefonar. Se conhece a extensão do destinatário, marque-a agora, ou marque nove para ir para o directório." filename="ivr-generic_greeting.wav"/>
<prompt phrase="Se isto é correcto, marque 1. Se não é correcto, marque 2." filename="ivr-if_correct_one_if_not_two.wav"/>
<prompt phrase="Para ouvir novamente esta informação.." filename="ivr-repeat_this_information.wav"/>
<prompt phrase="Não não não!" filename="ivr-no_no_no.wav"/>
<prompt phrase="Você pretendia marcar esta tecla?" filename="ivr-did_you_mean_to_press_key.wav"/>
<prompt phrase="A sério? Pretendia MESMO marcar esta tecla?" filename="ivr-seriously_mean_to_press_key.wav"/>
<prompt phrase="Oh, tanto faz." filename="ivr-oh_whatever.wav"/>
<prompt phrase="Já chega! Um erro mais e desligo a chamada." filename="ivr-one_more_mistake.wav"/>
<prompt phrase="Felicidades, você pressionou estrela. Isto não significa que você é uma estrela. Apenas significa que pode pressionar teclas e que provavelmente tem dedos." filename="ivr-congratulations_you_pressed_star.wav"/>
<prompt phrase="Todos os nossos engenheiros estão ocupados demonstrando como é impressionante CudaTel." filename="ivr-engineers_busy_assisting_other_sales.wav"/>
<prompt phrase="O destino que deseja contactar não está disponível e não tem correio de voz." filename="vm-not_available_no_voicemail.wav"/>
<prompt phrase="Esta mensagem vai autodestruir-se em 5, 4, 3, 2, 1..." filename="ivr-message_self_destruct.wav"/>
<prompt phrase="Você já está em silêncio." filename="conf-you_are_already_muted.wav"/>
<prompt phrase="Você está agora em silêncio em ambos sentidos." filename="conf-you_are_now_bidirectionally_muted.wav"/>
<prompt phrase="Todas as suas chamadas pertencem-nos." filename="ivr-all_your_call_are_belong_to_us.wav"/>
<prompt phrase="Adoro a forma como você pressiona as teclas!" filename="ivr-love_those_touch_tones.wav"/>
<prompt phrase="Sim, nós não temos bananas." filename="ivr-yes_we_have_no_bananas.wav"/>
<prompt phrase="Homem, você está a ser ridículo!" filename="ivr-dude_you_suck.wav"/>
<prompt phrase="A sua chamada é muito importante para nós, mas a sua saúde mental não, então estamos felizes por mantê-lo em espera, torturando-o com a irritante música em espera." filename="ivr-on_hold_indefinitely.wav"/>
<prompt phrase="...deixou o edifício." filename="ivr-has_left_the_building.wav"/>
<prompt phrase="Este telefone não está associado e não pode realizar chamadas externas." filename="ivr-phone_is_unassigned.wav"/>
<prompt phrase="Este telefone não está configurado correctamente." filename="ivr-phone_not_configured.wav"/>
<prompt phrase="Parabéns! Este telefone está configurado correctamente e pode agora ser associado a um utilizador." filename="ivr-phone_is_configured_properly.wav"/>
<prompt phrase="Por favor contacte o administrador do sistema para assistência." filename="ivr-contact_system_administrator.wav"/>
<prompt phrase="Barracuda Networks" filename="ivr-barracuda_networks.wav"/>
<prompt phrase="CudaTel Communication Server" filename="ivr-cudatel_communication_server.wav"/>
<prompt phrase="Por favor, introduza as primeiras letras do primeiro ou último nome da pessoa" filename="dir-enter_person_first_or_last.wav"/>
<prompt phrase="Não há mais chamadas á espera nesta fila." filename="ivr-no_calls_waiting_in_queue.wav"/>
<prompt phrase="Brian West" filename="misc-Brian_West.wav"/>
<prompt phrase="Anthony Minessale" filename="misc-Anthony_Minessale.wav"/>
<prompt phrase="Michael Jerris" filename="misc-Michael_Jerris.wav"/>
<prompt phrase="Raymond Chandler" filename="misc-Raymond_Chandler.wav"/>
<prompt phrase="Michael Collins" filename="misc-Michael_Collins.wav"/>
<prompt phrase="Mark Mann" filename="misc-Mark_Mann.wav"/>
<prompt phrase="William King" filename="misc-William_King.wav"/>
<prompt phrase="Rudy Fleminger" filename="misc-Rudy_Fleminger.wav"/>
<prompt phrase="Andrew Thompson" filename="misc-Andrew_Thompson.wav"/>
<prompt phrase="Graham Saathoff" filename="misc-Graham_Saathoff.wav"/>
<prompt phrase="Nicholaus Belluni" filename="misc-Nicholaus_Belluni.wav"/>
<prompt phrase="Sean Heiney" filename="misc-Sean_Heiney.wav"/>
</ivr>
<misc>
<prompt phrase="Foi activada a segurança para esta chamada." filename="call_secured.wav"/>
<prompt phrase="...seguido de cardinal." filename="followed.wav"/>
<prompt phrase="Se você é esta pessoa..." filename="if_you_are_this_person.wav"/>
<prompt phrase="Se você deseja..." filename="if_you_would_like_to.wav"/>
<prompt phrase="Forneça o número de referência" filename="provide_reference_number.wav"/>
<prompt phrase="Por favor, introduza a extensão para a qual pretende transferir." filename="transfer1.wav"/>
<prompt phrase="Transferir" filename="transfer2.wav"/>
<prompt phrase="Estamos a tentar contactar..." filename="we_are_trying_to_reach.wav"/>
<prompt phrase="Ocorreu um erro, por favor entre em contacto com o administrador." filename="error.wav"/>
<prompt phrase="A sua chamada irá terminar em..." filename="misc-your_call_will_be_terminated_in.wav"/>
<prompt phrase="A sua chamada foi concluída." filename="misc-your_call_has_been_terminated.wav"/>
</misc>
<zrtp>
<!-- base256 prompts for SAS -->
<prompt phrase="Algol" filename="Algol.wav"/>
<prompt phrase="Apollo" filename="Apollo.wav"/>
<prompt phrase="Athens" filename="Athens.wav"/>
<prompt phrase="Atlantic" filename="Atlantic.wav"/>
<prompt phrase="Aztec" filename="Aztec.wav"/>
<prompt phrase="Babylon" filename="Babylon.wav"/>
<prompt phrase="Belfast" filename="Belfast.wav"/>
<prompt phrase="Bradbury" filename="Bradbury.wav"/>
<prompt phrase="Brazilian" filename="Brazilian.wav"/>
<prompt phrase="Burbank" filename="Burbank.wav"/>
<prompt phrase="Burlington" filename="Burlington.wav"/>
<prompt phrase="Camelot" filename="Camelot.wav"/>
<prompt phrase="Capricorn" filename="Capricorn.wav"/>
<prompt phrase="Cherokee" filename="Cherokee.wav"/>
<prompt phrase="Chicago" filename="Chicago.wav"/>
<prompt phrase="Christmas" filename="Christmas.wav"/>
<prompt phrase="Dakota" filename="Dakota.wav"/>
<prompt phrase="December" filename="December.wav"/>
<prompt phrase="Dupont" filename="Dupont.wav"/>
<prompt phrase="Eskimo" filename="Eskimo.wav"/>
<prompt phrase="Galveston" filename="Galveston.wav"/>
<prompt phrase="Geiger" filename="Geiger.wav"/>
<prompt phrase="Hamilton" filename="Hamilton.wav"/>
<prompt phrase="Istanbul" filename="Istanbul.wav"/>
<prompt phrase="Jamaica" filename="Jamaica.wav"/>
<prompt phrase="Jupiter" filename="Jupiter.wav"/>
<prompt phrase="Medusa" filename="Medusa.wav"/>
<prompt phrase="Mohawk" filename="Mohawk.wav"/>
<prompt phrase="Montana" filename="Montana.wav"/>
<prompt phrase="Neptune" filename="Neptune.wav"/>
<prompt phrase="Norwegian" filename="Norwegian.wav"/>
<prompt phrase="Oakland" filename="Oakland.wav"/>
<prompt phrase="October" filename="October.wav"/>
<prompt phrase="Ohio" filename="Ohio.wav"/>
<prompt phrase="Orlando" filename="Orlando.wav"/>
<prompt phrase="Pacific" filename="Pacific.wav"/>
<prompt phrase="Pandora" filename="Pandora.wav"/>
<prompt phrase="Pegasus" filename="Pegasus.wav"/>
<prompt phrase="Pluto" filename="Pluto.wav"/>
<prompt phrase="Saturday" filename="Saturday.wav"/>
<prompt phrase="Scotland" filename="Scotland.wav"/>
<prompt phrase="Trojan" filename="Trojan.wav"/>
<prompt phrase="Virginia" filename="Virginia.wav"/>
<prompt phrase="Vulcan" filename="Vulcan.wav"/>
<prompt phrase="Waterloo" filename="Waterloo.wav"/>
<prompt phrase="Wichita" filename="Wichita.wav"/>
<prompt phrase="Wilmington" filename="Wilmington.wav"/>
<prompt phrase="Wyoming" filename="Wyoming.wav"/>
<prompt phrase="Yucatan" filename="Yucatan.wav"/>
<prompt phrase="Zulu" filename="Zulu.wav"/>
<prompt phrase="aardvark" filename="aardvark.wav"/>
<prompt phrase="absurd" filename="absurd.wav"/>
<prompt phrase="accrue" filename="accrue.wav"/>
<prompt phrase="acme" filename="acme.wav"/>
<prompt phrase="adrift" filename="adrift.wav"/>
<prompt phrase="adroitness" filename="adroitness.wav"/>
<prompt phrase="adult" filename="adult.wav"/>
<prompt phrase="adviser" filename="adviser.wav"/>
<prompt phrase="afflict" filename="afflict.wav"/>
<prompt phrase="aftermath" filename="aftermath.wav"/>
<prompt phrase="aggregate" filename="aggregate.wav"/>
<prompt phrase="ahead" filename="ahead.wav"/>
<prompt phrase="aimless" filename="aimless.wav"/>
<prompt phrase="alkali" filename="alkali.wav"/>
<prompt phrase="allow" filename="allow.wav"/>
<prompt phrase="almighty" filename="almighty.wav"/>
<prompt phrase="alone" filename="alone.wav"/>
<prompt phrase="ammo" filename="ammo.wav"/>
<prompt phrase="amulet" filename="amulet.wav"/>
<prompt phrase="amusement" filename="amusement.wav"/>
<prompt phrase="ancient" filename="ancient.wav"/>
<prompt phrase="antenna" filename="antenna.wav"/>
<prompt phrase="apple" filename="apple.wav"/>
<prompt phrase="applicant" filename="applicant.wav"/>
<prompt phrase="armistice" filename="armistice.wav"/>
<prompt phrase="article" filename="article.wav"/>
<prompt phrase="artist" filename="artist.wav"/>
<prompt phrase="assume" filename="assume.wav"/>
<prompt phrase="asteroid" filename="asteroid.wav"/>
<prompt phrase="atlas" filename="atlas.wav"/>
<prompt phrase="atmosphere" filename="atmosphere.wav"/>
<prompt phrase="autopsy" filename="autopsy.wav"/>
<prompt phrase="baboon" filename="baboon.wav"/>
<prompt phrase="backfield" filename="backfield.wav"/>
<prompt phrase="backward" filename="backward.wav"/>
<prompt phrase="backwater" filename="backwater.wav"/>
<prompt phrase="banjo" filename="banjo.wav"/>
<prompt phrase="barbecue" filename="barbecue.wav"/>
<prompt phrase="beaming" filename="beaming.wav"/>
<prompt phrase="bedlamp" filename="bedlamp.wav"/>
<prompt phrase="beehive" filename="beehive.wav"/>
<prompt phrase="beeswax" filename="beeswax.wav"/>
<prompt phrase="befriend" filename="befriend.wav"/>
<prompt phrase="belowground" filename="belowground.wav"/>
<prompt phrase="berserk" filename="berserk.wav"/>
<prompt phrase="bifocals" filename="bifocals.wav"/>
<prompt phrase="billiard" filename="billiard.wav"/>
<prompt phrase="bison" filename="bison.wav"/>
<prompt phrase="blackjack" filename="blackjack.wav"/>
<prompt phrase="blockade" filename="blockade.wav"/>
<prompt phrase="blowtorch" filename="blowtorch.wav"/>
<prompt phrase="bluebird" filename="bluebird.wav"/>
<prompt phrase="bodyguard" filename="bodyguard.wav"/>
<prompt phrase="bombast" filename="bombast.wav"/>
<prompt phrase="bookseller" filename="bookseller.wav"/>
<prompt phrase="bookshelf" filename="bookshelf.wav"/>
<prompt phrase="borderline" filename="borderline.wav"/>
<prompt phrase="bottomless" filename="bottomless.wav"/>
<prompt phrase="brackish" filename="brackish.wav"/>
<prompt phrase="bravado" filename="bravado.wav"/>
<prompt phrase="breadline" filename="breadline.wav"/>
<prompt phrase="breakaway" filename="breakaway.wav"/>
<prompt phrase="breakup" filename="breakup.wav"/>
<prompt phrase="brickyard" filename="brickyard.wav"/>
<prompt phrase="briefcase" filename="briefcase.wav"/>
<prompt phrase="businessman" filename="businessman.wav"/>
<prompt phrase="butterfat" filename="butterfat.wav"/>
<prompt phrase="button" filename="button.wav"/>
<prompt phrase="buzzard" filename="buzzard.wav"/>
<prompt phrase="candidate" filename="candidate.wav"/>
<prompt phrase="cannonball" filename="cannonball.wav"/>
<prompt phrase="caravan" filename="caravan.wav"/>
<prompt phrase="caretaker" filename="caretaker.wav"/>
<prompt phrase="celebrate" filename="celebrate.wav"/>
<prompt phrase="cellulose" filename="cellulose.wav"/>
<prompt phrase="cement" filename="cement.wav"/>
<prompt phrase="certify" filename="certify.wav"/>
<prompt phrase="chairlift" filename="chairlift.wav"/>
<prompt phrase="chambermaid" filename="chambermaid.wav"/>
<prompt phrase="chatter" filename="chatter.wav"/>
<prompt phrase="checkup" filename="checkup.wav"/>
<prompt phrase="chisel" filename="chisel.wav"/>
<prompt phrase="choking" filename="choking.wav"/>
<prompt phrase="chopper" filename="chopper.wav"/>
<prompt phrase="clamshell" filename="clamshell.wav"/>
<prompt phrase="classic" filename="classic.wav"/>
<prompt phrase="classroom" filename="classroom.wav"/>
<prompt phrase="cleanup" filename="cleanup.wav"/>
<prompt phrase="clergyman" filename="clergyman.wav"/>
<prompt phrase="clockwork" filename="clockwork.wav"/>
<prompt phrase="cobra" filename="cobra.wav"/>
<prompt phrase="coherence" filename="coherence.wav"/>
<prompt phrase="combustion" filename="combustion.wav"/>
<prompt phrase="commando" filename="commando.wav"/>
<prompt phrase="commence" filename="commence.wav"/>
<prompt phrase="company" filename="company.wav"/>
<prompt phrase="component" filename="component.wav"/>
<prompt phrase="concert" filename="concert.wav"/>
<prompt phrase="concurrent" filename="concurrent.wav"/>
<prompt phrase="confidence" filename="confidence.wav"/>
<prompt phrase="conformist" filename="conformist.wav"/>
<prompt phrase="congregate" filename="congregate.wav"/>
<prompt phrase="consensus" filename="consensus.wav"/>
<prompt phrase="consulting" filename="consulting.wav"/>
<prompt phrase="corporate" filename="corporate.wav"/>
<prompt phrase="corrosion" filename="corrosion.wav"/>
<prompt phrase="councilman" filename="councilman.wav"/>
<prompt phrase="cowbell" filename="cowbell.wav"/>
<prompt phrase="crackdown" filename="crackdown.wav"/>
<prompt phrase="cranky" filename="cranky.wav"/>
<prompt phrase="crossover" filename="crossover.wav"/>
<prompt phrase="crowfoot" filename="crowfoot.wav"/>
<prompt phrase="crucial" filename="crucial.wav"/>
<prompt phrase="crucifix" filename="crucifix.wav"/>
<prompt phrase="crumpled" filename="crumpled.wav"/>
<prompt phrase="crusade" filename="crusade.wav"/>
<prompt phrase="cubic" filename="cubic.wav"/>
<prompt phrase="cumbersome" filename="cumbersome.wav"/>
<prompt phrase="customer" filename="customer.wav"/>
<prompt phrase="dashboard" filename="dashboard.wav"/>
<prompt phrase="deadbolt" filename="deadbolt.wav"/>
<prompt phrase="decadence" filename="decadence.wav"/>
<prompt phrase="decimal" filename="decimal.wav"/>
<prompt phrase="deckhand" filename="deckhand.wav"/>
<prompt phrase="designing" filename="designing.wav"/>
<prompt phrase="detector" filename="detector.wav"/>
<prompt phrase="detergent" filename="detergent.wav"/>
<prompt phrase="determine" filename="determine.wav"/>
<prompt phrase="dictator" filename="dictator.wav"/>
<prompt phrase="dinosaur" filename="dinosaur.wav"/>
<prompt phrase="direction" filename="direction.wav"/>
<prompt phrase="disable" filename="disable.wav"/>
<prompt phrase="disbelief" filename="disbelief.wav"/>
<prompt phrase="disruptive" filename="disruptive.wav"/>
<prompt phrase="distortion" filename="distortion.wav"/>
<prompt phrase="document" filename="document.wav"/>
<prompt phrase="dogsled" filename="dogsled.wav"/>
<prompt phrase="dragnet" filename="dragnet.wav"/>
<prompt phrase="drainage" filename="drainage.wav"/>
<prompt phrase="dreadful" filename="dreadful.wav"/>
<prompt phrase="drifter" filename="drifter.wav"/>
<prompt phrase="dropper" filename="dropper.wav"/>
<prompt phrase="drumbeat" filename="drumbeat.wav"/>
<prompt phrase="drunken" filename="drunken.wav"/>
<prompt phrase="dwelling" filename="dwelling.wav"/>
<prompt phrase="eating" filename="eating.wav"/>
<prompt phrase="edict" filename="edict.wav"/>
<prompt phrase="egghead" filename="egghead.wav"/>
<prompt phrase="eightball" filename="eightball.wav"/>
<prompt phrase="embezzle" filename="embezzle.wav"/>
<prompt phrase="enchanting" filename="enchanting.wav"/>
<prompt phrase="endorse" filename="endorse.wav"/>
<prompt phrase="endow" filename="endow.wav"/>
<prompt phrase="enlist" filename="enlist.wav"/>
<prompt phrase="enrollment" filename="enrollment.wav"/>
<prompt phrase="enterprise" filename="enterprise.wav"/>
<prompt phrase="equation" filename="equation.wav"/>
<prompt phrase="equipment" filename="equipment.wav"/>
<prompt phrase="erase" filename="erase.wav"/>
<prompt phrase="escapade" filename="escapade.wav"/>
<prompt phrase="escape" filename="escape.wav"/>
<prompt phrase="everyday" filename="everyday.wav"/>
<prompt phrase="examine" filename="examine.wav"/>
<prompt phrase="exceed" filename="exceed.wav"/>
<prompt phrase="existence" filename="existence.wav"/>
<prompt phrase="exodus" filename="exodus.wav"/>
<prompt phrase="eyeglass" filename="eyeglass.wav"/>
<prompt phrase="eyetooth" filename="eyetooth.wav"/>
<prompt phrase="facial" filename="facial.wav"/>
<prompt phrase="fallout" filename="fallout.wav"/>
<prompt phrase="fascinate" filename="fascinate.wav"/>
<prompt phrase="filament" filename="filament.wav"/>
<prompt phrase="finicky" filename="finicky.wav"/>
<prompt phrase="flagpole" filename="flagpole.wav"/>
<prompt phrase="flatfoot" filename="flatfoot.wav"/>
<prompt phrase="flytrap" filename="flytrap.wav"/>
<prompt phrase="forever" filename="forever.wav"/>
<prompt phrase="fortitude" filename="fortitude.wav"/>
<prompt phrase="fracture" filename="fracture.wav"/>
<prompt phrase="framework" filename="framework.wav"/>
<prompt phrase="freedom" filename="freedom.wav"/>
<prompt phrase="frequency" filename="frequency.wav"/>
<prompt phrase="frighten" filename="frighten.wav"/>
<prompt phrase="gadgetry" filename="gadgetry.wav"/>
<prompt phrase="gazelle" filename="gazelle.wav"/>
<prompt phrase="getaway" filename="getaway.wav"/>
<prompt phrase="glitter" filename="glitter.wav"/>
<prompt phrase="glossary" filename="glossary.wav"/>
<prompt phrase="glucose" filename="glucose.wav"/>
<prompt phrase="goggles" filename="goggles.wav"/>
<prompt phrase="goldfish" filename="goldfish.wav"/>
<prompt phrase="gossamer" filename="gossamer.wav"/>
<prompt phrase="graduate" filename="graduate.wav"/>
<prompt phrase="gravity" filename="gravity.wav"/>
<prompt phrase="gremlin" filename="gremlin.wav"/>
<prompt phrase="guidance" filename="guidance.wav"/>
<prompt phrase="guitarist" filename="guitarist.wav"/>
<prompt phrase="hamburger" filename="hamburger.wav"/>
<prompt phrase="hamlet" filename="hamlet.wav"/>
<prompt phrase="handiwork" filename="handiwork.wav"/>
<prompt phrase="hazardous" filename="hazardous.wav"/>
<prompt phrase="headwaters" filename="headwaters.wav"/>
<prompt phrase="hemisphere" filename="hemisphere.wav"/>
<prompt phrase="hesitate" filename="hesitate.wav"/>
<prompt phrase="hideaway" filename="hideaway.wav"/>
<prompt phrase="highchair" filename="highchair.wav"/>
<prompt phrase="hockey" filename="hockey.wav"/>
<prompt phrase="holiness" filename="holiness.wav"/>
<prompt phrase="hurricane" filename="hurricane.wav"/>
<prompt phrase="hydraulic" filename="hydraulic.wav"/>
<prompt phrase="impartial" filename="impartial.wav"/>
<prompt phrase="impetus" filename="impetus.wav"/>
<prompt phrase="inception" filename="inception.wav"/>
<prompt phrase="indigo" filename="indigo.wav"/>
<prompt phrase="indoors" filename="indoors.wav"/>
<prompt phrase="indulge" filename="indulge.wav"/>
<prompt phrase="inertia" filename="inertia.wav"/>
<prompt phrase="infancy" filename="infancy.wav"/>
<prompt phrase="inferno" filename="inferno.wav"/>
<prompt phrase="informant" filename="informant.wav"/>
<prompt phrase="insincere" filename="insincere.wav"/>
<prompt phrase="insurgent" filename="insurgent.wav"/>
<prompt phrase="integrate" filename="integrate.wav"/>
<prompt phrase="intention" filename="intention.wav"/>
<prompt phrase="inventive" filename="inventive.wav"/>
<prompt phrase="inverse" filename="inverse.wav"/>
<prompt phrase="involve" filename="involve.wav"/>
<prompt phrase="island" filename="island.wav"/>
<prompt phrase="jawbone" filename="jawbone.wav"/>
<prompt phrase="keyboard" filename="keyboard.wav"/>
<prompt phrase="kickoff" filename="kickoff.wav"/>
<prompt phrase="kiwi" filename="kiwi.wav"/>
<prompt phrase="klaxon" filename="klaxon.wav"/>
<prompt phrase="leprosy" filename="leprosy.wav"/>
<prompt phrase="letterhead" filename="letterhead.wav"/>
<prompt phrase="liberty" filename="liberty.wav"/>
<prompt phrase="locale" filename="locale.wav"/>
<prompt phrase="lockup" filename="lockup.wav"/>
<prompt phrase="maritime" filename="maritime.wav"/>
<prompt phrase="matchmaker" filename="matchmaker.wav"/>
<prompt phrase="maverick" filename="maverick.wav"/>
<prompt phrase="megaton" filename="megaton.wav"/>
<prompt phrase="merit" filename="merit.wav"/>
<prompt phrase="microscope" filename="microscope.wav"/>
<prompt phrase="microwave" filename="microwave.wav"/>
<prompt phrase="midsummer" filename="midsummer.wav"/>
<prompt phrase="millionaire" filename="millionaire.wav"/>
<prompt phrase="minnow" filename="minnow.wav"/>
<prompt phrase="miracle" filename="miracle.wav"/>
<prompt phrase="miser" filename="miser.wav"/>
<prompt phrase="misnomer" filename="misnomer.wav"/>
<prompt phrase="molasses" filename="molasses.wav"/>
<prompt phrase="molecule" filename="molecule.wav"/>
<prompt phrase="monument" filename="monument.wav"/>
<prompt phrase="mosquito" filename="mosquito.wav"/>
<prompt phrase="mural" filename="mural.wav"/>
<prompt phrase="music" filename="music.wav"/>
<prompt phrase="narrative" filename="narrative.wav"/>
<prompt phrase="nebula" filename="nebula.wav"/>
<prompt phrase="necklace" filename="necklace.wav"/>
<prompt phrase="newborn" filename="newborn.wav"/>
<prompt phrase="newsletter" filename="newsletter.wav"/>
<prompt phrase="nightbird" filename="nightbird.wav"/>
<prompt phrase="obtuse" filename="obtuse.wav"/>
<prompt phrase="offload" filename="offload.wav"/>
<prompt phrase="onlooker" filename="onlooker.wav"/>
<prompt phrase="optic" filename="optic.wav"/>
<prompt phrase="opulent" filename="opulent.wav"/>
<prompt phrase="orca" filename="orca.wav"/>
<prompt phrase="outfielder" filename="outfielder.wav"/>
<prompt phrase="pandemic" filename="pandemic.wav"/>
<prompt phrase="paperweight" filename="paperweight.wav"/>
<prompt phrase="paragon" filename="paragon.wav"/>
<prompt phrase="paragraph" filename="paragraph.wav"/>
<prompt phrase="paramount" filename="paramount.wav"/>
<prompt phrase="passenger" filename="passenger.wav"/>
<prompt phrase="payday" filename="payday.wav"/>
<prompt phrase="peachy" filename="peachy.wav"/>
<prompt phrase="pedigree" filename="pedigree.wav"/>
<prompt phrase="penetrate" filename="penetrate.wav"/>
<prompt phrase="perceptive" filename="perceptive.wav"/>
<prompt phrase="performance" filename="performance.wav"/>
<prompt phrase="pharmacy" filename="pharmacy.wav"/>
<prompt phrase="pheasant" filename="pheasant.wav"/>
<prompt phrase="phonetic" filename="phonetic.wav"/>
<prompt phrase="photograph" filename="photograph.wav"/>
<prompt phrase="physique" filename="physique.wav"/>
<prompt phrase="pioneer" filename="pioneer.wav"/>
<prompt phrase="playhouse" filename="playhouse.wav"/>
<prompt phrase="pocketful" filename="pocketful.wav"/>
<prompt phrase="politeness" filename="politeness.wav"/>
<prompt phrase="positive" filename="positive.wav"/>
<prompt phrase="potato" filename="potato.wav"/>
<prompt phrase="preclude" filename="preclude.wav"/>
<prompt phrase="prefer" filename="prefer.wav"/>
<prompt phrase="preshrunk" filename="preshrunk.wav"/>
<prompt phrase="printer" filename="printer.wav"/>
<prompt phrase="processor" filename="processor.wav"/>
<prompt phrase="provincial" filename="provincial.wav"/>
<prompt phrase="prowler" filename="prowler.wav"/>
<prompt phrase="proximate" filename="proximate.wav"/>
<prompt phrase="puberty" filename="puberty.wav"/>
<prompt phrase="publisher" filename="publisher.wav"/>
<prompt phrase="pupil" filename="pupil.wav"/>
<prompt phrase="puppy" filename="puppy.wav"/>
<prompt phrase="pyramid" filename="pyramid.wav"/>
<prompt phrase="python" filename="python.wav"/>
<prompt phrase="quadrant" filename="quadrant.wav"/>
<prompt phrase="quantity" filename="quantity.wav"/>
<prompt phrase="quiver" filename="quiver.wav"/>
<prompt phrase="quota" filename="quota.wav"/>
<prompt phrase="racketeer" filename="racketeer.wav"/>
<prompt phrase="ragtime" filename="ragtime.wav"/>
<prompt phrase="ratchet" filename="ratchet.wav"/>
<prompt phrase="rebellion" filename="rebellion.wav"/>
<prompt phrase="rebirth" filename="rebirth.wav"/>
<prompt phrase="recipe" filename="recipe.wav"/>
<prompt phrase="recover" filename="recover.wav"/>
<prompt phrase="reform" filename="reform.wav"/>
<prompt phrase="regain" filename="regain.wav"/>
<prompt phrase="reindeer" filename="reindeer.wav"/>
<prompt phrase="rematch" filename="rematch.wav"/>
<prompt phrase="repay" filename="repay.wav"/>
<prompt phrase="repellent" filename="repellent.wav"/>
<prompt phrase="replica" filename="replica.wav"/>
<prompt phrase="reproduce" filename="reproduce.wav"/>
<prompt phrase="resistor" filename="resistor.wav"/>
<prompt phrase="responsive" filename="responsive.wav"/>
<prompt phrase="retouch" filename="retouch.wav"/>
<prompt phrase="retraction" filename="retraction.wav"/>
<prompt phrase="retrieval" filename="retrieval.wav"/>
<prompt phrase="retrospect" filename="retrospect.wav"/>
<prompt phrase="revenge" filename="revenge.wav"/>
<prompt phrase="revenue" filename="revenue.wav"/>
<prompt phrase="revival" filename="revival.wav"/>
<prompt phrase="revolver" filename="revolver.wav"/>
<prompt phrase="reward" filename="reward.wav"/>
<prompt phrase="rhythm" filename="rhythm.wav"/>
<prompt phrase="ribcage" filename="ribcage.wav"/>
<prompt phrase="ringbolt" filename="ringbolt.wav"/>
<prompt phrase="robust" filename="robust.wav"/>
<prompt phrase="rocker" filename="rocker.wav"/>
<prompt phrase="ruffled" filename="ruffled.wav"/>
<prompt phrase="sailboat" filename="sailboat.wav"/>
<prompt phrase="sandalwood" filename="sandalwood.wav"/>
<prompt phrase="sardonic" filename="sardonic.wav"/>
<prompt phrase="savagery" filename="savagery.wav"/>
<prompt phrase="sawdust" filename="sawdust.wav"/>
<prompt phrase="scallion" filename="scallion.wav"/>
<prompt phrase="scavenger" filename="scavenger.wav"/>
<prompt phrase="scenic" filename="scenic.wav"/>
<prompt phrase="scorecard" filename="scorecard.wav"/>
<prompt phrase="seabird" filename="seabird.wav"/>
<prompt phrase="select" filename="select.wav"/>
<prompt phrase="sensation" filename="sensation.wav"/>
<prompt phrase="sentence" filename="sentence.wav"/>
<prompt phrase="shadow" filename="shadow.wav"/>
<prompt phrase="shamrock" filename="shamrock.wav"/>
<prompt phrase="showgirl" filename="showgirl.wav"/>
<prompt phrase="skullcap" filename="skullcap.wav"/>
<prompt phrase="skydive" filename="skydive.wav"/>
<prompt phrase="slingshot" filename="slingshot.wav"/>
<prompt phrase="slowdown" filename="slowdown.wav"/>
<prompt phrase="snapline" filename="snapline.wav"/>
<prompt phrase="snapshot" filename="snapshot.wav"/>
<prompt phrase="snowcap" filename="snowcap.wav"/>
<prompt phrase="snowslide" filename="snowslide.wav"/>
<prompt phrase="sociable" filename="sociable.wav"/>
<prompt phrase="solo" filename="solo.wav"/>
<prompt phrase="southward" filename="southward.wav"/>
<prompt phrase="souvenir" filename="souvenir.wav"/>
<prompt phrase="soybean" filename="soybean.wav"/>
<prompt phrase="spaniel" filename="spaniel.wav"/>
<prompt phrase="spearhead" filename="spearhead.wav"/>
<prompt phrase="specialist" filename="specialist.wav"/>
<prompt phrase="speculate" filename="speculate.wav"/>
<prompt phrase="spellbind" filename="spellbind.wav"/>
<prompt phrase="spheroid" filename="spheroid.wav"/>
<prompt phrase="spigot" filename="spigot.wav"/>
<prompt phrase="spindle" filename="spindle.wav"/>
<prompt phrase="spyglass" filename="spyglass.wav"/>
<prompt phrase="stagehand" filename="stagehand.wav"/>
<prompt phrase="stagnate" filename="stagnate.wav"/>
<prompt phrase="stairway" filename="stairway.wav"/>
<prompt phrase="standard" filename="standard.wav"/>
<prompt phrase="stapler" filename="stapler.wav"/>
<prompt phrase="steamship" filename="steamship.wav"/>
<prompt phrase="sterling" filename="sterling.wav"/>
<prompt phrase="stethoscope" filename="stethoscope.wav"/>
<prompt phrase="stockman" filename="stockman.wav"/>
<prompt phrase="stopwatch" filename="stopwatch.wav"/>
<prompt phrase="stormy" filename="stormy.wav"/>
<prompt phrase="stupendous" filename="stupendous.wav"/>
<prompt phrase="sugar" filename="sugar.wav"/>
<prompt phrase="supportive" filename="supportive.wav"/>
<prompt phrase="surmount" filename="surmount.wav"/>
<prompt phrase="surrender" filename="surrender.wav"/>
<prompt phrase="suspense" filename="suspense.wav"/>
<prompt phrase="suspicious" filename="suspicious.wav"/>
<prompt phrase="sweatband" filename="sweatband.wav"/>
<prompt phrase="swelter" filename="swelter.wav"/>
<prompt phrase="sympathy" filename="sympathy.wav"/>
<prompt phrase="tactics" filename="tactics.wav"/>
<prompt phrase="talon" filename="talon.wav"/>
<prompt phrase="tambourine" filename="tambourine.wav"/>
<prompt phrase="tapeworm" filename="tapeworm.wav"/>
<prompt phrase="telephone" filename="telephone.wav"/>
<prompt phrase="tempest" filename="tempest.wav"/>
<prompt phrase="therapist" filename="therapist.wav"/>
<prompt phrase="tiger" filename="tiger.wav"/>
<prompt phrase="tissue" filename="tissue.wav"/>
<prompt phrase="tobacco" filename="tobacco.wav"/>
<prompt phrase="tolerance" filename="tolerance.wav"/>
<prompt phrase="tomorrow" filename="tomorrow.wav"/>
<prompt phrase="tonic" filename="tonic.wav"/>
<prompt phrase="topmost" filename="topmost.wav"/>
<prompt phrase="torpedo" filename="torpedo.wav"/>
<prompt phrase="tracker" filename="tracker.wav"/>
<prompt phrase="tradition" filename="tradition.wav"/>
<prompt phrase="transit" filename="transit.wav"/>
<prompt phrase="trauma" filename="trauma.wav"/>
<prompt phrase="travesty" filename="travesty.wav"/>
<prompt phrase="treadmill" filename="treadmill.wav"/>
<prompt phrase="trombonist" filename="trombonist.wav"/>
<prompt phrase="trouble" filename="trouble.wav"/>
<prompt phrase="truncated" filename="truncated.wav"/>
<prompt phrase="tumor" filename="tumor.wav"/>
<prompt phrase="tunnel" filename="tunnel.wav"/>
<prompt phrase="tycoon" filename="tycoon.wav"/>
<prompt phrase="typewriter" filename="typewriter.wav"/>
<prompt phrase="ultimate" filename="ultimate.wav"/>
<prompt phrase="uncut" filename="uncut.wav"/>
<prompt phrase="undaunted" filename="undaunted.wav"/>
<prompt phrase="underfoot" filename="underfoot.wav"/>
<prompt phrase="unearth" filename="unearth.wav"/>
<prompt phrase="unicorn" filename="unicorn.wav"/>
<prompt phrase="unify" filename="unify.wav"/>
<prompt phrase="universe" filename="universe.wav"/>
<prompt phrase="unravel" filename="unravel.wav"/>
<prompt phrase="unwind" filename="unwind.wav"/>
<prompt phrase="upcoming" filename="upcoming.wav"/>
<prompt phrase="uproot" filename="uproot.wav"/>
<prompt phrase="upset" filename="upset.wav"/>
<prompt phrase="upshot" filename="upshot.wav"/>
<prompt phrase="vacancy" filename="vacancy.wav"/>
<prompt phrase="vagabond" filename="vagabond.wav"/>
<prompt phrase="vapor" filename="vapor.wav"/>
<prompt phrase="vertigo" filename="vertigo.wav"/>
<prompt phrase="village" filename="village.wav"/>
<prompt phrase="virus" filename="virus.wav"/>
<prompt phrase="visitor" filename="visitor.wav"/>
<prompt phrase="vocalist" filename="vocalist.wav"/>
<prompt phrase="voyager" filename="voyager.wav"/>
<prompt phrase="waffle" filename="waffle.wav"/>
<prompt phrase="wallet" filename="wallet.wav"/>
<prompt phrase="warranty" filename="warranty.wav"/>
<prompt phrase="watchword" filename="watchword.wav"/>
<prompt phrase="wayside" filename="wayside.wav"/>
<prompt phrase="whimsical" filename="whimsical.wav"/>
<prompt phrase="willow" filename="willow.wav"/>
<prompt phrase="woodlark" filename="woodlark.wav"/>
<prompt phrase="yesteryear" filename="yesteryear.wav"/>
<!-- Event prompts -->
<prompt phrase="Bem-vindo ao agente de registo ZRTP." filename="zrtp-enroll_welcome.wav"/>
<prompt phrase="Deve verificar a chave de autenticação com destinatário. Se não for igual, indica a presença de uma escuta." filename="zrtp-check_sas.wav"/>
<prompt phrase="Apenas telefones que estão autenticados podem ser configurados para usarem este sistema de retransmissão ZRTP para chamadas com modo de segurança activo. Se o seu telefone não está autenticado com o sistema, esta chamada não terá qualquer efeito." filename="zrtp-enroll_not_sip_registered.wav"/>
<prompt phrase="O seu telefone indica que já confia neste sistema de retransmissão ZRTP para chamadas com o modo de segurança activo, portanto você já não precisa de fazer mais nada." filename="zrtp-enroll_already_enrolled.wav"/>
<prompt phrase="Apenas telefones equipados com o protocolo ZRTP podem usar esta extensão. O seu telefone não suporta ZRTP, portanto esta chamada não terá qualquer efeito." filename="zrtp-enroll_notzrtp.wav"/>
<prompt phrase="Este sistema está preparado para suportar chamadas encriptadas ZRTP. Você deve determinar se deseja permitir que o sistema possa interceptar ou gravar as suas chamadas telefónicas com o modo de segurança activado. Você pode desligar após confirmar este comportamento." filename="zrtp-enroll_confirmed.wav"/>
<prompt phrase="Comparando verbalmente o código desta autenticação com o destinatário." filename="zrtp-is_secure.wav"/>
<prompt phrase="O código de autenticação não foi verificado." filename="zrtp-is_unverified.wav"/>
<prompt phrase="O código de autenticação foi verificado." filename="zrtp-is_verified.wav"/>
<prompt phrase="Obrigado por telefonar. Até breve." filename="zrtp-thankyou_goodbye.wav"/>
<prompt phrase="Algo está errado" filename="zrtp-somethings_wrong.wav"/>
<prompt phrase="Erro." filename="zrtp-status_error.wav"/>
<prompt phrase="O modo de segurança não está activo na chamada." filename="zrtp-status_notsecure.wav"/>
<prompt phrase="O modo de segurança está activo na chamada." filename="zrtp-status_secure.wav"/>
<prompt phrase="Activando o modo de segurança na chamada." filename="zrtp-status_securing.wav"/>
</zrtp>
</pt_PT>
</language>

View File

@ -9,9 +9,9 @@ CXXFLAGS=$(BASE_FLAGS) -Wall -Werror -Wno-unused-variable
MYLIB=libesl.a
LIBS=-lncurses -lpthread -lesl -lm
LDFLAGS=-L.
OBJS=src/esl.o src/esl_event.o src/esl_threadmutex.o src/esl_config.o src/esl_json.o
SRC=src/esl.c src/esl_json.c src/esl_event.c src/esl_threadmutex.c src/esl_config.c src/esl_oop.cpp src/esl_json.c
HEADERS=src/include/esl_config.h src/include/esl_event.h src/include/esl.h src/include/esl_threadmutex.h src/include/esl_oop.h src/include/esl_json.h
OBJS=src/esl.o src/esl_event.o src/esl_threadmutex.o src/esl_config.o src/esl_json.o src/esl_buffer.o
SRC=src/esl.c src/esl_json.c src/esl_event.c src/esl_threadmutex.c src/esl_config.c src/esl_oop.cpp src/esl_json.c src/esl_buffer.c
HEADERS=src/include/esl_config.h src/include/esl_event.h src/include/esl.h src/include/esl_threadmutex.h src/include/esl_oop.h src/include/esl_json.h src/include/esl_buffer.h
SOLINK=-shared -Xlinker -x
# comment the next line to disable c++ (no swig mods for you then)
OBJS += src/esl_oop.o

View File

@ -290,6 +290,10 @@
RelativePath=".\esl.c"
>
</File>
<File
RelativePath=".\esl_buffer.c"
>
</File>
<File
RelativePath=".\esl_config.c"
>
@ -316,6 +320,10 @@
RelativePath=".\include\esl.h"
>
</File>
<File
RelativePath=".\include\esl_buffer.h"
>
</File>
<File
RelativePath=".\include\esl_config.h"
>

View File

@ -128,6 +128,7 @@
<ClCompile Include="esl_event.c" />
<ClCompile Include="esl_json.c" />
<ClCompile Include="esl_threadmutex.c" />
<ClCompile Include="esl_buffer.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="include\esl.h" />
@ -135,6 +136,7 @@
<ClInclude Include="include\esl_event.h" />
<ClInclude Include="include\esl_json.h" />
<ClInclude Include="include\esl_threadmutex.h" />
<ClInclude Include="include\esl_buffer.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -428,6 +428,10 @@ ESL_DECLARE(esl_status_t) esl_attach_handle(esl_handle_t *handle, esl_socket_t s
esl_mutex_create(&handle->mutex);
}
if (!handle->packet_buf) {
esl_buffer_create(&handle->packet_buf, BUF_CHUNK, BUF_START, 0);
}
handle->connected = 1;
esl_send_recv(handle, "connect\n\n");
@ -632,6 +636,10 @@ ESL_DECLARE(esl_status_t) esl_connect_timeout(esl_handle_t *handle, const char *
if (!handle->mutex) {
esl_mutex_create(&handle->mutex);
}
if (!handle->packet_buf) {
esl_buffer_create(&handle->packet_buf, BUF_CHUNK, BUF_START, 0);
}
handle->sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
@ -805,6 +813,11 @@ ESL_DECLARE(esl_status_t) esl_disconnect(esl_handle_t *handle)
esl_mutex_destroy(&mutex);
}
if (handle->packet_buf) {
esl_buffer_destroy(&handle->packet_buf);
}
return status;
}
@ -825,7 +838,7 @@ ESL_DECLARE(esl_status_t) esl_recv_event_timed(esl_handle_t *handle, uint32_t ms
if (check_q) {
esl_mutex_lock(handle->mutex);
if (handle->race_event) {
if (handle->race_event || esl_buffer_packet_count(handle->packet_buf)) {
esl_mutex_unlock(handle->mutex);
return esl_recv_event(handle, check_q, save_event);
}
@ -894,12 +907,15 @@ ESL_DECLARE(esl_status_t) esl_recv_event_timed(esl_handle_t *handle, uint32_t ms
}
static esl_ssize_t handle_recv(esl_handle_t *handle, void *data, esl_size_t datalen)
{
return recv(handle->sock, data, datalen, 0);
}
ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_event_t **save_event)
{
char *c;
esl_ssize_t rrval;
int crc = 0;
esl_event_t *revent = NULL;
char *beg;
char *hname, *hval;
@ -907,7 +923,6 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
char *cl;
esl_ssize_t len;
int zc = 0;
int bread = 0;
if (!handle || !handle->connected || handle->sock == ESL_SOCK_INVALID) {
return ESL_FAIL;
@ -916,9 +931,7 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
esl_mutex_lock(handle->mutex);
if (!handle->connected || handle->sock == ESL_SOCK_INVALID) {
handle->connected = 0;
esl_mutex_unlock(handle->mutex);
return ESL_FAIL;
goto fail;
}
esl_event_safe_destroy(&handle->last_event);
@ -932,76 +945,62 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
goto parse_event;
}
memset(handle->header_buf, 0, sizeof(handle->header_buf));
while(!revent && handle->connected) {
esl_size_t len1;
if ((len1 = esl_buffer_read_packet(handle->packet_buf, handle->socket_buf, sizeof(handle->socket_buf)))) {
char *data = (char *) handle->socket_buf;
char *p, *e;
esl_event_create(&revent, ESL_EVENT_CLONE);
revent->event_id = ESL_EVENT_SOCKET_DATA;
esl_event_add_header_string(revent, ESL_STACK_BOTTOM, "Event-Name", "SOCKET_DATA");
hname = p = data;
while(p) {
hname = p;
p = NULL;
c = handle->header_buf;
beg = c;
if ((hval = strchr(hname, ':'))) {
*hval++ = '\0';
while(*hval == ' ' || *hval == '\t') hval++;
while(handle->connected) {
if (bread + 2 >= sizeof(handle->header_buf)) {
esl_log(ESL_LOG_CRIT, "OUT OF BUFFER SPACE!\n");
handle->connected = 0;
esl_mutex_unlock(handle->mutex);
return ESL_DISCONNECTED;
if ((e = strchr(hval, '\n'))) {
*e++ = '\0';
while(*e == '\n' || *e == '\r') e++;
if (hname && hval) {
esl_url_decode(hval);
esl_log(ESL_LOG_DEBUG, "RECV HEADER [%s] = [%s]\n", hname, hval);
esl_event_add_header_string(revent, ESL_STACK_BOTTOM, hname, hval);
}
p = e;
}
}
}
break;
}
rrval = recv(handle->sock, c, 1, 0);
rrval = handle_recv(handle, handle->socket_buf, sizeof(handle->socket_buf));
if (rrval == 0) {
if (++zc >= 100) {
handle->connected = 0;
esl_mutex_unlock(handle->mutex);
return ESL_DISCONNECTED;
goto fail;
}
continue;
} else if (rrval < 0) {
strerror_r(handle->errnum, handle->err, sizeof(handle->err));
goto fail;
} else {
zc = 0;
if (*c == '\n') {
*(c+1) = '\0';
if (++crc == 2) {
break;
}
if (!revent) {
esl_event_create(&revent, ESL_EVENT_CLONE);
revent->event_id = ESL_EVENT_SOCKET_DATA;
esl_event_add_header_string(revent, ESL_STACK_BOTTOM, "Event-Name", "SOCKET_DATA");
}
hname = beg;
hval = col = NULL;
if (hname && (col = strchr(hname, ':'))) {
hval = col + 1;
*col = '\0';
while(*hval == ' ') hval++;
}
*c = '\0';
if (hname && hval) {
esl_url_decode(hval);
esl_log(ESL_LOG_DEBUG, "RECV HEADER [%s] = [%s]\n", hname, hval);
esl_event_add_header_string(revent, ESL_STACK_BOTTOM, hname, hval);
}
c = beg;
bread = 0;
continue;
} else {
crc = 0;
}
c++;
}
}
zc = 0;
esl_buffer_write(handle->packet_buf, handle->socket_buf, rrval);
}
if (!revent) {
goto fail;
}
@ -1016,12 +1015,28 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
*(body + len) = '\0';
do {
esl_ssize_t r;
if ((r = recv(handle->sock, body + sofar, len - sofar, 0)) < 0) {
strerror_r(handle->errnum, handle->err, sizeof(handle->err));
goto fail;
esl_ssize_t r,s = esl_buffer_inuse(handle->packet_buf);
if (s >= len) {
sofar = esl_buffer_read(handle->packet_buf, body, len);
} else {
r = handle_recv(handle, handle->socket_buf, sizeof(handle->socket_buf));
if (r < 0) {
strerror_r(handle->errnum, handle->err, sizeof(handle->err));
goto fail;
} else if (r == 0) {
if (++zc >= 100) {
goto fail;
}
continue;
}
zc = 0;
esl_buffer_write(handle->packet_buf, handle->socket_buf, r);
}
sofar += r;
} while (sofar < len);
revent->body = body;
@ -1123,6 +1138,8 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
fail:
esl_mutex_unlock(handle->mutex);
handle->connected = 0;
return ESL_FAIL;
@ -1177,7 +1194,6 @@ ESL_DECLARE(esl_status_t) esl_send_recv_timed(esl_handle_t *handle, const char *
return ESL_FAIL;
}
esl_event_safe_destroy(&handle->last_event);
esl_event_safe_destroy(&handle->last_sr_event);
*handle->last_sr_reply = '\0';

354
libs/esl/src/esl_buffer.c Normal file
View File

@ -0,0 +1,354 @@
/*
* Copyright (c) 2010, Anthony Minessale II
* 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 "esl_buffer.h"
static unsigned buffer_id = 0;
struct esl_buffer {
unsigned char *data;
unsigned char *head;
esl_size_t used;
esl_size_t actually_used;
esl_size_t datalen;
esl_size_t max_len;
esl_size_t blocksize;
unsigned id;
int loops;
};
ESL_DECLARE(esl_status_t) esl_buffer_create(esl_buffer_t **buffer, esl_size_t blocksize, esl_size_t start_len, esl_size_t max_len)
{
esl_buffer_t *new_buffer;
new_buffer = malloc(sizeof(*new_buffer));
if (new_buffer) {
memset(new_buffer, 0, sizeof(*new_buffer));
if (start_len) {
new_buffer->data = malloc(start_len);
if (!new_buffer->data) {
free(new_buffer);
return ESL_FAIL;
}
memset(new_buffer->data, 0, start_len);
}
new_buffer->max_len = max_len;
new_buffer->datalen = start_len;
new_buffer->id = buffer_id++;
new_buffer->blocksize = blocksize;
new_buffer->head = new_buffer->data;
*buffer = new_buffer;
return ESL_SUCCESS;
}
return ESL_FAIL;
}
ESL_DECLARE(esl_size_t) esl_buffer_len(esl_buffer_t *buffer)
{
assert(buffer != NULL);
return buffer->datalen;
}
ESL_DECLARE(esl_size_t) esl_buffer_freespace(esl_buffer_t *buffer)
{
assert(buffer != NULL);
if (buffer->max_len) {
return (esl_size_t) (buffer->max_len - buffer->used);
}
return 1000000;
}
ESL_DECLARE(esl_size_t) esl_buffer_inuse(esl_buffer_t *buffer)
{
assert(buffer != NULL);
return buffer->used;
}
ESL_DECLARE(esl_size_t) esl_buffer_seek(esl_buffer_t *buffer, esl_size_t datalen)
{
esl_size_t reading = 0;
assert(buffer != NULL);
if (buffer->used < 1) {
buffer->used = 0;
return 0;
} else if (buffer->used >= datalen) {
reading = datalen;
} else {
reading = buffer->used;
}
buffer->used = buffer->actually_used - reading;
buffer->head = buffer->data + reading;
return reading;
}
ESL_DECLARE(esl_size_t) esl_buffer_toss(esl_buffer_t *buffer, esl_size_t datalen)
{
esl_size_t reading = 0;
assert(buffer != NULL);
if (buffer->used < 1) {
buffer->used = 0;
return 0;
} else if (buffer->used >= datalen) {
reading = datalen;
} else {
reading = buffer->used;
}
buffer->used -= reading;
buffer->head += reading;
return buffer->used;
}
ESL_DECLARE(void) esl_buffer_set_loops(esl_buffer_t *buffer, int loops)
{
buffer->loops = loops;
}
ESL_DECLARE(esl_size_t) esl_buffer_read_loop(esl_buffer_t *buffer, void *data, esl_size_t datalen)
{
esl_size_t len;
if ((len = esl_buffer_read(buffer, data, datalen)) < datalen) {
if (buffer->loops == 0) {
return len;
}
buffer->head = buffer->data;
buffer->used = buffer->actually_used;
len = esl_buffer_read(buffer, (char*)data + len, datalen - len);
buffer->loops--;
}
return len;
}
ESL_DECLARE(esl_size_t) esl_buffer_read(esl_buffer_t *buffer, void *data, esl_size_t datalen)
{
esl_size_t reading = 0;
assert(buffer != NULL);
assert(data != NULL);
if (buffer->used < 1) {
buffer->used = 0;
return 0;
} else if (buffer->used >= datalen) {
reading = datalen;
} else {
reading = buffer->used;
}
memcpy(data, buffer->head, reading);
buffer->used -= reading;
buffer->head += reading;
/* if (buffer->id == 4) printf("%u o %d = %d\n", buffer->id, (unsigned)reading, (unsigned)buffer->used); */
return reading;
}
ESL_DECLARE(esl_size_t) esl_buffer_packet_count(esl_buffer_t *buffer)
{
char *pe, *p, *e, *head = (char *) buffer->head;
esl_size_t x = 0;
assert(buffer != NULL);
e = (head + buffer->used);
for (p = head; p && *p && p < e; p++) {
if (*p == '\n') {
pe = p+1;
if (*pe == '\r') pe++;
if (pe <= e && *pe == '\n') {
p = pe++;
x++;
}
}
}
return x;
}
ESL_DECLARE(esl_size_t) esl_buffer_read_packet(esl_buffer_t *buffer, void *data, esl_size_t maxlen)
{
char *pe, *p, *e, *head = (char *) buffer->head;
esl_size_t datalen = 0;
assert(buffer != NULL);
assert(data != NULL);
e = (head + buffer->used);
for (p = head; p && *p && p < e; p++) {
if (*p == '\n') {
pe = p+1;
if (*pe == '\r') pe++;
if (pe <= e && *pe == '\n') {
pe++;
datalen = pe - head;
if (datalen > maxlen) {
datalen = maxlen;
}
break;
}
}
}
return esl_buffer_read(buffer, data, datalen);
}
ESL_DECLARE(esl_size_t) esl_buffer_write(esl_buffer_t *buffer, const void *data, esl_size_t datalen)
{
esl_size_t freespace, actual_freespace;
assert(buffer != NULL);
assert(data != NULL);
assert(buffer->data != NULL);
if (!datalen) {
return buffer->used;
}
actual_freespace = buffer->datalen - buffer->actually_used;
if (actual_freespace < datalen && (!buffer->max_len || (buffer->used + datalen <= buffer->max_len))) {
memmove(buffer->data, buffer->head, buffer->used);
buffer->head = buffer->data;
buffer->actually_used = buffer->used;
}
freespace = buffer->datalen - buffer->used;
/*
if (buffer->data != buffer->head) {
memmove(buffer->data, buffer->head, buffer->used);
buffer->head = buffer->data;
}
*/
if (freespace < datalen) {
esl_size_t new_size, new_block_size;
void *data1;
new_size = buffer->datalen + datalen;
new_block_size = buffer->datalen + buffer->blocksize;
if (new_block_size > new_size) {
new_size = new_block_size;
}
buffer->head = buffer->data;
data1 = realloc(buffer->data, new_size);
if (!data1) {
return 0;
}
buffer->data = data1;
buffer->head = buffer->data;
buffer->datalen = new_size;
}
freespace = buffer->datalen - buffer->used;
if (freespace < datalen) {
return 0;
} else {
memcpy(buffer->head + buffer->used, data, datalen);
buffer->used += datalen;
buffer->actually_used += datalen;
}
/* if (buffer->id == 4) printf("%u i %d = %d\n", buffer->id, (unsigned)datalen, (unsigned)buffer->used); */
return buffer->used;
}
ESL_DECLARE(void) esl_buffer_zero(esl_buffer_t *buffer)
{
assert(buffer != NULL);
assert(buffer->data != NULL);
buffer->used = 0;
buffer->actually_used = 0;
buffer->head = buffer->data;
}
ESL_DECLARE(esl_size_t) esl_buffer_zwrite(esl_buffer_t *buffer, const void *data, esl_size_t datalen)
{
esl_size_t w;
if (!(w = esl_buffer_write(buffer, data, datalen))) {
esl_buffer_zero(buffer);
return esl_buffer_write(buffer, data, datalen);
}
return w;
}
ESL_DECLARE(void) esl_buffer_destroy(esl_buffer_t **buffer)
{
if (*buffer) {
free((*buffer)->data);
free(*buffer);
}
*buffer = NULL;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
*/

View File

@ -251,6 +251,7 @@ typedef int esl_filehandle_t;
#include "esl_json.h"
typedef int16_t esl_port_t;
typedef size_t esl_size_t;
typedef enum {
ESL_SUCCESS,
@ -259,7 +260,11 @@ typedef enum {
ESL_DISCONNECTED
} esl_status_t;
#define BUF_CHUNK 65536 * 50
#define BUF_START 65536 * 100
#include <esl_threadmutex.h>
#include <esl_buffer.h>
/*! \brief A handle that will hold the socket information and
different events received. */
@ -273,7 +278,8 @@ typedef struct {
/*! The error number reported by the OS */
int errnum;
/*! The inner contents received by the socket. Used only internally. */
char header_buf[4196];
esl_buffer_t *packet_buf;
char socket_buf[65536];
/*! Last command reply */
char last_reply[1024];
/*! Las command reply when called with esl_send_recv */

View File

@ -0,0 +1,146 @@
/*
* Copyright (c) 2010, Anthony Minessale II
* 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 "esl.h"
#ifndef ESL_BUFFER_H
#define ESL_BUFFER_H
/**
* @defgroup esl_buffer Buffer Routines
* @ingroup buffer
* The purpose of this module is to make a plain buffering interface that can be used for read/write buffers
* throughout the application.
* @{
*/
struct esl_buffer;
typedef struct esl_buffer esl_buffer_t;
/*! \brief Allocate a new dynamic esl_buffer
* \param buffer returned pointer to the new buffer
* \param blocksize length to realloc by as data is added
* \param start_len ammount of memory to reserve initially
* \param max_len length the buffer is allowed to grow to
* \return status
*/
ESL_DECLARE(esl_status_t) esl_buffer_create(esl_buffer_t **buffer, esl_size_t blocksize, esl_size_t start_len, esl_size_t max_len);
/*! \brief Get the length of a esl_buffer_t
* \param buffer any buffer of type esl_buffer_t
* \return int size of the buffer.
*/
ESL_DECLARE(esl_size_t) esl_buffer_len(esl_buffer_t *buffer);
/*! \brief Get the freespace of a esl_buffer_t
* \param buffer any buffer of type esl_buffer_t
* \return int freespace in the buffer.
*/
ESL_DECLARE(esl_size_t) esl_buffer_freespace(esl_buffer_t *buffer);
/*! \brief Get the in use amount of a esl_buffer_t
* \param buffer any buffer of type esl_buffer_t
* \return int ammount of buffer curently in use
*/
ESL_DECLARE(esl_size_t) esl_buffer_inuse(esl_buffer_t *buffer);
/*! \brief Read data from a esl_buffer_t up to the ammount of datalen if it is available. Remove read data from buffer.
* \param buffer any buffer of type esl_buffer_t
* \param data pointer to the read data to be returned
* \param datalen amount of data to be returned
* \return int ammount of data actually read
*/
ESL_DECLARE(esl_size_t) esl_buffer_read(esl_buffer_t *buffer, void *data, esl_size_t datalen);
ESL_DECLARE(esl_size_t) esl_buffer_read_packet(esl_buffer_t *buffer, void *data, esl_size_t maxlen);
ESL_DECLARE(esl_size_t) esl_buffer_packet_count(esl_buffer_t *buffer);
/*! \brief Read data endlessly from a esl_buffer_t
* \param buffer any buffer of type esl_buffer_t
* \param data pointer to the read data to be returned
* \param datalen amount of data to be returned
* \return int ammount of data actually read
* \note Once you have read all the data from the buffer it will loop around.
*/
ESL_DECLARE(esl_size_t) esl_buffer_read_loop(esl_buffer_t *buffer, void *data, esl_size_t datalen);
/*! \brief Assign a number of loops to read
* \param buffer any buffer of type esl_buffer_t
* \param loops the number of loops (-1 for infinite)
*/
ESL_DECLARE(void) esl_buffer_set_loops(esl_buffer_t *buffer, int32_t loops);
/*! \brief Write data into a esl_buffer_t up to the length of datalen
* \param buffer any buffer of type esl_buffer_t
* \param data pointer to the data to be written
* \param datalen amount of data to be written
* \return int amount of buffer used after the write, or 0 if no space available
*/
ESL_DECLARE(esl_size_t) esl_buffer_write(esl_buffer_t *buffer, const void *data, esl_size_t datalen);
/*! \brief Remove data from the buffer
* \param buffer any buffer of type esl_buffer_t
* \param datalen amount of data to be removed
* \return int size of buffer, or 0 if unable to toss that much data
*/
ESL_DECLARE(esl_size_t) esl_buffer_toss(esl_buffer_t *buffer, esl_size_t datalen);
/*! \brief Remove all data from the buffer
* \param buffer any buffer of type esl_buffer_t
*/
ESL_DECLARE(void) esl_buffer_zero(esl_buffer_t *buffer);
/*! \brief Destroy the buffer
* \param buffer buffer to destroy
* \note only neccessary on dynamic buffers (noop on pooled ones)
*/
ESL_DECLARE(void) esl_buffer_destroy(esl_buffer_t **buffer);
/*! \brief Seek to offset from the beginning of the buffer
* \param buffer buffer to seek
* \param datalen offset in bytes
* \return new position
*/
ESL_DECLARE(esl_size_t) esl_buffer_seek(esl_buffer_t *buffer, esl_size_t datalen);
/** @} */
ESL_DECLARE(esl_size_t) esl_buffer_zwrite(esl_buffer_t *buffer, const void *data, esl_size_t datalen);
#endif
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
*/

View File

@ -49,6 +49,7 @@ if HAVE_SNG_ISDN
INCS += -I/usr/include/sng_isdn
endif
# we needed to separate CFLAGS in FTDM_COMPAT_CFLAGS and FTDM_CFLAGS due to -c99 which causes problems with wanpipe headers
FTDM_COMPAT_CFLAGS = $(INCS) -DFTDM_CONFIG_DIR=\"@confdir@\" -DFTDM_MOD_DIR=\"$(moddir)\" @COMP_VENDOR_COMPAT_CFLAGS@ @DEFS@
FTDM_CFLAGS = $(INCS) -DFTDM_CONFIG_DIR=\"@confdir@\" -DFTDM_MOD_DIR=\"$(moddir)\" @COMP_VENDOR_CFLAGS@ @DEFS@
COMPILE = $(CC) $(FTDM_CFLAGS)
@ -183,8 +184,8 @@ ftmod_analog_em_la_LIBADD = libfreetdm.la
if HAVE_LIBSANGOMA
mod_LTLIBRARIES += ftmod_wanpipe.la
ftmod_wanpipe_la_SOURCES = $(SRC)/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
#some structures within Wanpipe drivers are not c99 compatible, so we need to compile ftmod_wanpipe
#without c99 flags
# some structures within Wanpipe drivers are not c99 compatible, so we need to compile ftmod_wanpipe
# without c99 flags, use FTDM_COMPAT_CFLAGS instead
ftmod_wanpipe_la_CFLAGS = $(AM_CFLAGS) $(FTDM_COMPAT_CFLAGS) -D__LINUX__ -I/usr/include/wanpipe
ftmod_wanpipe_la_LDFLAGS = -shared -module -avoid-version -lsangoma
ftmod_wanpipe_la_LIBADD = libfreetdm.la

View File

@ -82,7 +82,7 @@ sun)
fi
;;
*)
COMP_VENDOR_COMPAT_CFLAGS="-Wall -Wunused-variable -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes"
COMP_VENDOR_COMPAT_CFLAGS="-Wall -Werror -Wunused-variable -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes"
COMP_VENDOR_CFLAGS="-std=c99 $COMP_VENDOR_COMPAT_CFLAGS"
;;
esac

View File

@ -1,3 +1,3 @@
#! /bin/sh
./configure "$@" --with-pic
srcpath=$(dirname $0 2>/dev/null ) || srcpath="."
$srcpath/configure "$@" --with-pic

View File

@ -0,0 +1,59 @@
FreeTDM can both notify and set signaling status changes in the different protocols thru a unified interface. More
specific details on the C data types and function prototypes are found in freetdm.h
The API provides the following functions and data types to do it:
The signaling status in any channel/span is represented thru ftdm_signaling_status_t
/* The signaling link is down (no d-chans up in the span/group, MFC-R2 bit pattern unidentified) */
FTDM_SIG_STATE_DOWN,
/* The signaling link is suspended (MFC-R2 bit pattern blocked, PRI maintenance, ss7 blocked?) */
FTDM_SIG_STATE_SUSPENDED,
/* The signaling link is ready and calls can be placed (ie: d-chan up, MFC-R2 both rx and tx in IDLE) */
FTDM_SIG_STATE_UP,
/* Invalid status */
FTDM_SIG_STATE_INVALID
Changes in the signaling status are notified to the user using the standard callback notification function provided
during configuration using the sigevent type FTDM_SIGEVENT_SIGSTATUS_CHANGED which is sent when the line status changes.
On startup the signalling status default is FTDM_SIG_STATE_DOWN, and no notification is provided until the state change,
so applications must assume the status is down unless told otherwise.
When ftdm_span_start is called, the signaling stack takes care of attempting to bring the status to UP
but it will ultimately depend on the other side too.
== Setting the signaling status ==
Users can set the signaling status on a given channel/span thru FreeTDM the following API functions:
ftdm_channel_set_sig_status
ftdm_span_set_sig_status
If the user calls ftdm_channel_set_sig_status(chan, FTDM_SIG_STATE_SUSPENDED), the signaling stack will try to set
the status of the line to the one requested, if successful, it will result in a SIGEVENT_SIGSTATUS_CHANGED notification
being sent with status FTDM_SIG_STATE_SUSPENDED.
** MFC-R2 Signaling Notes **
For MFC-R2, calling ftdm_span_start() results in setting the tx CAS bits to IDLE. However, if the rx bits are in BLOCKED state
the signaling status will be reported as SUSPENDED.
If the user calls ftdm_channel_set_sig_status(chan, SUSPENDED), the tx CAS bits will be set to BLOCKED and, if, the current rx bits
are IDLE then a SIGEVENT_SIGSTATUS_CHANGED with state SUSPENDED will be sent. If the rx bits are already in blocked then no further
SIGEVENT_SIGSTATUS_CHANGED notification is needed (because it was already sent when the rx bits were initially detected as BLOCKED).
If the user calls ftdm_channel_set_sig_status(chan, UP), the tx CAS bits will be set to IDLE and, if, the current rx bits
are IDLE, then SIGEVENT_SIGSTATUS_CHANGED with state UP will be sent. If the rx bits are BLOCKED, then no notification is
sent at all until the rx bits change.
Bottom line is, for MFC-R2, SIGEVENT_SIGSTATUS_CHANGED UP is only sent to the user when both the rx and tx bits are in IDLE, and
SIGEVENT_SIGSTATUS_CHANGED SUSPENDED is only sent to the user when any of the rx or tx bits are in BLOCKED.
== Getting the signaling status ==
Users can get the signaling status on a given channel/span thru FreeTDM the following API functions:
ftdm_channel_get_sig_status
ftdm_span_get_sig_status
The line status returned should be the same as the last time a SIGEVENT_SIGSTATUS_CHANGED was reported.

View File

@ -119,10 +119,8 @@ Global
{0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.ActiveCfg = Release|x64
{0DA69C18-4FA1-4E8C-89CE-12498637C5BE}.Release|x64.Build.0 = Release|x64
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.ActiveCfg = Debug|Win32
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|Win32.Build.0 = Debug|Win32
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Debug|x64.ActiveCfg = Debug|x64
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.ActiveCfg = Release|Win32
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|Win32.Build.0 = Release|Win32
{B2AF4EA6-0CD7-4529-9EB5-5AF43DB90395}.Release|x64.ActiveCfg = Release|x64
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|Win32.ActiveCfg = Debug|Win32
{08C3EA27-A51D-47F8-B47D-B189C649CF30}.Debug|x64.ActiveCfg = Debug|x64

View File

@ -0,0 +1,217 @@
<?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>mod_freetdm</ProjectName>
<ProjectGuid>{FE3540C5-3303-46E0-A69E-D92F775687F1}</ProjectGuid>
<RootNamespace>mod_freetdm</RootNamespace>
<Keyword>Win32Proj</Keyword>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
</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" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</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" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</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" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</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" />
<Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)$(PlatformName)\$(Configuration)\mod\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)$(PlatformName)\$(Configuration)\mod\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)$(PlatformName)\$(Configuration)\mod\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)$(PlatformName)\$(Configuration)\mod\</OutDir>
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</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>../../../src/include;../src/include;../src/isdn/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>FreeSwitch.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(OutDir)mod_freetdm.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<AdditionalIncludeDirectories>../../../src/include;../src/include;../src/isdn/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>FreeSwitch.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(OutDir)mod_freetdm.lib</ImportLibrary>
<TargetMachine>MachineX86</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../../../src/include;../src/include;../src/isdn/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>FreeSwitchCore.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(OutDir)mod_freetdm.lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Midl>
<TargetEnvironment>X64</TargetEnvironment>
</Midl>
<ClCompile>
<AdditionalIncludeDirectories>../../../src/include;../src/include;../src/isdn/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>FreeSwitchCore.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>../../../$(PlatformName)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(OutDir)$(TargetName).pdb</ProgramDatabaseFile>
<SubSystem>Windows</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
<DataExecutionPrevention>
</DataExecutionPrevention>
<ImportLibrary>$(OutDir)mod_freetdm.lib</ImportLibrary>
<TargetMachine>MachineX64</TargetMachine>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="mod_freetdm.c" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\msvc\freetdm.2010.vcxproj">
<Project>{93b8812c-3ec4-4f78-8970-ffbfc99e167d}</Project>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="mod_freetdm.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -429,7 +429,7 @@ static switch_status_t channel_on_routing(switch_core_session_t *session)
assert(tech_pvt->ftdmchan != NULL);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel));
ftdm_channel_call_indicate(tech_pvt->ftdmchan, FTDM_CHANNEL_INDICATE_PROCEED);
return SWITCH_STATUS_SUCCESS;
}
@ -802,7 +802,7 @@ static switch_status_t channel_receive_message_cas(switch_core_session_t *sessio
phy_id = ftdm_channel_get_ph_id(tech_pvt->ftdmchan);
ftdm_log(FTDM_LOG_DEBUG, "Got Freeswitch message in R2 channel %d [%d]\n", phy_id, msg->message_id);
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_SUCCESS;
}
@ -849,7 +849,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
return SWITCH_STATUS_SUCCESS;
}
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_SUCCESS;
}
@ -892,7 +892,7 @@ static switch_status_t channel_receive_message_fxo(switch_core_session_t *sessio
return SWITCH_STATUS_FALSE;
}
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_SUCCESS;
}
@ -924,7 +924,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio
return SWITCH_STATUS_FALSE;
}
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_SUCCESS;
}
@ -981,7 +981,7 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_PROGRESS:
case SWITCH_MESSAGE_INDICATE_ANSWER:
if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
if ((var = switch_channel_get_variable(channel, "freetdm_pre_buffer_size"))) {
int tmp = atoi(var);
if (tmp > -1) {
@ -1136,6 +1136,10 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
direction = FTDM_BOTTOM_UP;
} else if (*argv[1] == 'a') {
direction = FTDM_TOP_DOWN;
} else if (*argv[1] == 'r') {
direction = FTDM_RR_DOWN;
} else if (*argv[1] == 'R') {
direction = FTDM_RR_UP;
} else {
chan_id = atoi(argv[1]);
}
@ -1278,6 +1282,10 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
caller_data.dnis.type = outbound_profile->destination_number_ton;
}
if ((var = channel_get_variable(session, var_event, "freetdm_calling_party_category"))) {
ftdm_set_calling_party_category(var, (uint8_t *)&caller_data.cpc);
}
if ((var = channel_get_variable(session, var_event, "freetdm_custom_call_data"))) {
ftdm_set_string(caller_data.raw_data, var);
caller_data.raw_data_len = (uint32_t)strlen(var);
@ -1329,7 +1337,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
char *v = h->name + FREETDM_VAR_PREFIX_LEN;
if (!zstr(v)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding outbound freetdm variable %s=%s to channel %d:%d\n", v, h->value, span_id, chan_id);
ftdm_channel_add_var(ftdmchan, v, h->value);
ftdm_call_add_var(&caller_data, v, h->value);
}
}
}
@ -1363,7 +1371,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
tech_pvt->caller_profile = caller_profile;
switch_channel_set_flag(channel, CF_OUTBOUND);
switch_channel_set_state(channel, CS_INIT);
if (ftdm_channel_add_token(ftdmchan, switch_core_session_get_uuid(*new_session), ftdm_channel_get_token_count(ftdmchan)) != FTDM_SUCCESS) {
switch_core_session_destroy(new_session);
@ -1528,6 +1535,7 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session
switch_channel_set_variable_printf(channel, "freetdm_chan_number", "%d", chanid);
switch_channel_set_variable_printf(channel, "freetdm_bearer_capability", "%d", channel_caller_data->bearer_capability);
switch_channel_set_variable_printf(channel, "freetdm_bearer_layer1", "%d", channel_caller_data->bearer_layer1);
if (globals.sip_headers) {
switch_channel_set_variable(channel, "sip_h_X-FreeTDM-SpanName", ftdm_channel_get_span_name(sigmsg->channel));
switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-SpanNumber", "%d", spanid);
@ -1561,8 +1569,18 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session
ftdm_channel_get_current_var(curr, &var_name, &var_value);
snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name);
switch_channel_set_variable_printf(channel, name, "%s", var_value);
}
/* Add any call variable to the dial plan */
iter = ftdm_call_get_var_iterator(channel_caller_data, iter);
for (curr = iter ; curr; curr = ftdm_iterator_next(curr)) {
ftdm_call_get_current_var(curr, &var_name, &var_value);
snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name);
switch_channel_set_variable_printf(channel, name, "%s", var_value);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Call Variable: %s=%s\n", name, var_value);
}
ftdm_iterator_free(iter);
switch_channel_set_state(channel, CS_INIT);
if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
@ -1661,11 +1679,11 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
ftdm_status_t status;
uint32_t spanid;
uint32_t chanid;
ftdm_caller_data_t *callerdata;
ftdm_caller_data_t *caller_data;
spanid = ftdm_channel_get_span_id(sigmsg->channel);
chanid = ftdm_channel_get_id(sigmsg->channel);
callerdata = ftdm_channel_get_caller_data(sigmsg->channel);
caller_data = ftdm_channel_get_caller_data(sigmsg->channel);
ftdm_log(FTDM_LOG_DEBUG, "got FXO sig %d:%d [%s]\n", spanid, chanid, ftdm_signal_event2str(sigmsg->event_id));
@ -1688,7 +1706,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
switch_set_flag_locked(tech_pvt, TFLAG_DEAD);
ftdm_channel_clear_token(sigmsg->channel, 0);
channel = switch_core_session_get_channel(session);
switch_channel_hangup(channel, callerdata->hangup_cause);
switch_channel_hangup(channel, caller_data->hangup_cause);
ftdm_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session));
switch_core_session_rwunlock(session);
}
@ -1712,8 +1730,9 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
}
}
break;
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
case FTDM_SIGEVENT_SIGSTATUS_CHANGED: { /* twiddle */ } break;
default:
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled msg type %d for channel %d:%d\n",
@ -1767,7 +1786,8 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxs_signal)
}
}
break;
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
case FTDM_SIGEVENT_STOP:
{
private_t *tech_pvt = NULL;
@ -1799,7 +1819,9 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxs_signal)
switch_clear_flag_locked(tech_pvt, TFLAG_HOLD);
}
if (channel_a && channel_b && !switch_channel_test_flag(channel_a, CF_OUTBOUND) && !switch_channel_test_flag(channel_b, CF_OUTBOUND)) {
if (channel_a && channel_b && switch_channel_direction(channel_a) == SWITCH_CALL_DIRECTION_INBOUND &&
switch_channel_direction(channel_b) == SWITCH_CALL_DIRECTION_INBOUND) {
cause = SWITCH_CAUSE_ATTENDED_TRANSFER;
if (br_a_uuid && br_b_uuid) {
switch_ivr_uuid_bridge(br_a_uuid, br_b_uuid);
@ -1899,7 +1921,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxs_signal)
case FTDM_SIGEVENT_COLLECTED_DIGIT:
{
int span_id = ftdm_channel_get_span_id(sigmsg->channel);
char *dtmf = sigmsg->raw_data;
char *dtmf = sigmsg->ev_data.collected.digits;
char *regex = SPAN_CONFIG[span_id].dial_regex;
char *fail_regex = SPAN_CONFIG[span_id].fail_dial_regex;
ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(sigmsg->channel);
@ -1991,8 +2013,8 @@ static FIO_SIGNAL_CB_FUNCTION(on_r2_signal)
}
break;
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
/* on DNIS received from the R2 forward side, return status == FTDM_BREAK to stop requesting DNIS */
case FTDM_SIGEVENT_COLLECTED_DIGIT:
{
@ -2065,7 +2087,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_r2_signal)
case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
{
ftdm_signaling_status_t sigstatus = sigmsg->raw_data ? *((ftdm_signaling_status_t*)(sigmsg->raw_data)) : sigmsg->sigstatus;
ftdm_signaling_status_t sigstatus = sigmsg->ev_data.sigstatus.status;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d:%d signalling changed to: %s\n",
spanid, chanid, ftdm_signaling_status2str(sigstatus));
}
@ -2104,14 +2126,14 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
switch(sigmsg->event_id) {
case FTDM_SIGEVENT_START:
{
ftdm_channel_add_var(sigmsg->channel, "screening_ind", ftdm_screening2str(caller_data->screen));
ftdm_channel_add_var(sigmsg->channel, "presentation_ind", ftdm_presentation2str(caller_data->pres));
ftdm_call_add_var(caller_data, "screening_ind", ftdm_screening2str(caller_data->screen));
ftdm_call_add_var(caller_data, "presentation_ind", ftdm_presentation2str(caller_data->pres));
return ftdm_channel_from_event(sigmsg, &session);
}
break;
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
case FTDM_SIGEVENT_RELEASED: { /* twiddle */ } break;
case FTDM_SIGEVENT_STOP:
case FTDM_SIGEVENT_RESTART:
{
@ -2155,6 +2177,7 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
}
break;
case FTDM_SIGEVENT_PROGRESS:
case FTDM_SIGEVENT_RINGING:
{
if ((session = ftdm_channel_get_session(sigmsg->channel, 0))) {
channel = switch_core_session_get_channel(session);
@ -2170,13 +2193,13 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
break;
case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
{
ftdm_signaling_status_t sigstatus = sigmsg->raw_data ? *((ftdm_signaling_status_t*)(sigmsg->raw_data)) : sigmsg->sigstatus;
ftdm_signaling_status_t sigstatus = sigmsg->ev_data.sigstatus.status;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d:%d signalling changed to :%s\n",
spanid, chanid, ftdm_signaling_status2str(sigstatus));
}
break;
case FTDM_SIGEVENT_PROCEED:
case FTDM_SIGEVENT_MSG:
case FTDM_SIGEVENT_FACILITY:
/* FS does not have handlers for these messages, so ignore them for now */
break;
default:
@ -3513,7 +3536,19 @@ void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *
switch_channel_cause2str(caller_data->hangup_cause));
}
#define FT_SYNTAX "list || dump <span_id> [<chan_id>] || q931_pcap <span_id> on|off [pcapfilename without suffix] || gains <txgain> <rxgain> <span_id> [<chan_id>] || dtmf on|off <span_id> [<chan_id>]"
#define FT_SYNTAX "USAGE:\n" \
"--------------------------------------------------------------------------------\n" \
"ftdm list\n" \
"ftdm start|stop <span_name|span_id>\n" \
"ftdm restart <span_id|span_name> <chan_id>\n" \
"ftdm dump <span_id|span_name> [<chan_id>]\n" \
"ftdm sigstatus get|set [<span_id|span_name>] [<channel>] [<sigstatus>]\n" \
"ftdm trace <path> <span_id|span_name> [<chan_id>]\n" \
"ftdm notrace <span_id|span_name> [<chan_id>]\n" \
"ftdm q931_pcap <span_id> on|off [pcapfilename without suffix]\n" \
"ftdm gains <txgain> <rxgain> <span_id> [<chan_id>]\n" \
"ftdm dtmf on|off <span_id> [<chan_id>]\n" \
"--------------------------------------------------------------------------------\n"
SWITCH_STANDARD_API(ft_function)
{
char *mycmd = NULL, *argv[10] = { 0 };
@ -3530,7 +3565,83 @@ SWITCH_STANDARD_API(ft_function)
goto end;
}
if (!strcasecmp(argv[0], "dump")) {
if (!strcasecmp(argv[0], "sigstatus")) {
ftdm_span_t *span = NULL;
ftdm_signaling_status_t sigstatus;
if (argc < 3) {
stream->write_function(stream, "-ERR Usage: ftdm sigstatus get|set [<span_id>] [<channel>] [<sigstatus>]\n");
goto end;
}
if (!strcasecmp(argv[1], "get") && argc < 3) {
stream->write_function(stream, "-ERR sigstatus get usage: get <span_id>\n");
goto end;
}
if (!strcasecmp(argv[1], "set") && argc != 5) {
stream->write_function(stream, "-ERR sigstatus set usage: set <span_id> <channel>|all <sigstatus>\n");
goto end;
}
ftdm_span_find_by_name(argv[2], &span);
if (!span) {
stream->write_function(stream, "-ERR invalid span\n");
goto end;
}
if (!strcasecmp(argv[1], "get")) {
if (argc == 4) {
uint32_t chan_id = atol(argv[3]);
ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id);
if (!fchan) {
stream->write_function(stream, "-ERR failed to get channel id '%d'\n", chan_id);
goto end;
}
if ((FTDM_SUCCESS == ftdm_channel_get_sig_status(fchan, &sigstatus))) {
stream->write_function(stream, "channel %d signaling status: %s\n", chan_id, ftdm_signaling_status2str(sigstatus));
} else {
stream->write_function(stream, "-ERR failed to get channel sigstatus\n");
}
goto end;
} else {
if ((FTDM_SUCCESS == ftdm_span_get_sig_status(span, &sigstatus))) {
stream->write_function(stream, "signaling_status: %s\n", ftdm_signaling_status2str(sigstatus));
} else {
stream->write_function(stream, "-ERR failed to read span status: %s\n", ftdm_span_get_last_error(span));
}
}
goto end;
}
if (!strcasecmp(argv[1], "set")) {
sigstatus = ftdm_str2ftdm_signaling_status(argv[4]);
if (!strcasecmp(argv[3], "all")) {
if ((FTDM_SUCCESS == ftdm_span_set_sig_status(span, sigstatus))) {
stream->write_function(stream, "Signaling status of all channels from span %s set to %s\n",
ftdm_span_get_name(span), ftdm_signaling_status2str(sigstatus));
} else {
stream->write_function(stream, "-ERR failed to set span sigstatus to '%s'\n", ftdm_signaling_status2str(sigstatus));
}
goto end;
} else {
uint32_t chan_id = atol(argv[3]);
ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id);
if (!fchan) {
stream->write_function(stream, "-ERR failed to get channel id '%d'\n", chan_id);
goto end;
}
if ((FTDM_SUCCESS == ftdm_channel_set_sig_status(fchan, sigstatus))) {
stream->write_function(stream, "Signaling status of channel %d set to %s\n", chan_id,
ftdm_signaling_status2str(sigstatus));
} else {
stream->write_function(stream, "-ERR failed to set span sigstatus to '%s'\n", ftdm_signaling_status2str(sigstatus));
}
goto end;
}
}
} else if (!strcasecmp(argv[0], "dump")) {
if (argc < 2) {
stream->write_function(stream, "-ERR Usage: ftdm dump <span_id> [<chan_id>]\n");
goto end;
@ -3910,6 +4021,28 @@ SWITCH_STANDARD_API(ft_function)
}
}
stream->write_function(stream, "+OK gains set to Rx %f and Tx %f\n", rxgain, txgain);
} else if (!strcasecmp(argv[0], "restart")) {
uint32_t chan_id = 0;
ftdm_channel_t *chan;
ftdm_span_t *span = NULL;
if (argc < 3) {
stream->write_function(stream, "-ERR Usage: ftdm restart <span_id> <chan_id>\n");
goto end;
}
ftdm_span_find_by_name(argv[1], &span);
if (!span) {
stream->write_function(stream, "-ERR invalid span\n");
goto end;
}
chan_id = atoi(argv[2]);
chan = ftdm_span_get_channel(span, chan_id);
if (!chan) {
stream->write_function(stream, "-ERR Could not find chan\n");
goto end;
}
stream->write_function(stream, "Resetting channel %s:%s\n", argv[2], argv[3]);
ftdm_channel_reset(chan);
} else {
char *rply = ftdm_api_execute(cmd);

View File

@ -30,6 +30,12 @@
* 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.
*
* Contributors:
*
* Moises Silva <moy@sangoma.com>
* Ricardo Barroetaveña <rbarroetavena@anura.com.ar>
*
*/
#include "private/ftdm_core.h"
@ -144,3 +150,20 @@ FT_DECLARE(ftdm_status_t) ftdm_is_number(const char *number)
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) ftdm_set_calling_party_category(const char *string, uint8_t *target)
{
uint8_t val;
ftdm_status_t status = FTDM_SUCCESS;
val = ftdm_str2ftdm_calling_party_category(string);
if (val == FTDM_CPC_INVALID) {
ftdm_log(FTDM_LOG_WARNING, "Invalid category string (%s)\n", string);
val = FTDM_CPC_ORDINARY;
status = FTDM_FAIL;
}
*target = val;
return status;
}

File diff suppressed because it is too large Load Diff

View File

@ -156,7 +156,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
release_request_id((m3ua_request_id_t)ftdmchan->extra_id);
ftdmchan->extra_id = 0;
}
ftdm_channel_done(ftdmchan);
ftdm_channel_close(&ftdmchan);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:

View File

@ -96,6 +96,10 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(analog_fxs_outgoing_call)
static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(analog_get_channel_sig_status)
{
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) {
*status = FTDM_SIG_STATE_DOWN;
return FTDM_SUCCESS;
}
*status = FTDM_SIG_STATE_UP;
return FTDM_SUCCESS;
}
@ -109,7 +113,25 @@ static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(analog_get_channel_sig_status)
static FIO_SPAN_GET_SIG_STATUS_FUNCTION(analog_get_span_sig_status)
{
*status = FTDM_SIG_STATE_UP;
ftdm_iterator_t *citer = NULL;
ftdm_iterator_t *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);
return FTDM_FAIL;
}
/* if ALL channels are in alarm, report DOWN, UP otherwise. */
*status = FTDM_SIG_STATE_DOWN;
for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) {
ftdm_channel_t *fchan = ftdm_iterator_current(citer);
ftdm_channel_lock(fchan);
if (!ftdm_test_flag(fchan, FTDM_CHANNEL_IN_ALARM)) {
*status = FTDM_SIG_STATE_UP;
ftdm_channel_unlock(fchan);
break;
}
ftdm_channel_unlock(fchan);
}
ftdm_iterator_free(chaniter);
return FTDM_SUCCESS;
}
@ -491,9 +513,12 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
ftdm_channel_command(ftdmchan, FTDM_COMMAND_GENERATE_RING_OFF, NULL);
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) &&
(ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE
|| ftdmchan->last_state >= FTDM_CHANNEL_STATE_RING)) {
if (ftdmchan->type == FTDM_CHAN_TYPE_FXS &&
ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) &&
(ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING
|| ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE
|| ftdmchan->last_state == FTDM_CHANNEL_STATE_RING
|| ftdmchan->last_state == FTDM_CHANNEL_STATE_UP)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
} else {
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING;
@ -716,7 +741,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
dtmf_offset = strlen(dtmf);
last_digit = elapsed;
sig.event_id = FTDM_SIGEVENT_COLLECTED_DIGIT;
sig.raw_data = dtmf;
ftdm_set_string(sig.ev_data.collected.digits, dtmf);
if (ftdm_span_send_signal(ftdmchan->span, &sig) == FTDM_BREAK) {
collecting = 0;
}
@ -883,14 +908,14 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
{
if (event->channel->type != FTDM_CHAN_TYPE_FXO) {
ftdm_log_chan_msg(event->channel, FTDM_LOG_ERROR, "Cannot get a RING_START event on a non-fxo channel, please check your config.\n");
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DOWN);
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN);
goto end;
}
if (!event->channel->ring_count && (event->channel->state == FTDM_CHANNEL_STATE_DOWN && !ftdm_test_flag(event->channel, FTDM_CHANNEL_INTHREAD))) {
if (ftdm_test_flag(analog_data, FTDM_ANALOG_CALLERID)) {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_GET_CALLERID);
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_GET_CALLERID);
} else {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_RING);
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_RING);
}
event->channel->ring_count = 1;
ftdm_mutex_unlock(event->channel->mutex);
@ -908,7 +933,12 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
}
if (event->channel->state != FTDM_CHANNEL_STATE_DOWN) {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DOWN);
if (event->channel->state == FTDM_CHANNEL_STATE_HANGUP &&
ftdm_test_flag(event->channel, FTDM_CHANNEL_STATE_CHANGE)) {
ftdm_clear_flag(event->channel, FTDM_CHANNEL_STATE_CHANGE);
/* we do not need to process HANGUP since the device also hangup already */
}
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN);
}
}
@ -916,16 +946,16 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
case FTDM_OOB_FLASH:
{
if (event->channel->state == FTDM_CHANNEL_STATE_CALLWAITING) {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_UP);
ftdm_clear_flag_locked(event->channel, FTDM_CHANNEL_STATE_CHANGE);
ftdm_clear_flag_locked(event->channel->span, FTDM_SPAN_STATE_CHANGE);
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_UP);
ftdm_clear_flag(event->channel, FTDM_CHANNEL_STATE_CHANGE);
ftdm_clear_flag(event->channel->span, FTDM_SPAN_STATE_CHANGE);
event->channel->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK] = 0;
}
ftdm_channel_rotate_tokens(event->channel);
if (ftdm_test_flag(event->channel, FTDM_CHANNEL_HOLD) && event->channel->token_count != 1) {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_UP);
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_UP);
} else {
sig.event_id = FTDM_SIGEVENT_FLASH;
ftdm_span_send_signal(span, &sig);
@ -939,12 +969,12 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
if (ftdm_test_flag(event->channel, FTDM_CHANNEL_RINGING)) {
ftdm_channel_command(event->channel, FTDM_COMMAND_GENERATE_RING_OFF, NULL);
}
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_UP);
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_UP);
} else {
if(!analog_data->max_dialstr) {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_COLLECT);
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_COLLECT);
} else {
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DIALTONE);
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DIALTONE);
}
ftdm_mutex_unlock(event->channel->mutex);
locked = 0;
@ -956,9 +986,24 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
ftdm_channel_command(event->channel, FTDM_COMMAND_ONHOOK, NULL);
}
}
ftdm_set_state_locked(event->channel, FTDM_CHANNEL_STATE_DOWN);
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_DOWN);
}
}
break;
case FTDM_OOB_ALARM_TRAP:
{
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sig.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(span, &sig);
}
break;
case FTDM_OOB_ALARM_CLEAR:
{
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sig.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(span, &sig);
}
break;
default:
{
ftdm_log_chan(event->channel, FTDM_LOG_DEBUG, "Ignoring event [%s] in state [%s]\n", ftdm_oob_event2str(event->enum_id), ftdm_channel_state2str(event->channel->state));

View File

@ -329,8 +329,8 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
{
if (state_counter > 500) {
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OFFHOOK) &&
(ftdmchan->last_state == FTDM_CHANNEL_STATE_RING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE
|| ftdmchan->last_state >= FTDM_CHANNEL_STATE_IDLE)) {
(ftdmchan->last_state == FTDM_CHANNEL_STATE_RINGING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALTONE
|| ftdmchan->last_state == FTDM_CHANNEL_STATE_RING)) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_BUSY);
} else {
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING;
@ -340,7 +340,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
}
break;
case FTDM_CHANNEL_STATE_UP:
case FTDM_CHANNEL_STATE_IDLE:
case FTDM_CHANNEL_STATE_RING:
{
ftdm_sleep(interval);
continue;
@ -386,7 +386,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
ftdm_channel_use(ftdmchan);
}
break;
case FTDM_CHANNEL_STATE_IDLE:
case FTDM_CHANNEL_STATE_RING:
{
ftdm_channel_use(ftdmchan);
@ -421,7 +421,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
ftdm_channel_command(ftdmchan, FTDM_COMMAND_WINK, NULL);
}
break;
case FTDM_CHANNEL_STATE_RING:
case FTDM_CHANNEL_STATE_RINGING:
{
ftdm_buffer_zero(dt_buffer);
teletone_run(&ts, ftdmchan->span->tone_map[FTDM_TONEMAP_RING]);
@ -467,7 +467,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
dtmf_offset = strlen(dtmf);
last_digit = elapsed;
sig.event_id = FTDM_SIGEVENT_COLLECTED_DIGIT;
sig.raw_data = dtmf;
ftdm_set_string(sig.ev_data.collected.digits, dtmf);
if (ftdm_span_send_signal(ftdmchan->span, &sig) == FTDM_BREAK) {
collecting = 0;
}
@ -477,7 +477,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
if (last_digit && (!collecting || ((elapsed - last_digit > analog_data->digit_timeout) || strlen(dtmf) > analog_data->max_dialstr))) {
ftdm_log(FTDM_LOG_DEBUG, "Number obtained [%s]\n", dtmf);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING);
last_digit = 0;
collecting = 0;
}

View File

@ -1325,7 +1325,7 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
}
Q931ReleaseCRV(&isdn_data->q931, gen->CRV);
}
ftdm_channel_done(ftdmchan);
ftdm_channel_close(&ftdmchan);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS:

View File

@ -515,23 +515,17 @@ static __inline__ void state_advance(ftdm_channel_t *chan)
switch (ftdm_channel_get_state(chan)) {
case FTDM_CHANNEL_STATE_DOWN:
{
ftdm_channel_t *chtmp = chan;
chan->call_data = NULL;
ftdm_channel_done(chan);
/*
* Close channel completely, BRI PTMP will thank us
*/
if (ftdm_test_flag(chan, FTDM_CHANNEL_OPEN)) {
ftdm_channel_t *chtmp = chan;
if (ftdm_channel_close(&chtmp) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_WARNING, "-- Failed to close channel %d:%d\n",
ftdm_channel_get_span_id(chan),
ftdm_channel_get_id(chan));
} else {
ftdm_log(FTDM_LOG_DEBUG, "-- Closed channel %d:%d\n",
ftdm_channel_get_span_id(chan),
ftdm_channel_get_id(chan));
}
if (ftdm_channel_close(&chtmp) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_WARNING, "-- Failed to close channel %d:%d\n",
ftdm_channel_get_span_id(chan),
ftdm_channel_get_id(chan));
} else {
ftdm_log(FTDM_LOG_DEBUG, "-- Closed channel %d:%d\n",
ftdm_channel_get_span_id(chan),
ftdm_channel_get_id(chan));
}
}
break;
@ -1403,8 +1397,7 @@ static int on_dchan_up(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_ev
sig.chan_id = ftdm_channel_get_id(chan);
sig.channel = chan;
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sig.raw_data = &status;
sig.ev_data.sigstatus.status = status;
ftdm_span_send_signal(span, &sig);
}
}
@ -1440,7 +1433,7 @@ static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_
sig.chan_id = ftdm_channel_get_id(chan);
sig.channel = chan;
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sig.raw_data = &status;
sig.ev_data.sigstatus.status = status;
ftdm_span_send_signal(span, &sig);
}

View File

@ -127,24 +127,24 @@ static int __pri_lpwrap_read(struct pri *pri, void *buf, int buflen)
} else {
ftdm_log(FTDM_LOG_CRIT, "span %d D-READ TIMEOUT\n", spri->span->span_id);
}
ftdm_clear_flag(spri, LPWRAP_PRI_READY);
return -1;
/* we cannot return -1, libpri seems to expect values >= 0 */
return 0;
}
spri->errs = 0;
res = (int)len;
memset(&((unsigned char*)buf)[res], 0, 2);
res += 2;
if (res > 0) {
memset(&((unsigned char*)buf)[res], 0, 2);
res += 2;
#ifdef IODEBUG
{
char bb[2048] = { 0 };
{
char bb[2048] = { 0 };
print_hex_bytes(buf, res - 2, bb, sizeof(bb));
ftdm_log(FTDM_LOG_DEBUG, "READ %d\n", res - 2);
}
print_hex_bytes(buf, res - 2, bb, sizeof(bb));
ftdm_log(FTDM_LOG_DEBUG, "READ %d\n", res - 2);
}
#endif
}
return res;
}
@ -155,8 +155,8 @@ static int __pri_lpwrap_write(struct pri *pri, void *buf, int buflen)
if (ftdm_channel_write(spri->dchan, buf, buflen, &len) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "span %d D-WRITE FAIL! [%s]\n", spri->span->span_id, spri->dchan->last_error);
ftdm_clear_flag(spri, LPWRAP_PRI_READY);
return -1;
/* we cannot return -1, libpri seems to expect values >= 0 */
return 0;
}
#ifdef IODEBUG

View File

@ -280,12 +280,12 @@ static __inline__ void state_advance(ftdm_channel_t *ftdmchan)
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_DOWN:
{
ftdm_channel_done(ftdmchan);
{
ftdmchan->call_data = NULL;
ftdm_channel_close(&ftdmchan);
ftdm_channel_done(peerchan);
peerchan->call_data = NULL;
ftdm_channel_close(&peerchan);
}
break;

View File

@ -29,6 +29,12 @@
* 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.
*
* Contributors:
*
* Arnaldo Pereira <arnaldo@sangoma.com>
* Ricardo Barroetaveña <rbarroetavena@anura.com.ar>
*
*/
#ifdef __linux__
@ -44,16 +50,15 @@
#include "freetdm.h"
#include "private/ftdm_core.h"
/* debug thread count for r2 legs */
static ftdm_mutex_t* g_thread_count_mutex;
static int32_t g_thread_count = 0;
typedef int openr2_call_status_t;
/* when the users kills a span we clear this flag to kill the signaling thread */
/* when the user stops a span, we clear FTDM_R2_SPAN_STARTED, so that the signaling thread
* knows it must stop, and we wait for FTDM_R2_RUNNING to be clear, which tells us the
* signaling thread is done. */
/* FIXME: what about the calls that are already up-and-running? */
typedef enum {
FTDM_R2_RUNNING = (1 << 0),
FTDM_R2_SPAN_STARTED = (1 << 1),
} ftdm_r2_flag_t;
/* private call information stored in ftdmchan->call_data void* ptr,
@ -250,7 +255,7 @@ static void ftdm_r2_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling
sig.span_id = ftdmchan->span_id;
sig.channel = ftdmchan;
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sig.sigstatus = status;
sig.ev_data.sigstatus.status = status;
if (ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to change channel status to %s\n", ftdm_signaling_status2str(status));
}
@ -372,11 +377,72 @@ static void ft_r2_answer_call(ftdm_channel_t *ftdmchan)
R2CALL(ftdmchan)->answer_pending = 0;
}
static __inline__ ftdm_calling_party_category_t ftdm_openr2_cpc_to_r2_ftdm_cpc(openr2_calling_party_category_t cpc)
{
switch (cpc) {
case OR2_CALLING_PARTY_CATEGORY_UNKNOWN:
return FTDM_CPC_UNKNOWN;
case OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER:
return FTDM_CPC_ORDINARY;
case OR2_CALLING_PARTY_CATEGORY_NATIONAL_PRIORITY_SUBSCRIBER:
return FTDM_CPC_PRIORITY;
case OR2_CALLING_PARTY_CATEGORY_INTERNATIONAL_SUBSCRIBER:
return FTDM_CPC_UNKNOWN;
case OR2_CALLING_PARTY_CATEGORY_INTERNATIONAL_PRIORITY_SUBSCRIBER:
return FTDM_CPC_UNKNOWN;
case OR2_CALLING_PARTY_CATEGORY_TEST_EQUIPMENT:
return FTDM_CPC_TEST;
case OR2_CALLING_PARTY_CATEGORY_PAY_PHONE:
return FTDM_CPC_PAYPHONE;
case OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL:
return FTDM_CPC_OPERATOR;
}
return FTDM_CPC_INVALID;
}
static __inline openr2_calling_party_category_t ftdm_r2_ftdm_cpc_to_openr2_cpc(ftdm_calling_party_category_t cpc)
{
switch (cpc) {
case FTDM_CPC_UNKNOWN:
return OR2_CALLING_PARTY_CATEGORY_UNKNOWN;
case FTDM_CPC_OPERATOR:
return OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL;
case FTDM_CPC_ORDINARY:
return OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
case FTDM_CPC_PRIORITY:
return OR2_CALLING_PARTY_CATEGORY_NATIONAL_PRIORITY_SUBSCRIBER;
case FTDM_CPC_DATA:
return OR2_CALLING_PARTY_CATEGORY_UNKNOWN;
case FTDM_CPC_TEST:
return OR2_CALLING_PARTY_CATEGORY_TEST_EQUIPMENT;
case FTDM_CPC_PAYPHONE:
return OR2_CALLING_PARTY_CATEGORY_PAY_PHONE;
case FTDM_CPC_INVALID:
return OR2_CALLING_PARTY_CATEGORY_UNKNOWN;
}
return OR2_CALLING_PARTY_CATEGORY_UNKNOWN;
}
/* this function must be called with the chan mutex held! */
static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call)
{
openr2_call_status_t callstatus;
ftdm_r2_data_t *r2data;
openr2_calling_party_category_t category = OR2_CALLING_PARTY_CATEGORY_NATIONAL_SUBSCRIBER;
r2data = ftdmchan->span->signal_data;
@ -389,6 +455,12 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call)
ft_r2_clean_call(ftdmchan->call_data);
if (ftdmchan->caller_data.cpc == FTDM_CPC_INVALID || ftdmchan->caller_data.cpc == FTDM_CPC_UNKNOWN) {
category = r2data->category;
} else {
category = ftdm_r2_ftdm_cpc_to_openr2_cpc(ftdmchan->caller_data.cpc);
}
/* start io dump */
if (r2data->mf_dump_size) {
ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_INPUT_DUMP, &r2data->mf_dump_size);
@ -396,9 +468,9 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call)
}
callstatus = openr2_chan_make_call(R2CALL(ftdmchan)->r2chan,
ftdmchan->caller_data.cid_num.digits,
ftdmchan->caller_data.pres == FTDM_PRES_ALLOWED ? ftdmchan->caller_data.cid_num.digits : NULL,
ftdmchan->caller_data.dnis.digits,
r2data->category);
category);
if (callstatus) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to make call in R2 channel, openr2_chan_make_call failed\n");
@ -419,13 +491,14 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(r2_outgoing_call)
static ftdm_status_t ftdm_r2_start(ftdm_span_t *span)
{
ftdm_r2_data_t *r2_data = span->signal_data;
ftdm_set_flag(r2_data, FTDM_R2_RUNNING);
ftdm_set_flag(r2_data, FTDM_R2_SPAN_STARTED);
return ftdm_thread_create_detached(ftdm_r2_run, span);
}
static ftdm_status_t ftdm_r2_stop(ftdm_span_t *span)
{
ftdm_r2_data_t *r2_data = span->signal_data;
ftdm_clear_flag(r2_data, FTDM_R2_SPAN_STARTED);
while (ftdm_test_flag(r2_data, FTDM_R2_RUNNING)) {
ftdm_log(FTDM_LOG_DEBUG, "Waiting for R2 span %s\n", span->name);
ftdm_sleep(100);
@ -444,6 +517,95 @@ static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_channel_sig_status)
return FTDM_SUCCESS;
}
static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_channel_sig_status)
{
openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan;
openr2_cas_signal_t rxcas, txcas;
/* get the current rx and tx cas bits */
openr2_chan_get_cas(r2chan, &rxcas, &txcas);
/* if we're already in the state the user asks us to be, we have nothing to do */
if (status == FTDM_SIG_STATE_SUSPENDED && txcas == OR2_CAS_BLOCK) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Channel signaling status already in BLOCK state\n");
return FTDM_SUCCESS;
}
if (status == FTDM_SIG_STATE_UP && txcas == OR2_CAS_IDLE) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Channel signaling status already in IDLE state\n");
return FTDM_SUCCESS;
}
/* set the signaling as requested and send SIGEVENT_SIGSTATUS_CHANGED, if applicable.
* see docs/sigstatus.txt for details */
switch(status) {
case FTDM_SIG_STATE_SUSPENDED:
openr2_chan_set_blocked(r2chan);
if (rxcas == OR2_CAS_IDLE) {
ftdm_r2_set_chan_sig_status(ftdmchan, status);
}
break;
case FTDM_SIG_STATE_UP:
openr2_chan_set_idle(r2chan);
if (rxcas == OR2_CAS_IDLE) {
ftdm_r2_set_chan_sig_status(ftdmchan, status);
}
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status);
return FTDM_FAIL;
}
return FTDM_SUCCESS;
}
static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_span_sig_status)
{
ftdm_iterator_t *citer = NULL;
ftdm_iterator_t *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);
return FTDM_FAIL;
}
/* if ALL channels are non-idle, report SUSPENDED. UP otherwise. */
*status = FTDM_SIG_STATE_SUSPENDED;
for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) {
ftdm_channel_t *fchan = ftdm_iterator_current(citer);
ftdm_channel_lock(fchan);
if (ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP)) {
*status = FTDM_SIG_STATE_UP;
ftdm_channel_unlock(fchan);
break;
}
ftdm_channel_unlock(fchan);
}
ftdm_iterator_free(chaniter);
return FTDM_SUCCESS;
}
static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_r2_set_span_sig_status)
{
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *citer = NULL;
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);
return FTDM_FAIL;
}
/* iterate over all channels, setting them to the requested state */
for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) {
ftdm_channel_t *fchan = ftdm_iterator_current(citer);
/* we set channel's state through ftdm_r2_set_channel_sig_status(), since it already takes
* care of notifying the user when appropriate */
ftdm_channel_lock(fchan);
if ((ftdm_r2_set_channel_sig_status(fchan, status)) != FTDM_SUCCESS) {
ftdm_log_chan(fchan, FTDM_LOG_ERROR, "Failed to set signaling status to %s\n", ftdm_signaling_status2str(status));
}
ftdm_channel_unlock(fchan);
}
ftdm_iterator_free(chaniter);
return FTDM_SUCCESS;
}
/* always called from the monitor thread */
static void ftdm_r2_on_call_init(openr2_chan_t *r2chan)
{
@ -510,13 +672,21 @@ static void ftdm_r2_on_call_offered(openr2_chan_t *r2chan, const char *ani, cons
ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Call offered with ANI = %s, DNIS = %s, Category = (%d)\n", ani, dnis, category);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
/* nothing went wrong during call setup, MF has ended, we can and must disable the MF dump */
if (r2data->mf_dump_size) {
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_INPUT_DUMP, NULL);
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_OUTPUT_DUMP, NULL);
}
/* check if this is a collect call and if we should accept it */
if (!r2data->allow_collect_calls && category == OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Rejecting collect call\n");
openr2_chan_disconnect_call(r2chan, OR2_CAUSE_COLLECT_CALL_REJECTED);
} else {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
}
ftdmchan->caller_data.cpc = ftdm_openr2_cpc_to_r2_ftdm_cpc(category);
}
/*
@ -556,14 +726,14 @@ static void dump_mf(openr2_chan_t *r2chan)
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO output in prefix %s\n", logname);
snprintf(dfile, sizeof(dfile), logname ? "%s.s%dc%d.input.alaw" : "%s/s%dc%d.input.alaw",
logname ? logname : r2data->logdir, ftdmchan->span_id, ftdmchan->chan_id);
f = fopen(dfile, "w");
f = fopen(dfile, "wb");
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO input in file %s\n", dfile);
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_INPUT, f);
fclose(f);
snprintf(dfile, sizeof(dfile), logname ? "%s.s%dc%d.output.alaw" : "%s/s%dc%d.output.alaw",
logname ? logname : r2data->logdir, ftdmchan->span_id, ftdmchan->chan_id);
f = fopen(dfile, "w");
f = fopen(dfile, "wb");
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dumping IO output in file %s\n", dfile);
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DUMP_OUTPUT, f);
fclose(f);
@ -573,6 +743,8 @@ static void dump_mf(openr2_chan_t *r2chan)
static void ftdm_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t mode)
{
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_NOTICE, "Call accepted\n");
clear_accept_pending(ftdmchan);
@ -595,6 +767,11 @@ static void ftdm_r2_on_call_accepted(openr2_chan_t *r2chan, openr2_call_mode_t m
return;
}
} else {
/* nothing went wrong during call setup, MF has ended, we can and must disable the MF dump */
if (r2data->mf_dump_size) {
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_INPUT_DUMP, NULL);
ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_OUTPUT_DUMP, NULL);
}
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
}
}
@ -653,7 +830,7 @@ static void ftdm_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf
static void ftdm_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
{
ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Alarm notification: %d\n", alarm);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Alarm notification: %d\n", alarm);
}
static void ftdm_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
@ -895,7 +1072,7 @@ static int ftdm_r2_io_write(openr2_chan_t *r2chan, const void *buf, int size)
if (FTDM_FAIL == status) {
return -1;
}
return outsize;
return (int)outsize;
}
static int ftdm_r2_io_read(openr2_chan_t *r2chan, const void *buf, int size)
@ -906,7 +1083,7 @@ static int ftdm_r2_io_read(openr2_chan_t *r2chan, const void *buf, int size)
if (FTDM_FAIL == status) {
return -1;
}
return outsize;
return (int)outsize;
}
static int ftdm_r2_io_wait(openr2_chan_t *r2chan, int *flags, int block)
@ -988,6 +1165,10 @@ static int ftdm_r2_io_get_oob_event(openr2_chan_t *r2chan, openr2_oob_event_t *e
return -1;
}
if (fevent->e_type != FTDM_EVENT_OOB) {
return 0;
}
switch (fevent->enum_id) {
case FTDM_OOB_CAS_BITS_CHANGE:
{
@ -1396,13 +1577,14 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
span->sig_read = NULL;
span->sig_write = NULL;
/* let the core set the states, we just read them */
span->get_channel_sig_status = ftdm_r2_get_channel_sig_status;
span->signal_cb = sig_cb;
span->signal_type = FTDM_SIGTYPE_R2;
span->signal_data = r2data;
span->outgoing_call = r2_outgoing_call;
span->get_span_sig_status = ftdm_r2_get_span_sig_status;
span->set_span_sig_status = ftdm_r2_set_span_sig_status;
span->get_channel_sig_status = ftdm_r2_get_channel_sig_status;
span->set_channel_sig_status = ftdm_r2_set_channel_sig_status;
span->state_map = &r2_state_map;
@ -1593,6 +1775,13 @@ static int ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
}
break;
/* INDICATE_RINGING doesn't apply to MFC/R2. maybe we could generate a tone */
case FTDM_CHANNEL_STATE_RINGING:
{
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "RINGING indicated, ignoring it as it doesn't apply to MFC/R2\n");
}
break;
default:
{
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Unhandled channel state change: %s\n", ftdm_channel_state2str(ftdmchan->state));
@ -1639,9 +1828,13 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
int index = 0;
struct timeval start, end;
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *citer = NULL;
uint32_t txqueue_size = 4;
short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count);
/* as long as this thread is running, this flag is set */
ftdm_set_flag(r2data, FTDM_R2_RUNNING);
#ifdef __linux__
r2data->monitor_thread_id = syscall(SYS_gettid);
#endif
@ -1649,8 +1842,12 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
ftdm_log(FTDM_LOG_DEBUG, "OpenR2 monitor thread %lu started.\n", r2data->monitor_thread_id);
r2chan = NULL;
chaniter = ftdm_span_get_chan_iterator(span, NULL);
for (i = 1; chaniter; chaniter = ftdm_iterator_next(chaniter), i++) {
ftdmchan = ftdm_iterator_current(chaniter);
if (!chaniter) {
ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
goto done;
}
for (i = 1, citer = chaniter; citer; citer = ftdm_iterator_next(citer), i++) {
ftdmchan = ftdm_iterator_current(citer);
r2chan = R2CALL(ftdmchan)->r2chan;
openr2_chan_set_span_id(r2chan, span->span_id);
openr2_chan_set_idle(r2chan);
@ -1660,7 +1857,7 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
memset(&start, 0, sizeof(start));
memset(&end, 0, sizeof(end));
while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_RUNNING)) {
while (ftdm_running() && ftdm_test_flag(r2data, FTDM_R2_SPAN_STARTED)) {
res = gettimeofday(&end, NULL);
if (res) {
ftdm_log(FTDM_LOG_CRIT, "Failure gettimeofday [%s]\n", strerror(errno));
@ -1685,24 +1882,24 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
/* deliver the actual channel events to the user now without any channel locking */
ftdm_span_trigger_signals(span);
#ifndef WIN32
/* figure out what event to poll each channel for. POLLPRI when the channel is down,
* POLLPRI|POLLIN|POLLOUT otherwise */
memset(poll_events, 0, sizeof(short)*span->chan_count);
chaniter = ftdm_span_get_chan_iterator(span, chaniter);
for (i = 0; chaniter; chaniter = ftdm_iterator_next(chaniter), i++) {
ftdmchan = ftdm_iterator_current(chaniter);
citer = ftdm_span_get_chan_iterator(span, chaniter);
if (!citer) {
ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
goto done;
}
for (i = 0; citer; citer = ftdm_iterator_next(citer), i++) {
ftdmchan = ftdm_iterator_current(citer);
r2chan = R2CALL(ftdmchan)->r2chan;
poll_events[i] = POLLPRI;
poll_events[i] = FTDM_EVENTS;
if (openr2_chan_get_read_enabled(r2chan)) {
poll_events[i] |= POLLIN;
poll_events[i] |= FTDM_READ;
}
}
status = ftdm_span_poll_event(span, waitms, poll_events);
#else
status = ftdm_span_poll_event(span, waitms, NULL);
#endif
/* run any span timers */
ftdm_sched_run(r2data->sched);
@ -1732,9 +1929,9 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
/* this main loop takes care of MF and CAS signaling during call setup and tear down
* for every single channel in the span, do not perform blocking operations here! */
chaniter = ftdm_span_get_chan_iterator(span, chaniter);
for ( ; chaniter; chaniter = ftdm_iterator_next(chaniter)) {
ftdmchan = ftdm_iterator_current(chaniter);
citer = ftdm_span_get_chan_iterator(span, chaniter);
for ( ; citer; citer = ftdm_iterator_next(citer)) {
ftdmchan = ftdm_iterator_current(citer);
ftdm_mutex_lock(ftdmchan->mutex);
@ -1761,10 +1958,11 @@ static void *ftdm_r2_run(ftdm_thread_t *me, void *obj)
ftdm_mutex_unlock(ftdmchan->mutex);
}
}
chaniter = ftdm_span_get_chan_iterator(span, chaniter);
for ( ; chaniter; chaniter = ftdm_iterator_next(chaniter)) {
ftdmchan = ftdm_iterator_current(chaniter);
done:
citer = ftdm_span_get_chan_iterator(span, chaniter);
for ( ; citer; citer = ftdm_iterator_next(citer)) {
ftdmchan = ftdm_iterator_current(citer);
r2chan = R2CALL(ftdmchan)->r2chan;
openr2_chan_set_blocked(r2chan);
}
@ -1821,6 +2019,14 @@ static void __inline__ unblock_channel(ftdm_channel_t *fchan, ftdm_stream_handle
ftdm_mutex_unlock(fchan->mutex);
}
#define FT_SYNTAX "USAGE:\n" \
"--------------------------------------------------------------------------------\n" \
"ftdm r2 status <span_id|span_name>\n" \
"ftdm r2 loopstats <span_id|span_name>\n" \
"ftdm r2 block|unblock <span_id|span_name> [<chan_id>]\n" \
"ftdm r2 version\n" \
"ftdm r2 variants\n" \
"--------------------------------------------------------------------------------\n"
static FIO_API_FUNCTION(ftdm_r2_api)
{
ftdm_span_t *span = NULL;
@ -1922,7 +2128,7 @@ static FIO_API_FUNCTION(ftdm_r2_api)
"Max DNIS: %d\n"
"ANI First: %s\n"
"Immediate Accept: %s\n"
"Job Thread: %lu\n"
"Job Thread: %u\n"
"Job Max ms: %d\n"
"Job Loops: %lu\n",
openr2_proto_get_variant_string(r2variant),
@ -2004,14 +2210,6 @@ static FIO_API_FUNCTION(ftdm_r2_api)
}
if (argc == 1) {
if (!strcasecmp(argv[0], "threads")) {
ftdm_mutex_lock(g_thread_count_mutex);
stream->write_function(stream, "%d R2 channel threads up\n", g_thread_count);
ftdm_mutex_unlock(g_thread_count_mutex);
stream->write_function(stream, "+OK.\n");
goto done;
}
if (!strcasecmp(argv[0], "version")) {
stream->write_function(stream, "OpenR2 version: %s, revision: %s\n", openr2_get_version(), openr2_get_revision());
stream->write_function(stream, "+OK.\n");
@ -2037,7 +2235,7 @@ static FIO_API_FUNCTION(ftdm_r2_api)
}
}
stream->write_function(stream, "-ERR invalid command.\n");
stream->write_function(stream, "%s", FT_SYNTAX);
done:
@ -2066,7 +2264,6 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_r2_init)
if (!g_mod_data_hash) {
return FTDM_FAIL;
}
ftdm_mutex_create(&g_thread_count_mutex);
return FTDM_SUCCESS;
}
@ -2086,7 +2283,6 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_r2_destroy)
}
}
hashtable_destroy(g_mod_data_hash);
ftdm_mutex_destroy(&g_thread_count_mutex);
return FTDM_SUCCESS;
}

View File

@ -839,7 +839,7 @@ static void handle_call_released(ftdm_span_t *span, sangomabc_connection_t *mcon
if ((ftdmchan = find_ftdmchan(span, event, 1))) {
ftdm_log(FTDM_LOG_DEBUG, "Releasing completely chan s%dc%d\n", BOOST_EVENT_SPAN(mcon->sigmod, event),
BOOST_EVENT_CHAN(mcon->sigmod, event));
ftdm_channel_done(ftdmchan);
ftdm_channel_close(&ftdmchan);
} else {
ftdm_log(FTDM_LOG_CRIT, "Odd, We could not find chan: s%dc%d to release the call completely!!\n",
BOOST_EVENT_SPAN(mcon->sigmod, event), BOOST_EVENT_CHAN(mcon->sigmod, event));
@ -1105,8 +1105,9 @@ static void handle_call_loop_start(ftdm_span_t *span, sangomabc_connection_t *mc
ftdm_set_state_r(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP, res);
if (res != FTDM_SUCCESS) {
ftdm_channel_t *toclose = ftdmchan;
ftdm_log(FTDM_LOG_CRIT, "yay, could not set the state of the channel to IN_LOOP, loop will fail\n");
ftdm_channel_done(ftdmchan);
ftdm_channel_close(&toclose);
return;
}
ftdm_log(FTDM_LOG_DEBUG, "%d:%d starting loop\n", ftdmchan->span_id, ftdmchan->chan_id);
@ -1426,11 +1427,12 @@ static __inline__ ftdm_status_t state_advance(ftdm_channel_t *ftdmchan)
ftdmchan->sflags = 0;
memset(ftdmchan->call_data, 0, sizeof(sangoma_boost_call_t));
if (sangoma_boost_data->sigmod && call_stopped_ack_sent) {
/* we dont want to call ftdm_channel_done just yet until call released is received */
/* we dont want to call ftdm_channel_close just yet until call released is received */
ftdm_log(FTDM_LOG_DEBUG, "Waiting for call release confirmation before declaring chan %d:%d as available \n",
ftdmchan->span_id, ftdmchan->chan_id);
} else {
ftdm_channel_done(ftdmchan);
ftdm_channel_t *toclose = ftdmchan;
ftdm_channel_close(&toclose);
}
}
break;
@ -2476,7 +2478,7 @@ static BOOST_SIG_STATUS_CB_FUNCTION(ftdm_boost_sig_status_change)
sig.span_id = ftdmchan->span_id;
sig.channel = ftdmchan;
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sig.raw_data = &status;
sig.ev_data.sigstatus.status = status;
ftdm_span_send_signal(ftdmchan->span, &sig);
return;
}

View File

@ -31,6 +31,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define _GNU_SOURCE
#if HAVE_NETDB_H
#include <netdb.h>
#endif

View File

@ -65,7 +65,13 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_ANY_STATE, FTDM_END},
{FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END}
{FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_RESTART, FTDM_END}
},
{
ZSD_INBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_RESET, FTDM_END},
{FTDM_CHANNEL_STATE_DOWN, FTDM_END}
},
{
ZSD_INBOUND,
@ -170,7 +176,13 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_ANY_STATE, FTDM_END},
{FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
{FTDM_CHANNEL_STATE_RESET, FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}
},
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_RESET, FTDM_END},
{FTDM_CHANNEL_STATE_DOWN, FTDM_END}
},
{
ZSD_OUTBOUND,
@ -203,7 +215,7 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_DIALING, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
FTDM_CHANNEL_STATE_PROCEED, FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
FTDM_CHANNEL_STATE_DOWN, FTDM_END}
},
{
@ -211,14 +223,20 @@ ftdm_state_map_t sangoma_isdn_state_map = {
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_PROCEED, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
FTDM_CHANNEL_STATE_RINGING, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
{FTDM_CHANNEL_STATE_RINGING, FTDM_END},
{FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_END},
},
{
ZSD_OUTBOUND,
ZSM_UNACCEPTABLE,
@ -626,8 +644,11 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
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);
sngisdn_snd_proceed(ftdmchan, prog_ind);
}
/* Wait in this state until we get FACILITY msg */
}
@ -666,16 +687,28 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
ftdm_span_send_signal(ftdmchan->span, &sigev);
} 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);
sngisdn_snd_proceed(ftdmchan, prog_ind);
}
}
}
break;
case FTDM_CHANNEL_STATE_RINGING:
{
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
sngisdn_snd_alert(ftdmchan, prog_ind);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
/* OUTBOUND...so we were told by the line of this so notify the user */
sigev.event_id = FTDM_SIGEVENT_RINGING;
ftdm_span_send_signal(ftdmchan->span, &sigev);
if (sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY)) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
}
} else {
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
sngisdn_snd_alert(ftdmchan, prog_ind);
}
}
break;
case FTDM_CHANNEL_STATE_PROGRESS:
@ -686,12 +719,9 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
sigev.event_id = FTDM_SIGEVENT_PROGRESS;
ftdm_span_send_signal(ftdmchan->span, &sigev);
} else {
/* If we already sent a PROCEED before, do not send a PROGRESS as there is nothing to indicate to the remote switch */
if (ftdmchan->last_state != FTDM_CHANNEL_STATE_PROCEED) {
/* Send a progress message, indicating: Call is not end-to-end ISDN, further call progress may be available */
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
sngisdn_snd_progress(ftdmchan, prog_ind);
}
/* Send a progress message, indicating: Call is not end-to-end ISDN, further call progress may be available */
ftdm_sngisdn_progind_t prog_ind = {SNGISDN_PROGIND_LOC_USER, SNGISDN_PROGIND_DESCR_NETE_ISDN};
sngisdn_snd_progress(ftdmchan, prog_ind);
}
}
break;
@ -774,7 +804,7 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
sngisdn_snd_release(ftdmchan, 0);
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
sngisdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
sngisdn_set_span_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
}
} else {
sngisdn_snd_disconnect(ftdmchan);
@ -832,6 +862,11 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
/* IMPLEMENT ME */
}
break;
case FTDM_CHANNEL_STATE_RESET:
{
sngisdn_snd_restart(ftdmchan);
}
break;
default:
{
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "unsupported sngisdn_rcvd state %s\n", ftdm_channel_state2str(ftdmchan->state));
@ -851,6 +886,22 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
return;
}
static FIO_CHANNEL_SEND_MSG_FUNCTION(ftdm_sangoma_isdn_send_msg)
{
ftdm_status_t status = FTDM_FAIL;
switch (sigmsg->event_id) {
case FTDM_SIGEVENT_FACILITY:
sngisdn_snd_fac_req(ftdmchan);
break;
default:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Unsupported signalling msg requested\n");
status = FTDM_BREAK;
}
ftdm_call_clear_data(&ftdmchan->caller_data);
return status;
}
static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_isdn_outgoing_call)
{
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
@ -925,7 +976,8 @@ static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_span_sig_status)
}
static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
{
{
sngisdn_span_data_t *signal_data = span->signal_data;
ftdm_log(FTDM_LOG_INFO,"Starting span %s:%u.\n",span->name,span->span_id);
if (sngisdn_stack_start(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name);
@ -935,6 +987,14 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD);
ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
if (signal_data->raw_trace_q921 == SNGISDN_OPT_TRUE) {
sngisdn_activate_trace(span, SNGISDN_TRACE_Q921);
}
if (signal_data->raw_trace_q931 == SNGISDN_OPT_TRUE) {
sngisdn_activate_trace(span, SNGISDN_TRACE_Q931);
}
/*start the span monitor thread*/
if (ftdm_thread_create_detached(ftdm_sangoma_isdn_run, span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT,"Failed to start Sangoma ISDN Span Monitor Thread!\n");
@ -1030,6 +1090,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
span->stop = ftdm_sangoma_isdn_stop;
span->signal_type = FTDM_SIGTYPE_ISDN;
span->outgoing_call = ftdm_sangoma_isdn_outgoing_call;
span->send_msg = ftdm_sangoma_isdn_send_msg;
span->channel_request = NULL;
span->signal_cb = sig_cb;
span->get_channel_sig_status = ftdm_sangoma_isdn_get_chan_sig_status;
@ -1040,11 +1101,12 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE);
ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE);
ftdm_set_flag(span, FTDM_SPAN_USE_PROCEED_STATE);
ftdm_set_flag(span, FTDM_SPAN_USE_SKIP_STATES);
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
span->trunk_type == FTDM_TRUNK_BRI) {
sngisdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
sngisdn_set_span_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING);
}
/* Initialize scheduling context */
@ -1139,6 +1201,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
goto done;
}
/* TODO: Move functions to table + function pointers */
if (!strcasecmp(argv[0], "trace")) {
char *trace_opt;
@ -1156,6 +1219,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
stream->write_function(stream, "-ERR failed to find span by name %s\n", argv[2]);
goto done;
}
if (!strcasecmp(trace_opt, "q921")) {
sngisdn_activate_trace(span, SNGISDN_TRACE_Q921);
} else if (!strcasecmp(trace_opt, "q931")) {
@ -1164,7 +1228,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
sngisdn_activate_trace(span, SNGISDN_TRACE_DISABLE);
} else {
stream->write_function(stream, "-ERR invalid trace option <q921|q931> <span name>\n");
}
}
}
if (!strcasecmp(argv[0], "l1_stats")) {
ftdm_span_t *span;
@ -1182,7 +1246,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
}
sngisdn_print_phy_stats(stream, span);
}
if (!strcasecmp(argv[0], "show_spans")) {
ftdm_span_t *span = NULL;
if (argc == 2) {

View File

@ -101,9 +101,11 @@ typedef enum {
FLAG_GLARE = (1 << 6),
FLAG_DELAYED_REL = (1 << 7),
FLAG_SENT_PROCEED = (1 << 8),
FLAG_SEND_DISC = (1 << 9),
FLAG_SEND_DISC = (1 << 9),
/* Used for BRI only, flag is set after we request line CONNECTED */
FLAG_ACTIVATING = (1 << 10),
FLAG_ACTIVATING = (1 << 10),
/* Used when we receive an ALERT msg + inband tones ready */
FLAG_MEDIA_READY = (1 << 11),
} sngisdn_flag_t;
@ -259,6 +261,8 @@ typedef struct sngisdn_span_data {
int8_t facility_timeout;
uint8_t num_local_numbers;
uint8_t ignore_cause_value;
uint8_t raw_trace_q931;
uint8_t raw_trace_q921;
uint8_t timer_t3;
uint8_t restart_opt;
char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS];
@ -352,8 +356,11 @@ void clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info);
ftdm_status_t get_ftdmchan_by_suInstId(int16_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data);
ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data);
ftdm_status_t sngisdn_set_span_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail);
ftdm_status_t sngisdn_set_chan_avail_rate(ftdm_channel_t *chan, sngisdn_avail_t avail);
void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status);
void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status);
ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail);
ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
@ -363,7 +370,7 @@ void stack_pst_init(Pst *pst);
/* Outbound Call Control functions */
void sngisdn_snd_setup(ftdm_channel_t *ftdmchan);
void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan);
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan);
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind);
void sngisdn_snd_connect(ftdm_channel_t *ftdmchan);
@ -374,6 +381,7 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan);
void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan);
void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan);
void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan);
void sngisdn_snd_restart(ftdm_channel_t *ftdmchan);
void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len);
void sngisdn_snd_event(ftdm_channel_t *dchan, ftdm_oob_event_t event);
@ -421,8 +429,11 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event);
void sngisdn_rcv_phy_ind(SuId suId, Reason reason);
void sngisdn_rcv_q921_ind(BdMngmt *status);
void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
void sngisdn_trace_interpreted_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
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);
ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
@ -436,6 +447,7 @@ void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...);
void sngisdn_rcv_sng_assert(char *message);
ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb);
ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb);
ftdm_status_t get_calling_name_from_display(ftdm_channel_t *ftdmchan, Display *display);
@ -443,16 +455,20 @@ ftdm_status_t get_calling_name_from_usr_usr(ftdm_channel_t *ftdmchan, UsrUsr *us
ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad);
ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd);
ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr);
ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t data_len);
ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t data_len);
ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb);
ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb);
ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb);
ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt);
ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad);
ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_sngisdn_progind_t prog_ind);
ftdm_status_t set_bear_cap_ie(ftdm_channel_t *ftdmchan, BearCap *bearCap);
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, ftdm_size_t *data_len);
ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len);
uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability);
@ -480,7 +496,6 @@ static __inline__ void sngisdn_set_flag(sngisdn_chan_data_t *sngisdn_info, sngis
void handle_sng_log(uint8_t level, char *fmt,...);
void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status);
void sngisdn_delayed_setup(void* p_sngisdn_info);
void sngisdn_delayed_release(void* p_sngisdn_info);
void sngisdn_delayed_connect(void* p_sngisdn_info);

View File

@ -296,6 +296,10 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
parse_yesno(var, val, &signal_data->facility_ie_decode);
} else if (!strcasecmp(var, "ignore-cause-value")) {
parse_yesno(var, val, &signal_data->ignore_cause_value);
} else if (!strcasecmp(var, "q931-raw-trace")) {
parse_yesno(var, val, &signal_data->raw_trace_q931);
} else if (!strcasecmp(var, "q921-raw-trace")) {
parse_yesno(var, val, &signal_data->raw_trace_q921);
} else {
ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
}

View File

@ -47,7 +47,7 @@ void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status
sig.span_id = ftdmchan->span_id;
sig.channel = ftdmchan;
sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sig.sigstatus = status;
sig.ev_data.sigstatus.status = status;
ftdm_span_send_signal(ftdmchan->span, &sig);
return;
}

View File

@ -33,7 +33,8 @@
*/
#include "ftmod_sangoma_isdn.h"
ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn);
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);
/* Remote side transmit a SETUP */
void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
@ -123,12 +124,9 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
break;
}
#if 0
/* Export ftdmchan variables here if we need to */
ftdm_channel_add_var(ftdmchan, "isdn_specific_var", "1");
#endif
/* Fill in call information */
get_calling_num(ftdmchan, &conEvnt->cgPtyNmb);
get_calling_num2(ftdmchan, &conEvnt->cgPtyNmb2);
get_called_num(ftdmchan, &conEvnt->cdPtyNmb);
get_redir_num(ftdmchan, &conEvnt->redirNmb);
get_calling_subaddr(ftdmchan, &conEvnt->cgPtySad);
@ -235,6 +233,9 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
}
break;
case FTDM_CHANNEL_STATE_RESET:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing SETUP in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
break;
@ -277,6 +278,7 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_RINGING:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_DIALING:
@ -288,6 +290,9 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
case FTDM_CHANNEL_STATE_HANGUP:
/* Race condition, we just hung up the call - ignore this message */
break;
case FTDM_CHANNEL_STATE_RESET:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
@ -304,6 +309,9 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* Race condition, We just hung up an incoming call right after we sent a CONNECT - ignore this message */
break;
case FTDM_CHANNEL_STATE_RESET:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
@ -357,27 +365,47 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
goto sngisdn_process_cnst_ind_end;
}
switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_DIALING:
case FTDM_CHANNEL_STATE_PROCEED:
if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
} else if (evntType == MI_CALLPROC) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED);
} else {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_RINGING:
if (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
sngisdn_set_flag(sngisdn_info, FLAG_MEDIA_READY);
}
switch (evntType) {
case MI_CALLPROC:
if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROCEED);
}
break;
case MI_ALERTING:
if (ftdmchan->state == FTDM_CHANNEL_STATE_PROCEED) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RINGING);
}
break;
case MI_PROGRESS:
if (sngisdn_test_flag(sngisdn_info, FLAG_MEDIA_READY)) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
} else if (ftdmchan->state != FTDM_CHANNEL_STATE_PROGRESS) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
}
break;
default:
/* We should never reach this section !*/
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle this event %d\n", evntType);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
/* We are already in progress media, we can't go to any higher state except up */
/* Do nothing */
break;
case FTDM_CHANNEL_STATE_RESET:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing ALERT/PROCEED/PROGRESS in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
@ -410,12 +438,16 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
}
break;
case FTDM_CHANNEL_STATE_RING:
case FTDM_CHANNEL_STATE_RINGING:
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_UP:
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Receiving more digits %s, but we already proceeded with call\n", cnStEvnt->cdPtyNmb.nmbDigits.val);
break;
case FTDM_CHANNEL_STATE_RESET:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "\n", suId, suInstId, spInstId);
break;
@ -450,6 +482,7 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event)
ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_RING:
case FTDM_CHANNEL_STATE_RINGING:
case FTDM_CHANNEL_STATE_DIALING:
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
@ -478,6 +511,9 @@ void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event)
/* This is a race condition. We just sent a DISCONNECT, on this channel */
/* Do nothing */
break;
case FTDM_CHANNEL_STATE_RESET:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received DISCONNECT in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
@ -532,7 +568,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
case FTDM_CHANNEL_STATE_DIALING:
/* Remote side rejected our SETUP message on outbound call */
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
sngisdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
sngisdn_set_span_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
}
/* fall-through */
case FTDM_CHANNEL_STATE_PROCEED:
@ -540,6 +576,7 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_UP:
case FTDM_CHANNEL_STATE_RING:
case FTDM_CHANNEL_STATE_RINGING:
/* If we previously had a glare on this channel,
this RELEASE could be for the previous call. Confirm whether call_data has
not changed while we were waiting for ftdmchan->mutex by comparing suInstId's */
@ -581,6 +618,9 @@ void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
/* set abort flag so that we do not transmit another release complete on this channel once FS core is done */
}
break;
case FTDM_CHANNEL_STATE_RESET:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP but channel in RESET state, ignoring\n");
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RELEASE in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
@ -757,14 +797,14 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
{
ftdm_sigmsg_t sigev;
if (facEvnt->facElmt.facStr.pres) {
get_facility_ie_str(ftdmchan, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len);
get_facility_ie_str(ftdmchan, &facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len-2);
}
memset(&sigev, 0, sizeof(sigev));
sigev.chan_id = ftdmchan->chan_id;
sigev.span_id = ftdmchan->span_id;
sigev.channel = ftdmchan;
sigev.event_id = FTDM_SIGEVENT_MSG;
sigev.event_id = FTDM_SIGEVENT_FACILITY;
ftdm_span_send_signal(ftdmchan->span, &sigev);
}
break;
@ -884,6 +924,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
break;
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_RINGING:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Remote switch expecting OVERLAP receive, but we are already PROCEEDING\n");
sngisdn_snd_disconnect(ftdmchan);
@ -902,6 +943,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_RINGING:
/* T310 timer has expired */
ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T310 Timer expired, hanging up call\n");
@ -938,6 +980,7 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
break;
case 9: /* Remote switch is in "Incoming call proceeding" state */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_RINGING:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_GET_CALLERID:
@ -1047,18 +1090,91 @@ void sngisdn_process_srv_cfm (sngisdn_event_data_t *sngisdn_event)
return;
}
static void sngisdn_process_restart_confirm(ftdm_channel_t *ftdmchan)
{
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_RESET:
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
break;
case FTDM_CHANNEL_STATE_DOWN:
/* Do nothing */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RESTART CFM in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
}
return;
}
void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
{
int16_t suId = sngisdn_event->suId;
int16_t dChan = sngisdn_event->dChan;
uint8_t ces = sngisdn_event->ces;
uint8_t evntType = sngisdn_event->evntType;
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
/* Function does not require any info from ssHlEvnt struct for now */
/*Rst *rstEvnt = &sngisdn_event->event.rstEvnt;*/
uint8_t chan_no = 0;
Rst *rstEvnt = &sngisdn_event->event.rstEvnt;
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);
return;
}
if (!rstEvnt->rstInd.eh.pres || !rstEvnt->rstInd.rstClass.pres) {
ftdm_log(FTDM_LOG_DEBUG, "Receved RESTART, 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 on invalid channel:%d\n", chan_no);
} else {
ftdm_channel_t *ftdmchan = ftdm_span_get_channel(signal_data->ftdm_span, chan_no);
sngisdn_process_restart_confirm(ftdmchan);
}
} 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_process_restart_confirm((ftdm_channel_t*)ftdm_iterator_current(curr));
}
ftdm_iterator_free(chaniter);
}
ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART CFM (suId:%u dChan:%d ces:%d type:%d)\n", suId, dChan, ces, evntType);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
@ -1087,7 +1203,7 @@ void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
return;
}
ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn)
static ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;

View File

@ -51,72 +51,6 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
ftdm_mutex_unlock(g_sngisdn_data.ccs[signal_data->cc_id].mutex);
memset(&conEvnt, 0, sizeof(conEvnt));
conEvnt.bearCap[0].eh.pres = PRSNT_NODEF;
conEvnt.bearCap[0].infoTranCap.pres = PRSNT_NODEF;
conEvnt.bearCap[0].infoTranCap.val = sngisdn_get_infoTranCap_from_user(ftdmchan->caller_data.bearer_capability);
conEvnt.bearCap[0].codeStand0.pres = PRSNT_NODEF;
conEvnt.bearCap[0].codeStand0.val = IN_CSTD_CCITT;
conEvnt.bearCap[0].infoTranRate0.pres = PRSNT_NODEF;
conEvnt.bearCap[0].infoTranRate0.val = IN_ITR_64KBIT;
conEvnt.bearCap[0].tranMode.pres = PRSNT_NODEF;
conEvnt.bearCap[0].tranMode.val = IN_TM_CIRCUIT;
conEvnt.chanId.eh.pres = PRSNT_NODEF;
conEvnt.chanId.prefExc.pres = PRSNT_NODEF;
conEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
conEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
conEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
conEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
conEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
conEvnt.chanId.intIdent.pres = NOTPRSNT;
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
/* Trillium stack rejests lyr1Ident on BRI, but Netbricks always sends it.
Check with Trillium if this ever causes calls to fail in the field */
/* BRI only params */
conEvnt.chanId.intType.pres = PRSNT_NODEF;
conEvnt.chanId.intType.val = IN_IT_BASIC;
conEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
conEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
} else {
/* PRI only params */
conEvnt.bearCap[0].usrInfoLyr1Prot.pres = PRSNT_NODEF;
conEvnt.bearCap[0].usrInfoLyr1Prot.val = sngisdn_get_usrInfoLyr1Prot_from_user(ftdmchan->caller_data.bearer_layer1);
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN &&
conEvnt.bearCap[0].usrInfoLyr1Prot.val == IN_UIL1_G711ULAW) {
/* We are bridging a call from T1 */
conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ALAW;
} else if (conEvnt.bearCap[0].usrInfoLyr1Prot.val == IN_UIL1_G711ALAW) {
/* We are bridging a call from E1 */
conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ULAW;
}
conEvnt.bearCap[0].lyr1Ident.pres = PRSNT_NODEF;
conEvnt.bearCap[0].lyr1Ident.val = IN_L1_IDENT;
conEvnt.chanId.intType.pres = PRSNT_NODEF;
conEvnt.chanId.intType.val = IN_IT_OTHER;
conEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
conEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
conEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
conEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
conEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
conEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
conEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
conEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
conEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
conEvnt.chanId.chanNmbSlotMap.len = 1;
conEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) {
conEvnt.sndCmplt.eh.pres = PRSNT_NODEF;
}
@ -126,8 +60,11 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Outgoing call: Called No:[%s] Calling No:[%s]\n", ftdmchan->caller_data.dnis.digits, ftdmchan->caller_data.cid_num.digits);
set_chan_id_ie(ftdmchan, &conEvnt.chanId);
set_bear_cap_ie(ftdmchan, &conEvnt.bearCap[0]);
set_called_num(ftdmchan, &conEvnt.cdPtyNmb);
set_calling_num(ftdmchan, &conEvnt.cgPtyNmb);
set_calling_num2(ftdmchan, &conEvnt.cgPtyNmb2);
set_calling_subaddr(ftdmchan, &conEvnt.cgPtySad);
set_redir_num(ftdmchan, &conEvnt.redirNmb);
set_calling_name(ftdmchan, &conEvnt);
@ -160,38 +97,7 @@ void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan)
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
/* BRI only params */
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_BASIC;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
} else {
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_OTHER;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP ACK (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);
@ -220,38 +126,7 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan)
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
/* BRI only params */
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_BASIC;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
} else {
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_OTHER;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
set_chan_id_ie(ftdmchan, &cnStEvnt.chanId);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT COMPL (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);
@ -262,10 +137,9 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan)
}
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan)
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind)
{
CnStEvnt cnStEvnt;
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
@ -277,40 +151,12 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan)
}
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
/* BRI only params */
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_BASIC;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
} else {
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_OTHER;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
set_chan_id_ie(ftdmchan, &cnStEvnt.chanId);
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
ftdm_call_clear_data(&ftdmchan->caller_data);
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);
@ -343,6 +189,7 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_PROGRESS, signal_data->dchan_id, sngisdn_info->ces)) {
@ -369,6 +216,7 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan, ftdm_sngisdn_progind_t prog_ind
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending ALERT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
@ -393,41 +241,11 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
}
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
/* BRI only params */
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_BASIC;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
} else {
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_OTHER;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
set_chan_id_ie(ftdmchan, &cnStEvnt.chanId);
set_prog_ind_ie(ftdmchan, &cnStEvnt.progInd, prog_ind);
set_facility_ie(ftdmchan, &cnStEvnt.facilityStr);
ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_con_response(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
@ -450,10 +268,17 @@ void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan)
memset(&facEvnt, 0, sizeof(facEvnt));
set_facility_ie_str(ftdmchan, &facEvnt.facElmt.facStr.val[2], (ftdm_size_t*)&facEvnt.facElmt.facStr.len);
if (set_facility_ie_str(ftdmchan, &facEvnt.facElmt.facStr.val[2], (uint8_t*)&facEvnt.facElmt.facStr.len) != FTDM_SUCCESS) {
/* No point in sending a FACILITY message if there is no Facility IE to transmit */
return;
}
ftdm_call_clear_data(&ftdmchan->caller_data);
facEvnt.facElmt.eh.pres = PRSNT_NODEF;
facEvnt.facElmt.facStr.pres = PRSNT_NODEF;
facEvnt.facElmt.facStr.val[0] = 0x1C;
facEvnt.facElmt.facStr.val[1] = facEvnt.facElmt.facStr.len;
facEvnt.facElmt.facStr.val[1] = (uint8_t)facEvnt.facElmt.facStr.len;
facEvnt.facElmt.facStr.len +=2; /* Need to include the size of identifier + len */
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending FACILITY (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
@ -481,6 +306,8 @@ void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan)
//ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ\n");
ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_con_status(signal_data->cc_id, 0, 0, &cnStEvnt, MI_INFO, signal_data->dchan_id, sngisdn_info->ces)) {
@ -501,6 +328,8 @@ void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan)
memset(&staEvnt, 0, sizeof(StaEvnt));
ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Status ENQ on suId:%d suInstId:%u spInstId:%d 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_status_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &staEvnt, MI_STATENQ)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused Status ENQ request\n");
@ -539,6 +368,7 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT;
set_facility_ie(ftdmchan, &discEvnt.facilityStr);
ftdm_call_clear_data(&ftdmchan->caller_data);
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)) {
@ -546,6 +376,7 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
}
return;
}
void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
{
RelEvnt relEvnt;
@ -585,6 +416,7 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
}
set_facility_ie(ftdmchan, &relEvnt.facilityStr);
ftdm_call_clear_data(&ftdmchan->caller_data);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, suInstId, spInstId);
@ -600,6 +432,24 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
return;
}
void sngisdn_snd_restart(ftdm_channel_t *ftdmchan)
{
Rst rstEvnt;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
memset(&rstEvnt, 0, sizeof(rstEvnt));
set_chan_id_ie(ftdmchan, &rstEvnt.chanId);
set_restart_ind_ie(ftdmchan, &rstEvnt.rstInd);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RESTART (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, signal_data->dchan_id, CES_MNGMNT);
if (sng_isdn_restart_request(signal_data->cc_id, &rstEvnt, signal_data->dchan_id, CES_MNGMNT, IN_SND_RST)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused RESTART request\n");
}
return;
}
/* We received an incoming frame on the d-channel, send data to the stack */
void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len)

View File

@ -34,9 +34,6 @@
#include "ftmod_sangoma_isdn.h"
#define MAX_DECODE_STR_LEN 2000
void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces)
{
uint8_t bchan_no = 0;
@ -630,8 +627,9 @@ void sngisdn_rcv_rst_cfm (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received RESTART CFM (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType);
/* Enqueue the event to each span within the dChan */
for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
signal_data = g_sngisdn_data.dchans[dChan].spans[i];
@ -725,14 +723,25 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
ftdmspan = signal_data->ftdm_span;
if (status->t.usta.alarm.event == LCM_EVENT_UP) {
uint32_t chan_no = status->t.usta.evntParm[2];
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
status->t.usta.suId,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_UP);
sngisdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_UP);
if (chan_no) {
ftdm_channel_t *ftdmchan = ftdm_span_get_channel(ftdmspan, chan_no);
if (ftdmchan) {
sngisdn_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
sngisdn_set_chan_avail_rate(ftdmchan, SNGISDN_AVAIL_UP);
} else {
ftdm_log(FTDM_LOG_CRIT, "stack alarm event on invalid channel :%d\n", chan_no);
}
} else {
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_UP);
sngisdn_set_span_avail_rate(ftdmspan, SNGISDN_AVAIL_UP);
}
} else {
ftdm_log(FTDM_LOG_WARNING, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
status->t.usta.suId,
@ -741,7 +750,7 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_DOWN);
sngisdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
sngisdn_set_span_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
}
}
break;
@ -765,9 +774,6 @@ void sngisdn_rcv_cc_ind(CcMngmt *status)
return;
}
#define Q931_TRC_EVENT(event) (event == TL3PKTTX)?"TX": \
(event == TL3PKTRX)?"RX":"UNKNOWN"
void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
{
MsgLen mlen;
@ -776,13 +782,20 @@ void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
Buffer *tmp;
Data *cptr;
uint8_t data;
ftdm_trace_dir_t dir;
uint8_t tdata[1000];
char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[trc->t.trc.suId];
ftdm_assert(mBuf != NULLP, "Received a Q931 trace with no buffer");
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
if (mlen != 0) {
if (trc->t.trc.evnt == TL3PKTTX) {
dir = FTDM_TRACE_OUTGOING;
} else {
dir = FTDM_TRACE_INCOMING;
}
if (mlen) {
tmp = mBuf->b_cont;
cptr = tmp->b_rptr;
data = *cptr++;
@ -797,41 +810,40 @@ void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
}
data = *cptr++;
}
sngisdn_trace_q931(data_str, tdata, mlen);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] s%d FRAME %s:%s\n", trc->t.trc.suId, Q931_TRC_EVENT(trc->t.trc.evnt), data_str);
if (signal_data->raw_trace_q931 == SNGISDN_OPT_TRUE) {
sngisdn_trace_raw_q931(signal_data, dir, tdata, mlen);
} else {
sngisdn_trace_interpreted_q931(signal_data, dir, tdata, mlen);
}
}
ftdm_safe_free(data_str);
/* We do not need to free mBuf in this case because stack does it */
/* SPutMsg(mBuf); */
return;
}
#define Q921_TRC_EVENT(event) (event == TL2FRMRX)?"RX": \
(event == TL2FRMTX)?"TX": \
(event == TL2TMR)?"TMR EXPIRED":"UNKNOWN"
void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
{
MsgLen mlen;
Buffer *tmp;
MsgLen i;
int16_t j;
Buffer *tmp;
Data *cptr;
uint8_t data;
uint8_t tdata[16];
char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
ftdm_trace_dir_t dir;
uint8_t tdata[1000];
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[trc->t.trc.lnkNmb];
if (trc->t.trc.evnt == TL2TMR) {
goto end_of_trace;
return;
}
if (trc->t.trc.evnt == TL2FRMTX) {
dir = FTDM_TRACE_OUTGOING;
} else {
dir = FTDM_TRACE_INCOMING;
}
ftdm_assert(mBuf != NULLP, "Received a Q921 trace with no buffer");
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
if (mlen != 0) {
tmp = mBuf->b_cont;
cptr = tmp->b_rptr;
@ -853,12 +865,12 @@ void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
}
}
sngisdn_trace_q921(data_str, tdata, mlen);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] s%d FRAME %s:%s\n", trc->t.trc.lnkNmb, Q921_TRC_EVENT(trc->t.trc.evnt), data_str);
if (signal_data->raw_trace_q921 == SNGISDN_OPT_TRUE) {
sngisdn_trace_raw_q921(signal_data, dir, tdata, mlen);
} else {
sngisdn_trace_interpreted_q921(signal_data, dir, tdata, mlen);
}
}
end_of_trace:
ftdm_safe_free(data_str);
SPutMsg(mBuf);
return;
}

View File

@ -136,19 +136,25 @@ ftdm_status_t get_ftdmchan_by_spInstId(int16_t cc_id, uint32_t spInstId, sngisdn
return FTDM_SUCCESS;
}
ftdm_status_t sngisdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail)
ftdm_status_t sngisdn_set_chan_avail_rate(ftdm_channel_t *chan, sngisdn_avail_t avail)
{
if (span->trunk_type == FTDM_TRUNK_BRI ||
span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
if (FTDM_SPAN_IS_BRI(chan->span)) {
ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Setting availability rate to:%d\n", avail);
chan->availability_rate = avail;
}
return FTDM_SUCCESS;
}
ftdm_status_t sngisdn_set_span_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail)
{
if (FTDM_SPAN_IS_BRI(span)) {
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdm_log_chan(((ftdm_channel_t*)ftdm_iterator_current(curr)), FTDM_LOG_DEBUG, "Setting availability rate to:%d\n", avail);
((ftdm_channel_t*)ftdm_iterator_current(curr))->availability_rate = avail;
sngisdn_set_chan_avail_rate(((ftdm_channel_t*)ftdm_iterator_current(curr)), avail);
}
ftdm_iterator_free(chaniter);
}
@ -185,6 +191,39 @@ ftdm_status_t get_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
return FTDM_SUCCESS;
}
ftdm_status_t get_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (cgPtyNmb->eh.pres != PRSNT_NODEF) {
return FTDM_FAIL;
}
if (cgPtyNmb->screenInd.pres == PRSNT_NODEF) {
ftdm_call_add_var(caller_data, "isdn.cg_pty2.screen_ind", ftdm_screening2str(cgPtyNmb->screenInd.val));
}
if (cgPtyNmb->presInd0.pres == PRSNT_NODEF) {
ftdm_call_add_var(caller_data, "isdn.cg_pty2.presentation_ind", ftdm_presentation2str(cgPtyNmb->presInd0.val));
}
if (cgPtyNmb->nmbPlanId.pres == PRSNT_NODEF) {
ftdm_call_add_var(caller_data, "isdn.cg_pty2.npi", ftdm_npi2str(cgPtyNmb->nmbPlanId.val));
}
if (cgPtyNmb->typeNmb1.pres == PRSNT_NODEF) {
ftdm_call_add_var(caller_data, "isdn.cg_pty2.ton", ftdm_ton2str(cgPtyNmb->typeNmb1.val));
}
if (cgPtyNmb->nmbDigits.pres == PRSNT_NODEF) {
char digits_string [32];
memcpy(digits_string, (const char*)cgPtyNmb->nmbDigits.val, cgPtyNmb->nmbDigits.len);
digits_string[cgPtyNmb->nmbDigits.len] = '\0';
ftdm_call_add_var(caller_data, "isdn.cg_pty2.digits", digits_string);
}
memcpy(&caller_data->ani, &caller_data->cid_num, sizeof(caller_data->ani));
return FTDM_SUCCESS;
}
ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
@ -278,7 +317,7 @@ ftdm_status_t get_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
memcpy(subaddress, (char*)cgPtySad->sadInfo.val, cgPtySad->sadInfo.len);
subaddress[cgPtySad->sadInfo.len] = '\0';
ftdm_channel_add_var(ftdmchan, "isdn.calling_subaddr", subaddress);
ftdm_call_add_var(&ftdmchan->caller_data, "isdn.calling_subaddr", subaddress);
return FTDM_SUCCESS;
}
@ -291,17 +330,16 @@ ftdm_status_t get_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr
return get_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, facilityStr->facilityStr.len);
}
ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t data_len)
ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t data_len)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
if (signal_data->facility_ie_decode == SNGISDN_OPT_FALSE) {
if (data_len > sizeof(caller_data->raw_data)-2) {
ftdm_log(FTDM_LOG_CRIT, "Length of Facility IE exceeds maximum length\n");
return FTDM_FAIL;
}
/* size of facilityStr->facilityStr.len is a uint8_t so no need to check
for overflow here as facilityStr->facilityStr.len will always be smaller
than sizeof(caller_data->raw_data) */
memset(caller_data->raw_data, 0, sizeof(caller_data->raw_data));
/* Always include Facility IE identifier + len so this can be used as a sanity check by the user */
caller_data->raw_data[0] = SNGISDN_Q931_FACILITY_IE_ID;
@ -348,7 +386,7 @@ ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd)
val = SNGISDN_PROGIND_DESCR_INVALID;
break;
}
ftdm_channel_add_var(ftdmchan, "isdn.prog_ind.descr", ftdm_sngisdn_progind_descr2str(val));
ftdm_call_add_var(&ftdmchan->caller_data, "isdn.prog_ind.descr", ftdm_sngisdn_progind_descr2str(val));
}
if (progInd->location.pres) {
@ -379,7 +417,7 @@ ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd)
val = SNGISDN_PROGIND_LOC_INVALID;
break;
}
ftdm_channel_add_var(ftdmchan, "isdn.prog_ind.loc", ftdm_sngisdn_progind_loc2str(val));
ftdm_call_add_var(&ftdmchan->caller_data, "isdn.prog_ind.loc", ftdm_sngisdn_progind_loc2str(val));
}
return FTDM_SUCCESS;
}
@ -423,6 +461,89 @@ ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
return FTDM_SUCCESS;
}
ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
{
const char* string = NULL;
uint8_t len,val;
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.digits");
if ((string == NULL) || !(*string)) {
return FTDM_FAIL;
}
cgPtyNmb->eh.pres = PRSNT_NODEF;
len = strlen(string);
cgPtyNmb->nmbDigits.len = len;
cgPtyNmb->nmbDigits.pres = PRSNT_NODEF;
memcpy(cgPtyNmb->nmbDigits.val, string, len);
/* Screening Indicator */
cgPtyNmb->screenInd.pres = PRSNT_NODEF;
val = FTDM_SCREENING_INVALID;
string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.screening_ind");
if ((string != NULL) && (*string)) {
val = ftdm_str2ftdm_screening(string);
}
/* isdn.cg_pty2.screen_ind does not exist or we could not parse its value */
if (val == FTDM_SCREENING_INVALID) {
/* default to caller data screening ind */
cgPtyNmb->screenInd.val = caller_data->screen;
} else {
cgPtyNmb->screenInd.val = val;
}
/* Presentation Indicator */
cgPtyNmb->presInd0.pres = PRSNT_NODEF;
val = FTDM_PRES_INVALID;
string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.presentation_ind");
if ((string != NULL) && (*string)) {
val = ftdm_str2ftdm_presentation(string);
}
if (val == FTDM_PRES_INVALID) {
cgPtyNmb->presInd0.val = caller_data->pres;
} else {
cgPtyNmb->presInd0.val = val;
}
/* Numbering Plan Indicator */
cgPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
val = FTDM_NPI_INVALID;
string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.npi");
if ((string != NULL) && (*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->typeNmb1.pres = PRSNT_NODEF;
/* Type of Number */
val = FTDM_TON_INVALID;
string = ftdm_call_get_var(caller_data, "isdn.cg_pty2.ton");
if ((string != NULL) && (*string)) {
val = ftdm_str2ftdm_ton(string);
}
if (val == FTDM_TON_INVALID) {
cgPtyNmb->typeNmb1.val = caller_data->cid_num.type;
} else {
cgPtyNmb->typeNmb1.val = val;
}
return FTDM_SUCCESS;
}
ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
@ -544,7 +665,7 @@ ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt)
ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
{
const char* clg_subaddr = NULL;
clg_subaddr = ftdm_channel_get_var(ftdmchan, "isdn.calling_subaddr");
clg_subaddr = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.calling_subaddr");
if ((clg_subaddr != NULL) && (*clg_subaddr)) {
unsigned len = strlen (clg_subaddr);
cgPtySad->eh.pres = PRSNT_NODEF;
@ -561,11 +682,10 @@ ftdm_status_t set_calling_subaddr(ftdm_channel_t *ftdmchan, CgPtySad *cgPtySad)
return FTDM_SUCCESS;
}
ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr)
{
ftdm_status_t status;
status = set_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, (ftdm_size_t*)&facilityStr->facilityStr.len);
status = set_facility_ie_str(ftdmchan, facilityStr->facilityStr.val, (uint8_t*)&(facilityStr->facilityStr.len));
if (status == FTDM_SUCCESS) {
facilityStr->eh.pres = PRSNT_NODEF;
facilityStr->facilityStr.pres = PRSNT_NODEF;
@ -573,13 +693,15 @@ ftdm_status_t set_facility_ie(ftdm_channel_t *ftdmchan, FacilityStr *facilityStr
return status;
}
ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, ftdm_size_t *data_len)
ftdm_status_t set_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8_t *data_len)
{
int len;
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
if (caller_data->raw_data_len > 0 && caller_data->raw_data[0] == SNGISDN_Q931_FACILITY_IE_ID) {
*data_len = caller_data->raw_data[1];
memcpy(data, &caller_data->raw_data[2], *data_len);
len = caller_data->raw_data[1];
memcpy(data, &caller_data->raw_data[2], len);
*data_len = len;
return FTDM_SUCCESS;
}
return FTDM_FAIL;
@ -591,7 +713,7 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s
int descr = prog_ind.descr;
int loc = prog_ind.loc;
str = ftdm_channel_get_var(ftdmchan, "isdn.prog_ind.descr");
str = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.prog_ind.descr");
if (str && *str) {
/* User wants to override progress indicator */
descr = ftdm_str2ftdm_sngisdn_progind_descr(str);
@ -602,8 +724,8 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s
return FTDM_SUCCESS;
}
str = ftdm_channel_get_var(ftdmchan, "isdn.prog_ind.loc");
if (str && *str) {
str = ftdm_call_get_var(&ftdmchan->caller_data, "isdn.prog_ind.loc");
if (str && *str) {
loc = ftdm_str2ftdm_sngisdn_progind_loc(str);
}
if (loc == SNGISDN_PROGIND_LOC_INVALID) {
@ -672,6 +794,93 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s
return FTDM_SUCCESS;
}
ftdm_status_t set_chan_id_ie(ftdm_channel_t *ftdmchan, ChanId *chanId)
{
if (!ftdmchan) {
return FTDM_SUCCESS;
}
chanId->eh.pres = PRSNT_NODEF;
chanId->prefExc.pres = PRSNT_NODEF;
chanId->prefExc.val = IN_PE_EXCLSVE;
chanId->dChanInd.pres = PRSNT_NODEF;
chanId->dChanInd.val = IN_DSI_NOTDCHAN;
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) {
/* BRI only params */
chanId->intType.pres = PRSNT_NODEF;
chanId->intType.val = IN_IT_BASIC;
chanId->infoChanSel.pres = PRSNT_NODEF;
chanId->infoChanSel.val = ftdmchan->physical_chan_id;
} else {
chanId->intType.pres = PRSNT_NODEF;
chanId->intType.val = IN_IT_OTHER;
chanId->infoChanSel.pres = PRSNT_NODEF;
chanId->infoChanSel.val = IN_ICS_B1CHAN;
chanId->chanMapType.pres = PRSNT_NODEF;
chanId->chanMapType.val = IN_CMT_BCHAN;
chanId->nmbMap.pres = PRSNT_NODEF;
chanId->nmbMap.val = IN_NM_CHNNMB;
chanId->codeStand1.pres = PRSNT_NODEF;
chanId->codeStand1.val = IN_CSTD_CCITT;
chanId->chanNmbSlotMap.pres = PRSNT_NODEF;
chanId->chanNmbSlotMap.len = 1;
chanId->chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
return FTDM_SUCCESS;
}
ftdm_status_t set_bear_cap_ie(ftdm_channel_t *ftdmchan, BearCap *bearCap)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
bearCap->eh.pres = PRSNT_NODEF;
bearCap->infoTranCap.pres = PRSNT_NODEF;
bearCap->infoTranCap.val = sngisdn_get_infoTranCap_from_user(ftdmchan->caller_data.bearer_capability);
bearCap->codeStand0.pres = PRSNT_NODEF;
bearCap->codeStand0.val = IN_CSTD_CCITT;
bearCap->infoTranRate0.pres = PRSNT_NODEF;
bearCap->infoTranRate0.val = IN_ITR_64KBIT;
bearCap->tranMode.pres = PRSNT_NODEF;
bearCap->tranMode.val = IN_TM_CIRCUIT;
if (!FTDM_SPAN_IS_BRI(ftdmchan->span)) {
/* Trillium stack rejests lyr1Ident on BRI, but Netbricks always sends it.
Check with Trillium if this ever causes calls to fail in the field */
/* PRI only params */
bearCap->usrInfoLyr1Prot.pres = PRSNT_NODEF;
bearCap->usrInfoLyr1Prot.val = sngisdn_get_usrInfoLyr1Prot_from_user(ftdmchan->caller_data.bearer_layer1);
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN &&
bearCap->usrInfoLyr1Prot.val == IN_UIL1_G711ULAW) {
/* We are bridging a call from T1 */
bearCap->usrInfoLyr1Prot.val = IN_UIL1_G711ALAW;
} else if (bearCap->usrInfoLyr1Prot.val == IN_UIL1_G711ALAW) {
/* We are bridging a call from E1 */
bearCap->usrInfoLyr1Prot.val = IN_UIL1_G711ULAW;
}
bearCap->lyr1Ident.pres = PRSNT_NODEF;
bearCap->lyr1Ident.val = IN_L1_IDENT;
}
return FTDM_SUCCESS;
}
ftdm_status_t set_restart_ind_ie(ftdm_channel_t *ftdmchan, RstInd *rstInd)
{
rstInd->eh.pres = PRSNT_NODEF;
rstInd->rstClass.pres = PRSNT_NODEF;
rstInd->rstClass.val = IN_CL_INDCHAN;
return FTDM_SUCCESS;
}
void sngisdn_t3_timeout(void* p_sngisdn_info)
{

View File

@ -36,14 +36,15 @@
#include "ftmod_sangoma_isdn_trace.h"
#define OCTET(x) (ieData[x-1] & 0xFF)
#define MAX_DECODE_STR_LEN 2000
void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_start, uint32_t index_end);
void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset, uint8_t *data, uint16_t index_start);
uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi);
char* get_code_2_str(int code, struct code2str *pCodeTable);
void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len);
void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len);
char* get_code_2_str(int code, struct code2str *pCodeTable)
{
@ -97,7 +98,43 @@ uint8_t get_bits(uint8_t octet, uint8_t bitLo, uint8_t bitHi)
return 0;
}
void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len)
void sngisdn_trace_interpreted_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
{
char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
sngisdn_decode_q921(data_str, data, data_len);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] s%d FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
ftdm_safe_free(data_str);
}
void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
{
uint8_t *raw_data;
ftdm_sigmsg_t sigev;
memset(&sigev, 0, sizeof(sigev));
sigev.span_id = signal_data->ftdm_span->span_id;
sigev.chan_id = signal_data->dchan->chan_id;
sigev.channel = signal_data->dchan;
sigev.event_id = FTDM_SIGEVENT_TRACE_RAW;
sigev.ev_data.logevent.dir = dir;
sigev.ev_data.logevent.level = 2;
/* TODO: Map trace to call ID here */
sigev.call_id = 0;
raw_data = ftdm_malloc(data_len);
ftdm_assert(raw_data, "Failed to malloc");
memcpy(raw_data, data, data_len);
sigev.raw.data = raw_data;
sigev.raw.len = data_len;
sigev.raw.autofree = 1;
ftdm_span_send_signal(signal_data->ftdm_span, &sigev);
}
void sngisdn_decode_q921(char* str, uint8_t* data, uint32_t data_len)
{
int str_len;
uint32_t i;
@ -169,7 +206,43 @@ void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len)
return;
}
void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len)
void sngisdn_trace_interpreted_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
{
char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */
sngisdn_decode_q931(data_str, data, data_len);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] %s FRAME %s:%s\n", signal_data->ftdm_span->name, ftdm_trace_dir2str(dir), data_str);
ftdm_safe_free(data_str);
}
void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len)
{
uint8_t *raw_data;
ftdm_sigmsg_t sigev;
memset(&sigev, 0, sizeof(sigev));
sigev.span_id = signal_data->ftdm_span->span_id;
sigev.chan_id = signal_data->dchan->chan_id;
sigev.channel = signal_data->dchan;
sigev.event_id = FTDM_SIGEVENT_TRACE_RAW;
sigev.ev_data.logevent.dir = dir;
sigev.ev_data.logevent.level = 3;
/* TODO: Map trace to call ID here */
raw_data = ftdm_malloc(data_len);
ftdm_assert(raw_data, "Failed to malloc");
memcpy(raw_data, data, data_len);
sigev.raw.data = raw_data;
sigev.raw.len = data_len;
sigev.raw.autofree = 1;
ftdm_span_send_signal(signal_data->ftdm_span, &sigev);
}
void sngisdn_decode_q931(char* str, uint8_t* data, uint32_t data_len)
{
uint32_t str_len;
uint8_t prot_disc, callRefFlag;

View File

@ -1589,7 +1589,7 @@ static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int c
sigev.span_id = ftdmchan->span_id;
sigev.channel = ftdmchan;
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* if this is the first channel in the range */
@ -1689,7 +1689,7 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c
sigev.span_id = ftdmchan->span_id;
sigev.channel = ftdmchan;
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* if this is the first channel in the range */

View File

@ -211,10 +211,10 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* add any special variables for the dialplan */
sprintf(nadi, "%d", siConEvnt->cgPtyNum.natAddrInd.val);
ftdm_channel_add_var(ftdmchan, "ss7_clg_nadi", nadi);
ftdm_call_add_var(&ftdmchan->caller_data, "ss7_clg_nadi", nadi);
sprintf(nadi, "%d", siConEvnt->cdPtyNum.natAddrInd.val);
ftdm_channel_add_var(ftdmchan, "ss7_cld_nadi", nadi);
ftdm_call_add_var(&ftdmchan->caller_data, "ss7_cld_nadi", nadi);
/* check if a COT test is requested */
@ -2004,7 +2004,7 @@ ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* unlock the channel again before we exit */
@ -2135,7 +2135,7 @@ ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* unlock the channel again before we exit */

View File

@ -502,6 +502,8 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/**************************************************************************/
case FTDM_CHANNEL_STATE_COLLECT: /* IAM received but wating on digits */
isup_intf = &g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId];
if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
break;
@ -521,8 +523,8 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/*now go to the RING state */
ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING);
} else if (i >= g_ftdm_sngss7_data.min_digits) {
SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, g_ftdm_sngss7_data.min_digits);
} else if (i >= isup_intf->min_digits) {
SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, isup_intf->min_digits);
/*now go to the RING state */
ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING);
@ -532,7 +534,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
if (ftdmchan->last_state != FTDM_CHANNEL_STATE_IDLE) {
SS7_INFO_CHAN(ftdmchan,"Received %d out of %d so far: %s...starting T35\n",
i,
g_ftdm_sngss7_data.min_digits,
isup_intf->min_digits,
ftdmchan->caller_data.dnis.digits);
/* start ISUP t35 */
@ -839,7 +841,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
SS7_DEBUG_CHAN(ftdmchan,"All reset flags cleared %s\n", "");
/* all flags are down so we can bring up the sig status */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal (ftdmchan->span, &sigev);
} /* if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) */
} /* if !blocked */
@ -947,7 +949,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* if the sig_status is up...bring it down */
if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal (ftdmchan->span, &sigev);
}
@ -1031,7 +1033,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status back up */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
}
@ -1044,7 +1046,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* go back to the last state */
@ -1056,7 +1058,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a BLA */
@ -1074,7 +1076,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status up */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a uba */
@ -1090,7 +1092,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a blo */
@ -1108,7 +1110,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the sig status up */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_UP;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_UP;
ftdm_span_send_signal(ftdmchan->span, &sigev);
/* send a ubl */
@ -1147,7 +1149,7 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
/* bring the channel signaling status to down */
sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
sigev.sigstatus = FTDM_SIG_STATE_DOWN;
sigev.ev_data.sigstatus.status = FTDM_SIG_STATE_DOWN;
ftdm_span_send_signal (ftdmchan->span, &sigev);
/* remove any reset flags */
@ -1520,9 +1522,6 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init)
/* initalize the global gen_config flag */
g_ftdm_sngss7_data.gen_config = 0;
/* min. number of digitis to wait for */
g_ftdm_sngss7_data.min_digits = 7;
/* function trace initizalation */
g_ftdm_sngss7_data.function_trace = 1;
g_ftdm_sngss7_data.function_trace_level = 7;

View File

@ -50,7 +50,7 @@
/******************************************************************************/
/* DEFINES ********************************************************************/
#define MAX_NAME_LEN 10
#define MAX_NAME_LEN 25
#define MAX_PATH 255
#define MAX_CIC_LENGTH 5
@ -224,6 +224,7 @@ typedef struct sng_isup_intf {
uint32_t isap;
uint32_t clg_nadi;
uint32_t cld_nadi;
uint32_t min_digits;
uint16_t t4;
uint32_t t10;
uint32_t t11;
@ -326,7 +327,6 @@ typedef struct sng_ss7_cfg {
typedef struct ftdm_sngss7_data {
sng_ss7_cfg_t cfg;
int gen_config;
int min_digits;
int function_trace;
int function_trace_level;
int message_trace;

View File

@ -187,7 +187,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
copy_cgPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cgPtyNum);
/* check if the user would like a custom NADI value for the calling Pty Num */
clg_nadi = ftdm_channel_get_var(ftdmchan, "ss7_clg_nadi");
clg_nadi = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_clg_nadi");
if ((clg_nadi != NULL) && (*clg_nadi)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling NADI value \"%s\"\n", clg_nadi);
iam.cgPtyNum.natAddrInd.val = atoi(clg_nadi);
@ -196,7 +196,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
SS7_DEBUG_CHAN(ftdmchan,"No user supplied NADI value found for CLG, using \"%d\"\n", iam.cgPtyNum.natAddrInd.val);
}
cld_nadi = ftdm_channel_get_var(ftdmchan, "ss7_cld_nadi");
cld_nadi = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_cld_nadi");
if ((cld_nadi != NULL) && (*cld_nadi)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called NADI value \"%s\"\n", cld_nadi);
iam.cdPtyNum.natAddrInd.val = atoi(cld_nadi);
@ -206,7 +206,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
}
/* check if the user would like us to send a clg_sub-address */
clg_subAddr = ftdm_channel_get_var(ftdmchan, "ss7_clg_subaddr");
clg_subAddr = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_clg_subaddr");
if ((clg_subAddr != NULL) && (*clg_subAddr)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling Sub-Address value \"%s\"\n", clg_subAddr);
@ -245,7 +245,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
}
/* check if the user would like us to send a cld_sub-address */
cld_subAddr = ftdm_channel_get_var(ftdmchan, "ss7_cld_subaddr");
cld_subAddr = ftdm_call_get_var(&ftdmchan->caller_data, "ss7_cld_subaddr");
if ((cld_subAddr != NULL) && (*cld_subAddr)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called Sub-Address value \"%s\"\n", cld_subAddr);
@ -298,7 +298,8 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
iam.cgPtyNum.natAddrInd.val,
ftdmchan->caller_data.dnis.digits,
iam.cdPtyNum.natAddrInd.val);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -379,7 +380,7 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
ADDRCMPLT);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ACM\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -403,7 +404,7 @@ void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan)
5);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ANM\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -438,7 +439,7 @@ void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan)
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx REL cause=%d \n",
sngss7_info->circuit->cic,
ftdmchan->caller_data.hangup_cause );
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -461,7 +462,7 @@ void ft_to_sngss7_rlc (ftdm_channel_t * ftdmchan)
&rlc);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RLC\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -482,7 +483,7 @@ void ft_to_sngss7_rsc (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -503,7 +504,7 @@ void ft_to_sngss7_rsca (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx RSC-RLC\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -524,7 +525,7 @@ void ft_to_sngss7_blo (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLO\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -545,7 +546,7 @@ void ft_to_sngss7_bla (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx BLA\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -567,7 +568,7 @@ ft_to_sngss7_ubl (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBL\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -588,7 +589,7 @@ void ft_to_sngss7_uba (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx UBA\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -609,7 +610,7 @@ void ft_to_sngss7_lpa (ftdm_channel_t * ftdmchan)
NULL);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx LPA\n", sngss7_info->circuit->cic);
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -654,6 +655,7 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->rx_grs.range));
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -686,7 +688,8 @@ void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan)
sngss7_info->circuit->cic,
sngss7_info->circuit->cic,
(sngss7_info->circuit->cic + sngss7_span->tx_grs.range));
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -735,7 +738,7 @@ void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan)
/* clean out the saved data */
memset(&sngss7_span->rx_cgb, 0x0, sizeof(sngss7_group_data_t));
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -785,6 +788,7 @@ void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan)
/* clean out the saved data */
memset(&sngss7_span->rx_cgu, 0x0, sizeof(sngss7_group_data_t));
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -835,6 +839,7 @@ void ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan)
/* clean out the saved data */
memset(&sngss7_span->tx_cgb, 0x0, sizeof(sngss7_group_data_t));
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -885,6 +890,7 @@ void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan)
/* clean out the saved data */
memset(&sngss7_span->tx_cgu, 0x0, sizeof(sngss7_group_data_t));
ftdm_call_clear_vars(&ftdmchan->caller_data);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}

View File

@ -142,7 +142,7 @@ int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *spa
if (!strcasecmp(var, "ch_map")) {
/**********************************************************************/
strcpy(isupCkt.ch_map, val);
strncpy(isupCkt.ch_map, val, MAX_CIC_MAP_LENGTH-1);
SS7_DEBUG("\tFound channel map \"%s\"\n", isupCkt.ch_map);
/**********************************************************************/
} else if (!strcasecmp(var, "typeCntrl")) {
@ -393,7 +393,7 @@ static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset)
for (i = 0; i < num_parms; i++) {
/**********************************************************************/
if (!strcasecmp(parm->var, "name")) {
strcpy((char *)mtpLinkSet.name, parm->val);
strncpy((char *)mtpLinkSet.name, parm->val, MAX_NAME_LEN-1);
SS7_DEBUG("\tFound an \"mtp_linkset\" named = %s\n", mtpLinkSet.name);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "apc")) {
@ -508,7 +508,7 @@ static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp_link_t *
/* try to match the parameter to what we expect */
/**********************************************************************/
if (!strcasecmp(parm->var, "name")) {
strcpy((char *)mtpLink->name, parm->val);
strncpy((char *)mtpLink->name, parm->val, MAX_NAME_LEN-1);
SS7_DEBUG("\tFound an \"mtp_link\" named = %s\n", mtpLink->name);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "span")) {
@ -827,7 +827,7 @@ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route)
/* try to match the parameter to what we expect */
/**********************************************************************/
if (!strcasecmp(parm->var, "name")) {
strcpy((char *)mtpRoute.name, parm->val);
strncpy((char *)mtpRoute.name, parm->val, MAX_NAME_LEN-1);
SS7_DEBUG("\tFound an \"mtp_route\" named = %s\n", mtpRoute.name);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "dpc")) {
@ -999,7 +999,7 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
/* try to match the parameter to what we expect */
/**********************************************************************/
if (!strcasecmp(parm->var, "name")) {
strcpy((char *)sng_isup.name, parm->val);
strncpy((char *)sng_isup.name, parm->val, MAX_NAME_LEN-1);
SS7_DEBUG("\tFound an \"isup_interface\" named = %s\n", sng_isup.name);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "spc")) {
@ -1047,6 +1047,11 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
SS7_DEBUG("\tFound MTP3 Route = %s\n", parm->val);
}
/**********************************************************************/
} else if (!strcasecmp(parm->var, "min_digits")) {
sng_isup.min_digits = atoi(parm->val);
SS7_DEBUG("\tFound min_digits = %d\n", sng_isup.min_digits);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "ssf")) {
if (!strcasecmp(parm->val, "nat")) {
sng_isup.ssf = SSF_NAT;
@ -1067,8 +1072,8 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
/**********************************************************************/
} else if (!strcasecmp(parm->var, "license")) {
/**********************************************************************/
strcpy(g_ftdm_sngss7_data.cfg.license, parm->val);
strcpy(g_ftdm_sngss7_data.cfg.signature, parm->val);
strncpy(g_ftdm_sngss7_data.cfg.license, parm->val, MAX_PATH-1);
strncpy(g_ftdm_sngss7_data.cfg.signature, parm->val, MAX_PATH-1);
strcat(g_ftdm_sngss7_data.cfg.signature, ".sig");
SS7_DEBUG("\tFound license file = %s\n", g_ftdm_sngss7_data.cfg.license);
SS7_DEBUG("\tFound signature file = %s\n", g_ftdm_sngss7_data.cfg.signature);
@ -1304,6 +1309,13 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface)
sng_isup.clg_nadi = 0x03;
}
/* check if the user requested min_digits value */
if (sng_isup.min_digits == 0) {
/* default to 7 */
sng_isup.min_digits = 7;
}
/* trickle down the SPC to all sub entities */
linkSetId = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].linkSetId;
@ -1359,7 +1371,7 @@ static int ftmod_ss7_fill_in_mtpLink(sng_mtp_link_t *mtpLink)
}
/* fill in the information */
strcpy((char *)g_ftdm_sngss7_data.cfg.mtpLink[i].name, (char *)mtpLink->name);
strncpy((char *)g_ftdm_sngss7_data.cfg.mtpLink[i].name, (char *)mtpLink->name, MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.mtpLink[i].id = mtpLink->id;
@ -1521,7 +1533,7 @@ static int ftmod_ss7_fill_in_mtpLinkSet(sng_link_set_t *mtpLinkSet)
{
int i = mtpLinkSet->id;
strcpy((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[i].name, (char *)mtpLinkSet->name);
strncpy((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[i].name, (char *)mtpLinkSet->name, MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.mtpLinkSet[i].id = mtpLinkSet->id;
g_ftdm_sngss7_data.cfg.mtpLinkSet[i].apc = mtpLinkSet->apc;
@ -1559,7 +1571,7 @@ static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route)
SS7_DEBUG("found existing mtp3_route, id is = %d\n", mtp3_route->id);
}
strcpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, (char *)mtp3_route->name);
strncpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, (char *)mtp3_route->name, MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.mtpRoute[i].id = mtp3_route->id;
g_ftdm_sngss7_data.cfg.mtpRoute[i].dpc = mtp3_route->dpc;
@ -1693,7 +1705,7 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
SS7_DEBUG("found existing isup interface, id is = %d\n", sng_isup->id);
}
strcpy((char *)g_ftdm_sngss7_data.cfg.isupIntf[i].name, (char *)sng_isup->name);
strncpy((char *)g_ftdm_sngss7_data.cfg.isupIntf[i].name, (char *)sng_isup->name, MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.isupIntf[i].id = sng_isup->id;
g_ftdm_sngss7_data.cfg.isupIntf[i].mtpRouteId = sng_isup->mtpRouteId;
@ -1705,6 +1717,7 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup)
g_ftdm_sngss7_data.cfg.isupIntf[i].isap = sng_isup->isap;
g_ftdm_sngss7_data.cfg.isupIntf[i].cld_nadi = sng_isup->cld_nadi;
g_ftdm_sngss7_data.cfg.isupIntf[i].clg_nadi = sng_isup->clg_nadi;
g_ftdm_sngss7_data.cfg.isupIntf[i].min_digits = sng_isup->min_digits;
g_ftdm_sngss7_data.cfg.isupIntf[i].options = sng_isup->options;
if (sng_isup->t4 != 0) {
g_ftdm_sngss7_data.cfg.isupIntf[i].t4 = sng_isup->t4;
@ -1976,7 +1989,7 @@ static int ftmod_ss7_fill_in_self_route(int spc, int linkType, int switchType, i
return FTDM_FAIL;
}
strcpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[0].name, "self-route");
strncpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[0].name, "self-route", MAX_NAME_LEN-1);
g_ftdm_sngss7_data.cfg.mtpRoute[0].id = 0;
g_ftdm_sngss7_data.cfg.mtpRoute[0].dpc = spc;
@ -2230,7 +2243,7 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot)
int lower;
int upper;
char tmp[5]; /*KONRAD FIX ME*/
char new_ch_map[MAX_CIC_LENGTH];
char new_ch_map[MAX_CIC_MAP_LENGTH];
memset(&tmp[0], '\0', sizeof(tmp));
memset(&new_ch_map[0], '\0', sizeof(new_ch_map));
@ -2337,7 +2350,9 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot)
/* the the rest of ch_map to new_ch_map */
strncat(new_ch_map, &ch_map[x], strlen(&ch_map[x]));
/* set the new cic map to ch_map*/
memset(ch_map, '\0', sizeof(ch_map));
strcpy(ch_map, new_ch_map);
} else if (ch_map[x] == ',') {
@ -2345,16 +2360,21 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot)
x++;
/* copy the rest of the list to new_ch_map */
memset(new_ch_map, '\0', sizeof(new_ch_map));
strcpy(new_ch_map, &ch_map[x]);
/* copy the new_ch_map over the old one */
memset(ch_map, '\0', sizeof(ch_map));
strcpy(ch_map, new_ch_map);
} else if (ch_map[x] == '\0') {
/* we're at the end of the string...copy the rest of the list to new_ch_map */
memset(new_ch_map, '\0', sizeof(new_ch_map));
strcpy(new_ch_map, &ch_map[x]);
/* set the new cic map to ch_map*/
memset(ch_map, '\0', sizeof(ch_map));
strcpy(ch_map, new_ch_map);
} else {
/* nothing to do */

View File

@ -811,13 +811,14 @@ static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *t
ftdm_clear_flag(&(ftdmchan->iostats.tx), FTDM_IOSTATS_ERROR_QUEUE_FULL);
}
if (ftdmchan->iostats.tx.idle_packets < tx_stats->wp_api_tx_hdr_number_of_frames_in_queue) {
ftdmchan->iostats.tx.idle_packets = tx_stats->wp_api_tx_hdr_tx_idle_packets;
if (ftdmchan->iostats.tx.idle_packets < tx_stats->wp_api_tx_hdr_tx_idle_packets) {
/* HDLC channels do not always transmit, so its ok for drivers to fill with idle
* also do not report idle warning when we just started transmitting */
if (ftdmchan->iostats.tx.packets && FTDM_IS_VOICE_CHANNEL(ftdmchan)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx idle: %d\n", ftdmchan->iostats.tx.idle_packets);
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx idle changed from %d to %d\n",
ftdmchan->iostats.tx.idle_packets, tx_stats->wp_api_tx_hdr_tx_idle_packets);
}
ftdmchan->iostats.tx.idle_packets = tx_stats->wp_api_tx_hdr_tx_idle_packets;
}
if (!ftdmchan->iostats.tx.packets) {
@ -941,7 +942,6 @@ static FIO_WRITE_FUNCTION(wanpipe_write)
{
int bsent = 0;
int err = 0;
ftdm_time_t ms = 0;
wp_tdm_api_tx_hdr_t hdrframe;
/* Do we even need the headerframe here? on windows, we don't even pass it to the driver */
@ -1051,16 +1051,34 @@ FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
for(i = 1; i <= span->chan_count; i++) {
ftdm_channel_t *ftdmchan = span->channels[i];
uint32_t chan_events = 0;
/* translate events from ftdm to libsnagoma. if the user don't specify which events to poll the
* channel for, we just use SANG_WAIT_OBJ_HAS_EVENTS */
if (poll_events) {
if (poll_events[j] & FTDM_READ) {
chan_events = SANG_WAIT_OBJ_HAS_INPUT;
}
if (poll_events[j] & FTDM_WRITE) {
chan_events |= SANG_WAIT_OBJ_HAS_OUTPUT;
}
if (poll_events[j] & FTDM_EVENTS) {
chan_events |= SANG_WAIT_OBJ_HAS_EVENTS;
}
} else {
chan_events = SANG_WAIT_OBJ_HAS_EVENTS;
}
#ifdef LIBSANGOMA_VERSION
if (!ftdmchan->io_data) {
continue; /* should never happen but happens when shutting down */
}
pfds[j] = ftdmchan->io_data;
inflags[j] = poll_events ? poll_events[j] : POLLPRI;
inflags[j] = chan_events;
#else
memset(&pfds[j], 0, sizeof(pfds[j]));
pfds[j].fd = span->channels[i]->sockfd;
pfds[j].events = poll_events ? poll_events[j] : POLLPRI;
pfds[j].events = chan_events;
#endif
/* The driver probably should be able to do this wink/flash/ringing by itself this is sort of a hack to make it work! */

View File

@ -31,10 +31,14 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "private/ftdm_core.h"
#include "ftmod_zt.h"
/* used by dahdi to indicate there is no data available, but events to read */
#ifndef ELAST
#define ELAST 500
#endif
/**
* \brief Zaptel globals
*/
@ -48,42 +52,48 @@ static struct {
float txgain;
} zt_globals;
#if defined(__FreeBSD__)
typedef unsigned long ioctlcmd;
#else
typedef int ioctlcmd;
#endif
/**
* \brief General IOCTL codes
*/
struct ioctl_codes {
int GET_BLOCKSIZE;
int SET_BLOCKSIZE;
int FLUSH;
int SYNC;
int GET_PARAMS;
int SET_PARAMS;
int HOOK;
int GETEVENT;
int IOMUX;
int SPANSTAT;
int MAINT;
int GETCONF;
int SETCONF;
int CONFLINK;
int CONFDIAG;
int GETGAINS;
int SETGAINS;
int SPANCONFIG;
int CHANCONFIG;
int SET_BUFINFO;
int GET_BUFINFO;
int AUDIOMODE;
int ECHOCANCEL;
int HDLCRAWMODE;
int HDLCFCSMODE;
int SPECIFY;
int SETLAW;
int SETLINEAR;
int GETCONFMUTE;
int ECHOTRAIN;
int SETTXBITS;
int GETRXBITS;
ioctlcmd GET_BLOCKSIZE;
ioctlcmd SET_BLOCKSIZE;
ioctlcmd FLUSH;
ioctlcmd SYNC;
ioctlcmd GET_PARAMS;
ioctlcmd SET_PARAMS;
ioctlcmd HOOK;
ioctlcmd GETEVENT;
ioctlcmd IOMUX;
ioctlcmd SPANSTAT;
ioctlcmd MAINT;
ioctlcmd GETCONF;
ioctlcmd SETCONF;
ioctlcmd CONFLINK;
ioctlcmd CONFDIAG;
ioctlcmd GETGAINS;
ioctlcmd SETGAINS;
ioctlcmd SPANCONFIG;
ioctlcmd CHANCONFIG;
ioctlcmd SET_BUFINFO;
ioctlcmd GET_BUFINFO;
ioctlcmd AUDIOMODE;
ioctlcmd ECHOCANCEL;
ioctlcmd HDLCRAWMODE;
ioctlcmd HDLCFCSMODE;
ioctlcmd SPECIFY;
ioctlcmd SETLAW;
ioctlcmd SETLINEAR;
ioctlcmd GETCONFMUTE;
ioctlcmd ECHOTRAIN;
ioctlcmd SETTXBITS;
ioctlcmd GETRXBITS;
};
/**
@ -1183,7 +1193,6 @@ FIO_SPAN_NEXT_EVENT_FUNCTION(zt_next_event)
}
return FTDM_FAIL;
}
/**
@ -1202,12 +1211,19 @@ static FIO_READ_FUNCTION(zt_read)
if ((r = read(ftdmchan->sockfd, data, *datalen)) > 0) {
break;
}
ftdm_sleep(10);
if (r == 0) {
errs--;
else if (r == 0) {
ftdm_sleep(10);
if (errs) errs--;
}
else {
if (errno == EAGAIN || errno == EINTR)
continue;
if (errno == ELAST)
break;
ftdm_log(FTDM_LOG_ERROR, "read failed: %s\n", strerror(errno));
}
}
if (r > 0) {
*datalen = r;
if (ftdmchan->type == FTDM_CHAN_TYPE_DQ921) {
@ -1215,7 +1231,9 @@ static FIO_READ_FUNCTION(zt_read)
}
return FTDM_SUCCESS;
}
else if (errno == ELAST) {
return FTDM_SUCCESS;
}
return r == 0 ? FTDM_TIMEOUT : FTDM_FAIL;
}
@ -1236,6 +1254,7 @@ static FIO_WRITE_FUNCTION(zt_write)
bytes += 2;
}
tryagain:
w = write(ftdmchan->sockfd, data, bytes);
if (w >= 0) {
@ -1243,6 +1262,17 @@ static FIO_WRITE_FUNCTION(zt_write)
return FTDM_SUCCESS;
}
if (errno == ELAST) {
zt_event_t zt_event_id = 0;
if (ioctl(ftdmchan->sockfd, codes.GETEVENT, &zt_event_id) == -1) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed retrieving event after ELAST on write: %s\n", strerror(errno));
return FTDM_FAIL;
}
/* we should enqueue this event somewhere so it can be retrieved by the user, for now, dropping it to see what it is! */
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Dropping event %d to be able to write data\n", zt_event_id);
goto tryagain;
}
return FTDM_FAIL;
}

View File

@ -144,7 +144,9 @@ typedef enum {
/*! \brief Hunting direction (when hunting for free channels) */
typedef enum {
FTDM_TOP_DOWN,
FTDM_BOTTOM_UP
FTDM_BOTTOM_UP,
FTDM_RR_DOWN,
FTDM_RR_UP,
} ftdm_direction_t;
/*! \brief I/O channel type */
@ -265,13 +267,32 @@ typedef enum {
#define USER_LAYER1_PROT_STRINGS "V.110", "u-law", "a-law", "Invalid"
FTDM_STR2ENUM_P(ftdm_str2ftdm_usr_layer1_prot, ftdm_user_layer1_prot2str, ftdm_user_layer1_prot_t)
/*! Calling Party Category */
typedef enum {
FTDM_CPC_UNKNOWN,
FTDM_CPC_OPERATOR,
FTDM_CPC_ORDINARY,
FTDM_CPC_PRIORITY,
FTDM_CPC_DATA,
FTDM_CPC_TEST,
FTDM_CPC_PAYPHONE,
FTDM_CPC_INVALID
} ftdm_calling_party_category_t;
#define CALLING_PARTY_CATEGORY_STRINGS "unknown", "operator", "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)
/*! \brief Digit limit used in DNIS/ANI */
#define FTDM_DIGITS_LIMIT 25
/*! \brief Number abstraction */
typedef struct {
char digits[25];
char digits[FTDM_DIGITS_LIMIT];
uint8_t type;
uint8_t plan;
} ftdm_number_t;
typedef void * ftdm_variable_container_t;
/*! \brief Caller information */
typedef struct ftdm_caller_data {
char cid_date[8]; /*!< Caller ID date */
@ -280,18 +301,25 @@ typedef struct ftdm_caller_data {
ftdm_number_t ani; /*!< ANI (Automatic Number Identification) */
ftdm_number_t dnis; /*!< DNIS (Dialed Number Identification Service) */
ftdm_number_t rdnis; /*!< RDNIS (Redirected Dialed Number Identification Service) */
char aniII[25]; /*! ANI II */
char aniII[FTDM_DIGITS_LIMIT]; /*! ANI II */
uint8_t screen; /*!< Screening */
uint8_t pres; /*!< Presentation*/
char collected[25]; /*!< Collected digits so far */
char collected[FTDM_DIGITS_LIMIT]; /*!< Collected digits so far */
int hangup_cause; /*!< Hangup cause */
char raw_data[1024]; /*!< Protocol specific raw caller data */
uint32_t raw_data_len; /* !< Raw data length */
uint32_t raw_data_len; /*!< Raw data length */
/* these 2 are undocumented right now, only used by boost: */
/* bearer capability */
ftdm_bearer_cap_t bearer_capability;
/* user information layer 1 protocol */
ftdm_user_layer1_prot_t bearer_layer1;
ftdm_calling_party_category_t cpc; /*!< Calling party category */
ftdm_variable_container_t variables; /*!< Variables attached to this call */
/* We need call_id inside caller_data for the user to be able to retrieve
* the call_id when ftdm_channel_call_place is called. This is the only time
* that the user can use caller_data.call_id to obtain the call_id. The user
* should use the call_id from sigmsg otherwise */
uint32_t call_id; /*!< Unique call ID for this call */
} ftdm_caller_data_t;
/*! \brief Tone type */
@ -306,7 +334,8 @@ typedef enum {
FTDM_SIGEVENT_RELEASED, /*!< Channel is completely released and available */
FTDM_SIGEVENT_UP, /*!< Outgoing call has been answered */
FTDM_SIGEVENT_FLASH, /*!< Flash event (typically on-hook/off-hook for analog devices) */
FTDM_SIGEVENT_PROCEED, /*!< Outgoing call got a response */
FTDM_SIGEVENT_PROCEED, /*!< Outgoing call got a response */
FTDM_SIGEVENT_RINGING, /*!< Remote side is in ringing state */
FTDM_SIGEVENT_PROGRESS, /*!< Outgoing call is making progress */
FTDM_SIGEVENT_PROGRESS_MEDIA, /*!< Outgoing call is making progress and there is media available */
FTDM_SIGEVENT_ALARM_TRAP, /*!< Hardware alarm ON */
@ -316,12 +345,14 @@ typedef enum {
FTDM_SIGEVENT_RESTART, /*!< Restart has been requested. Typically you hangup your call resources here */
FTDM_SIGEVENT_SIGSTATUS_CHANGED, /*!< Signaling protocol status changed (ie: D-chan up), see new status in raw_data ftdm_sigmsg_t member */
FTDM_SIGEVENT_COLLISION, /*!< Outgoing call was dropped because an incoming call arrived at the same time */
FTDM_SIGEVENT_MSG, /*!< We received an in-call msg */
FTDM_SIGEVENT_INVALID
FTDM_SIGEVENT_FACILITY, /*!< In call facility event */
FTDM_SIGEVENT_TRACE, /*!<Interpreted trace event */
FTDM_SIGEVENT_TRACE_RAW, /*!<Raw trace event */
FTDM_SIGEVENT_INVALID, /*!<Invalid */
} ftdm_signal_event_t;
#define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROCEED", "PROGRESS", \
#define SIGNAL_STRINGS "START", "STOP", "RELEASED", "UP", "FLASH", "PROCEED", "RINGING", "PROGRESS", \
"PROGRESS_MEDIA", "ALARM_TRAP", "ALARM_CLEAR", \
"COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "COLLISION", "MSG", "INVALID"
"COLLECTED_DIGIT", "ADD_CALL", "RESTART", "SIGSTATUS_CHANGED", "COLLISION", "FACILITY", "TRACE", "TRACE_RAW", "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)
@ -356,6 +387,7 @@ typedef struct ftdm_channel_config {
/*!
\brief Signaling status on a given span or specific channel on protocols that support it
\note see docs/sigstatus.txt for more extensive documentation on signaling status
*/
typedef enum {
/* The signaling link is down (no d-chans up in the span/group, MFC-R2 bit pattern unidentified) */
@ -372,15 +404,52 @@ typedef enum {
/*! \brief Move from string to ftdm_signaling_status_t and viceversa */
FTDM_STR2ENUM_P(ftdm_str2ftdm_signaling_status, ftdm_signaling_status2str, ftdm_signaling_status_t)
typedef struct {
ftdm_signaling_status_t status;
} ftdm_event_sigstatus_t;
typedef enum {
/* This is an received frame */
FTDM_TRACE_INCOMING,
/* This is a transmitted frame */
FTDM_TRACE_OUTGOING,
/* Invalid */
FTDM_TRACE_INVALID,
} ftdm_trace_dir_t;
#define TRACE_DIR_STRINGS "INCOMING", "OUTGOING", "INVALID"
/*! \brief Move string to ftdm_trace_dir_t and viceversa */
FTDM_STR2ENUM_P(ftdm_str2ftdm_trace_dir, ftdm_trace_dir2str, ftdm_trace_dir_t)
typedef struct {
/* Direction - incoming or outgoing */
ftdm_trace_dir_t dir;
uint8_t level; /* 1 for phy layer, 2 for q921/mtp2, 3 for q931/mtp3 */
} ftdm_event_trace_t;
typedef struct {
/* Digits collected */
char digits[FTDM_DIGITS_LIMIT];
} ftdm_event_collected_t;
/*! \brief Generic signaling message */
struct ftdm_sigmsg {
ftdm_signal_event_t event_id; /*!< The type of message */
ftdm_channel_t *channel; /*!< Related channel */
uint32_t chan_id; /*!< easy access to chan id */
uint32_t span_id; /*!< easy access to span_id */
ftdm_signaling_status_t sigstatus; /*!< Signaling status (valid if event_id is FTDM_SIGEVENT_SIGSTATUS_CHANGED) */
void *raw_data; /*!< Message specific data if any */
uint32_t raw_data_len; /*!< Data len in case is needed */
uint32_t call_id; /*!< unique call id for this call */
union {
ftdm_event_sigstatus_t sigstatus; /*!< valid if event_id is FTDM_SIGEVENT_SIGSTATUS_CHANGED */
ftdm_event_trace_t logevent; /*!< valid if event_id is FTDM_SIGEVENT_TRACE or FTDM_SIGEVENT_TRACE_RAW */
ftdm_event_collected_t collected; /*!< valif if event_id is FTDM_SIGEVENT_COLLECTED_DIGIT */
} ev_data;
struct {
uint8_t autofree; /*!< Whether the freetdm core will free it after message delivery */
uint32_t len; /*!< Data len */
void *data; /*!< Signaling module specific data */
} raw;
};
/*! \brief Crash policy
@ -507,6 +576,7 @@ struct ftdm_memory_handler {
* You don't need these unless your implementing an I/O interface module (most users don't) */
#define FIO_CHANNEL_REQUEST_ARGS (ftdm_span_t *span, uint32_t chan_id, ftdm_direction_t direction, ftdm_caller_data_t *caller_data, ftdm_channel_t **ftdmchan)
#define FIO_CHANNEL_OUTGOING_CALL_ARGS (ftdm_channel_t *ftdmchan)
#define FIO_CHANNEL_SEND_MSG_ARGS (ftdm_channel_t *ftdmchan, ftdm_sigmsg_t *sigmsg)
#define FIO_CHANNEL_SET_SIG_STATUS_ARGS (ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status)
#define FIO_CHANNEL_GET_SIG_STATUS_ARGS (ftdm_channel_t *ftdmchan, ftdm_signaling_status_t *status)
#define FIO_SPAN_SET_SIG_STATUS_ARGS (ftdm_span_t *span, ftdm_signaling_status_t status)
@ -539,6 +609,7 @@ struct ftdm_memory_handler {
* You don't need these unless your implementing an I/O interface module (most users don't) */
typedef ftdm_status_t (*fio_channel_request_t) FIO_CHANNEL_REQUEST_ARGS ;
typedef ftdm_status_t (*fio_channel_outgoing_call_t) FIO_CHANNEL_OUTGOING_CALL_ARGS ;
typedef ftdm_status_t (*fio_channel_send_msg_t) FIO_CHANNEL_SEND_MSG_ARGS;
typedef ftdm_status_t (*fio_channel_set_sig_status_t) FIO_CHANNEL_SET_SIG_STATUS_ARGS;
typedef ftdm_status_t (*fio_channel_get_sig_status_t) FIO_CHANNEL_GET_SIG_STATUS_ARGS;
typedef ftdm_status_t (*fio_span_set_sig_status_t) FIO_SPAN_SET_SIG_STATUS_ARGS;
@ -572,6 +643,7 @@ typedef ftdm_status_t (*fio_api_t) FIO_API_ARGS ;
* You don't need these unless your implementing an I/O interface module (most users don't) */
#define FIO_CHANNEL_REQUEST_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_REQUEST_ARGS
#define FIO_CHANNEL_OUTGOING_CALL_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_OUTGOING_CALL_ARGS
#define FIO_CHANNEL_SEND_MSG_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_SEND_MSG_ARGS
#define FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_SET_SIG_STATUS_ARGS
#define FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_CHANNEL_GET_SIG_STATUS_ARGS
#define FIO_SPAN_SET_SIG_STATUS_FUNCTION(name) ftdm_status_t name FIO_SPAN_SET_SIG_STATUS_ARGS
@ -654,6 +726,14 @@ typedef enum {
/*! \brief Override the default queue handler */
FT_DECLARE(ftdm_status_t) ftdm_global_set_queue_handler(ftdm_queue_handler_t *handler);
/*! \brief Return the availability rate for a channel
* \param ftdmchan Channel to get the availability from
*
* \retval > 0 if availability is supported
* \retval -1 if availability is not supported
*/
FT_DECLARE(int) ftdm_channel_get_availability(ftdm_channel_t *ftdmchan);
/*! \brief Answer call */
#define ftdm_channel_call_answer(ftdmchan) _ftdm_channel_call_answer(__FILE__, __FUNCTION__, __LINE__, (ftdmchan))
@ -672,6 +752,12 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char
/*! \brief Indicate a new condition in an incoming call recording the source code point where it was called (see ftdm_channel_call_indicate for an easy to use macro) */
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_channel_indication_t indication);
/*! \brief Send a message on a call */
#define ftdm_channel_call_send_msg(ftdmchan, sigmsg) _ftdm_channel_call_send_msg(__FILE__, __FUNCTION__, __LINE__, (ftdmchan), (sigmsg))
/*! \brief Send a signal on a call recording the source code point where it was called (see ftdm_channel_call_send_msg for an easy to use macro) */
FT_DECLARE(ftdm_status_t) _ftdm_channel_call_send_msg(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_sigmsg_t *sigmsg);
/*! \brief Hangup the call without cause */
#define ftdm_channel_call_hangup(ftdmchan) _ftdm_channel_call_hangup(__FILE__, __FUNCTION__, __LINE__, (ftdmchan))
@ -684,6 +770,14 @@ 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);
/*! \brief Reset the channel */
#define ftdm_channel_reset(ftdmchan) _ftdm_channel_reset(__FILE__, __FUNCTION__, __LINE__, (ftdmchan))
/*! \brief Reset the channel (see _ftdm_channel_reset for an easy to use macro)
* \note if there was a call on this channel, call will be cleared without any notifications to the user
*/
FT_DECLARE(ftdm_status_t) _ftdm_channel_reset(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan);
/*! \brief Put a call on hold (if supported by the signaling stack) */
#define ftdm_channel_call_hold(ftdmchan) _ftdm_channel_call_hold(__FILE__, __FUNCTION__, __LINE__, (ftdmchan))
@ -723,6 +817,7 @@ FT_DECLARE(ftdm_status_t) ftdm_span_set_sig_status(ftdm_span_t *span, ftdm_signa
/*! \brief Get span signaling status (ie: whether protocol layer is up or down) */
FT_DECLARE(ftdm_status_t) ftdm_span_get_sig_status(ftdm_span_t *span, ftdm_signaling_status_t *status);
/*!
* \brief Set user private data in the channel
*
@ -1128,6 +1223,45 @@ FT_DECLARE(ftdm_iterator_t *) ftdm_iterator_next(ftdm_iterator_t *iter);
*/
FT_DECLARE(ftdm_status_t) ftdm_iterator_free(ftdm_iterator_t *iter);
/*! \brief Add a custom variable to the call
* \note This variables may be used by signaling modules to override signaling parameters
* \todo Document which signaling variables are available
* */
FT_DECLARE(ftdm_status_t) ftdm_call_add_var(ftdm_caller_data_t *caller_data, const char *var_name, const char *value);
/*! \brief Get a custom variable from the call.
* \note The variable pointer returned is only valid during the callback receiving SIGEVENT. */
FT_DECLARE(const char *) ftdm_call_get_var(ftdm_caller_data_t *caller_data, const char *var_name);
/*! \brief Get an iterator to iterate over the channel variables
* \param caller_data The signal msg structure containing the variables
* \param iter Optional iterator. You can reuse an old iterator (not previously freed) to avoid the extra allocation of a new iterator.
* \note The iterator pointer returned is only valid while the signal message and it'll be destroyed when the signal message is processed.
* This iterator is completely non-thread safe, if you are adding variables or removing variables while iterating
* results are unpredictable
*/
FT_DECLARE(ftdm_iterator_t *) ftdm_call_get_var_iterator(const ftdm_caller_data_t *caller_data, ftdm_iterator_t *iter);
/*! \brief Get variable name and value for the current iterator position */
FT_DECLARE(ftdm_status_t) ftdm_call_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val);
/*! \brief Clear all variables attached to the call
* \note Variables are cleared at the end of each call back, so it is not necessary for the user to call this function.
* \todo Document which signaling variables are available
* */
FT_DECLARE(ftdm_status_t) ftdm_call_clear_vars(ftdm_caller_data_t *caller_data);
/*! \brief Remove a variable attached to the call
* \note Removes a variable that was attached to the call.
* \todo Document which call variables are available
* */
FT_DECLARE(ftdm_status_t) ftdm_call_remove_var(ftdm_caller_data_t *caller_data, const char *var_name);
/*! \brief Clears all the temporary data attached to this call
* \note Clears caller_data->variables and caller_data->raw_data.
* */
FT_DECLARE(void) ftdm_call_clear_data(ftdm_caller_data_t *caller_data);
/*! \brief Get the span pointer associated to the channel */
FT_DECLARE(ftdm_span_t *) ftdm_channel_get_span(const ftdm_channel_t *ftdmchan);

View File

@ -30,6 +30,12 @@
* 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.
*
* Contributors:
*
* Moises Silva <moy@sangoma.com>
* Ricardo Barroetaveña <rbarroetavena@anura.com.ar>
*
*/
#ifndef __FTDM_CALL_UTILS_H__
@ -114,5 +120,16 @@ FT_DECLARE(ftdm_status_t) ftdm_set_presentation_ind(const char *string, uint8_t
*/
FT_DECLARE(ftdm_status_t) ftdm_is_number(const char *number);
/*!
* \brief Set the Calling Party Category from an enum
*
* \param cpc_string string value
* \param target the target to set value to
*
* \retval FTDM_SUCCESS success
* \retval FTDM_FAIL failure
*/
FT_DECLARE(ftdm_status_t) ftdm_set_calling_party_category(const char *string, uint8_t *target);
#endif /* __FTDM_CALL_UTILS_H__ */

View File

@ -158,12 +158,16 @@ typedef __int64 int64_t;
typedef __int32 int32_t;
typedef __int16 int16_t;
typedef __int8 int8_t;
#define FTDM_O_BINARY O_BINARY
#define FTDM_SIZE_FMT "Id"
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
#endif /* _MSC_VER */
#else /* __WINDOWS__ */
#define FTDM_O_BINARY 0
#define FTDM_SIZE_FMT "zd"
#define FTDM_INVALID_SOCKET -1
typedef int ftdm_socket_t;
#include <stdio.h>

View File

@ -39,9 +39,12 @@
extern "C" {
#endif
#if defined(__linux__) && !defined(__USE_BSD)
#define __USE_BSD
#endif
#include "ftdm_declare.h"
#include "ftdm_threadmutex.h"
#include <string.h>
#ifndef __WINDOWS__

View File

@ -411,7 +411,7 @@ struct ftdm_channel {
uint32_t extra_id;
ftdm_chan_type_t type;
ftdm_socket_t sockfd;
uint32_t flags;
uint64_t flags;
uint32_t pflags;
uint32_t sflags;
ftdm_alarm_flag_t alarm_flags;
@ -493,6 +493,7 @@ struct ftdm_span {
ftdm_trunk_type_t trunk_type;
ftdm_analog_start_type_t start_type;
ftdm_signal_type_t signal_type;
uint32_t last_used_index;
/* Private signaling data. Do not touch unless you are a signaling module */
void *signal_data;
fio_signal_cb_t signal_cb;
@ -503,6 +504,7 @@ struct ftdm_span {
teletone_multi_tone_t tone_finder[FTDM_TONEMAP_INVALID+1];
ftdm_channel_t *channels[FTDM_MAX_CHANNELS_SPAN+1];
fio_channel_outgoing_call_t outgoing_call;
fio_channel_send_msg_t send_msg;
fio_channel_set_sig_status_t set_channel_sig_status;
fio_channel_get_sig_status_t get_channel_sig_status;
fio_span_set_sig_status_t set_span_sig_status;
@ -598,7 +600,6 @@ FT_DECLARE(void) ftdm_channel_rotate_tokens(ftdm_channel_t *ftdmchan);
FT_DECLARE(int) ftdm_load_module(const char *name);
FT_DECLARE(int) ftdm_load_module_assume(const char *name);
FT_DECLARE(int) ftdm_vasprintf(char **ret, const char *fmt, va_list ap);
FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan);
FT_DECLARE(ftdm_status_t) ftdm_span_close_all(void);
FT_DECLARE(ftdm_status_t) ftdm_channel_open_chan(ftdm_channel_t *ftdmchan);

View File

@ -184,6 +184,9 @@ typedef enum {
FTDM_SPAN_USE_SIGNALS_QUEUE = (1 << 10),
/* If this flag is set, channel will be moved to proceed state when calls goes to routing */
FTDM_SPAN_USE_PROCEED_STATE = (1 << 11),
/* If this flag is set, the signalling module supports jumping directly to state up, without
going through PROGRESS/PROGRESS_MEDIA */
FTDM_SPAN_USE_SKIP_STATES = (1 << 12),
} ftdm_span_flag_t;
/*! \brief Channel supported features */
@ -225,60 +228,50 @@ typedef enum {
FTDM_CHANNEL_STATE_HANGUP,
FTDM_CHANNEL_STATE_HANGUP_COMPLETE,
FTDM_CHANNEL_STATE_IN_LOOP,
FTDM_CHANNEL_STATE_RESET,
FTDM_CHANNEL_STATE_INVALID
} 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", \
"HANGUP", "HANGUP_COMPLETE", "IN_LOOP", "INVALID"
"HANGUP", "HANGUP_COMPLETE", "IN_LOOP", "RESET", "INVALID"
FTDM_STR2ENUM_P(ftdm_str2ftdm_channel_state, ftdm_channel_state2str, ftdm_channel_state_t)
typedef enum {
FTDM_CHANNEL_CONFIGURED = (1 << 0),
FTDM_CHANNEL_READY = (1 << 1),
FTDM_CHANNEL_OPEN = (1 << 2),
FTDM_CHANNEL_DTMF_DETECT = (1 << 3),
FTDM_CHANNEL_SUPRESS_DTMF = (1 << 4),
FTDM_CHANNEL_TRANSCODE = (1 << 5),
FTDM_CHANNEL_BUFFER = (1 << 6),
FTDM_CHANNEL_EVENT = (1 << 7),
FTDM_CHANNEL_INTHREAD = (1 << 8),
FTDM_CHANNEL_WINK = (1 << 9),
FTDM_CHANNEL_FLASH = (1 << 10),
FTDM_CHANNEL_STATE_CHANGE = (1 << 11),
FTDM_CHANNEL_HOLD = (1 << 12),
FTDM_CHANNEL_INUSE = (1 << 13),
FTDM_CHANNEL_OFFHOOK = (1 << 14),
FTDM_CHANNEL_RINGING = (1 << 15),
FTDM_CHANNEL_PROGRESS_DETECT = (1 << 16),
FTDM_CHANNEL_CALLERID_DETECT = (1 << 17),
FTDM_CHANNEL_OUTBOUND = (1 << 18),
FTDM_CHANNEL_SUSPENDED = (1 << 19),
FTDM_CHANNEL_3WAY = (1 << 20),
FTDM_CHANNEL_PROGRESS = (1 << 21),
FTDM_CHANNEL_MEDIA = (1 << 22),
FTDM_CHANNEL_ANSWERED = (1 << 23),
FTDM_CHANNEL_MUTE = (1 << 24),
FTDM_CHANNEL_USE_RX_GAIN = (1 << 25),
FTDM_CHANNEL_USE_TX_GAIN = (1 << 26),
FTDM_CHANNEL_IN_ALARM = (1 << 27),
FTDM_CHANNEL_SIG_UP = (1 << 28),
FTDM_CHANNEL_USER_HANGUP = (1 << 29),
FTDM_CHANNEL_RX_DISABLED = (1 << 30),
FTDM_CHANNEL_TX_DISABLED = (1 << 31),
/* ok, when we reach 32, we need to move to uint64_t all the flag stuff */
} ftdm_channel_flag_t;
#if defined(__cplusplus) && defined(WIN32)
// fix C2676
__inline__ ftdm_channel_flag_t operator|=(ftdm_channel_flag_t a, int32_t b) {
a = (ftdm_channel_flag_t)(a | b);
return a;
}
__inline__ ftdm_channel_flag_t operator&=(ftdm_channel_flag_t a, int32_t b) {
a = (ftdm_channel_flag_t)(a & b);
return a;
}
#endif
/*!< 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)
#define FTDM_CHANNEL_OPEN (1ULL << 2)
#define FTDM_CHANNEL_DTMF_DETECT (1ULL << 3)
#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)
#define FTDM_CHANNEL_STATE_CHANGE (1ULL << 11)
#define FTDM_CHANNEL_HOLD (1ULL << 12)
#define FTDM_CHANNEL_INUSE (1ULL << 13)
#define FTDM_CHANNEL_OFFHOOK (1ULL << 14)
#define FTDM_CHANNEL_RINGING (1ULL << 15)
#define FTDM_CHANNEL_PROGRESS_DETECT (1ULL << 16)
#define FTDM_CHANNEL_CALLERID_DETECT (1ULL << 17)
#define FTDM_CHANNEL_OUTBOUND (1ULL << 18)
#define FTDM_CHANNEL_SUSPENDED (1ULL << 19)
#define FTDM_CHANNEL_3WAY (1ULL << 20)
#define FTDM_CHANNEL_PROGRESS (1ULL << 21)
#define FTDM_CHANNEL_MEDIA (1ULL << 22)
#define FTDM_CHANNEL_ANSWERED (1ULL << 23)
#define FTDM_CHANNEL_MUTE (1ULL << 24)
#define FTDM_CHANNEL_USE_RX_GAIN (1ULL << 25)
#define FTDM_CHANNEL_USE_TX_GAIN (1ULL << 26)
#define FTDM_CHANNEL_IN_ALARM (1ULL << 27)
#define FTDM_CHANNEL_SIG_UP (1ULL << 28)
#define FTDM_CHANNEL_USER_HANGUP (1ULL << 29)
#define FTDM_CHANNEL_RX_DISABLED (1ULL << 30)
#define FTDM_CHANNEL_TX_DISABLED (1ULL << 31)
/*!< The user knows about a call in this channel */
#define FTDM_CHANNEL_CALL_STARTED (1ULL << 32)
typedef enum {
ZSM_NONE,

View File

@ -48,12 +48,7 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#ifdef __linux__
#ifndef __USE_BSD
#define __USE_BSD
#endif
#include <unistd.h>
#endif
#include "freetdm.h"

View File

@ -821,7 +821,7 @@ static switch_status_t channel_receive_message_cas(switch_core_session_t *sessio
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_RINGING:
{
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
} else {
zap_set_state_locked_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS);
@ -830,7 +830,7 @@ static switch_status_t channel_receive_message_cas(switch_core_session_t *sessio
break;
case SWITCH_MESSAGE_INDICATE_PROGRESS:
{
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_MEDIA);
} else {
@ -841,7 +841,7 @@ static switch_status_t channel_receive_message_cas(switch_core_session_t *sessio
break;
case SWITCH_MESSAGE_INDICATE_ANSWER:
{
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED);
} else {
/* lets make the ozmod_r2 module life easier by moving thru each
@ -888,7 +888,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_RINGING:
{
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
} else {
zap_set_state_wait(tech_pvt->zchan, ZAP_CHANNEL_STATE_PROGRESS);
@ -897,7 +897,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
break;
case SWITCH_MESSAGE_INDICATE_PROGRESS:
{
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_MEDIA);
} else {
@ -914,7 +914,7 @@ static switch_status_t channel_receive_message_b(switch_core_session_t *session,
break;
case SWITCH_MESSAGE_INDICATE_ANSWER:
{
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
zap_set_flag(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED);
} else {
/* Don't skip messages in the ISDN call setup
@ -957,7 +957,7 @@ static switch_status_t channel_receive_message_fxo(switch_core_session_t *sessio
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_PROGRESS:
case SWITCH_MESSAGE_INDICATE_ANSWER:
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED);
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_MEDIA);
@ -991,7 +991,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_PROGRESS:
case SWITCH_MESSAGE_INDICATE_ANSWER:
if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_ANSWERED);
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_PROGRESS);
zap_set_flag_locked(tech_pvt->zchan, ZAP_CHANNEL_MEDIA);
@ -1000,7 +1000,7 @@ static switch_status_t channel_receive_message_fxs(switch_core_session_t *sessio
}
break;
case SWITCH_MESSAGE_INDICATE_RINGING:
if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
if (!switch_channel_test_flag(channel, CF_ANSWERED) &&
!switch_channel_test_flag(channel, CF_EARLY_MEDIA) &&
@ -1052,7 +1052,7 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
switch (msg->message_id) {
case SWITCH_MESSAGE_INDICATE_PROGRESS:
case SWITCH_MESSAGE_INDICATE_ANSWER:
if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
if ((var = switch_channel_get_variable(channel, "openzap_pre_buffer_size"))) {
int tmp = atoi(var);
if (tmp > -1) {
@ -1327,7 +1327,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
tech_pvt->caller_profile = caller_profile;
switch_channel_set_flag(channel, CF_OUTBOUND);
switch_channel_set_state(channel, CS_INIT);
if (zap_channel_add_token(zchan, switch_core_session_get_uuid(*new_session), zchan->token_count) != ZAP_SUCCESS) {
switch_core_session_destroy(new_session);
@ -1678,7 +1677,9 @@ static ZIO_SIGNAL_CB_FUNCTION(on_fxs_signal)
switch_clear_flag_locked(tech_pvt, TFLAG_HOLD);
}
if (channel_a && channel_b && !switch_channel_test_flag(channel_a, CF_OUTBOUND) && !switch_channel_test_flag(channel_b, CF_OUTBOUND)) {
if (channel_a && channel_b && switch_channel_direction(channel_a) == SWITCH_CALL_DIRECTION_INBOUND &&
switch_channel_direction(channel_b) == SWITCH_CALL_DIRECTION_INBOUND) {
cause = SWITCH_CAUSE_ATTENDED_TRANSFER;
if (br_a_uuid && br_b_uuid) {
switch_ivr_uuid_bridge(br_a_uuid, br_b_uuid);

View File

@ -39,8 +39,9 @@
#include <limits.h>
#include <time.h>
@INSERT_MATH_HEADER@
#if !defined(SPANDSP_NO_TIFF)
#include <tiffio.h>
#endif
#include <spandsp/telephony.h>
#include <spandsp/fast_convert.h>
#include <spandsp/logging.h>

View File

@ -27,58 +27,162 @@
*/
#include "stfu.h"
//#define DB_JB 1
#ifndef UINT_MAX
# define UINT_MAX 4294967295U
#endif
#ifndef UINT16_MAX
# define UINT16_MAX 65535
#endif
#ifdef _MSC_VER
/* warning C4706: assignment within conditional expression*/
#pragma warning(disable: 4706)
/* warning C4996: 'strdup': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strdup. See online help for details. */
#pragma warning(disable:4996)
#endif
#define least1(_z) (_z ? _z : 1)
static int stfu_log_level = 7;
struct stfu_queue {
struct stfu_frame *array;
struct stfu_frame int_frame;
uint32_t real_array_size;
uint32_t array_size;
uint32_t array_len;
uint32_t wr_len;
uint32_t last_index;
int32_t last_jitter;
};
typedef struct stfu_queue stfu_queue_t;
struct stfu_instance {
struct stfu_queue a_queue;
struct stfu_queue b_queue;
struct stfu_queue c_queue;
struct stfu_queue *in_queue;
struct stfu_queue *out_queue;
struct stfu_queue *old_queue;
struct stfu_frame *last_frame;
uint32_t cur_ts;
uint32_t last_wr_ts;
uint32_t last_rd_ts;
uint32_t interval;
uint32_t samples_per_packet;
uint32_t samples_per_second;
uint32_t miss_count;
uint32_t max_plc;
uint32_t qlen;
uint32_t max_qlen;
uint32_t orig_qlen;
uint32_t packet_count;
uint32_t consecutive_good_count;
uint32_t consecutive_bad_count;
uint32_t period_good_count;
uint32_t period_bad_count;
uint32_t period_packet_in_count;
uint32_t period_packet_out_count;
uint32_t period_missing_count;
uint32_t period_need_range;
uint32_t period_need_range_avg;
uint32_t period_clean_count;
uint32_t session_clean_count;
uint32_t session_missing_count;
uint32_t session_packet_in_count;
uint32_t session_packet_out_count;
uint32_t sync_out;
uint32_t sync_in;
int32_t ts_diff;
int32_t last_ts_diff;
int32_t same_ts;
uint32_t period_time;
uint32_t decrement_time;
uint32_t plc_len;
uint32_t plc_pt;
uint32_t diff;
uint32_t diff_total;
uint8_t ready;
uint8_t debug;
char *name;
stfu_n_call_me_t callback;
void *udata;
};
static void stfu_n_reset_counters(stfu_instance_t *i);
static void null_logger(const char *file, const char *func, int line, int level, const char *fmt, ...);
static void default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...);
stfu_logger_t stfu_log = null_logger;
void stfu_global_set_logger(stfu_logger_t logger)
{
if (logger) {
stfu_log = logger;
} else {
stfu_log = null_logger;
}
}
void stfu_global_set_default_logger(int level)
{
if (level < 0 || level > 7) {
level = 7;
}
stfu_log = default_logger;
stfu_log_level = level;
}
static stfu_status_t stfu_n_resize_aqueue(stfu_queue_t *queue, uint32_t qlen)
{
unsigned char *m;
if (qlen <= queue->array_size) {
return STFU_IT_FAILED;;
if (qlen <= queue->real_array_size) {
queue->array_size = qlen;
if (queue->array_len > qlen) {
queue->array_len = qlen;
}
} else {
m = realloc(queue->array, qlen * sizeof(struct stfu_frame));
assert(m);
memset(m + queue->array_size * sizeof(struct stfu_frame), 0, (qlen * sizeof(struct stfu_frame)) - (queue->array_size * sizeof(struct stfu_frame)));
queue->array = (struct stfu_frame *) m;
queue->real_array_size = queue->array_size = qlen;
}
m = realloc(queue->array, qlen * sizeof(struct stfu_frame));
assert(m);
memset(m + queue->array_size, 0, qlen * sizeof(struct stfu_frame) - queue->array_size);
queue->array = (struct stfu_frame *) m;
queue->array_size = qlen;
return STFU_IT_WORKED;
}
static void stfu_n_init_aqueue(stfu_queue_t *queue, uint32_t qlen)
{
queue->array = calloc(qlen, sizeof(struct stfu_frame));
assert(queue->array != NULL);
memset(queue->array, 0, sizeof(struct stfu_frame) * qlen);
queue->array_size = qlen;
queue->real_array_size = queue->array_size = qlen;
queue->int_frame.plc = 1;
memset(queue->int_frame.data, 255, sizeof(queue->int_frame.data));
}
void stfu_n_call_me(stfu_instance_t *i, stfu_n_call_me_t callback, void *udata)
{
i->callback = callback;
i->udata = udata;
}
void stfu_n_destroy(stfu_instance_t **i)
@ -88,33 +192,66 @@ void stfu_n_destroy(stfu_instance_t **i)
if (i && *i) {
ii = *i;
*i = NULL;
if (ii->name) free(ii->name);
free(ii->a_queue.array);
free(ii->b_queue.array);
free(ii->c_queue.array);
free(ii);
}
}
void stfu_n_debug(stfu_instance_t *i, const char *name)
{
if (i->name) free(i->name);
if (name) {
i->name = strdup(name);
i->debug = 1;
} else {
i->name = strdup("none");
i->debug = 0;
}
}
void stfu_n_report(stfu_instance_t *i, stfu_report_t *r)
{
assert(i);
r->in_len = i->in_queue->array_len;
r->in_size = i->in_queue->array_size;
r->out_len = i->out_queue->array_len;
r->out_size = i->out_queue->array_size;
r->qlen = i->qlen;
r->packet_in_count = i->period_packet_in_count;
r->clean_count = i->period_clean_count;
r->consecutive_good_count = i->consecutive_good_count;
r->consecutive_bad_count = i->consecutive_bad_count;
}
stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen)
{
stfu_status_t s;
if (i->qlen == i->max_qlen) {
return STFU_IT_FAILED;
}
if (i->max_qlen && qlen > i->max_qlen) {
if (i->qlen < i->max_qlen) {
qlen = i->max_qlen;
} else {
return STFU_IT_FAILED;
}
}
if ((s = stfu_n_resize_aqueue(&i->a_queue, qlen)) == STFU_IT_WORKED) {
s = stfu_n_resize_aqueue(&i->b_queue, qlen);
s = stfu_n_resize_aqueue(&i->c_queue, qlen);
i->qlen = qlen;
i->max_plc = 5;
i->last_frame = NULL;
}
return s;
}
stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_plc)
stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_per_packet, uint32_t samples_per_second)
{
struct stfu_instance *i;
@ -123,116 +260,259 @@ stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_plc)
return NULL;
}
memset(i, 0, sizeof(*i));
i->qlen = qlen;
i->max_qlen = max_qlen;
i->orig_qlen = qlen;
i->samples_per_packet = samples_per_packet;
stfu_n_init_aqueue(&i->a_queue, qlen);
stfu_n_init_aqueue(&i->b_queue, qlen);
stfu_n_init_aqueue(&i->c_queue, qlen);
i->in_queue = &i->a_queue;
i->out_queue = &i->b_queue;
i->old_queue = &i->c_queue;
i->name = strdup("none");
i->max_plc = i->qlen / 2;
if (max_plc) {
i->max_plc = max_plc;
} else {
i->max_plc = qlen / 2;
}
i->samples_per_second = samples_per_second ? samples_per_second : 8000;
i->period_time = ((i->samples_per_second * 20) / i->samples_per_packet);
i->decrement_time = ((i->samples_per_second * 15) / i->samples_per_packet);
return i;
}
static void stfu_n_reset_counters(stfu_instance_t *i)
{
if (stfu_log != null_logger && i->debug) {
stfu_log(STFU_LOG_EMERG, "%s COUNTER RESET........\n", i->name);
}
if (i->callback) {
i->callback(i, i->udata);
}
i->consecutive_good_count = 0;
i->consecutive_bad_count = 0;
i->period_good_count = 0;
i->period_clean_count = 0;
i->period_bad_count = 0;
i->period_packet_in_count = 0;
i->period_packet_out_count = 0;
i->period_missing_count = 0;
i->period_need_range = 0;
i->period_need_range_avg = 0;
i->diff = 0;
i->diff_total = 0;
}
void stfu_n_reset(stfu_instance_t *i)
{
if (stfu_log != null_logger && i->debug) {
stfu_log(STFU_LOG_EMERG, "%s RESET\n", i->name);
}
i->ready = 0;
i->in_queue = &i->a_queue;
i->out_queue = &i->b_queue;
i->old_queue = &i->c_queue;
i->in_queue->array_len = 0;
i->out_queue->array_len = 0;
i->out_queue->wr_len = 0;
i->last_frame = NULL;
i->miss_count = 0;
i->in_queue->last_jitter = 0;
i->out_queue->last_jitter = 0;
stfu_n_reset_counters(i);
stfu_n_sync(i, 1);
i->cur_ts = 0;
i->last_wr_ts = 0;
i->miss_count = 0;
i->interval = 0;
i->last_rd_ts = 0;
i->miss_count = 0;
i->packet_count = 0;
}
static int32_t stfu_n_measure_interval(stfu_queue_t *queue)
stfu_status_t stfu_n_sync(stfu_instance_t *i, uint32_t packets)
{
uint32_t index;
int32_t d, most = 0, last = 0, this, track[STFU_MAX_TRACK] = {0};
for(index = 0; index < queue->array_len; index++) {
this = queue->array[index].ts;
if (last) {
if (packets > i->qlen) {
stfu_n_reset(i);
} else {
i->sync_out = packets;
i->sync_in = packets;
}
if ((d = this - last) > 0 && d / 10 < STFU_MAX_TRACK) {
track[(d/10)]++;
}
}
last = this;
}
for(index = 0; index < STFU_MAX_TRACK; index++) {
if (track[index] > track[most]) {
most = index;
}
}
return most * 10;
return STFU_IT_WORKED;
}
static int16_t stfu_n_process(stfu_instance_t *i, stfu_queue_t *queue)
{
if (!i->interval && !(i->interval = stfu_n_measure_interval(queue))) {
return -1;
}
return 0;
static void stfu_n_swap(stfu_instance_t *i)
{
stfu_queue_t *last_in = i->in_queue, *last_out = i->out_queue, *last_old = i->old_queue;
i->ready = 1;
i->in_queue = last_out;
i->out_queue = last_old;
i->old_queue = last_in;
i->in_queue->array_len = 0;
i->out_queue->wr_len = 0;
i->last_frame = NULL;
i->miss_count = 0;
i->in_queue->last_index = 0;
i->out_queue->last_index = 0;
i->out_queue->last_jitter = 0;
}
stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, int last)
{
uint32_t index;
uint32_t index = 0;
stfu_frame_t *frame;
size_t cplen = 0;
int good_ts = 0;
if (!i->samples_per_packet && ts && i->last_rd_ts) {
i->ts_diff = ts - i->last_rd_ts;
if (i->last_ts_diff == i->ts_diff) {
if (++i->same_ts == 5) {
i->samples_per_packet = i->ts_diff;
}
} else {
i->same_ts = 0;
}
i->last_ts_diff = i->ts_diff;
if (!i->samples_per_packet) {
i->last_rd_ts = ts;
return STFU_IT_FAILED;
}
}
if (i->sync_in) {
good_ts = 1;
i->sync_in = 0;
} else {
if ((ts && ts == i->last_rd_ts + i->samples_per_packet) || (i->last_rd_ts > 4294900000 && ts < 5000)) {
good_ts = 1;
}
if (i->last_wr_ts) {
if ((ts <= i->last_wr_ts && (i->last_wr_ts != UINT_MAX || ts == i->last_wr_ts))) {
if (stfu_log != null_logger && i->debug) {
stfu_log(STFU_LOG_EMERG, "%s TOO LATE !!! %u \n\n\n", i->name, ts);
}
if (i->in_queue->array_len < i->in_queue->array_size) {
i->in_queue->array_len++;
}
return STFU_ITS_TOO_LATE;
}
}
}
if (good_ts) {
i->period_clean_count++;
i->session_clean_count++;
}
i->period_packet_in_count++;
i->session_packet_in_count++;
i->period_need_range_avg = i->period_need_range / least1(i->period_missing_count);
if (i->period_missing_count > i->qlen * 2) {
if (stfu_log != null_logger && i->debug) {
stfu_log(STFU_LOG_EMERG, "%s resize %u %u\n", i->name, i->qlen, i->qlen + 1);
}
stfu_n_resize(i, i->qlen + 1);
stfu_n_reset_counters(i);
} else {
if (i->qlen > i->orig_qlen && (i->consecutive_good_count > i->decrement_time || i->period_clean_count > i->decrement_time)) {
stfu_n_resize(i, i->qlen - 1);
stfu_n_reset_counters(i);
stfu_n_sync(i, i->qlen);
}
}
i->diff = 0;
if (i->last_wr_ts) {
if (ts < 1000 && i->last_wr_ts > (UINT_MAX - 1000)) {
i->diff = abs(((UINT_MAX - i->last_wr_ts) + ts) / i->samples_per_packet);
} else if (ts) {
i->diff = abs(i->last_wr_ts - ts) / i->samples_per_packet;
}
}
i->diff_total += i->diff;
if ((i->period_packet_in_count > i->period_time)) {
uint32_t avg;
avg = i->diff_total / least1(i->period_packet_in_count);
i->period_packet_in_count = 0;
if (i->period_missing_count == 0 && i->qlen > i->orig_qlen) {
stfu_n_resize(i, i->qlen - 1);
stfu_n_sync(i, i->qlen);
}
stfu_n_reset_counters(i);
}
if (stfu_log != null_logger && i->debug) {
stfu_log(STFU_LOG_EMERG, "%s %u i=%u/%u - g:%u/%u c:%u/%u b:%u - %u:%u - %u %d %u %u %d %d\n", i->name,
i->qlen, i->period_packet_in_count, i->period_time, i->consecutive_good_count,
i->decrement_time, i->period_clean_count, i->decrement_time, i->consecutive_bad_count,
ts, ts / i->samples_per_packet,
i->period_missing_count, i->period_need_range_avg,
i->last_wr_ts, ts, i->diff, i->diff_total / least1(i->period_packet_in_count));
}
if (last || i->in_queue->array_len == i->in_queue->array_size) {
stfu_queue_t *other_queue;
if (i->out_queue->wr_len < i->out_queue->array_len) {
return STFU_IT_FAILED;
}
other_queue = i->in_queue;
i->in_queue = i->out_queue;
i->out_queue = other_queue;
i->in_queue->array_len = 0;
i->out_queue->wr_len = 0;
i->last_frame = NULL;
i->miss_count = 0;
if (stfu_n_process(i, i->out_queue) < 0) {
if (i->in_queue->array_len == i->in_queue->array_size && i->out_queue->array_len == i->out_queue->array_size) {
stfu_n_resize(i, i->out_queue->array_size * 2);
}
//return STFU_IT_FAILED;
}
for(index = 0; index < i->out_queue->array_len; index++) {
i->out_queue->array[index].was_read = 0;
}
}
stfu_n_swap(i);
}
if (last) {
return STFU_IM_DONE;
}
index = i->in_queue->array_len++;
index = i->in_queue->array_len++;
assert(index < i->in_queue->array_size);
frame = &i->in_queue->array[index];
if (i->in_queue->array_len == i->in_queue->array_size) {
stfu_n_swap(i);
}
if ((cplen = datalen) > sizeof(frame->data)) {
cplen = sizeof(frame->data);
}
i->last_rd_ts = ts;
i->packet_count++;
memcpy(frame->data, data, cplen);
frame->pt = pt;
frame->ts = ts;
frame->dlen = cplen;
@ -241,23 +521,51 @@ stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void
return STFU_IT_WORKED;
}
static int stfu_n_find_frame(stfu_queue_t *queue, uint32_t ts, stfu_frame_t **r_frame, uint32_t *index)
static int stfu_n_find_any_frame(stfu_instance_t *in, stfu_queue_t *queue, stfu_frame_t **r_frame)
{
uint32_t i = 0;
stfu_frame_t *frame = NULL;
assert(r_frame);
assert(index);
*r_frame = NULL;
for(i = 0; i < queue->array_len; i++) {
for(i = 0; i < queue->real_array_size; i++) {
frame = &queue->array[i];
if (!frame->was_read) {
*r_frame = frame;
queue->last_index = i;
frame->was_read = 1;
in->period_packet_out_count++;
in->session_packet_out_count++;
return 1;
}
}
return 0;
}
static int stfu_n_find_frame(stfu_instance_t *in, stfu_queue_t *queue, uint32_t ts, stfu_frame_t **r_frame)
{
uint32_t i = 0;
stfu_frame_t *frame = NULL;
if (r_frame) {
*r_frame = NULL;
}
for(i = 0; i < queue->array_size; i++) {
frame = &queue->array[i];
if (frame->ts == ts) {
*r_frame = frame;
*index = i;
frame->was_read = 1;
if (r_frame) {
*r_frame = frame;
queue->last_index = i;
frame->was_read = 1;
in->period_packet_out_count++;
in->session_packet_out_count++;
}
return 1;
}
}
@ -267,47 +575,300 @@ static int stfu_n_find_frame(stfu_queue_t *queue, uint32_t ts, stfu_frame_t **r_
stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i)
{
uint32_t index;
stfu_frame_t *rframe = NULL;
if (((i->out_queue->wr_len == i->out_queue->array_len) || !i->out_queue->array_len)) {
return NULL;
}
int found = 0;
if (i->cur_ts == 0) {
i->cur_ts = i->out_queue->array[0].ts;
} else {
i->cur_ts += i->interval;
if (!i->samples_per_packet) {
return NULL;
}
if (!i->ready) {
if (stfu_log != null_logger && i->debug) {
stfu_log(STFU_LOG_EMERG, "%s XXXSKIP\n", i->name);
}
return NULL;
}
if (stfu_n_find_frame(i->out_queue, i->cur_ts, &rframe, &index) || stfu_n_find_frame(i->in_queue, i->cur_ts, &rframe, &index)) {
if (i->cur_ts == 0 && i->last_wr_ts < 1000) {
uint32_t x = 0;
for (x = 0; x < i->out_queue->array_len; x++) {
if (!i->out_queue->array[x].was_read) {
i->cur_ts = i->out_queue->array[x].ts;
break;
}
if (i->cur_ts == 0) {
if (stfu_log != null_logger && i->debug) {
stfu_log(STFU_LOG_EMERG, "%s XXXPUNT\n", i->name);
return NULL;
}
}
}
} else {
i->cur_ts = i->cur_ts + i->samples_per_packet;
}
found = stfu_n_find_frame(i, i->out_queue, i->cur_ts, &rframe);
if (found) {
if (i->out_queue->array_len) {
i->out_queue->array_len--;
}
} else {
found = stfu_n_find_frame(i, i->in_queue, i->cur_ts, &rframe);
if (!found) {
found = stfu_n_find_frame(i, i->old_queue, i->cur_ts, &rframe);
}
}
if (i->sync_out) {
if (!found) {
if ((found = stfu_n_find_any_frame(i, i->out_queue, &rframe))) {
i->cur_ts = rframe->ts;
}
if (stfu_log != null_logger && i->debug) {
stfu_log(STFU_LOG_EMERG, "%s SYNC %u %u:%u\n", i->name, i->sync_out, i->cur_ts, i->cur_ts / i->samples_per_packet);
}
}
i->sync_out = 0;
}
if (!i->cur_ts) {
if (stfu_log != null_logger && i->debug) {
stfu_log(STFU_LOG_EMERG, "%s NO TS\n", i->name);
}
return NULL;
}
if (!found && i->samples_per_packet) {
uint32_t y;
stfu_frame_t *frame = NULL;
int32_t delay = i->last_rd_ts - i->cur_ts;
uint32_t need = abs(i->last_rd_ts - i->cur_ts) / i->samples_per_packet;
i->period_missing_count++;
i->session_missing_count++;
i->period_need_range += need;
if (stfu_log != null_logger && i->debug) {
stfu_log(STFU_LOG_EMERG, "%s MISSING %u:%u %u %u %d %u %d\n", i->name,
i->cur_ts, i->cur_ts / i->samples_per_packet, i->packet_count, i->last_rd_ts, delay, i->qlen, need);
}
if (i->packet_count > i->orig_qlen * 100 && delay > 0 && need > i->qlen && need < (i->qlen + 5)) {
i->packet_count = 0;
}
if (stfu_log != null_logger && i->debug) {
stfu_log(STFU_LOG_EMERG, "%s ", i->name);
for(y = 0; y < i->out_queue->array_size; y++) {
if ((y % 5) == 0) stfu_log(STFU_LOG_EMERG, "\n%s ", i->name);
frame = &i->out_queue->array[y];
stfu_log(STFU_LOG_EMERG, "%u:%u\t", frame->ts, frame->ts / i->samples_per_packet);
}
stfu_log(STFU_LOG_EMERG, "\n%s ", i->name);
for(y = 0; y < i->in_queue->array_size; y++) {
if ((y % 5) == 0) stfu_log(STFU_LOG_EMERG, "\n%s ", i->name);
frame = &i->in_queue->array[y];
stfu_log(STFU_LOG_EMERG, "%u:%u\t", frame->ts, frame->ts / i->samples_per_packet);
}
stfu_log(STFU_LOG_EMERG, "\n%s\n\n\n", i->name);
}
if (delay < 0) {
stfu_n_reset(i);
return NULL;
}
}
if (stfu_log != null_logger && i->debug) {
if (found) {
stfu_log(STFU_LOG_EMERG, "%s O: %u:%u %u\n", i->name, rframe->ts, rframe->ts / i->samples_per_packet, rframe->plc);
}
}
if (found) {
i->consecutive_good_count++;
i->period_good_count++;
i->consecutive_bad_count = 0;
} else {
i->consecutive_bad_count++;
i->period_bad_count++;
i->consecutive_good_count = 0;
}
if (found) {
i->last_frame = rframe;
i->out_queue->wr_len++;
i->last_wr_ts = rframe->ts;
i->miss_count = 0;
i->out_queue->wr_len++;
i->last_wr_ts = rframe->ts;
i->miss_count = 0;
if (rframe->dlen) {
i->plc_len = rframe->dlen;
}
i->plc_pt = rframe->pt;
} else {
i->last_wr_ts = i->cur_ts;
rframe = &i->out_queue->int_frame;
if (i->last_frame && i->last_frame != rframe) {
rframe->dlen = i->last_frame->dlen;
/* poor man's plc.. Copy the last frame, but we flag it so you can use a better one if you wish */
memcpy(rframe->data, i->last_frame->data, rframe->dlen);
rframe->dlen = i->plc_len;
rframe->pt = i->plc_pt;
rframe->ts = i->cur_ts;
i->miss_count++;
if (stfu_log != null_logger && i->debug) {
stfu_log(STFU_LOG_EMERG, "%s PLC %d %d %ld %u:%u\n", i->name,
i->miss_count, rframe->plc, rframe->dlen, rframe->ts, rframe->ts / i->samples_per_packet);
}
rframe->ts = i->cur_ts;
if (++i->miss_count > i->max_plc) {
i->out_queue->wr_len = i->out_queue->array_size;
i->cur_ts = 0;
if (i->miss_count > i->max_plc) {
stfu_n_reset(i);
rframe = NULL;
}
}
return rframe;
return rframe;
}
#ifdef WIN32
#ifndef vsnprintf
#define vsnprintf _vsnprintf
#endif
#endif
int vasprintf(char **ret, const char *format, va_list ap);
int stfu_vasprintf(char **ret, const char *fmt, va_list ap)
{
#if !defined(WIN32) && !defined(__sun)
return vasprintf(ret, fmt, ap);
#else
char *buf;
int len;
size_t buflen;
va_list ap2;
char *tmp = NULL;
#ifdef _MSC_VER
#if _MSC_VER >= 1500
/* hack for incorrect assumption in msvc header files for code analysis */
__analysis_assume(tmp);
#endif
ap2 = ap;
#else
va_copy(ap2, ap);
#endif
len = vsnprintf(tmp, 0, fmt, ap2);
if (len > 0 && (buf = malloc((buflen = (size_t) (len + 1)))) != NULL) {
len = vsnprintf(buf, buflen, fmt, ap);
*ret = buf;
} else {
*ret = NULL;
len = -1;
}
va_end(ap2);
return len;
#endif
}
int stfu_snprintf(char *buffer, size_t count, const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
ret = vsnprintf(buffer, count-1, fmt, ap);
if (ret < 0)
buffer[count-1] = '\0';
va_end(ap);
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) {
return;
}
return;
}
static const char *LEVEL_NAMES[] = {
"EMERG",
"ALERT",
"CRIT",
"ERROR",
"WARNING",
"NOTICE",
"INFO",
"DEBUG",
NULL
};
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 default_logger(const char *file, const char *func, int line, int level, const char *fmt, ...)
{
const char *fp;
char *data;
va_list ap;
int ret;
if (level < 0 || level > 7) {
level = 7;
}
if (level > stfu_log_level) {
return;
}
fp = cut_path(file);
va_start(ap, fmt);
ret = stfu_vasprintf(&data, fmt, ap);
if (ret != -1) {
fprintf(stderr, "[%s] %s:%d %s() %s", LEVEL_NAMES[level], file, line, func, data);
free(data);
}
va_end(ap);
}
/* For Emacs:
* Local Variables:
* mode:c

View File

@ -38,6 +38,8 @@ extern "C" {
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#ifdef _MSC_VER
#ifndef uint32_t
@ -62,6 +64,85 @@ typedef unsigned long in_addr_t;
#endif
#include <assert.h>
#ifdef WIN32
#include <winsock2.h>
#include <windows.h>
typedef SOCKET stfu_socket_t;
typedef unsigned __int64 uint64_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int8 uint8_t;
typedef __int64 int64_t;
typedef __int32 int32_t;
typedef __int16 int16_t;
typedef __int8 int8_t;
typedef intptr_t stfu_ssize_t;
typedef int stfu_filehandle_t;
#define STFU_SOCK_INVALID INVALID_SOCKET
#define strerror_r(num, buf, size) strerror_s(buf, size, num)
#if defined(STFU_DECLARE_STATIC)
#define STFU_DECLARE(type) type __stdcall
#define STFU_DECLARE_NONSTD(type) type __cdecl
#define STFU_DECLARE_DATA
#elif defined(STFU_EXPORTS)
#define STFU_DECLARE(type) __declspec(dllexport) type __stdcall
#define STFU_DECLARE_NONSTD(type) __declspec(dllexport) type __cdecl
#define STFU_DECLARE_DATA __declspec(dllexport)
#else
#define STFU_DECLARE(type) __declspec(dllimport) type __stdcall
#define STFU_DECLARE_NONSTD(type) __declspec(dllimport) type __cdecl
#define STFU_DECLARE_DATA __declspec(dllimport)
#endif
#else
#define STFU_DECLARE(type) type
#define STFU_DECLARE_NONSTD(type) type
#define STFU_DECLARE_DATA
#include <stdint.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <stdarg.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define STFU_SOCK_INVALID -1
typedef int stfu_socket_t;
typedef ssize_t stfu_ssize_t;
typedef int stfu_filehandle_t;
#endif
#define STFU_PRE __FILE__, __FUNCTION__, __LINE__
#define STFU_LOG_LEVEL_DEBUG 7
#define STFU_LOG_LEVEL_INFO 6
#define STFU_LOG_LEVEL_NOTICE 5
#define STFU_LOG_LEVEL_WARNING 4
#define STFU_LOG_LEVEL_ERROR 3
#define STFU_LOG_LEVEL_CRIT 2
#define STFU_LOG_LEVEL_ALERT 1
#define STFU_LOG_LEVEL_EMERG 0
#define STFU_LOG_DEBUG STFU_PRE, STFU_LOG_LEVEL_DEBUG
#define STFU_LOG_INFO STFU_PRE, STFU_LOG_LEVEL_INFO
#define STFU_LOG_NOTICE STFU_PRE, STFU_LOG_LEVEL_NOTICE
#define STFU_LOG_WARNING STFU_PRE, STFU_LOG_LEVEL_WARNING
#define STFU_LOG_ERROR STFU_PRE, STFU_LOG_LEVEL_ERROR
#define STFU_LOG_CRIT STFU_PRE, STFU_LOG_LEVEL_CRIT
#define STFU_LOG_ALERT STFU_PRE, STFU_LOG_LEVEL_ALERT
#define STFU_LOG_EMERG STFU_PRE, STFU_LOG_LEVEL_EMERG
typedef void (*stfu_logger_t)(const char *file, const char *func, int line, int level, const char *fmt, ...);
int stfu_vasprintf(char **ret, const char *fmt, va_list ap);
extern stfu_logger_t stfu_log;
/*! Sets the logger for libstfu. Default is the null_logger */
void stfu_global_set_logger(stfu_logger_t logger);
/*! Sets the default log level for libstfu */
void stfu_global_set_default_logger(int level);
#define STFU_DATALEN 16384
#define STFU_QLEN 300
#define STFU_MAX_TRACK 256
@ -69,7 +150,8 @@ typedef unsigned long in_addr_t;
typedef enum {
STFU_IT_FAILED,
STFU_IT_WORKED,
STFU_IM_DONE
STFU_IM_DONE,
STFU_ITS_TOO_LATE
} stfu_status_t;
struct stfu_frame {
@ -86,21 +168,25 @@ struct stfu_instance;
typedef struct stfu_instance stfu_instance_t;
typedef struct {
uint32_t in_len;
uint32_t in_size;
uint32_t out_len;
uint32_t out_size;
uint32_t qlen;
uint32_t packet_in_count;
uint32_t clean_count;
uint32_t consecutive_good_count;
uint32_t consecutive_bad_count;
} stfu_report_t;
typedef void (*stfu_n_call_me_t)(stfu_instance_t *i, void *);
void stfu_n_report(stfu_instance_t *i, stfu_report_t *r);
void stfu_n_destroy(stfu_instance_t **i);
stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_plc);
stfu_instance_t *stfu_n_init(uint32_t qlen, uint32_t max_qlen, uint32_t samples_per_packet, uint32_t samples_per_second);
stfu_status_t stfu_n_resize(stfu_instance_t *i, uint32_t qlen);
stfu_status_t stfu_n_add_data(stfu_instance_t *i, uint32_t ts, uint32_t pt, void *data, size_t datalen, int last);
stfu_frame_t *stfu_n_read_a_frame(stfu_instance_t *i);
void stfu_n_reset(stfu_instance_t *i);
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);
#define stfu_im_done(i) stfu_n_add_data(i, 0, NULL, 0, 1)
#define stfu_n_eat(i,t,p,d,l) stfu_n_add_data(i, t, p, d, l, 0)

View File

@ -31,7 +31,8 @@
* this file does not exist!!!!
*
*/
#define SPANDSP_NO_TIFF 1
#include "spandsp.h"
#include "switch_profile.h"
#ifndef WIN32
@ -169,6 +170,7 @@ struct switch_core_session {
switch_log_level_t loglevel;
uint32_t soft_lock;
switch_ivr_dmachine_t *dmachine;
plc_state_t *plc;
};
struct switch_media_bug {

View File

@ -1110,6 +1110,8 @@ SWITCH_DECLARE(int) switch_sockaddr_equal(const switch_sockaddr_t *sa1, const sw
SWITCH_DECLARE(switch_status_t) switch_sockaddr_info_get(switch_sockaddr_t ** sa, const char *hostname,
int32_t family, switch_port_t port, int32_t flags, switch_memory_pool_t *pool);
SWITCH_DECLARE(switch_status_t) switch_sockaddr_create(switch_sockaddr_t **sa, switch_memory_pool_t *pool);
/**
* Send data over a network.
* @param sock The socket to send the data over.

View File

@ -312,6 +312,8 @@ SWITCH_DECLARE(switch_status_t) switch_channel_caller_extension_masquerade(switc
*/
SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension);
SWITCH_DECLARE(void) switch_channel_sort_cid(switch_channel_t *channel, switch_bool_t in);
/*!
\brief Retrieve caller extension from a given channel
\param channel channel to retrieve extension from

View File

@ -229,7 +229,14 @@ SWITCH_DECLARE(switch_status_t) switch_rtp_activate_rtcp(switch_rtp_t *rtp_sessi
\param queue_frames the number of frames to delay
\return SWITCH_STATUS_SUCCESS
*/
SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *rtp_session, uint32_t queue_frames);
SWITCH_DECLARE(switch_status_t) switch_rtp_activate_jitter_buffer(switch_rtp_t *rtp_session,
uint32_t queue_frames,
uint32_t max_queue_frames,
uint32_t samples_per_packet, uint32_t samples_per_second);
SWITCH_DECLARE(switch_status_t) switch_rtp_debug_jitter_buffer(switch_rtp_t *rtp_session, const char *name);
SWITCH_DECLARE(switch_status_t) switch_rtp_deactivate_jitter_buffer(switch_rtp_t *rtp_session);
/*!
\brief Set an RTP Flag

View File

@ -790,6 +790,7 @@ typedef enum {
SWITCH_MESSAGE_INDICATE_T38_DESCRIPTION,
SWITCH_MESSAGE_INDICATE_UDPTL_MODE,
SWITCH_MESSAGE_INDICATE_CLEAR_PROGRESS,
SWITCH_MESSAGE_INDICATE_JITTER_BUFFER,
SWITCH_MESSAGE_INVALID
} switch_core_session_message_types_t;
@ -1093,6 +1094,8 @@ typedef enum {
CF_PASSTHRU_PTIME_MISMATCH,
CF_BRIDGE_NOWRITE,
CF_RECOVERED,
CF_JITTERBUFFER,
CF_DIALPLAN,
/* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */
CF_FLAG_MAX
} switch_channel_flag_t;

View File

@ -2491,24 +2491,101 @@ SWITCH_STANDARD_API(uuid_display_function)
#define SIMPLIFY_SYNTAX "<uuid>"
SWITCH_STANDARD_API(uuid_simplify_function)
{
char *mydata = NULL, *argv[2] = { 0 };
int argc = 0;
switch_status_t status = SWITCH_STATUS_FALSE;
if (zstr(cmd)) {
stream->write_function(stream, "-USAGE: %s\n", SIMPLIFY_SYNTAX);
} else {
goto error;
}
mydata = strdup(cmd);
switch_assert(mydata);
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
if (argc < 1) {
goto error;
}
if (argv[0]) {
switch_core_session_message_t msg = { 0 };
switch_core_session_t *lsession = NULL;
msg.message_id = SWITCH_MESSAGE_INDICATE_SIMPLIFY;
msg.string_arg = cmd;
msg.string_arg = argv[0];
msg.from = __FILE__;
if ((lsession = switch_core_session_locate(cmd))) {
if ((lsession = switch_core_session_locate(argv[0]))) {
status = switch_core_session_receive_message(lsession, &msg);
switch_core_session_rwunlock(lsession);
}
goto ok;
} else {
goto error;
}
error:
stream->write_function(stream, "-USAGE: %s\n", SIMPLIFY_SYNTAX);
switch_safe_free(mydata);
return SWITCH_STATUS_SUCCESS;
ok:
switch_safe_free(mydata);
if (status == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "+OK Success\n");
} else {
stream->write_function(stream, "-ERR Operation Failed\n");
}
return SWITCH_STATUS_SUCCESS;
}
#define JITTERBUFFER_SYNTAX "<uuid> [0|<min_msec>[:<max_msec>]]"
SWITCH_STANDARD_API(uuid_jitterbuffer_function)
{
char *mydata = NULL, *argv[2] = { 0 };
int argc = 0;
switch_status_t status = SWITCH_STATUS_FALSE;
if (zstr(cmd)) {
goto error;
}
mydata = strdup(cmd);
switch_assert(mydata);
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
if (argc < 2) {
goto error;
}
if (argv[1]) {
switch_core_session_message_t msg = { 0 };
switch_core_session_t *lsession = NULL;
msg.message_id = SWITCH_MESSAGE_INDICATE_JITTER_BUFFER;
msg.string_arg = argv[1];
msg.from = __FILE__;
if ((lsession = switch_core_session_locate(argv[0]))) {
status = switch_core_session_receive_message(lsession, &msg);
switch_core_session_rwunlock(lsession);
}
goto ok;
} else {
goto error;
}
error:
stream->write_function(stream, "-USAGE: %s\n", JITTERBUFFER_SYNTAX);
switch_safe_free(mydata);
return SWITCH_STATUS_SUCCESS;
ok:
switch_safe_free(mydata);
if (status == SWITCH_STATUS_SUCCESS) {
stream->write_function(stream, "+OK Success\n");
} else {
@ -4255,21 +4332,33 @@ SWITCH_STANDARD_API(strftime_tz_api_function)
char *format = NULL;
const char *tz_name = NULL;
char date[80] = "";
char *mycmd = NULL, *p;
switch_time_t when = 0;
if (!zstr(cmd)) {
format = strchr(cmd, ' ');
tz_name = cmd;
if (format) {
if (cmd) mycmd = strdup(cmd);
if (!zstr(mycmd)) {
tz_name = mycmd;
if ((format = strchr(mycmd, ' '))) {
*format++ = '\0';
}
if ((p = strchr(format, '|'))) {
*p++ = '\0';
when = atol(format);
format = p;
}
}
if (switch_strftime_tz(tz_name, format, date, sizeof(date), 0) == SWITCH_STATUS_SUCCESS) { /* The lookup of the zone may fail. */
if (switch_strftime_tz(tz_name, format, date, sizeof(date), when * 1000000) == SWITCH_STATUS_SUCCESS) { /* The lookup of the zone may fail. */
stream->write_function(stream, "%s", date);
} else {
stream->write_function(stream, "-ERR Invalid Timezone\n");
}
switch_safe_free(mycmd);
return SWITCH_STATUS_SUCCESS;
}
@ -4692,7 +4781,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "show", "Show", show_function, SHOW_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "sql_escape", "Escape a string to prevent sql injection", sql_escape, SQL_ESCAPE_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "status", "status", status_function, "");
SWITCH_ADD_API(commands_api_interface, "strftime_tz", "strftime_tz", strftime_tz_api_function, "<Timezone_name> [format string]");
SWITCH_ADD_API(commands_api_interface, "strftime_tz", "strftime_tz", strftime_tz_api_function, "<Timezone_name> [<epoch>|][format string]");
SWITCH_ADD_API(commands_api_interface, "stun", "stun", stun_function, "<stun_server>[:port]");
SWITCH_ADD_API(commands_api_interface, "system", "Execute a system command", system_function, SYSTEM_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "time_test", "time_test", time_test_function, "<mss> [count]");
@ -4735,6 +4824,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
SWITCH_ADD_API(commands_api_interface, "uuid_transfer", "Transfer a session", transfer_function, TRANSFER_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_dual_transfer", "Transfer a session and its partner", dual_transfer_function, DUAL_TRANSFER_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_simplify", "Try to cut out of a call path / attended xfer", uuid_simplify_function, SIMPLIFY_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "uuid_jitterbuffer", "Try to cut out of a call path / attended xfer",
uuid_jitterbuffer_function, JITTERBUFFER_SYNTAX);
SWITCH_ADD_API(commands_api_interface, "xml_locate", "find some xml", xml_locate_function, "[root | <section> <tag> <tag_attr_name> <tag_attr_val>]");
SWITCH_ADD_API(commands_api_interface, "xml_wrap", "Wrap another api command in xml", xml_wrap_api_function, "<command> <args>");
switch_console_set_complete("add alias add");
@ -4831,6 +4922,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
switch_console_set_complete("add uuid_flush_dtmf ::console::list_uuid");
switch_console_set_complete("add uuid_getvar ::console::list_uuid");
switch_console_set_complete("add uuid_hold ::console::list_uuid");
switch_console_set_complete("add uuid_jitterbuffer ::console::list_uuid");
switch_console_set_complete("add uuid_kill ::console::list_uuid");
switch_console_set_complete("add uuid_limit_release ::console::list_uuid");
switch_console_set_complete("add uuid_loglevel ::console::list_uuid console");
@ -4853,6 +4945,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load)
switch_console_set_complete("add uuid_session_heartbeat ::console::list_uuid");
switch_console_set_complete("add uuid_setvar_multi ::console::list_uuid");
switch_console_set_complete("add uuid_setvar ::console::list_uuid");
switch_console_set_complete("add uuid_simplify ::console::list_uuid");
switch_console_set_complete("add uuid_transfer ::console::list_uuid");
switch_console_set_complete("add uuid_dual_transfer ::console::list_uuid");
switch_console_set_complete("add version");

View File

@ -2456,7 +2456,7 @@ static void conference_loop_output(conference_member_t *member)
switch_event_destroy(&event);
}
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
/* test to see if outbound channel has answered */
if (switch_channel_test_flag(channel, CF_ANSWERED) && !switch_test_flag(member->conference, CFLAG_ANSWERED)) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(member->session), SWITCH_LOG_DEBUG,
@ -2599,7 +2599,7 @@ static void conference_loop_output(conference_member_t *member)
switch_channel_cause2str(switch_channel_get_cause(channel)));
/* if it's an outbound channel, store the release cause in the conference struct, we might need it */
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
member->conference->bridge_hangup_cause = switch_channel_get_cause(channel);
}
@ -4366,6 +4366,8 @@ static switch_status_t conf_api_sub_transfer(conference_obj_t *conference, switc
}
}
switch_channel_set_variable(channel, "last_transfered_conference", argv[2]);
unlock_member(member);
stream->write_function(stream, "OK Member '%d' sent to conference %s.\n", member->id, argv[2]);
@ -5374,6 +5376,14 @@ SWITCH_STANDARD_APP(conference_function)
}
#endif
if (switch_channel_test_flag(channel, CF_RECOVERED)) {
const char *check = switch_channel_get_variable(channel, "last_transfered_conference");
if (!zstr(check)) {
conf_name = (char *) check;
}
}
switch_event_create(&params, SWITCH_EVENT_COMMAND);
switch_assert(params);
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "conf_name", conf_name);
@ -5436,7 +5446,7 @@ SWITCH_STANDARD_APP(conference_function)
launch_conference_thread(conference);
} else {
int enforce_security = !switch_channel_test_flag(channel, CF_OUTBOUND);
int enforce_security = switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND;
const char *pvar = switch_channel_get_variable(channel, "conference_enforce_security");
if (pvar) {
@ -5645,7 +5655,7 @@ SWITCH_STANDARD_APP(conference_function)
} else {
/* if we're not using "bridge:" set the conference answered flag */
/* and this isn't an outbound channel, answer the call */
if (!switch_channel_test_flag(channel, CF_OUTBOUND))
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND)
switch_set_flag(conference, CFLAG_ANSWERED);
}

View File

@ -269,7 +269,7 @@ SWITCH_STANDARD_APP(bind_digit_action_function)
}
#define DETECT_SPEECH_SYNTAX "<mod_name> <gram_name> <gram_path> [<addr>] OR grammar <gram_name> [<path>] OR pause OR resume"
#define DETECT_SPEECH_SYNTAX "<mod_name> <gram_name> <gram_path> [<addr>] OR grammar <gram_name> [<path>] OR nogrammar <gram_name> OR pause OR resume OR stop OR param <name> <value>"
SWITCH_STANDARD_APP(detect_speech_function)
{
char *argv[4];
@ -957,6 +957,17 @@ SWITCH_STANDARD_APP(redirect_function)
switch_core_session_receive_message(session, &msg);
}
SWITCH_STANDARD_APP(jitterbuffer_function)
{
switch_core_session_message_t msg = { 0 };
/* Tell the channel to change the jitter buffer */
msg.from = __FILE__;
msg.string_arg = data;
msg.message_id = SWITCH_MESSAGE_INDICATE_JITTER_BUFFER;
switch_core_session_receive_message(session, &msg);
}
SWITCH_STANDARD_APP(display_function)
{
switch_core_session_message_t msg = { 0 };
@ -1303,13 +1314,22 @@ SWITCH_STANDARD_API(strftime_api_function)
char date[80] = "";
switch_time_t thetime;
char *p;
if (!zstr(cmd) && (p = strchr(cmd, '|'))) {
thetime = switch_time_make(atoi(cmd), 0);
char *mycmd = NULL;
if (!zstr(cmd)) {
mycmd = strdup(cmd);
}
if (!zstr(mycmd) && (p = strchr(cmd, '|'))) {
*p++ = '\0';
thetime = switch_time_make(atol(cmd), 0);
cmd = p + 1;
} else {
thetime = switch_micro_time_now();
}
switch_time_exp_lt(&tm, thetime);
if (zstr(cmd)) {
switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);
} else {
@ -3513,6 +3533,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load)
SWITCH_ADD_APP(app_interface, "ivr", "Run an ivr menu", "Run an ivr menu.", ivr_application_function, "<menu_name>", SAF_NONE);
SWITCH_ADD_APP(app_interface, "redirect", "Send session redirect", "Send a redirect message to a session.", redirect_function, "<redirect_data>",
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "jitterbuffer", "Send session jitterbuffer", "Send a jitterbuffer message to a session.",
jitterbuffer_function, "<jitterbuffer_data>", SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "send_display", "Send session a new display", "Send session a new display.", display_function, "<text>",
SAF_SUPPORT_NOMEDIA);
SWITCH_ADD_APP(app_interface, "respond", "Send session respond", "Send a respond message to a session.", respond_function, "<respond_data>",

View File

@ -291,6 +291,7 @@ static switch_status_t fifo_queue_popfly(fifo_queue_t *queue, const char *uuid)
struct fifo_node {
char *name;
switch_mutex_t *mutex;
switch_mutex_t *update_mutex;
fifo_queue_t *fifo_list[MAX_PRI];
switch_hash_t *consumer_hash;
int outbound_priority;
@ -801,6 +802,7 @@ static fifo_node_t *create_node(const char *name, uint32_t importance, switch_mu
switch_core_hash_init(&node->consumer_hash, node->pool);
switch_thread_rwlock_create(&node->rwlock, node->pool);
switch_mutex_init(&node->mutex, SWITCH_MUTEX_NESTED, node->pool);
switch_mutex_init(&node->update_mutex, SWITCH_MUTEX_NESTED, node->pool);
cbt.buf = outbound_count;
cbt.len = sizeof(outbound_count);
sql = switch_mprintf("select count(*) from fifo_outbound where fifo_name = '%q'", name);
@ -1193,10 +1195,10 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void
if (node) {
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
node->busy = 0;
node->ring_consumer_count = 1;
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
} else {
goto end;
}
@ -1437,10 +1439,10 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void
cbh->ready = 1;
if (node) {
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
node->ring_consumer_count = 0;
node->busy = 0;
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
}
@ -1501,10 +1503,10 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
switch_mutex_unlock(globals.mutex);
if (node) {
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
node->ring_consumer_count++;
node->busy = 0;
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
}
switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS);
@ -1601,12 +1603,12 @@ static void *SWITCH_THREAD_FUNC o_thread_run(switch_thread_t *thread, void *obj)
switch_event_destroy(&ovars);
if (node) {
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
if (node->ring_consumer_count-- < 0) {
node->ring_consumer_count = 0;
}
node->busy = 0;
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
}
switch_core_destroy_memory_pool(&h->pool);
@ -1754,9 +1756,35 @@ static void *SWITCH_THREAD_FUNC node_thread_run(switch_thread_t *thread, void *o
if (globals.debug) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Trying priority: %d\n", cur_priority);
restart:
for (hi = switch_hash_first(NULL, globals.fifo_hash); hi; hi = switch_hash_next(hi)) {
switch_hash_this(hi, &var, NULL, &val);
if ((node = (fifo_node_t *) val)) {
if (node->ready == FIFO_DELAY_DESTROY) {
int doit = 0;
switch_mutex_lock(node->update_mutex);
doit = node->consumer_count == 0 && node_caller_count(node) == 0;
switch_mutex_unlock(node->update_mutex);
if (doit) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s removed.\n", node->name);
switch_core_hash_delete(globals.fifo_hash, node->name);
node->ready = 0;
switch_mutex_lock(node->mutex);
switch_core_hash_destroy(&node->consumer_hash);
switch_mutex_unlock(node->mutex);
switch_mutex_unlock(node->update_mutex);
switch_core_destroy_memory_pool(&node->pool);
goto restart;
}
}
if (node->outbound_priority == 0) node->outbound_priority = 5;
if (node->has_outbound && node->ready && !node->busy && node->outbound_priority == cur_priority) {
ppl_waiting = node_caller_count(node);
@ -2219,6 +2247,7 @@ SWITCH_STANDARD_APP(fifo_function)
if (!(node = switch_core_hash_find(globals.fifo_hash, nlist[i]))) {
node = create_node(nlist[i], importance, globals.sql_mutex);
node->ready = 1;
switch_thread_rwlock_rdlock(node->rwlock);
}
node_list[node_count++] = node;
}
@ -2306,7 +2335,7 @@ SWITCH_STANDARD_APP(fifo_function)
switch_channel_answer(channel);
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
if ((pri = switch_channel_get_variable(channel, "fifo_priority"))) {
p = atoi(pri);
@ -2344,7 +2373,7 @@ SWITCH_STANDARD_APP(fifo_function)
switch_channel_set_variable(channel, "fifo_priority", tmp);
}
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
ts = switch_micro_time_now();
switch_time_exp_lt(&tm, ts);
@ -2450,9 +2479,9 @@ SWITCH_STANDARD_APP(fifo_function)
}
switch_mutex_lock(globals.mutex);
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
node_remove_uuid(node, uuid);
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
send_presence(node);
check_cancel(node);
switch_mutex_unlock(globals.mutex);
@ -2682,9 +2711,9 @@ SWITCH_STANDARD_APP(fifo_function)
}
if (pop && !node_caller_count(node)) {
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
node->start_waiting = 0;
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
}
}
@ -3074,21 +3103,9 @@ SWITCH_STANDARD_APP(fifo_function)
done:
switch_mutex_lock(globals.mutex);
if (node && node->ready == FIFO_DELAY_DESTROY && node->consumer_count == 0 && node_caller_count(node) == 0) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_NOTICE, "%s removed.\n", node->name);
switch_core_hash_delete(globals.fifo_hash, node->name);
switch_thread_rwlock_wrlock(node->rwlock);
node->ready = 0;
switch_mutex_lock(node->mutex);
switch_core_hash_destroy(&node->consumer_hash);
switch_mutex_unlock(node->mutex);
if (node) {
switch_thread_rwlock_unlock(node->rwlock);
switch_core_destroy_memory_pool(&node->pool);
}
switch_mutex_unlock(globals.mutex);
switch_channel_clear_app_flag_key(FIFO_APP_KEY, channel, FIFO_APP_BRIDGE_TAG);
@ -3699,9 +3716,9 @@ SWITCH_STANDARD_API(fifo_api_function)
switch_hash_this(hi, &var, NULL, &val);
node = (fifo_node_t *) val;
len = node_caller_count(node);
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
stream->write_function(stream, "%s:%d:%d:%d\n", (char *) var, node->consumer_count, node_caller_count(node), len);
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
x++;
}
@ -3710,9 +3727,9 @@ SWITCH_STANDARD_API(fifo_api_function)
}
} else if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
len = node_caller_count(node);
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
stream->write_function(stream, "%s:%d:%d:%d\n", argv[1], node->consumer_count, node_caller_count(node), len);
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
} else {
stream->write_function(stream, "none\n");
}
@ -3722,9 +3739,9 @@ SWITCH_STANDARD_API(fifo_api_function)
switch_hash_this(hi, &var, NULL, &val);
node = (fifo_node_t *) val;
len = node_caller_count(node);
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
stream->write_function(stream, "%s:%d\n", (char *) var, node->has_outbound);
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
x++;
}
@ -3733,9 +3750,9 @@ SWITCH_STANDARD_API(fifo_api_function)
}
} else if ((node = switch_core_hash_find(globals.fifo_hash, argv[1]))) {
len = node_caller_count(node);
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
stream->write_function(stream, "%s:%d\n", argv[1], node->has_outbound);
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
} else {
stream->write_function(stream, "none\n");
}
@ -4108,7 +4125,7 @@ static switch_status_t load_config(int reload, int del_all)
node->ready = FIFO_DELAY_DESTROY;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "%s removed.\n", node->name);
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
for (x = 0; x < MAX_PRI; x++) {
while (fifo_queue_pop(node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) {
switch_event_destroy(&pop);
@ -4117,7 +4134,7 @@ static switch_status_t load_config(int reload, int del_all)
switch_core_hash_delete(globals.fifo_hash, node->name);
switch_core_hash_destroy(&node->consumer_hash);
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
switch_core_destroy_memory_pool(&node->pool);
goto top;
}
@ -4393,7 +4410,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown)
switch_hash_this(hi, NULL, NULL, &val);
node = (fifo_node_t *) val;
switch_thread_rwlock_wrlock(node->rwlock);
switch_mutex_lock(node->update_mutex);
switch_mutex_lock(node->mutex);
for (x = 0; x < MAX_PRI; x++) {
while (fifo_queue_pop(node->fifo_list[x], &pop, 2) == SWITCH_STATUS_SUCCESS) {
@ -4403,7 +4420,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_fifo_shutdown)
switch_mutex_unlock(node->mutex);
switch_core_hash_delete(globals.fifo_hash, node->name);
switch_core_hash_destroy(&node->consumer_hash);
switch_thread_rwlock_unlock(node->rwlock);
switch_mutex_unlock(node->update_mutex);
switch_core_destroy_memory_pool(&node->pool);
}

View File

@ -131,7 +131,6 @@ SWITCH_STANDARD_API(dump_hash)
static switch_status_t process_event(switch_event_t *event)
{
switch_core_session_t *session = NULL;
switch_channel_t *channel;
char *username[3] = { 0 };
char *domain[3] = { 0 };
char key[512];
@ -172,18 +171,19 @@ static switch_status_t process_event(switch_event_t *event)
return SWITCH_STATUS_FALSE;
}
session = switch_core_session_locate(uuid);
channel = switch_core_session_get_channel(session);
if ((session = switch_core_session_locate(uuid))) {
switch_channel_t *channel = switch_core_session_get_channel(session);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop \n", uuid, key);
my_uuid = switch_event_get_header(event, "Unique-ID");
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UserSpy retrieved uuid %s for key %s, activating eavesdrop \n", uuid, key);
my_uuid = switch_event_get_header(event, "Unique-ID");
switch_channel_set_variable(channel, "spy_uuid", my_uuid);
switch_channel_set_variable(channel, "spy_uuid", my_uuid);
switch_channel_set_state(channel, CS_EXCHANGE_MEDIA);
switch_channel_set_flag(channel, CF_BREAK);
switch_channel_set_state(channel, CS_EXCHANGE_MEDIA);
switch_channel_set_flag(channel, CF_BREAK);
switch_core_session_rwunlock(session);
switch_core_session_rwunlock(session);
}
return SWITCH_STATUS_SUCCESS;
}

View File

@ -1324,7 +1324,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
caller_profile = tech_pvt->caller_profile;
caller_profile->destination_number = rdest;
switch_channel_set_flag(channel, CF_OUTBOUND);
switch_set_flag(tech_pvt, TFLAG_OUTBOUND);
switch_channel_set_state(channel, CS_INIT);
gsmopen_call(tech_pvt, rdest, 30);

View File

@ -725,7 +725,6 @@ FSH323Connection::FSH323Connection(FSH323EndPoint& endpoint, H323Transport* tran
name += outbound_profile->destination_number;
switch_channel_set_name(m_fsChannel, name);
switch_channel_set_flag(m_fsChannel, CF_OUTBOUND);
switch_channel_set_state(m_fsChannel, CS_INIT);
}
@ -1508,7 +1507,7 @@ switch_status_t FSH323Connection::receive_message(switch_core_session_message_t
break;
}
case SWITCH_MESSAGE_INDICATE_ANSWER: {
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_FALSE;
}
AnsweringCall(H323Connection::AnswerCallNow);

View File

@ -868,7 +868,6 @@ switch_status_t Board::KhompPvt::justStart(switch_caller_profile_t *profile)
_caller_profile = switch_caller_profile_clone(_session, profile);
switch_channel_set_caller_profile(channel, _caller_profile);
switch_channel_set_flag(channel, CF_OUTBOUND);
switch_channel_set_state(channel, CS_INIT);
}
else

View File

@ -580,7 +580,6 @@ FSConnection::FSConnection(OpalCall & call, FSEndPoint & endpoint, void* userDat
name += outbound_profile->destination_number;
switch_channel_set_name(m_fsChannel, name);
switch_channel_set_flag(m_fsChannel, CF_OUTBOUND);
switch_channel_set_state(m_fsChannel, CS_INIT);
}
}
@ -966,7 +965,7 @@ switch_status_t FSConnection::receive_message(switch_core_session_message_t *msg
It would only happen if someone called switch_channel_answer() instead of switch_channel_mark_answered() on an outbound call.
it should not do anything if someone does it by accident somewhere hense this in both cases:
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_FALSE;
}
@ -1025,7 +1024,7 @@ switch_status_t FSConnection::receive_message(switch_core_session_message_t *msg
{
int fixed = 0;
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_FALSE;
}

View File

@ -48,7 +48,7 @@ sub _find {
my ($name, $value) = ($1,hex($2));
$sub{$name} = sub () { $value };
$const{$name} = $value;
} elsif(/^\s*struct\s+([a-z_]+)\s*\{\s*$/) {
} elsif(/^\s*struct\s+PACKED\s+([a-z_]+)\s*\{\s*$/) {
my $struct_name = $1;
$struct{$struct_name} = [];
while(<$fh>) {

View File

@ -1080,8 +1080,6 @@ switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, swi
switch_channel_set_caller_profile(nchannel, caller_profile);
tech_pvt->caller_profile = caller_profile;
switch_channel_set_flag(nchannel, CF_OUTBOUND);
if ((sql = switch_mprintf(
"INSERT INTO skinny_active_lines "
"(device_name, device_instance, line_instance, channel_uuid, call_id, call_state) "

View File

@ -42,6 +42,7 @@
#define SKINNY_EVENT_UNREGISTER "skinny::unregister"
#define SKINNY_EVENT_EXPIRE "skinny::expire"
#define SKINNY_EVENT_ALARM "skinny::alarm"
#define SKINNY_EVENT_XML_ALARM "skinny::xml_alarm"
#define SKINNY_EVENT_CALL_STATE "skinny::call_state"
#define SKINNY_EVENT_USER_TO_DEVICE "skinny::user_to_device"
#define SKINNY_EVENT_DEVICE_TO_USER "skinny::device_to_user"

View File

@ -547,12 +547,15 @@ struct PACKED service_url_stat_res_message {
#define USER_TO_DEVICE_DATA_VERSION1_MESSAGE 0x013F
/* See struct PACKED extended_data_message */
/* XMLAlarmMessage */
#define XML_ALARM_MESSAGE 0x015A
/*****************************************************************************/
/* SKINNY MESSAGE */
/*****************************************************************************/
#define SKINNY_MESSAGE_FIELD_SIZE 4 /* 4-bytes field */
#define SKINNY_MESSAGE_HEADERSIZE 12 /* three 4-bytes fields */
#define SKINNY_MESSAGE_MAXSIZE 1000
#define SKINNY_MESSAGE_MAXSIZE 2048
union skinny_data {
/* no data for KEEP_ALIVE_MESSAGE */
@ -624,8 +627,7 @@ union skinny_data {
struct extended_data_message extended_data;
uint16_t as_uint16;
char as_char;
void *raw;
char as_char[1];
};
/*

View File

@ -343,7 +343,7 @@ switch_status_t skinny_session_send_call_info(switch_core_session_t *session, li
zstr((called_party_number = switch_channel_get_variable(channel, "destination_number")))) {
called_party_number = "0000000000";
}
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
call_type = SKINNY_INBOUND_CALL;
} else {
call_type = SKINNY_OUTBOUND_CALL;
@ -1674,7 +1674,7 @@ switch_status_t skinny_handle_open_receive_channel_ack_message(listener_t *liste
);
switch_set_flag_locked(tech_pvt, TFLAG_IO);
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
switch_channel_mark_answered(channel);
}
if (switch_channel_test_flag(channel, CF_HOLD)) {
@ -1963,6 +1963,26 @@ switch_status_t skinny_handle_extended_data_message(listener_t *listener, skinny
return SWITCH_STATUS_SUCCESS;
}
switch_status_t skinny_handle_xml_alarm(listener_t *listener, skinny_message_t *request)
{
switch_event_t *event = NULL;
char *tmp = NULL;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
"Received XML alarm.\n");
/* skinny::xml_alarm event */
skinny_device_event(listener, &event, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_XML_ALARM);
/* Ensure that the body is null-terminated */
tmp = malloc(request->length - 4 + 1);
memcpy(tmp, request->data.as_char, request->length - 4);
tmp[request->length - 4] = '\0';
switch_event_add_body(event, "%s", tmp);
switch_safe_free(tmp);
switch_event_fire(&event);
return SWITCH_STATUS_SUCCESS;
}
switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *request)
{
if (listener->profile->debug >= 10 || request->type != KEEP_ALIVE_MESSAGE) {
@ -1970,7 +1990,7 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re
"Received %s (type=%x,length=%d) from %s:%d.\n", skinny_message_type2str(request->type), request->type, request->length,
listener->device_name, listener->device_instance);
}
if(zstr(listener->device_name) && request->type != REGISTER_MESSAGE && request->type != ALARM_MESSAGE) {
if(zstr(listener->device_name) && request->type != REGISTER_MESSAGE && request->type != ALARM_MESSAGE && request->type != XML_ALARM_MESSAGE) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
"Device should send a register message first.\n");
return SWITCH_STATUS_FALSE;
@ -2032,6 +2052,8 @@ switch_status_t skinny_handle_request(listener_t *listener, skinny_message_t *re
return skinny_handle_extended_data_message(listener, request);
case DEVICE_TO_USER_DATA_RESPONSE_VERSION1_MESSAGE:
return skinny_handle_extended_data_message(listener, request);
case XML_ALARM_MESSAGE:
return skinny_handle_xml_alarm(listener, request);
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
"Unhandled request %s (type=%x,length=%d).\n", skinny_message_type2str(request->type), request->type, request->length);

View File

@ -99,6 +99,7 @@ struct skinny_table SKINNY_MESSAGE_TYPES[] = {
{"DisplayPriNotifyMessage", DISPLAY_PRI_NOTIFY_MESSAGE},
{"ServiceUrlStatMessage", SERVICE_URL_STAT_RES_MESSAGE},
{"UserToDeviceDataVersion1Message", USER_TO_DEVICE_DATA_VERSION1_MESSAGE},
{"XMLAlarmMessage", XML_ALARM_MESSAGE},
{NULL, 0}
};
SKINNY_DECLARE_ID2STR(skinny_message_type2str, SKINNY_MESSAGE_TYPES, "UnknownMessage")

View File

@ -87,7 +87,7 @@ uint32_t func(const char *str)\
}
extern struct skinny_table SKINNY_MESSAGE_TYPES[65];
extern struct skinny_table SKINNY_MESSAGE_TYPES[66];
const char *skinny_message_type2str(uint32_t id);
uint32_t skinny_str2message_type(const char *str);
#define SKINNY_PUSH_MESSAGE_TYPES SKINNY_DECLARE_PUSH_MATCH(SKINNY_MESSAGE_TYPES)

View File

@ -526,6 +526,10 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session)
switch_core_timer_destroy(&tech_pvt->timer_read);
}
if (tech_pvt->timer_read_srv.timer_interface && tech_pvt->timer_read_srv.timer_interface->timer_next) {
switch_core_timer_destroy(&tech_pvt->timer_read_srv);
}
if (tech_pvt->timer_write.timer_interface && tech_pvt->timer_write.timer_interface->timer_next) {
switch_core_timer_destroy(&tech_pvt->timer_write);
}
@ -1121,6 +1125,9 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
if (tech_pvt->timer_read.timer_interface && tech_pvt->timer_read.timer_interface->timer_next) {
switch_core_timer_sync(&tech_pvt->timer_read);
}
if (tech_pvt->timer_read_srv.timer_interface && tech_pvt->timer_read_srv.timer_interface->timer_next) {
switch_core_timer_sync(&tech_pvt->timer_read_srv);
}
switch_mutex_unlock(tech_pvt->mutex_audio_srv);
}
@ -1146,6 +1153,9 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
if (tech_pvt->timer_read.timer_interface && tech_pvt->timer_read.timer_interface->timer_next) {
switch_core_timer_sync(&tech_pvt->timer_read);
}
if (tech_pvt->timer_read_srv.timer_interface && tech_pvt->timer_read_srv.timer_interface->timer_next) {
switch_core_timer_sync(&tech_pvt->timer_read_srv);
}
switch_mutex_unlock(tech_pvt->mutex_audio_srv);
}
@ -1168,6 +1178,9 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
if (tech_pvt->timer_read.timer_interface && tech_pvt->timer_read.timer_interface->timer_next) {
switch_core_timer_sync(&tech_pvt->timer_read);
}
if (tech_pvt->timer_read_srv.timer_interface && tech_pvt->timer_read_srv.timer_interface->timer_next) {
switch_core_timer_sync(&tech_pvt->timer_read_srv);
}
switch_mutex_unlock(tech_pvt->mutex_audio_srv);
}
@ -1351,7 +1364,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
caller_profile = tech_pvt->caller_profile;
caller_profile->destination_number = rdest;
switch_channel_set_flag(channel, CF_OUTBOUND);
switch_mutex_lock(tech_pvt->flag_mutex);
switch_set_flag(tech_pvt, TFLAG_OUTBOUND);
switch_mutex_unlock(tech_pvt->flag_mutex);
@ -2168,6 +2180,13 @@ int start_audio_threads(private_t *tech_pvt)
switch_core_timer_sync(&tech_pvt->timer_read);
if (switch_core_timer_init(&tech_pvt->timer_read_srv, "soft", MS_SKYPOPEN, SAMPLES_PER_FRAME, skypopen_module_pool) != SWITCH_STATUS_SUCCESS) {
ERRORA("setup timer failed\n", SKYPOPEN_P_LOG);
return SWITCH_STATUS_FALSE;
}
switch_core_timer_sync(&tech_pvt->timer_read_srv);
if (switch_core_timer_init(&tech_pvt->timer_write, "soft", MS_SKYPOPEN, SAMPLES_PER_FRAME, skypopen_module_pool) != SWITCH_STATUS_SUCCESS) {
ERRORA("setup timer failed\n", SKYPOPEN_P_LOG);
return SWITCH_STATUS_FALSE;

View File

@ -0,0 +1,43 @@
# Comment/uncomment the following line to disable/enable debugging
#DEBUG = y
#LDDINC=/usr/src/linux-headers-2.6.32-26-server/include
# Add your debugging flag (or not) to CFLAGS
ifeq ($(DEBUG),y)
DEBFLAGS = -O -g -DSKYPOPEN_DEBUG # "-O" is needed to expand inlines
else
DEBFLAGS = -O2 -Wall
endif
EXTRA_CFLAGS += $(DEBFLAGS)
EXTRA_CFLAGS += -I$(LDDINC)
ifneq ($(KERNELRELEASE),)
# call from kernel build system
skypopen-objs := main.o
obj-m := skypopen.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) LDDINC=$(PWD)/../include modules
endif
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
depend .depend dep:
$(CC) $(EXTRA_CFLAGS) -M *.c > .depend
ifeq (.depend,$(wildcard .depend))
include .depend
endif

View File

@ -0,0 +1,470 @@
/*
* main.c -- the bare skypopen char module
*
* Copyright (C) 2010 Giovanni Maruzzelli
* Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
* Copyright (C) 2001 O'Reilly & Associates
*
* The source code in this file can be freely used, adapted,
* and redistributed in source or binary form, so long as an
* acknowledgment appears in derived source files. The citation
* should list that the code comes from the book "Linux Device
* Drivers" by Alessandro Rubini and Jonathan Corbet, published
* by O'Reilly & Associates. No warranty is attached;
* we cannot take responsibility for errors or fitness for use.
*
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/seq_file.h>
#include <linux/cdev.h>
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* copy_*_user */
#include <linux/soundcard.h>
#include <linux/delay.h>
#include <linux/hrtimer.h>
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/jiffies.h>
#include <linux/hrtimer.h>
#include <linux/ktime.h>
#include "skypopen.h" /* local definitions */
/*
* Our parameters which can be set at load time.
*/
int skypopen_major = SKYPOPEN_MAJOR;
int skypopen_minor = 3;
int skypopen_nr_devs = SKYPOPEN_NR_DEVS; /* number of bare skypopen devices */
module_param(skypopen_major, int, S_IRUGO);
module_param(skypopen_minor, int, S_IRUGO);
module_param(skypopen_nr_devs, int, S_IRUGO);
MODULE_AUTHOR("Original: Alessandro Rubini, Jonathan Corbet. Modified by: Giovanni Maruzzelli for FreeSWITCH skypopen");
MODULE_LICENSE("Dual BSD/GPL");
static struct skypopen_dev *skypopen_devices; /* allocated in skypopen_init_module */
static int unload = 0;
#ifdef CENTOS
#define HRTIMER_MODE_REL HRTIMER_REL
#endif// CENTOS
#ifndef WANT_HRTIMER
void my_timer_callback_inq( unsigned long data )
{
struct skypopen_dev *dev = (void *)data;
wake_up_interruptible(&dev->inq);
mod_timer( &dev->timer_inq, jiffies + msecs_to_jiffies(SKYPOPEN_SLEEP) );
}
void my_timer_callback_outq( unsigned long data )
{
struct skypopen_dev *dev = (void *)data;
wake_up_interruptible(&dev->outq);
mod_timer( &dev->timer_outq, jiffies + msecs_to_jiffies(SKYPOPEN_SLEEP) );
}
#else// WANT_HRTIMER
#ifndef CENTOS
static enum hrtimer_restart my_hrtimer_callback_inq( struct hrtimer *timer_inq )
{
struct skypopen_dev *dev = container_of(timer_inq, struct skypopen_dev, timer_inq);
ktime_t now;
if(unload)
return HRTIMER_NORESTART;
now = ktime_get();
hrtimer_forward(&dev->timer_inq, now, ktime_set(0, SKYPOPEN_SLEEP * 1000000));
wake_up_interruptible(&dev->inq);
return HRTIMER_RESTART;
}
static enum hrtimer_restart my_hrtimer_callback_outq( struct hrtimer *timer_outq )
{
struct skypopen_dev *dev = container_of(timer_outq, struct skypopen_dev, timer_outq);
ktime_t now;
if(unload)
return HRTIMER_NORESTART;
now = ktime_get();
hrtimer_forward(&dev->timer_outq, now, ktime_set(0, SKYPOPEN_SLEEP * 1000000));
wake_up_interruptible(&dev->outq);
return HRTIMER_RESTART;
}
#else// CENTOS
static int my_hrtimer_callback_inq( struct hrtimer *timer_inq )
{
struct skypopen_dev *dev = container_of(timer_inq, struct skypopen_dev, timer_inq);
if(unload)
return HRTIMER_NORESTART;
hrtimer_forward(&dev->timer_inq, timer_inq->expires, ktime_set(0, SKYPOPEN_SLEEP * 1000000));
wake_up_interruptible(&dev->inq);
return HRTIMER_RESTART;
}
static int my_hrtimer_callback_outq( struct hrtimer *timer_outq )
{
struct skypopen_dev *dev = container_of(timer_outq, struct skypopen_dev, timer_outq);
if(unload)
return HRTIMER_NORESTART;
hrtimer_forward(&dev->timer_outq, timer_outq->expires, ktime_set(0, SKYPOPEN_SLEEP * 1000000));
wake_up_interruptible(&dev->outq);
return HRTIMER_RESTART;
}
#endif// CENTOS
#endif// WANT_HRTIMER
/* The clone-specific data structure includes a key field */
struct skypopen_listitem {
struct skypopen_dev device;
dev_t key;
struct list_head list;
};
/* The list of devices, and a lock to protect it */
static LIST_HEAD(skypopen_c_list);
static spinlock_t skypopen_c_lock = SPIN_LOCK_UNLOCKED;
/* Look for a device or create one if missing */
static struct skypopen_dev *skypopen_c_lookfor_device(dev_t key)
{
struct skypopen_listitem *lptr;
#ifdef WANT_HRTIMER
#if 0
ktime_t ktime_inq;
ktime_t ktime_outq;
#endif //0
#endif// WANT_HRTIMER
list_for_each_entry(lptr, &skypopen_c_list, list) {
if (lptr->key == key)
return &(lptr->device);
}
/* not found */
lptr = kmalloc(sizeof(struct skypopen_listitem), GFP_KERNEL);
if (!lptr)
return NULL;
/* initialize the device */
memset(lptr, 0, sizeof(struct skypopen_listitem));
lptr->key = key;
init_waitqueue_head(&lptr->device.inq);
init_waitqueue_head(&lptr->device.outq);
#ifndef WANT_HRTIMER
setup_timer( &lptr->device.timer_inq, my_timer_callback_inq, (long int)lptr );
setup_timer( &lptr->device.timer_outq, my_timer_callback_outq, (long int)lptr );
printk( "Starting skypopen OSS driver read timer (%dms) skype client:(%d)\n", SKYPOPEN_SLEEP, current->tgid );
mod_timer( &lptr->device.timer_inq, jiffies + msecs_to_jiffies(SKYPOPEN_SLEEP) );
printk( "Starting skypopen OSS driver write timer (%dms) skype client:(%d)\n", SKYPOPEN_SLEEP, current->tgid );
mod_timer( &lptr->device.timer_outq, jiffies + msecs_to_jiffies(SKYPOPEN_SLEEP) );
#else// WANT_HRTIMER
#if 0
ktime_inq = ktime_set( 0, SKYPOPEN_SLEEP * 1000000);
hrtimer_init( &lptr->device.timer_inq, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
lptr->device.timer_inq.function = &my_hrtimer_callback_inq;
hrtimer_start( &lptr->device.timer_inq, ktime_inq, HRTIMER_MODE_REL );
ktime_outq = ktime_set( 0, SKYPOPEN_SLEEP * 1000000);
hrtimer_init( &lptr->device.timer_outq, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
lptr->device.timer_outq.function = &my_hrtimer_callback_outq;
hrtimer_start( &lptr->device.timer_outq, ktime_outq, HRTIMER_MODE_REL );
#endif
#endif// WANT_HRTIMER
/* place it in the list */
list_add(&lptr->list, &skypopen_c_list);
return &(lptr->device);
}
/*
* Open and close
*/
static int skypopen_c_open(struct inode *inode, struct file *filp)
{
struct skypopen_dev *dev;
dev_t key;
key = current->tgid;
/* look for a skypopenc device in the list */
spin_lock(&skypopen_c_lock);
dev = skypopen_c_lookfor_device(key);
spin_unlock(&skypopen_c_lock);
if (!dev)
return -ENOMEM;
/* then, everything else is copied from the bare skypopen device */
filp->private_data = dev;
return 0; /* success */
}
static int skypopen_c_release(struct inode *inode, struct file *filp)
{
/*
* Nothing to do, because the device is persistent.
* A `real' cloned device should be freed on last close
*/
return 0;
}
/*************************************************************/
static ssize_t skypopen_read(struct file *filp, char __user *buf, size_t count,
loff_t *f_pos)
{
DEFINE_WAIT(wait);
struct skypopen_dev *dev = filp->private_data;
if(unload)
return -1;
#ifdef WANT_HRTIMER
#if 1
if(dev->timer_inq_started == 0){
ktime_t ktime_inq;
ktime_inq = ktime_set( 0, SKYPOPEN_SLEEP * 1000000);
hrtimer_init( &dev->timer_inq, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
dev->timer_inq.function = &my_hrtimer_callback_inq;
hrtimer_start( &dev->timer_inq, ktime_inq, HRTIMER_MODE_REL );
dev->timer_inq_started = 1;
}
#endif
#endif// WANT_HRTIMER
//printk("READ\n");
prepare_to_wait(&dev->inq, &wait, TASK_INTERRUPTIBLE);
schedule();
finish_wait(&dev->inq, &wait);
return count;
}
static ssize_t skypopen_write(struct file *filp, const char __user *buf, size_t count,
loff_t *f_pos)
{
DEFINE_WAIT(wait);
struct skypopen_dev *dev = filp->private_data;
if(unload)
return -1;
#ifdef WANT_HRTIMER
#if 1
if(dev->timer_outq_started == 0){
ktime_t ktime_outq;
ktime_outq = ktime_set( 0, SKYPOPEN_SLEEP * 1000000);
hrtimer_init( &dev->timer_outq, CLOCK_MONOTONIC, HRTIMER_MODE_REL );
dev->timer_outq.function = &my_hrtimer_callback_outq;
hrtimer_start( &dev->timer_outq, ktime_outq, HRTIMER_MODE_REL );
dev->timer_outq_started = 1;
}
#endif
#endif// WANT_HRTIMER
//printk("WRITE\n");
prepare_to_wait(&dev->outq, &wait, TASK_INTERRUPTIBLE);
schedule();
finish_wait(&dev->outq, &wait);
return count;
}
/*
* The ioctl() implementation
*/
static int skypopen_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
int __user *p = argp;
switch (cmd) {
case OSS_GETVERSION:
return put_user(SOUND_VERSION, p);
case SNDCTL_DSP_GETBLKSIZE:
return put_user(SKYPOPEN_BLK, p);
case SNDCTL_DSP_GETFMTS:
return put_user(28731, p);
default:
return 0;
}
}
struct file_operations skypopen_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = skypopen_read,
.write = skypopen_write,
.ioctl = skypopen_ioctl,
.open = skypopen_c_open,
.release = skypopen_c_release,
};
/*
* Finally, the module stuff
*/
/*
* The cleanup function is used to handle initialization failures as well.
* Thefore, it must be careful to work correctly even if some of the items
* have not been initialized
*/
void skypopen_cleanup_module(void)
{
int i;
int ret;
struct skypopen_listitem *lptr, *next;
dev_t devno = MKDEV(skypopen_major, skypopen_minor);
unload = 1;
msleep(100);
/* Get rid of our char dev entries */
if (skypopen_devices) {
for (i = 0; i < skypopen_nr_devs; i++) {
cdev_del(&skypopen_devices[i].cdev);
}
kfree(skypopen_devices);
}
/* And all the cloned devices */
list_for_each_entry_safe(lptr, next, &skypopen_c_list, list) {
#ifndef WANT_HRTIMER
ret= del_timer( &lptr->device.timer_inq );
printk( "Stopped skypopen OSS driver read timer\n");
ret= del_timer( &lptr->device.timer_outq );
printk( "Stopped skypopen OSS driver write timer\n");
#else// WANT_HRTIMER
if(lptr->device.timer_inq_started){
ret = hrtimer_cancel( &lptr->device.timer_inq );
printk( "Stopped skypopen OSS driver read HRtimer\n");
}
if(lptr->device.timer_outq_started){
ret = hrtimer_cancel( &lptr->device.timer_outq );
printk( "Stopped skypopen OSS driver write HRtimer\n");
}
#endif// WANT_HRTIMER
list_del(&lptr->list);
kfree(lptr);
}
/* cleanup_module is never called if registering failed */
unregister_chrdev_region(devno, skypopen_nr_devs);
printk("skypopen OSS driver unloaded\n");
}
/*
* Set up the char_dev structure for this device.
*/
static void skypopen_setup_cdev(struct skypopen_dev *dev, int index)
{
int err, devno = MKDEV(skypopen_major, skypopen_minor + index);
cdev_init(&dev->cdev, &skypopen_fops);
dev->cdev.owner = THIS_MODULE;
dev->cdev.ops = &skypopen_fops;
err = cdev_add (&dev->cdev, devno, 1);
/* Fail gracefully if need be */
if (err)
printk(KERN_NOTICE "Error %d adding skypopen%d", err, index);
}
int skypopen_init_module(void)
{
int result, i;
dev_t dev = 0;
printk("skypopen OSS driver loading (www.freeswitch.org)\n");
/*
* Get a range of minor numbers to work with, asking for a dynamic
* major unless directed otherwise at load time.
*/
if (skypopen_major) {
dev = MKDEV(skypopen_major, skypopen_minor);
result = register_chrdev_region(dev, skypopen_nr_devs, "dsp");
} else {
result = alloc_chrdev_region(&dev, skypopen_minor, skypopen_nr_devs,
"dsp");
skypopen_major = MAJOR(dev);
}
if (result < 0) {
printk(KERN_WARNING "skypopen OSS driver: can't get major %d\n", skypopen_major);
return result;
}
/*
* allocate the devices -- we can't have them static, as the number
* can be specified at load time
*/
skypopen_devices = kmalloc(skypopen_nr_devs * sizeof(struct skypopen_dev), GFP_KERNEL);
if (!skypopen_devices) {
result = -ENOMEM;
goto fail; /* Make this more graceful */
}
memset(skypopen_devices, 0, skypopen_nr_devs * sizeof(struct skypopen_dev));
/* Initialize each device. */
for (i = 0; i < skypopen_nr_devs; i++) {
skypopen_setup_cdev(&skypopen_devices[i], i);
}
/* At this point call the init function for any friend device */
dev = MKDEV(skypopen_major, skypopen_minor + skypopen_nr_devs);
return 0; /* succeed */
fail:
skypopen_cleanup_module();
return result;
}
module_init(skypopen_init_module);
module_exit(skypopen_cleanup_module);

View File

@ -0,0 +1,71 @@
/*
* skypopen.h -- definitions for the char module
*
* Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet
* Copyright (C) 2001 O'Reilly & Associates
*
* The source code in this file can be freely used, adapted,
* and redistributed in source or binary form, so long as an
* acknowledgment appears in derived source files. The citation
* should list that the code comes from the book "Linux Device
* Drivers" by Alessandro Rubini and Jonathan Corbet, published
* by O'Reilly & Associates. No warranty is attached;
* we cannot take responsibility for errors or fitness for use.
*
* $Id: skypopen.h,v 1.15 2004/11/04 17:51:18 rubini Exp $
*/
#ifndef _SKYPOPEN_H_
#define _SKYPOPEN_H_
#include <linux/ioctl.h> /* needed for the _IOW etc stuff used later */
#define SKYPOPEN_BLK 960
#define SKYPOPEN_SLEEP 10
#define CENTOS
#ifndef SKYPOPEN_MAJOR
#define SKYPOPEN_MAJOR 14 /* dynamic major by default */
#endif
#ifndef SKYPOPEN_NR_DEVS
#define SKYPOPEN_NR_DEVS 1 /* skypopen0 through skypopen3 */
#endif
#define WANT_HRTIMER
struct skypopen_dev {
struct cdev cdev; /* Char device structure */
wait_queue_head_t inq; /* read and write queues */
wait_queue_head_t outq; /* read and write queues */
#ifndef WANT_HRTIMER
struct timer_list timer_inq;
struct timer_list timer_outq;
#else// WANT_HRTIMER
struct hrtimer timer_inq;
struct hrtimer timer_outq;
#endif// WANT_HRTIMER
int timer_inq_started;
int timer_outq_started;
};
/*
* The different configurable parameters
*/
extern int skypopen_major; /* main.c */
extern int skypopen_nr_devs;
/*
* Prototypes for shared functions
*/
//ssize_t skypopen_read(struct file *filp, char __user *buf, size_t count,
//loff_t *f_pos);
//ssize_t skypopen_write(struct file *filp, const char __user *buf, size_t count,
//loff_t *f_pos);
//int skypopen_ioctl(struct inode *inode, struct file *filp,
//unsigned int cmd, unsigned long arg);
#endif /* _SKYPOPEN_H_ */

View File

@ -76,8 +76,8 @@
#define SAMPLERATE_SKYPOPEN 16000
#define MS_SKYPOPEN 20
#define SAMPLES_PER_FRAME SAMPLERATE_SKYPOPEN/(1000/MS_SKYPOPEN)
#define BYTES_PER_FRAME SAMPLES_PER_FRAME * sizeof(short)
#define SAMPLES_PER_FRAME (SAMPLERATE_SKYPOPEN/(1000/MS_SKYPOPEN))
#define BYTES_PER_FRAME (SAMPLES_PER_FRAME * sizeof(short))
#ifdef SKYPOPEN_C_VER
#ifdef MODSKYPOPEN_C_VER
@ -341,6 +341,7 @@ struct private_object {
chat_t chats[MAX_CHATS];
uint32_t report_incoming_chatmessages;
switch_timer_t timer_read;
switch_timer_t timer_read_srv;
switch_timer_t timer_write;
int begin_to_write;
int begin_to_read;

View File

@ -547,6 +547,9 @@ int skypopen_signaling_read(private_t *tech_pvt)
if (tech_pvt->timer_read.timer_interface && tech_pvt->timer_read.timer_interface->timer_next) {
switch_core_timer_sync(&tech_pvt->timer_read);
}
if (tech_pvt->timer_read_srv.timer_interface && tech_pvt->timer_read_srv.timer_interface->timer_next) {
switch_core_timer_sync(&tech_pvt->timer_read_srv);
}
switch_mutex_unlock(tech_pvt->mutex_audio_srv);
}
@ -878,7 +881,7 @@ void *skypopen_do_tcp_srv_thread_func(void *obj)
|| tech_pvt->skype_callflow == CALLFLOW_STATUS_REMOTEHOLD || tech_pvt->skype_callflow == SKYPOPEN_STATE_UP)) {
unsigned int fdselect;
int rt;
int rt=1;
fd_set fs;
struct timeval to;
int nospace;
@ -891,7 +894,10 @@ void *skypopen_do_tcp_srv_thread_func(void *obj)
to.tv_usec = MS_SKYPOPEN * 1000 * 3;
to.tv_sec = 0;
rt = select(fdselect + 1, &fs, NULL, NULL, &to);
if (tech_pvt->timer_read_srv.timer_interface && tech_pvt->timer_read_srv.timer_interface->timer_next) {
switch_core_timer_next(&tech_pvt->timer_read_srv);
}
//rt = select(fdselect + 1, &fs, NULL, NULL, &to);
if (rt > 0) {
if (tech_pvt->skype_callflow != CALLFLOW_STATUS_REMOTEHOLD) {

View File

@ -508,7 +508,7 @@ switch_status_t sofia_on_hangup(switch_core_session_t *session)
TAG_IF(!zstr(bye_headers), SIPTAG_HEADER_STR(bye_headers)), TAG_END());
}
} else {
if (switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Sending CANCEL to %s\n", switch_channel_get_name(channel));
if (!tech_pvt->got_bye) {
switch_channel_set_variable(channel, "sip_hangup_disposition", "send_cancel");
@ -573,7 +573,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
char *sticky = NULL;
const char *call_info = switch_channel_get_variable(channel, "presence_call_info_full");
if (sofia_test_flag(tech_pvt, TFLAG_ANS) || switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (sofia_test_flag(tech_pvt, TFLAG_ANS) || switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
return SWITCH_STATUS_SUCCESS;
}
@ -653,7 +653,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
switch_channel_clear_flag(channel, CF_PROXY_MODE);
}
if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
tech_pvt->num_codecs = 0;
sofia_glue_tech_prepare_codecs(tech_pvt);
@ -723,7 +723,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route)),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
NUTAG_SESSION_TIMER(session_timeout),
TAG_IF(session_timeout, NUTAG_SESSION_REFRESHER(nua_remote_refresher)),
NUTAG_SESSION_REFRESHER(session_timeout ? nua_local_refresher : nua_no_refresher),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info")),
SOATAG_USER_SDP_STR(tech_pvt->local_sdp_str),
@ -739,7 +739,7 @@ static switch_status_t sofia_answer_channel(switch_core_session_t *session)
TAG_IF(sticky, NUTAG_PROXY(tech_pvt->record_route)),
TAG_IF(cid, SIPTAG_HEADER_STR(cid)),
NUTAG_SESSION_TIMER(session_timeout),
TAG_IF(session_timeout, NUTAG_SESSION_REFRESHER(nua_remote_refresher)),
NUTAG_SESSION_REFRESHER(session_timeout ? nua_local_refresher : nua_no_refresher),
SIPTAG_CONTACT_STR(tech_pvt->reply_contact),
SIPTAG_CALL_INFO_STR(switch_channel_get_variable(tech_pvt->channel, SOFIA_SIP_HEADER_PREFIX "call_info")),
SIPTAG_CONTENT_TYPE_STR("application/sdp"),
@ -906,7 +906,7 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
tech_pvt->read_frame.flags = SFF_NONE;
status = switch_rtp_zerocopy_read_frame(tech_pvt->rtp_session, &tech_pvt->read_frame, flags);
if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
if (status == SWITCH_STATUS_TIMEOUT) {
@ -1084,7 +1084,7 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
tech_pvt->last_ts = 0;
/* inform them of the codec they are actually sending */
#if 0
if (++tech_pvt->codec_reinvites > 2) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING,
"Ok, some devices *cough* X-lite *cough*\n"
@ -1093,7 +1093,10 @@ static switch_status_t sofia_read_frame(switch_core_session_t *session, switch_f
} else {
sofia_glue_do_invite(session);
}
#endif
*frame = &silence_frame;
return SWITCH_STATUS_SUCCESS;
}
}
@ -1332,6 +1335,60 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
}
}
break;
case SWITCH_MESSAGE_INDICATE_JITTER_BUFFER:
{
if (switch_rtp_ready(tech_pvt->rtp_session)) {
int len, maxlen = 0, qlen = 0, maxqlen = 50;
if (msg->string_arg) {
char *p;
const char *s;
if (!strncasecmp(msg->string_arg, "debug:", 6)) {
s = msg->string_arg + 6;
if (s && !strcmp(s, "off")) {
s = NULL;
}
switch_rtp_debug_jitter_buffer(tech_pvt->rtp_session, s);
goto end;
}
if ((len = atoi(msg->string_arg))) {
qlen = len / (tech_pvt->read_impl.microseconds_per_packet / 1000);
}
if (qlen) {
if ((p = strchr(msg->string_arg, ':'))) {
p++;
maxlen = atol(p);
}
}
if (maxlen) {
maxqlen = maxlen / (tech_pvt->read_impl.microseconds_per_packet / 1000);
}
}
if (qlen) {
if (switch_rtp_activate_jitter_buffer(tech_pvt->rtp_session, qlen, maxqlen,
tech_pvt->read_impl.samples_per_packet,
tech_pvt->read_impl.samples_per_second) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames) (%d max frames)\n", len, qlen, maxqlen);
switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", len, qlen);
}
} else {
switch_rtp_deactivate_jitter_buffer(tech_pvt->rtp_session);
}
}
}
break;
case SWITCH_MESSAGE_INDICATE_DEBUG_AUDIO:
{
if (switch_rtp_ready(tech_pvt->rtp_session) && !zstr(msg->string_array_arg[0]) && !zstr(msg->string_array_arg[1])) {
@ -1629,7 +1686,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
sofia_glue_tech_set_local_sdp(tech_pvt, NULL, SWITCH_FALSE);
if (!(switch_channel_test_flag(channel, CF_ANSWERED) || switch_channel_test_flag(channel, CF_EARLY_MEDIA))) {
if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
tech_pvt->num_codecs = 0;
@ -2144,7 +2201,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi
} else {
if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) || !tech_pvt->iananame) {
sofia_clear_flag_locked(tech_pvt, TFLAG_LATE_NEGOTIATION);
if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
tech_pvt->num_codecs = 0;

View File

@ -225,6 +225,7 @@ typedef enum {
PFLAG_DEL_SUBS_ON_REG,
PFLAG_IGNORE_183NOSDP,
PFLAG_PRESENCE_PROBE_ON_REGISTER,
PFLAG_NO_CONNECTION_REUSE,
/* No new flags below this line */
PFLAG_MAX
} PFLAGS;

View File

@ -357,7 +357,7 @@ void sofia_handle_sip_i_notify(switch_core_session_t *session, int status,
goto error;
}
if (!switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
switch_channel_answer(channel);
switch_channel_set_variable(channel, "auto_answer_destination", switch_channel_get_variable(channel, "destination_number"));
switch_ivr_session_transfer(session, "auto_answer", NULL, NULL);
@ -1486,6 +1486,8 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void
TAG_IF(profile->timer_t2, NTATAG_SIP_T2(profile->timer_t2)),
TAG_IF(profile->timer_t4, NTATAG_SIP_T4(profile->timer_t4)),
SIPTAG_ACCEPT_STR("application/sdp, multipart/mixed"),
TAG_IF(sofia_test_pflag(profile, PFLAG_NO_CONNECTION_REUSE),
TPTAG_REUSE(0)),
TAG_END()); /* Last tag should always finish the sequence */
if (!profile->nua) {
@ -1715,16 +1717,9 @@ void launch_sofia_profile_thread(sofia_profile_t *profile)
static void logger(void *logarg, char const *fmt, va_list ap)
{
/* gcc 4.4 gets mad at us for testing if (ap) so let's try to work around it....*/
void *ap_ptr = (void *) (intptr_t) ap;
if (!fmt) return;
if (ap_ptr) {
switch_log_vprintf(SWITCH_CHANNEL_LOG_CLEAN, mod_sofia_globals.tracelevel, fmt, ap);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, mod_sofia_globals.tracelevel, "%s", fmt);
}
switch_log_vprintf(SWITCH_CHANNEL_LOG_CLEAN, mod_sofia_globals.tracelevel, fmt, ap);
}
static su_log_t *sofia_get_logger(const char *name)
@ -3673,6 +3668,13 @@ switch_status_t config_sofia(int reload, char *profile_name)
} else {
profile->timer_t4 = 4000;
}
} else if (!strcasecmp(var, "reuse-connections")) {
switch_bool_t value = switch_true(val);
if (!value) {
sofia_set_pflag(profile, PFLAG_NO_CONNECTION_REUSE);
} else {
sofia_clear_pflag(profile, PFLAG_NO_CONNECTION_REUSE);
}
}
}
@ -4112,7 +4114,7 @@ static void sofia_handle_sip_r_invite(switch_core_session_t *session, int status
}
if (channel && sip && (status == 300 || status == 301 || status == 302 || status == 305) && switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (channel && sip && (status == 300 || status == 301 || status == 302 || status == 305) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
sip_contact_t *p_contact = sip->sip_contact;
int i = 0;
char var_name[80];
@ -4643,7 +4645,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
status = 183;
}
if (channel && (status == 180 || status == 183) && switch_channel_test_flag(channel, CF_OUTBOUND)) {
if (channel && (status == 180 || status == 183) && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
const char *val;
if ((val = switch_channel_get_variable(channel, "sip_auto_answer")) && switch_true(val)) {
nua_notify(nh, NUTAG_NEWSUB(1), NUTAG_SUBSTATE(nua_substate_active), SIPTAG_EVENT_STR("talk"), TAG_END());
@ -4690,7 +4692,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
if (r_sdp) {
if (switch_channel_test_flag(channel, CF_PROXY_MODE) || switch_channel_test_flag(channel, CF_PROXY_MEDIA)) {
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA) && !switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
if (switch_channel_test_flag(channel, CF_PROXY_MEDIA) && switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "PROXY MEDIA");
}
sofia_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
@ -4713,7 +4715,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
}
goto done;
} else {
if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) && !switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
if (sofia_test_flag(tech_pvt, TFLAG_LATE_NEGOTIATION) && switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
switch_channel_set_variable(channel, SWITCH_ENDPOINT_DISPOSITION_VARIABLE, "DELAYED NEGOTIATION");
} else {
if (sofia_glue_tech_media(tech_pvt, (char *) r_sdp) != SWITCH_STATUS_SUCCESS) {
@ -4908,7 +4910,7 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status,
sofia_glue_tech_set_local_sdp(tech_pvt, NULL, SWITCH_FALSE);
if (!switch_channel_media_ready(channel)) {
if (!switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND)) {
if (switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_INBOUND) {
//const char *r_sdp = switch_channel_get_variable(channel, SWITCH_R_SDP_VARIABLE);
tech_pvt->num_codecs = 0;
@ -6253,7 +6255,8 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
if (!is_nat && profile->nat_acl_count) {
uint32_t x = 0;
int ok = 1;
int contact_private_ip = 1;
int network_private_ip = 0;
char *last_acl = NULL;
const char *contact_host = NULL;
@ -6262,14 +6265,37 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_
}
if (!zstr(contact_host)) {
/* NAT mode double check logic and examples.
Example 1: the contact_host is 192.168.1.100 and the network_ip is also 192.168.1.100 the end point
is most likely behind nat with us so we need to veto that decision to turn on nat processing.
Example 2: the contact_host is 192.168.1.100 and the network_ip is 192.0.2.100 which is a public internet ip
the remote endpoint is likely behind a remote nat traversing the public internet.
This secondary check is here to double check the conclusion of nat settigs to ensure we don't set net
in cases where we don't really need to be doing this.
Why would you want to do this? Well if your FreeSWITCH is behind nat and you want to talk to endpoints behind
remote NAT over the public internet in addition to endpoints behind nat with you. This simplifies that process.
*/
for (x = 0; x < profile->nat_acl_count; x++) {
last_acl = profile->nat_acl[x];
if (!(ok = switch_check_network_list_ip(contact_host, last_acl))) {
if ((contact_private_ip = switch_check_network_list_ip(contact_host, last_acl))) {
break;
}
}
if (contact_private_ip) {
for (x = 0; x < profile->nat_acl_count; x++) {
if ((network_private_ip = switch_check_network_list_ip(network_ip, profile->nat_acl[x]))) {
break;
}
}
}
if (ok) {
if (contact_private_ip && !network_private_ip) {
is_nat = last_acl;
}
}

View File

@ -2342,7 +2342,7 @@ switch_status_t sofia_glue_do_invite(switch_core_session_t *session)
nua_invite(tech_pvt->nh,
NUTAG_AUTOANSWER(0),
NUTAG_SESSION_TIMER(session_timeout),
TAG_IF(session_timeout, NUTAG_SESSION_REFRESHER(nua_remote_refresher)),
NUTAG_SESSION_REFRESHER(session_timeout ? nua_local_refresher : nua_no_refresher),
TAG_IF(sofia_test_flag(tech_pvt, TFLAG_RECOVERED), NUTAG_INVITE_TIMER(UINT_MAX)),
TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)),
TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)),
@ -2669,7 +2669,8 @@ switch_status_t sofia_glue_tech_set_codec(private_object_t *tech_pvt, int force)
tech_pvt->rm_encoding,
tech_pvt->codec_ms,
tech_pvt->rm_rate);
switch_yield(tech_pvt->read_impl.microseconds_per_packet);
switch_core_session_lock_codec_write(tech_pvt->session);
switch_core_session_lock_codec_read(tech_pvt->session);
resetting = 1;
@ -3153,18 +3154,37 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f
if ((val = switch_channel_get_variable(tech_pvt->channel, "jitterbuffer_msec"))) {
int len = atoi(val);
int maxlen = 0;
char *p;
if (len < 100 || len > 1000) {
if ((p = strchr(val, ':'))) {
p++;
maxlen = atoi(p);
}
if (len < 20 || len > 10000) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR,
"Invalid Jitterbuffer spec [%d] must be between 100 and 1000\n", len);
"Invalid Jitterbuffer spec [%d] must be between 20 and 10000\n", len);
} else {
int qlen;
int qlen, maxqlen = 50;
qlen = len / (tech_pvt->read_impl.microseconds_per_packet / 1000);
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames)\n", len,
qlen);
switch_rtp_activate_jitter_buffer(tech_pvt->rtp_session, qlen);
if (maxlen) {
maxqlen = maxlen / (tech_pvt->read_impl.microseconds_per_packet / 1000);
}
if (switch_rtp_activate_jitter_buffer(tech_pvt->rtp_session, qlen, maxqlen,
tech_pvt->read_impl.samples_per_packet,
tech_pvt->read_impl.samples_per_second) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
SWITCH_LOG_DEBUG, "Setting Jitterbuffer to %dms (%d frames)\n", len, qlen);
switch_channel_set_flag(tech_pvt->channel, CF_JITTERBUFFER);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session),
SWITCH_LOG_WARNING, "Error Setting Jitterbuffer to %dms (%d frames)\n", len, qlen);
}
}
}
@ -4668,8 +4688,8 @@ void sofia_glue_pass_sdp(private_object_t *tech_pvt, char *sdp)
switch_channel_set_variable(other_channel, SWITCH_B_SDP_VARIABLE, sdp);
if (!sofia_test_flag(tech_pvt, TFLAG_CHANGE_MEDIA) && !sofia_test_flag(tech_pvt, TFLAG_RECOVERING) &&
(switch_channel_test_flag(other_channel, CF_OUTBOUND) &&
switch_channel_test_flag(tech_pvt->channel, CF_OUTBOUND) && switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE))) {
(switch_channel_direction(other_channel) == SWITCH_CALL_DIRECTION_OUTBOUND &&
switch_channel_direction(tech_pvt->channel) == SWITCH_CALL_DIRECTION_OUTBOUND && switch_channel_test_flag(tech_pvt->channel, CF_PROXY_MODE))) {
switch_ivr_nomedia(val, SMF_FORCE);
sofia_set_flag_locked(tech_pvt, TFLAG_CHANGE_MEDIA);
}
@ -5041,9 +5061,20 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName
const char *port = switch_channel_get_variable(channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE);
const char *r_ip = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE);
const char *r_port = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE);
const char *use_uuid;
sofia_set_flag(tech_pvt, TFLAG_RECOVERING);
if ((use_uuid = switch_channel_get_variable(channel, "origination_uuid"))) {
if (switch_core_session_set_uuid(session, use_uuid) == SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s set UUID=%s\n", switch_channel_get_name(channel),
use_uuid);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "%s set UUID=%s FAILED\n",
switch_channel_get_name(channel), use_uuid);
}
}
if (!switch_channel_test_flag(channel, CF_PROXY_MODE) && ip && port) {
const char *tmp;
tech_pvt->iananame = tech_pvt->rm_encoding = (char *) switch_channel_get_variable(channel, "sip_use_codec_name");

View File

@ -90,6 +90,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co
char *user_via = NULL;
char *contact_str = NULL;
char *dup_dest = NULL;
char *remote_host = NULL;
if (!to) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing To: header.\n");
@ -185,11 +186,9 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co
/* sofia_glue is running sofia_overcome_sip_uri_weakness we do not, not sure if it matters */
remote_ip = malloc(sizeof(80));
dup_dest = strdup(dst->contact);
if (switch_stristr("fs_path", dst->contact)) {
char *remote_host = NULL;
const char *s;
if ((s = switch_stristr("fs_path=", dst->contact))) {
@ -202,7 +201,6 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co
if (!zstr(remote_host)) {
switch_split_user_domain(remote_host, NULL, &remote_ip);
}
switch_safe_free(remote_host);
}
if (zstr(remote_ip)) {
@ -236,7 +234,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co
}
switch_safe_free(dup_dest);
free(remote_ip);
switch_safe_free(remote_host);
status = SWITCH_STATUS_SUCCESS;
@ -820,7 +818,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event)
sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sofia_presence_dialog_callback, &dh);
switch_safe_free(sql);
if ((sql = switch_mprintf("select sip_subscriptions.proto,sip_subscriptions.sip_user,sip_subscriptions.sip_host,"
if ((sql = switch_mprintf("select distinct sip_subscriptions.proto,sip_subscriptions.sip_user,sip_subscriptions.sip_host,"
"sip_subscriptions.sub_to_user,sip_subscriptions.sub_to_host,sip_subscriptions.event,"
"sip_subscriptions.contact,sip_subscriptions.call_id,sip_subscriptions.full_from,"
"sip_subscriptions.full_via,sip_subscriptions.expires,sip_subscriptions.user_agent,"

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