diff --git a/build/sounds_version.txt b/build/sounds_version.txt
index 55729b1f9f..056ebde66c 100644
--- a/build/sounds_version.txt
+++ b/build/sounds_version.txt
@@ -1,3 +1,3 @@
en-us-callie 1.0.16
-ru-RU-elena 1.0.12
+ru-RU-elena 1.0.13
diff --git a/conf/autoload_configs/modules.conf.xml b/conf/autoload_configs/modules.conf.xml
index 96079cd227..c9f1c17d7e 100644
--- a/conf/autoload_configs/modules.conf.xml
+++ b/conf/autoload_configs/modules.conf.xml
@@ -42,6 +42,7 @@
+
diff --git a/conf/autoload_configs/portaudio.conf.xml b/conf/autoload_configs/portaudio.conf.xml
index 1f758de896..02c21ef449 100644
--- a/conf/autoload_configs/portaudio.conf.xml
+++ b/conf/autoload_configs/portaudio.conf.xml
@@ -32,4 +32,187 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/autoload_configs/rtmp.conf.xml b/conf/autoload_configs/rtmp.conf.xml
new file mode 100644
index 0000000000..d5d278810e
--- /dev/null
+++ b/conf/autoload_configs/rtmp.conf.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/autoload_configs/unimrcp.conf.xml b/conf/autoload_configs/unimrcp.conf.xml
index 452936bf7c..45dda798a1 100644
--- a/conf/autoload_configs/unimrcp.conf.xml
+++ b/conf/autoload_configs/unimrcp.conf.xml
@@ -12,6 +12,7 @@
+
diff --git a/conf/dialplan/default.xml b/conf/dialplan/default.xml
index a19f68399e..36f0e52a2e 100644
--- a/conf/dialplan/default.xml
+++ b/conf/dialplan/default.xml
@@ -274,7 +274,15 @@
+
+
+
+
+
+
+
+
diff --git a/conf/dialplan/skinny-patterns.xml b/conf/dialplan/skinny-patterns.xml
index a78b83bdc7..9f5786d731 100644
--- a/conf/dialplan/skinny-patterns.xml
+++ b/conf/dialplan/skinny-patterns.xml
@@ -5,7 +5,7 @@
This context is used for skinny to match dialed number
The special applications:
- - skinny-route tells skinny to route the call
+ - skinny-process tells skinny to process the call (route, set call forwarding, ...)
- skinny-drop tells skinny to drop the call
- skinny-wait tells skinny to wait 'data' seconds for more numbers before drop
-->
diff --git a/conf/dialplan/skinny-patterns/20-Demo.xml b/conf/dialplan/skinny-patterns/20-Demo.xml
index 0246fe29a4..f69658128f 100644
--- a/conf/dialplan/skinny-patterns/20-Demo.xml
+++ b/conf/dialplan/skinny-patterns/20-Demo.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/conf/dialplan/skinny-patterns/20-Local_extension.xml b/conf/dialplan/skinny-patterns/20-Local_extension.xml
index a3693e80c8..9ad5651328 100644
--- a/conf/dialplan/skinny-patterns/20-Local_extension.xml
+++ b/conf/dialplan/skinny-patterns/20-Local_extension.xml
@@ -1,12 +1,12 @@
-
+
-
+
diff --git a/conf/dialplan/skinny-patterns/90-External.xml b/conf/dialplan/skinny-patterns/90-External.xml
index 706bf74027..50d6c37f24 100644
--- a/conf/dialplan/skinny-patterns/90-External.xml
+++ b/conf/dialplan/skinny-patterns/90-External.xml
@@ -1,7 +1,7 @@
-
+
diff --git a/conf/lang/en/dir/sounds.xml b/conf/lang/en/dir/sounds.xml
index 15ecec304a..85dd01c599 100644
--- a/conf/lang/en/dir/sounds.xml
+++ b/conf/lang/en/dir/sounds.xml
@@ -94,16 +94,16 @@
-
+
-
+
-
+
-
+
diff --git a/conf/lang/en/en.xml b/conf/lang/en/en.xml
index 1e23dc5d7b..2ccd513823 100644
--- a/conf/lang/en/en.xml
+++ b/conf/lang/en/en.xml
@@ -6,6 +6,7 @@
+
diff --git a/debian/changelog b/debian/changelog
index 35a8787d38..abfe17e081 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+freeswitch (1.0.head-git.master.20110530.1-1) unstable; urgency=low
+
+ * added mod_cdr_sqlite
+
+ -- Michal Bielicki Mon, 30 May 2011 16:02:02 +0200
+
freeswitch (1.0.head-git.master.20110402.1-1) unstable; urgency=low
* Added Hebrew lang package
diff --git a/debian/freeswitch.install b/debian/freeswitch.install
index 72ded2c48c..a72200294f 100644
--- a/debian/freeswitch.install
+++ b/debian/freeswitch.install
@@ -155,6 +155,7 @@ opt/freeswitch/mod/mod_skinny.so*
opt/freeswitch/mod/mod_skypopen.so*
opt/freeswitch/mod/mod_sndfile.so*
opt/freeswitch/mod/mod_snom.so*
+opt/freeswitch/mod/mod_cdr_sqlite.so*
opt/freeswitch/mod/mod_sofia.so*
opt/freeswitch/mod/mod_spandsp.so*
opt/freeswitch/mod/mod_speex.so*
diff --git a/debian/rules b/debian/rules
index d6b1915c88..2227a76552 100755
--- a/debian/rules
+++ b/debian/rules
@@ -23,7 +23,7 @@ export CODECS_MODULES= codecs/mod_bv codecs/mod_h26x codecs/mod_speex codecs/mod
export DIALPLANS_MODULES= dialplans/mod_dialplan_asterisk dialplans/mod_dialplan_directory dialplans/mod_dialplan_xml
export ENDPOINTS_MODULES= endpoints/mod_dingaling endpoints/mod_portaudio endpoints/mod_sofia endpoints/mod_loopback \
../../libs/freetdm/mod_freetdm endpoints/mod_skypopen endpoints/mod_skinny
-export EVENT_HANDLERS_MODULES=event_handlers/mod_event_multicast event_handlers/mod_event_socket event_handlers/mod_cdr_csv
+export EVENT_HANDLERS_MODULES=event_handlers/mod_event_multicast event_handlers/mod_event_socket event_handlers/mod_cdr_csv event_handlers/mod_cdr_sqlite
export FORMATS_MODULES= formats/mod_local_stream formats/mod_native_file formats/mod_portaudio_stream \
formats/mod_shout formats/mod_sndfile formats/mod_tone_stream
export LANGUAGES_MODULES=languages/mod_spidermonkey languages/mod_perl languages/mod_lua languages/mod_python
diff --git a/docs/ChangeLog b/docs/ChangeLog
index b4e93ab05c..379a1045f8 100644
--- a/docs/ChangeLog
+++ b/docs/ChangeLog
@@ -43,6 +43,10 @@ freeswitch (1.0.7)
config: add default to conf to demonstrate min-idle-cpu (r:b8b7266a)
config: change min/max enforcements to >= instead of > (r:0d5fcf65)
config: Add README_IMPORTANT.txt to default configuration (r:6cd5ce72)
+ config: Talking clock dialplan example (Thanks AviMarcus) (r:ffb4a3ae)
+ config: fix talking clock regexes (need ^ and $ so they don't match only 917x) (r:8529ba33)
+ config: Update phrase_en.xml to reflect 1.0.16 sounds version (r:7499dfb2)
+ config: bump en sounds version to 1.0.16 (r:50ce2cae)
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
@@ -245,6 +249,18 @@ freeswitch (1.0.7)
core: enable optimal defaults on linux kernels that can support newer features. (r:0b51aca3)
core: Lower NAT port mapping disabled log msg from WARNING to INFO (r:973a850d)
core: Change the structure of the phrases/language system. Previously it was fxml->phrases->macros->language->macro. Changed it so fxml->languages->language->phrases->macros->macro You can have sub macros and allow you to call it login@voicemail. Change the sound-path to sound-prefix to make it constistant with the rest of freeswitch. Also allow to set a sound-prefix to a macros, so you can override it for a specific file set. You can set say-modules="en" or whatever in the 2400+2600 -> 2600 occur. Transitions between tone off and tone on are clean. (r:bc13e944)
@@ -310,8 +327,10 @@ freeswitch (1.0.7)
libspandsp: Fix for T.30 processing of operator interrupts, to improve compatibility with some machines, which seem to send them when no operator is around. (r:84ee0ae6)
libspandsp: spandsp t38 fax receiving error in win XP - regression from f029f7ef (r:761cec8f/FS-2766)
libspandsp: Added missing error codes when an ECM FAX is abandoned with the T30_ERR message (r:ec57dc7a)
- libspandsp: Fixed a vulnerability in T.4 and T.6 processing which is similar to http://bugzilla.maptools.org/show_bug.cgi?id=2297 in libtiff. A really screwed up 2D T.4 image, or a maliciously constructed T.4 2D or T.6 image should potential run off the end of an image decoder buffer. (r:c6f67322)
+ libspandsp: Fixed a vulnerability in T.4 and T.6 processing which is similar to http://bugzilla.maptools.org/show_bug.cgi?id=2297 in libtiff. A really screwed up 2D T.4 image, or a maliciously constructed T.4 2D or T.6 image should potential run off the end of an image decoder buffer. (r:c6f67322)
+ libspandsp: Changed T.38 terminal handling, so errors from the user's packet transmit routine properly filter up the chain, cause termination of the FAX session, and are reported to the caller. (r:c890fbfa)
libstfu: add param to jb to try to recapture latency (disabled by default) (r:d59d41d7)
+ libsqlite: fix issue on mailing list mod_crd_sqlite entry limit and sqlite segfaults on triggers (r:1badec17)
mod_avmd: Initial check in - Advanced Voicemail Detect (r:10c6a30a) (by Eric Des Courtis)
mod_avmd: Add to windows build (r:df4bd935)
mod_avmd: Fix mem leak (r:cd951384/FS-2839)
@@ -349,6 +368,8 @@ freeswitch (1.0.7)
mod_callcenter: Reload a queue wont delete all the currently waiting members. Only a reload of the module will. (r:c5ae5de0/FS-3250)
mod_callcenter: Add a very prototype (and maybe not functional) strategy called : sequentially-by-next-agent-order. It will try to find the last agent we tried to reach, and start calling more agent after that one based on position. It will use the level for the next agent, but once that level is done, it start back at the lowest level (r:bef6f0f4)
mod_callcenter: New strategies: round-robin, random, and 'top-down' (r:2b4b23aa,r:bee247ca)
+ mod_callcenter: Display an warning when MOH is invalid and resume wait with silence. (r:37b14c9a/FS-2740)
+ mod_callcenter: Fix member been switch as abandoned when he was pickup by an agent (r:9ff8f53f/FS-3281)
mod_cdr_sqlite: initial commit (r:f625fe3b)
mod_cdr_sqlite: config file for mod_cdr_sqlite (r:25bc8fe3)
mod_cdr_sqlite: Drop transaction BEGIN/END around INSERT. We're only executing one command, and autocommit will automatically rollback if the INSERT fails. Sync state_handlers with mod_cdr_csv. Minor libpq fixups. (r:0f95b870)
@@ -411,6 +432,9 @@ freeswitch (1.0.7)
mod_conference: wait for channels to come up in paging mode (r:b8063c3d)
mod_conference: Conference APIs for enabling/disabling enter/exit sounds for active conferences (r:31cebd4f/FS-3219)
mod_conference: Fix pool swelling, replaced a pool strdup that could recur with a strdup/free to avoid it (r:bcd6c3a1/FS-3137)
+ mod_conference: remove auto gain events (r:7ba849b3)
+ mod_conference: add custom exit sound to match enter sound on conf (r:3d475876)
+ mod_conference: don't play default when playing a custom one (r:c7b36157)
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)
@@ -440,6 +464,8 @@ freeswitch (1.0.7)
mod_easyroute: Fix possible segfaults and memory leak during unload, and add new setting odbc-retries (r:7fbc47f8/FS-2973)
mod_enum: switch mod_enum to use new portable in-tree version (r:2bbc37e3)
mod_enum: fix race condition between ldns configure creating ldns/util.h and mod_enum (r:87884c5c)
+ mod_enum: fix ms resolution with new query-timeout-ms, query-timeout still works as expected (r:88f4828c/FS-3282)
+ mod_enum: fix ldns_lookup not respecting query-timeout (r:1d490df9/FS-3282)
mod_erlang_event: Make XML fetch reply ACKs distinguishable, update freeswitch.erl (r:9d44ed04)
mod_erlang_event: Add 3 new commands; session_event, session_noevents, session_nixevent (r:698fa045)
mod_erlang_event: generate long node names the same as erlang does (r:9ad509c2)
@@ -453,7 +479,9 @@ freeswitch (1.0.7)
mod_event_socket: Add "-ERR" to api cmd response when failure occurs (r:58759052/FS-2827)
mod_event_socket: clear unique headers on event_socket filters (r:436413e0)
mod_event_socket: Unlock mutex to prevent mortuus obfirmo (r:64bc1938/FS-3156/FS-3157)
+ mod_event_socket: (and mod_erlang_event) make empty apply-inbound-acl config line not deny all (r:8ae9ab5d/FS-3034)
mod_event_zmq: Intitial mod_event_zmq code (r:4d554067)
+ mod_event_zmq: Update download file from 2.1.3 to 2.1.4 (2.1.3 tar file is gone from zmq server) (r:0b780702)
mod_fifo: allow multiple dtmf to exit fifo, set fifo_caller_exit_key to specify which (MODAPP-420)
mod_fifo: cancel outbound call if customer hangs up (r:cadb4d94)
mod_fifo: add taking_calls param to fifo member add and config file (r:821488bf)
@@ -500,6 +528,8 @@ freeswitch (1.0.7)
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_freetdm: add specific alarm status in dump (r:7c971707)
+ mod_freetdm: make ananlog alarm (r:23d86585)
mod_fsk: add mod_fsk (r:fcc912a9)
mod_gsmopen: copy from branch
mod_gsmopen: fix FS-2793, compilation stops (r:355c0dbb/FS-2793)
@@ -526,6 +556,7 @@ freeswitch (1.0.7)
mod_h323: Add mod_h323 to windows (r:015bcaf6/MODENDP-301)
mod_h323: move PTrace level set to FSH323EndPoint::Initialise. partially apply patch from from Peter Olsson, Remove UnLock() when TryLock() failed and DEBUG_RTP_PACKETS directiv e. (r:7b5803f7)
mod_h323: set network_addr of caller profile to signaling ip address. (requested by Steven Ayre) (r:072bf5ad)
+ mod_h323: fix race condition on destroying signaling thread in h323 library (r:c22aac0e)
mod_java: fix eventConsumer issue and add flush() method (r:7fd3aff6)
mod_java: Allow user defined java methods to be called at startup and shutdown of JVM (r:1339e218/MODLANG-117)
mod_json_cdr: Fix segfault in mod_json_cdr.c (r:f347698a/MODEVENT-66)
@@ -542,12 +573,15 @@ freeswitch (1.0.7)
mod_lcr: don't count twice (r:eaeabc7b/FS-1810)
mod_lcr: properly destroy lcr object when done (r:084819a3/FS-3199)
mod_lcr: don't add routes that have no rate of the desired type (r:82e3ccf8)
+ mod_lcr: fix "as xml" for larger number of arguments (r:3dca2ebb/FS-3283)
+ mod_lcr: fix malformed XML when has embedded %s (r:5fa9619f/FS-3284)
mod_loopback: add loopback_bowout_on_execute var to make 1 legged loopback calls bow out of the picture
mod_loopback: only execute app once in app mode (r:64f58f2d)
mod_loopback: fix bug in mod_loopback where bowout=false (r:e9ab5368)
mod_loopback: pass indication when in app mode on mod_loopback (r:c423e209)
mod_loopback: fix voicemail failure (r:1a1881e8/FS-2795)
mod_loopback: pass ring_ready like we do with pre_answer (r:9d087d45)
+ mod_loopback: refactor mod_loopback timeout handling (r:43442e4f)
mod_lua: Add switch_core_sqldb functionality from inside Lua script (r:26f2e095/FS-1384)
mod_lua: Made 2nd arg to freeswitch.Dbh:query (cb func) optional (r:87db11af)
mod_lua: Added SAF_ROUTING_EXEC flag to lua app, so it can be run inline (r:7d5ca1c0)
@@ -559,11 +593,13 @@ freeswitch (1.0.7)
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_mongo: New mod, initial commit; module for MongoDB (http://www.mongodb.org/) (r:dc6ca6f8/FS-3278)
mod_mp4v: MP4V-ES passthru for washibechi on IRC
mod_mp4: New module. Supports playback of MP4 files. Depends on libmp4v2 (originally compiled against v1.6.1)
mod_nibblebill: free allocated mem at shutdown; free properly if using custom_sql
mod_nibblebill: Add SAF_SUPPORT_NOMEDIA to nibblebill
mod_nibblebill: fix compile issues in latest HEAD (r:b073e82b/FSMOD-51)
+ mod_nibblebill: remove on_reporting hook (r:897e6573/FS-2890)
mod_openzap: custom data (r:5d4db94d)
mod_openzap: more ss7 custom data (r:c93e392d)
mod_openzap: handle loop requests (r:23766e36)
@@ -579,6 +615,9 @@ freeswitch (1.0.7)
mod_portaudio: mod_portaudio improvements and bug fixes (r:33b74ca8/FS-3006)
mod_portaudio: Add pa devlist to portaudio webapi (r:e8f10ea3)
mod_protovm: This is a very early new prototype voicemail ivr system. You need to copy the sounds.xml and make it loadale in the language folder and protovm.conf.xml inside the autoload_configs folder. Configs file will most definitly change. Once stabilized, we make it install those file by default. (r:fb549777)
+ mod_radius_cdr: Add 'Freeswitch-Direction' av pair (r:a5170df0)
+ mod_radius_cdr: Add 'Freeswitch-Other-Leg-Id' av pair (r:18d29b46)
+ mod_radius_cdr: log errors with the call's uuid (r:fee49b16)
mod_sangoma_codec: Add sample config file
mod_sangoma_codec: added load/noload options for the supported codecs
mod_sangoma_codec: rename load/noload to register/noregister
@@ -594,6 +633,7 @@ freeswitch (1.0.7)
mod_sangoma_codec: add siren7 32kbps (r:fcaf2677)
mod_sangoma_codec: add SIREN7 24kbps (r:3acc5fdb)
mod_say: Fix crash for Say Number Pronounced with numbers of more than 9 digits (r:06bccf28/FS-3202)
+ mod_say_de: method PRONOUNCED - grammatical fixes, thank you Christian Benke (r:5d46ddbc/FS-3195)
mod_say_en: introduce new say_string method of doing say and use it in mod_say_en as an example. try: eval ${say_string en.gsm en current_date_time pronounced ${strepoch()}} from the cli with this patch. We can do more to centralize the say things and go back and apply it to other langs, using this method you can set the desired file ext as well which I think is a bounty.... (r:d5ef86d7)
mod_say_en: If you only tell SAY CURRENCY to say 100 it should only say 100 dollars without the "0 cents" (r:426a4e76/FS-2922)
mod_say_es: fix grammar when saying dates and time (r:6bed19b2/MODAPP-429)
@@ -630,6 +670,8 @@ freeswitch (1.0.7)
mod_skypopen: ignore early media sent by channels to be bridged before our channel is answered (r:ef14b78a)
mod_skypopen: OSS driver, refinement (r:b0a23f8e)
mod_skypopen: deleted osscuse subdir (r:4842a620)
+ mod_skypopen: adding installer and Skype client configuration directories (to be announced :) ) (r:25ebf715)
+ mod_skypopen: refining INTERACTIVE INSTALLER for Linux (to be announced :) ) (r:aa7f47ac)
mod_snapshot: fix bad codepaths in mod_snapshot (r:844ac220)
mod_sndfile: Add support for .alaw and .ulaw to mod_sndfile (r:facf09b8/MODFORM-41)
mod_sndfile: return break in mod_sndfile when seek returns failure (r:564dc7e4)
@@ -790,6 +832,14 @@ freeswitch (1.0.7)
mod_sofia: Don't assume incoming "gw" contact param is valid (prevent possible DoS) (r:2b6f7070/FS-3244)
mod_sofia: offer both avp and savp when using srtp (r:5857495e)
mod_sofia: fix race in sla (r:a4ed829d)
+ mod_sofia: Fix segfault when no channel is present and need to print err msg (r:ce5c8462/FS-3236)
+ mod_sofia: don't nat map on loopback addrs (r:e70af1f8)
+ mod_sofia: Add reporting chan vars: sip_bye_content_type and sip_bye_payload (r:2d856f8f/FS-3276)
+ mod_sofia: Add "tel:" patch - thanks jaybinks (r:154731a7)
+ mod_sofia: fix rare t38 gateway issue (r:123eaa52)
+ mod_sofia: fix sofia presence with dial does not maintain version number correctly (r:3ebd173c/FS-3307)
+ mod_sofia: fix One way audio problem from B-leg of the call on Session Refresh and HOLD if B-leg is using a dynamic payload type (r:66d16d17/FS-3270)
+ mod_sofia: chat API issue: dup_dest was being overwritten by switch_split_user_domain (r:765908f3/FS-3152)
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)
@@ -804,6 +854,8 @@ freeswitch (1.0.7)
mod_spandsp: Fire event when fax is finished; indicates result of fax attempt (r:314a2a1e/FS-3004)
mod_spandsp: new option to set sip_execute_on_image to 't38_gateway self nocng' this should skip the tone detection adn go right into the gateway mode so you should be able to do only this and have it work based on remote re-invite (r:9227b538/FS-3252)
mod_spandsp: additional fix to this bug and add better fax detect code to mod_spandsp (r:7fe313cf/FS-3252)
+ mod_spandsp: Fire event when fax finishes indicating result (r:a57336ba/FS-3004)
+ mod_spandsp: Prevent hung chans on fax errors (r:789a9ce8/FS-3213)
mod_spidermonkey: allow vars to be set containing vars from languages (r:5cd072a3)
mod_spidermonkey: fix seg in js hangup (r:7d554c11)
mod_spidermonkey: Fix mod_spidermonkey build on FreeBSD, (Undefined symbol PR_LocalTimeParameters). (r:3edb8419)
@@ -855,6 +907,7 @@ freeswitch (1.0.7)
tools: Add fs_encode tool (r:89b17601)
tools: Add randomize-passwords.pl script to main tree (r:5e6123ef)
tools: Change logger.pl host flag to -H from -h (conflicted w/ -h for help); add -H/--host to usage (r:73ca862c)
+ tools: Add sound_test.lua utility script (lets you listen to all the sound files in a particular rate/type combo (r:1a71dbf2)
freeswitch (1.0.6)
diff --git a/docs/phrase/phrase_en.xml b/docs/phrase/phrase_en.xml
index 507fc7bd34..88d0950d29 100644
--- a/docs/phrase/phrase_en.xml
+++ b/docs/phrase/phrase_en.xml
@@ -491,6 +491,9 @@
+
+
+
diff --git a/freeswitch.spec b/freeswitch.spec
index d13ae2686d..461597791f 100644
--- a/freeswitch.spec
+++ b/freeswitch.spec
@@ -5,7 +5,7 @@
#
# includes module(s): freeswitch-devel freeswitch-codec-passthru-amr freeswitch-codec-passthru-amrwb freeswitch-codec-passthru-g729
# freeswitch-codec-passthru-g7231 freeswitch-lua freeswitch-perl freeswitch-python freeswitch-spidermonkey
-# freeswitch-lan-de freeswitch-lang-en freeswitch-lang-fr freeswitch-lang-ru freeswitch-freetdm
+# freeswitch-lan-de freeswitch-lang-en freeswitch-lang-fr freeswitch-lang-hu freeswitch-lang-ru freeswitch-freetdm
#
# Initial Version Copyright (C) 2007 Peter Nixon and Michal Bielicki, All Rights Reserved.
#
@@ -471,7 +471,7 @@ DIRECTORIES_MODULES=""
#
######################################################################################################################
ENDPOINTS_MODULES="endpoints/mod_dingaling endpoints/mod_loopback ../../libs/freetdm/mod_freetdm endpoints/mod_portaudio \
- endpoints/mod_sofia endpoints/mod_skinny endpoints/mod_skypopen"
+ endpoints/mod_sofia endpoints/mod_skinny endpoints/mod_skypopen endpoints/mod_rtmp"
######################################################################################################################
#
@@ -785,6 +785,7 @@ fi
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/post_load_modules.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/redis.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/rss.conf.xml
+%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/rtmp.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/sangoma_codec.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/shout.conf.xml
%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/skinny.conf.xml
@@ -924,6 +925,7 @@ fi
%{prefix}/mod/mod_portaudio_stream.so*
%{prefix}/mod/mod_redis.so*
%{prefix}/mod/mod_rss.so*
+%{prefix}/mod/mod_rtmp.so*
%{prefix}/mod/mod_shout.so*
%{prefix}/mod/mod_silk.so*
%{prefix}/mod/mod_siren.so*
@@ -1127,6 +1129,8 @@ fi
#
######################################################################################################################
%changelog
+* Tue Jun 14 2011 - michal.bielicki@seventhsignal.de
+- added mod_rtmp
* Fri Apr 01 2011 - michal.bielicki@seventhsignal.de
- added hebrew language stuff
* Wed Mar 30 2011 - michal.bielicki@seventhsignal.de
diff --git a/libs/.gitignore b/libs/.gitignore
index b9aa87286c..4d2fea4b22 100644
--- a/libs/.gitignore
+++ b/libs/.gitignore
@@ -276,6 +276,17 @@
/ldns/packaging/ldns-config
/ldns/packaging/libldns.pc
/ldns-1.6.9/
+/libcodec2/src/c2dec
+/libcodec2/src/c2enc
+/libcodec2/src/c2sim
+/libcodec2/unittest/extract
+/libcodec2/unittest/genlsp
+/libcodec2/unittest/genres
+/libcodec2/unittest/tcodec2
+/libcodec2/unittest/tinterp
+/libcodec2/unittest/tnlp
+/libcodec2/unittest/tquant
+/libcodec2/unittest/vqtrain
/libdingaling/Makefile
/libdingaling/Makefile.in
/libdingaling/aclocal.m4
@@ -986,6 +997,7 @@
/xmlrpc-c/stamp-h2
/xmlrpc-c/xmlrpc_amconfig.h
/xmlrpc-c/xmlrpc_config.h
+/zeromq-*/
/apr/build/install-sh
/js/install-sh
/js/nsprpub/lib/ds/libplds4.dylib
@@ -1035,7 +1047,7 @@
/libshout-2.2.2/
/mpg123/
/openldap-2.4.19/
-/pocketsphinx-0.5.99/
+/pocketsphinx-0.7/
/portaudio/bin-stamp
/portaudio/bin/
/portaudio/lib-stamp
@@ -1043,7 +1055,7 @@
/silk/Encoder
/silk/signalCompare
/soundtouch-1.3.1/
-/sphinxbase-0.4.99/
+/sphinxbase-0.7/
/unimrcp/platforms/asr-client/asrclient
/unimrcp/platforms/umc/umc
/unimrcp/platforms/unimrcp-client/unimrcpclient
@@ -1067,7 +1079,6 @@
/libogg-1.1.3/
/pthreads-w32-2-7-0-release/
/sounds/
-/sphinxbase-0.4.99/
/sofia-sip/libsofia-sip-ua/http/http_tag_dll.c
/sofia-sip/libsofia-sip-ua/iptsec/auth_tag_dll.c
/sofia-sip/libsofia-sip-ua/msg/msg_tag_dll.c
diff --git a/libs/esl/Makefile b/libs/esl/Makefile
index 7363304cdb..60bae27b5f 100644
--- a/libs/esl/Makefile
+++ b/libs/esl/Makefile
@@ -34,10 +34,10 @@ testclient: $(MYLIB) testclient.c
fs_cli: $(MYLIB) fs_cli.c
$(CC) $(CC_CFLAGS) $(CFLAGS) fs_cli.c -o fs_cli $(LDFLAGS) -L$(LIBEDIT_DIR)/src/.libs $(LIBS) -ledit
-%.o: %.c
+%.o: %.c $(HEADERS)
$(CC) $(CC_CFLAGS) $(CFLAGS) -c $< -o $@
-%.o: %.cpp
+%.o: %.cpp $(HEADERS)
$(CXX) $(CXX_CFLAGS) $(CXXFLAGS) -c $< -o $@
clean:
diff --git a/libs/esl/fs_cli.c b/libs/esl/fs_cli.c
index b1cb8cda10..5d0c7eb8c1 100644
--- a/libs/esl/fs_cli.c
+++ b/libs/esl/fs_cli.c
@@ -572,7 +572,7 @@ COLORS[] = { ESL_SEQ_DEFAULT_COLOR, ESL_SEQ_FRED, ESL_SEQ_FRED,
ESL_SEQ_FRED, ESL_SEQ_FMAGEN, ESL_SEQ_FCYAN, ESL_SEQ_FGREEN, ESL_SEQ_FYELLOW };
static int usage(char *name){
- printf("Usage: %s [-H ] [-P ] [-p ] [-d ] [-x command] [profile]\n\n", name);
+ printf("Usage: %s [-H ] [-P ] [-p ] [-d ] [-x command] [-t ] [profile]\n\n", name);
printf(" -?,-h --help Usage Information\n");
printf(" -H, --host=hostname Host to connect\n");
printf(" -P, --port=port Port to connect (1 - 65535)\n");
@@ -584,7 +584,8 @@ static int usage(char *name){
printf(" -q, --quiet Disable logging\n");
printf(" -r, --retry Retry connection on failure\n");
printf(" -R, --reconnect Reconnect if disconnected\n");
- printf(" -d, --debug=level Debug Level (0 - 7)\n\n");
+ printf(" -d, --debug=level Debug Level (0 - 7)\n");
+ printf(" -t, --timeout Timeout for API commands (in miliseconds)\n\n");
return 1;
}
@@ -1026,6 +1027,7 @@ int main(int argc, char *argv[])
{"retry", 0, 0, 'r'},
{"interrupt", 0, 0, 'i'},
{"reconnect", 0, 0, 'R'},
+ {"timeout", 1, 0, 't'},
{0, 0, 0, 0}
};
@@ -1044,7 +1046,7 @@ int main(int argc, char *argv[])
char argv_command[1024] = "";
char argv_loglevel[128] = "";
int argv_quiet = 0;
- int loops = 2, reconnect = 0;
+ int loops = 2, reconnect = 0, timeout = 0;
strncpy(internal_profile.host, "127.0.0.1", sizeof(internal_profile.host));
strncpy(internal_profile.pass, "ClueCon", sizeof(internal_profile.pass));
@@ -1069,7 +1071,7 @@ int main(int argc, char *argv[])
for(;;) {
int option_index = 0;
- opt = getopt_long(argc, argv, "H:U:P:S:u:p:d:x:l:qrRhi?", options, &option_index);
+ opt = getopt_long(argc, argv, "H:U:P:S:u:p:d:x:l:t:qrRhi?", options, &option_index);
if (opt == -1) break;
switch (opt)
{
@@ -1122,6 +1124,9 @@ int main(int argc, char *argv[])
case 'R':
reconnect = 1;
break;
+ case 't':
+ timeout = atoi(optarg);
+ break;
case 'h':
case '?':
print_banner(stdout);
@@ -1278,7 +1283,17 @@ int main(int argc, char *argv[])
const char *err = NULL;
snprintf(cmd_str, sizeof(cmd_str), "api %s\n\n", argv_command);
- esl_send_recv(&handle, cmd_str);
+ if (timeout) {
+ esl_status_t status = esl_send_recv_timed(&handle, cmd_str, timeout);
+ if (status != ESL_SUCCESS) {
+ printf("Request timed out.\n");
+ esl_disconnect(&handle);
+ return -2;
+ }
+ } else {
+ esl_send_recv(&handle, cmd_str);
+ }
+
if (handle.last_sr_event) {
if (handle.last_sr_event->body) {
printf("%s\n", handle.last_sr_event->body);
diff --git a/libs/esl/java/esl_wrap.cpp b/libs/esl/java/esl_wrap.cpp
index 9a764dd030..52c5065d00 100644
--- a/libs/esl/java/esl_wrap.cpp
+++ b/libs/esl/java/esl_wrap.cpp
@@ -419,10 +419,11 @@ SWIGEXPORT jboolean JNICALL Java_org_freeswitch_esl_eslJNI_ESLevent_1setPriority
}
-SWIGEXPORT jstring JNICALL Java_org_freeswitch_esl_eslJNI_ESLevent_1getHeader(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
+SWIGEXPORT jstring JNICALL Java_org_freeswitch_esl_eslJNI_ESLevent_1getHeader(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2, jint jarg3) {
jstring jresult = 0 ;
ESLevent *arg1 = (ESLevent *) 0 ;
char *arg2 = (char *) 0 ;
+ int arg3 = (int) -1 ;
char *result = 0 ;
(void)jenv;
@@ -434,7 +435,8 @@ SWIGEXPORT jstring JNICALL Java_org_freeswitch_esl_eslJNI_ESLevent_1getHeader(JN
arg2 = (char *)jenv->GetStringUTFChars(jarg2, 0);
if (!arg2) return 0;
}
- result = (char *)(arg1)->getHeader((char const *)arg2);
+ arg3 = (int)jarg3;
+ result = (char *)(arg1)->getHeader((char const *)arg2,arg3);
if(result) jresult = jenv->NewStringUTF((const char *)result);
if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2);
return jresult;
@@ -522,6 +524,64 @@ SWIGEXPORT jboolean JNICALL Java_org_freeswitch_esl_eslJNI_ESLevent_1addHeader(J
}
+SWIGEXPORT jboolean JNICALL Java_org_freeswitch_esl_eslJNI_ESLevent_1pushHeader(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2, jstring jarg3) {
+ jboolean jresult = 0 ;
+ ESLevent *arg1 = (ESLevent *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) 0 ;
+ bool result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(ESLevent **)&jarg1;
+ arg2 = 0;
+ if (jarg2) {
+ arg2 = (char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2) return 0;
+ }
+ arg3 = 0;
+ if (jarg3) {
+ arg3 = (char *)jenv->GetStringUTFChars(jarg3, 0);
+ if (!arg3) return 0;
+ }
+ result = (bool)(arg1)->pushHeader((char const *)arg2,(char const *)arg3);
+ jresult = (jboolean)result;
+ if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2);
+ if (arg3) jenv->ReleaseStringUTFChars(jarg3, (const char *)arg3);
+ return jresult;
+}
+
+
+SWIGEXPORT jboolean JNICALL Java_org_freeswitch_esl_eslJNI_ESLevent_1unshiftHeader(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2, jstring jarg3) {
+ jboolean jresult = 0 ;
+ ESLevent *arg1 = (ESLevent *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) 0 ;
+ bool result;
+
+ (void)jenv;
+ (void)jcls;
+ (void)jarg1_;
+ arg1 = *(ESLevent **)&jarg1;
+ arg2 = 0;
+ if (jarg2) {
+ arg2 = (char *)jenv->GetStringUTFChars(jarg2, 0);
+ if (!arg2) return 0;
+ }
+ arg3 = 0;
+ if (jarg3) {
+ arg3 = (char *)jenv->GetStringUTFChars(jarg3, 0);
+ if (!arg3) return 0;
+ }
+ result = (bool)(arg1)->unshiftHeader((char const *)arg2,(char const *)arg3);
+ jresult = (jboolean)result;
+ if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2);
+ if (arg3) jenv->ReleaseStringUTFChars(jarg3, (const char *)arg3);
+ return jresult;
+}
+
+
SWIGEXPORT jboolean JNICALL Java_org_freeswitch_esl_eslJNI_ESLevent_1delHeader(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) {
jboolean jresult = 0 ;
ESLevent *arg1 = (ESLevent *) 0 ;
diff --git a/libs/esl/java/org/freeswitch/esl/ESLevent.java b/libs/esl/java/org/freeswitch/esl/ESLevent.java
index 5f5b303e8b..d3bbbf88b4 100644
--- a/libs/esl/java/org/freeswitch/esl/ESLevent.java
+++ b/libs/esl/java/org/freeswitch/esl/ESLevent.java
@@ -78,8 +78,8 @@ public class ESLevent {
return eslJNI.ESLevent_setPriority(swigCPtr, this, SWIGTYPE_p_esl_priority_t.getCPtr(priority));
}
- public String getHeader(String header_name) {
- return eslJNI.ESLevent_getHeader(swigCPtr, this, header_name);
+ public String getHeader(String header_name, int idx) {
+ return eslJNI.ESLevent_getHeader(swigCPtr, this, header_name, idx);
}
public String getBody() {
@@ -98,6 +98,14 @@ public class ESLevent {
return eslJNI.ESLevent_addHeader(swigCPtr, this, header_name, value);
}
+ public boolean pushHeader(String header_name, String value) {
+ return eslJNI.ESLevent_pushHeader(swigCPtr, this, header_name, value);
+ }
+
+ public boolean unshiftHeader(String header_name, String value) {
+ return eslJNI.ESLevent_unshiftHeader(swigCPtr, this, header_name, value);
+ }
+
public boolean delHeader(String header_name) {
return eslJNI.ESLevent_delHeader(swigCPtr, this, header_name);
}
diff --git a/libs/esl/java/org/freeswitch/esl/eslJNI.java b/libs/esl/java/org/freeswitch/esl/eslJNI.java
index e6e576f0dc..dfdedff60f 100644
--- a/libs/esl/java/org/freeswitch/esl/eslJNI.java
+++ b/libs/esl/java/org/freeswitch/esl/eslJNI.java
@@ -21,11 +21,13 @@ class eslJNI {
public final static native void delete_ESLevent(long jarg1);
public final static native String ESLevent_serialize(long jarg1, ESLevent jarg1_, String jarg2);
public final static native boolean ESLevent_setPriority(long jarg1, ESLevent jarg1_, long jarg2);
- public final static native String ESLevent_getHeader(long jarg1, ESLevent jarg1_, String jarg2);
+ public final static native String ESLevent_getHeader(long jarg1, ESLevent jarg1_, String jarg2, int jarg3);
public final static native String ESLevent_getBody(long jarg1, ESLevent jarg1_);
public final static native String ESLevent_getType(long jarg1, ESLevent jarg1_);
public final static native boolean ESLevent_addBody(long jarg1, ESLevent jarg1_, String jarg2);
public final static native boolean ESLevent_addHeader(long jarg1, ESLevent jarg1_, String jarg2, String jarg3);
+ public final static native boolean ESLevent_pushHeader(long jarg1, ESLevent jarg1_, String jarg2, String jarg3);
+ public final static native boolean ESLevent_unshiftHeader(long jarg1, ESLevent jarg1_, String jarg2, String jarg3);
public final static native boolean ESLevent_delHeader(long jarg1, ESLevent jarg1_, String jarg2);
public final static native String ESLevent_firstHeader(long jarg1, ESLevent jarg1_);
public final static native String ESLevent_nextHeader(long jarg1, ESLevent jarg1_);
diff --git a/libs/esl/lua/esl_wrap.cpp b/libs/esl/lua/esl_wrap.cpp
index 25fceb7bea..c3ee30811e 100644
--- a/libs/esl/lua/esl_wrap.cpp
+++ b/libs/esl/lua/esl_wrap.cpp
@@ -1923,18 +1923,23 @@ static int _wrap_ESLevent_getHeader(lua_State* L) {
int SWIG_arg = -1;
ESLevent *arg1 = (ESLevent *) 0 ;
char *arg2 = (char *) 0 ;
+ int arg3 = (int) -1 ;
char *result = 0 ;
- SWIG_check_num_args("getHeader",2,2)
+ SWIG_check_num_args("getHeader",2,3)
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("getHeader",1,"ESLevent *");
if(!lua_isstring(L,2)) SWIG_fail_arg("getHeader",2,"char const *");
+ if(lua_gettop(L)>=3 && !lua_isnumber(L,3)) SWIG_fail_arg("getHeader",3,"int");
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_ESLevent,0))){
SWIG_fail_ptr("ESLevent_getHeader",1,SWIGTYPE_p_ESLevent);
}
arg2 = (char *)lua_tostring(L, 2);
- result = (char *)(arg1)->getHeader((char const *)arg2);
+ if(lua_gettop(L)>=3){
+ arg3 = (int)lua_tonumber(L, 3);
+ }
+ result = (char *)(arg1)->getHeader((char const *)arg2,arg3);
SWIG_arg=0;
lua_pushstring(L,(const char*)result); SWIG_arg++;
return SWIG_arg;
@@ -2056,6 +2061,68 @@ fail:
}
+static int _wrap_ESLevent_pushHeader(lua_State* L) {
+ int SWIG_arg = -1;
+ ESLevent *arg1 = (ESLevent *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) 0 ;
+ bool result;
+
+ SWIG_check_num_args("pushHeader",3,3)
+ if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("pushHeader",1,"ESLevent *");
+ if(!lua_isstring(L,2)) SWIG_fail_arg("pushHeader",2,"char const *");
+ if(!lua_isstring(L,3)) SWIG_fail_arg("pushHeader",3,"char const *");
+
+ if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_ESLevent,0))){
+ SWIG_fail_ptr("ESLevent_pushHeader",1,SWIGTYPE_p_ESLevent);
+ }
+
+ arg2 = (char *)lua_tostring(L, 2);
+ arg3 = (char *)lua_tostring(L, 3);
+ result = (bool)(arg1)->pushHeader((char const *)arg2,(char const *)arg3);
+ SWIG_arg=0;
+ lua_pushboolean(L,(int)(result==true)); SWIG_arg++;
+ return SWIG_arg;
+
+ if(0) SWIG_fail;
+
+fail:
+ lua_error(L);
+ return SWIG_arg;
+}
+
+
+static int _wrap_ESLevent_unshiftHeader(lua_State* L) {
+ int SWIG_arg = -1;
+ ESLevent *arg1 = (ESLevent *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) 0 ;
+ bool result;
+
+ SWIG_check_num_args("unshiftHeader",3,3)
+ if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("unshiftHeader",1,"ESLevent *");
+ if(!lua_isstring(L,2)) SWIG_fail_arg("unshiftHeader",2,"char const *");
+ if(!lua_isstring(L,3)) SWIG_fail_arg("unshiftHeader",3,"char const *");
+
+ if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_ESLevent,0))){
+ SWIG_fail_ptr("ESLevent_unshiftHeader",1,SWIGTYPE_p_ESLevent);
+ }
+
+ arg2 = (char *)lua_tostring(L, 2);
+ arg3 = (char *)lua_tostring(L, 3);
+ result = (bool)(arg1)->unshiftHeader((char const *)arg2,(char const *)arg3);
+ SWIG_arg=0;
+ lua_pushboolean(L,(int)(result==true)); SWIG_arg++;
+ return SWIG_arg;
+
+ if(0) SWIG_fail;
+
+fail:
+ lua_error(L);
+ return SWIG_arg;
+}
+
+
static int _wrap_ESLevent_delHeader(lua_State* L) {
int SWIG_arg = -1;
ESLevent *arg1 = (ESLevent *) 0 ;
@@ -2146,6 +2213,8 @@ static swig_lua_method swig_ESLevent_methods[] = {
{"getType", _wrap_ESLevent_getType},
{"addBody", _wrap_ESLevent_addBody},
{"addHeader", _wrap_ESLevent_addHeader},
+ {"pushHeader", _wrap_ESLevent_pushHeader},
+ {"unshiftHeader", _wrap_ESLevent_unshiftHeader},
{"delHeader", _wrap_ESLevent_delHeader},
{"firstHeader", _wrap_ESLevent_firstHeader},
{"nextHeader", _wrap_ESLevent_nextHeader},
diff --git a/libs/esl/managed/ESLPINVOKE.cs b/libs/esl/managed/ESLPINVOKE.cs
index 1e487895d9..ee15a2b702 100644
--- a/libs/esl/managed/ESLPINVOKE.cs
+++ b/libs/esl/managed/ESLPINVOKE.cs
@@ -221,7 +221,7 @@ class ESLPINVOKE {
public static extern bool ESLevent_SetPriority(HandleRef jarg1, HandleRef jarg2);
[DllImport("ESL", EntryPoint="CSharp_ESLevent_GetHeader")]
- public static extern string ESLevent_GetHeader(HandleRef jarg1, string jarg2);
+ public static extern string ESLevent_GetHeader(HandleRef jarg1, string jarg2, int jarg3);
[DllImport("ESL", EntryPoint="CSharp_ESLevent_GetBody")]
public static extern string ESLevent_GetBody(HandleRef jarg1);
@@ -235,6 +235,12 @@ class ESLPINVOKE {
[DllImport("ESL", EntryPoint="CSharp_ESLevent_AddHeader")]
public static extern bool ESLevent_AddHeader(HandleRef jarg1, string jarg2, string jarg3);
+ [DllImport("ESL", EntryPoint="CSharp_ESLevent_pushHeader")]
+ public static extern bool ESLevent_pushHeader(HandleRef jarg1, string jarg2, string jarg3);
+
+ [DllImport("ESL", EntryPoint="CSharp_ESLevent_unshiftHeader")]
+ public static extern bool ESLevent_unshiftHeader(HandleRef jarg1, string jarg2, string jarg3);
+
[DllImport("ESL", EntryPoint="CSharp_ESLevent_DelHeader")]
public static extern bool ESLevent_DelHeader(HandleRef jarg1, string jarg2);
diff --git a/libs/esl/managed/ESLevent.cs b/libs/esl/managed/ESLevent.cs
index ab4df67212..65cd24d98c 100644
--- a/libs/esl/managed/ESLevent.cs
+++ b/libs/esl/managed/ESLevent.cs
@@ -89,8 +89,8 @@ public class ESLevent : IDisposable {
return ret;
}
- public string GetHeader(string header_name) {
- string ret = ESLPINVOKE.ESLevent_GetHeader(swigCPtr, header_name);
+ public string GetHeader(string header_name, int idx) {
+ string ret = ESLPINVOKE.ESLevent_GetHeader(swigCPtr, header_name, idx);
return ret;
}
@@ -114,6 +114,16 @@ public class ESLevent : IDisposable {
return ret;
}
+ public bool pushHeader(string header_name, string value) {
+ bool ret = ESLPINVOKE.ESLevent_pushHeader(swigCPtr, header_name, value);
+ return ret;
+ }
+
+ public bool unshiftHeader(string header_name, string value) {
+ bool ret = ESLPINVOKE.ESLevent_unshiftHeader(swigCPtr, header_name, value);
+ return ret;
+ }
+
public bool DelHeader(string header_name) {
bool ret = ESLPINVOKE.ESLevent_DelHeader(swigCPtr, header_name);
return ret;
diff --git a/libs/esl/managed/esl_wrap.cpp b/libs/esl/managed/esl_wrap.cpp
index 4d0e27d261..f07b4b3d3f 100644
--- a/libs/esl/managed/esl_wrap.cpp
+++ b/libs/esl/managed/esl_wrap.cpp
@@ -436,15 +436,17 @@ SWIGEXPORT unsigned int SWIGSTDCALL CSharp_ESLevent_SetPriority(void * jarg1, vo
}
-SWIGEXPORT char * SWIGSTDCALL CSharp_ESLevent_GetHeader(void * jarg1, char * jarg2) {
+SWIGEXPORT char * SWIGSTDCALL CSharp_ESLevent_GetHeader(void * jarg1, char * jarg2, int jarg3) {
char * jresult ;
ESLevent *arg1 = (ESLevent *) 0 ;
char *arg2 = (char *) 0 ;
+ int arg3 = (int) -1 ;
char *result = 0 ;
arg1 = (ESLevent *)jarg1;
arg2 = (char *)jarg2;
- result = (char *)(arg1)->getHeader((char const *)arg2);
+ arg3 = (int)jarg3;
+ result = (char *)(arg1)->getHeader((char const *)arg2,arg3);
jresult = SWIG_csharp_string_callback((const char *)result);
return jresult;
}
@@ -504,6 +506,38 @@ SWIGEXPORT unsigned int SWIGSTDCALL CSharp_ESLevent_AddHeader(void * jarg1, char
}
+SWIGEXPORT unsigned int SWIGSTDCALL CSharp_ESLevent_pushHeader(void * jarg1, char * jarg2, char * jarg3) {
+ unsigned int jresult ;
+ ESLevent *arg1 = (ESLevent *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) 0 ;
+ bool result;
+
+ arg1 = (ESLevent *)jarg1;
+ arg2 = (char *)jarg2;
+ arg3 = (char *)jarg3;
+ result = (bool)(arg1)->pushHeader((char const *)arg2,(char const *)arg3);
+ jresult = result;
+ return jresult;
+}
+
+
+SWIGEXPORT unsigned int SWIGSTDCALL CSharp_ESLevent_unshiftHeader(void * jarg1, char * jarg2, char * jarg3) {
+ unsigned int jresult ;
+ ESLevent *arg1 = (ESLevent *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) 0 ;
+ bool result;
+
+ arg1 = (ESLevent *)jarg1;
+ arg2 = (char *)jarg2;
+ arg3 = (char *)jarg3;
+ result = (bool)(arg1)->unshiftHeader((char const *)arg2,(char const *)arg3);
+ jresult = result;
+ return jresult;
+}
+
+
SWIGEXPORT unsigned int SWIGSTDCALL CSharp_ESLevent_DelHeader(void * jarg1, char * jarg2) {
unsigned int jresult ;
ESLevent *arg1 = (ESLevent *) 0 ;
diff --git a/libs/esl/perl/ESL.pm b/libs/esl/perl/ESL.pm
index b50ee4a083..b291d002d7 100644
--- a/libs/esl/perl/ESL.pm
+++ b/libs/esl/perl/ESL.pm
@@ -88,6 +88,8 @@ sub DESTROY {
*getType = *ESLc::ESLevent_getType;
*addBody = *ESLc::ESLevent_addBody;
*addHeader = *ESLc::ESLevent_addHeader;
+*pushHeader = *ESLc::ESLevent_pushHeader;
+*unshiftHeader = *ESLc::ESLevent_unshiftHeader;
*delHeader = *ESLc::ESLevent_delHeader;
*firstHeader = *ESLc::ESLevent_firstHeader;
*nextHeader = *ESLc::ESLevent_nextHeader;
diff --git a/libs/esl/perl/esl_wrap.cpp b/libs/esl/perl/esl_wrap.cpp
index ccce4bb6d0..1bc45fa2e1 100644
--- a/libs/esl/perl/esl_wrap.cpp
+++ b/libs/esl/perl/esl_wrap.cpp
@@ -2285,17 +2285,20 @@ XS(_wrap_ESLevent_getHeader) {
{
ESLevent *arg1 = (ESLevent *) 0 ;
char *arg2 = (char *) 0 ;
+ int arg3 = (int) -1 ;
char *result = 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
int res2 ;
char *buf2 = 0 ;
int alloc2 = 0 ;
+ int val3 ;
+ int ecode3 = 0 ;
int argvi = 0;
dXSARGS;
- if ((items < 2) || (items > 2)) {
- SWIG_croak("Usage: ESLevent_getHeader(self,header_name);");
+ if ((items < 2) || (items > 3)) {
+ SWIG_croak("Usage: ESLevent_getHeader(self,header_name,idx);");
}
res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_ESLevent, 0 | 0 );
if (!SWIG_IsOK(res1)) {
@@ -2307,14 +2310,23 @@ XS(_wrap_ESLevent_getHeader) {
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ESLevent_getHeader" "', argument " "2"" of type '" "char const *""'");
}
arg2 = reinterpret_cast< char * >(buf2);
- result = (char *)(arg1)->getHeader((char const *)arg2);
+ if (items > 2) {
+ ecode3 = SWIG_AsVal_int SWIG_PERL_CALL_ARGS_2(ST(2), &val3);
+ if (!SWIG_IsOK(ecode3)) {
+ SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "ESLevent_getHeader" "', argument " "3"" of type '" "int""'");
+ }
+ arg3 = static_cast< int >(val3);
+ }
+ result = (char *)(arg1)->getHeader((char const *)arg2,arg3);
ST(argvi) = SWIG_FromCharPtr((const char *)result); argvi++ ;
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+
XSRETURN(argvi);
fail:
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+
SWIG_croak_null();
}
}
@@ -2465,6 +2477,106 @@ XS(_wrap_ESLevent_addHeader) {
}
+XS(_wrap_ESLevent_pushHeader) {
+ {
+ ESLevent *arg1 = (ESLevent *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) 0 ;
+ bool result;
+ void *argp1 = 0 ;
+ int res1 = 0 ;
+ int res2 ;
+ char *buf2 = 0 ;
+ int alloc2 = 0 ;
+ int res3 ;
+ char *buf3 = 0 ;
+ int alloc3 = 0 ;
+ int argvi = 0;
+ dXSARGS;
+
+ if ((items < 3) || (items > 3)) {
+ SWIG_croak("Usage: ESLevent_pushHeader(self,header_name,value);");
+ }
+ res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_ESLevent, 0 | 0 );
+ if (!SWIG_IsOK(res1)) {
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ESLevent_pushHeader" "', argument " "1"" of type '" "ESLevent *""'");
+ }
+ arg1 = reinterpret_cast< ESLevent * >(argp1);
+ res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
+ if (!SWIG_IsOK(res2)) {
+ SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ESLevent_pushHeader" "', argument " "2"" of type '" "char const *""'");
+ }
+ arg2 = reinterpret_cast< char * >(buf2);
+ res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
+ if (!SWIG_IsOK(res3)) {
+ SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "ESLevent_pushHeader" "', argument " "3"" of type '" "char const *""'");
+ }
+ arg3 = reinterpret_cast< char * >(buf3);
+ result = (bool)(arg1)->pushHeader((char const *)arg2,(char const *)arg3);
+ ST(argvi) = SWIG_From_bool SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
+
+ if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+ if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+ XSRETURN(argvi);
+ fail:
+
+ if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+ if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+ SWIG_croak_null();
+ }
+}
+
+
+XS(_wrap_ESLevent_unshiftHeader) {
+ {
+ ESLevent *arg1 = (ESLevent *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) 0 ;
+ bool result;
+ void *argp1 = 0 ;
+ int res1 = 0 ;
+ int res2 ;
+ char *buf2 = 0 ;
+ int alloc2 = 0 ;
+ int res3 ;
+ char *buf3 = 0 ;
+ int alloc3 = 0 ;
+ int argvi = 0;
+ dXSARGS;
+
+ if ((items < 3) || (items > 3)) {
+ SWIG_croak("Usage: ESLevent_unshiftHeader(self,header_name,value);");
+ }
+ res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_ESLevent, 0 | 0 );
+ if (!SWIG_IsOK(res1)) {
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ESLevent_unshiftHeader" "', argument " "1"" of type '" "ESLevent *""'");
+ }
+ arg1 = reinterpret_cast< ESLevent * >(argp1);
+ res2 = SWIG_AsCharPtrAndSize(ST(1), &buf2, NULL, &alloc2);
+ if (!SWIG_IsOK(res2)) {
+ SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ESLevent_unshiftHeader" "', argument " "2"" of type '" "char const *""'");
+ }
+ arg2 = reinterpret_cast< char * >(buf2);
+ res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
+ if (!SWIG_IsOK(res3)) {
+ SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "ESLevent_unshiftHeader" "', argument " "3"" of type '" "char const *""'");
+ }
+ arg3 = reinterpret_cast< char * >(buf3);
+ result = (bool)(arg1)->unshiftHeader((char const *)arg2,(char const *)arg3);
+ ST(argvi) = SWIG_From_bool SWIG_PERL_CALL_ARGS_1(static_cast< bool >(result)); argvi++ ;
+
+ if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+ if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+ XSRETURN(argvi);
+ fail:
+
+ if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+ if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+ SWIG_croak_null();
+ }
+}
+
+
XS(_wrap_ESLevent_delHeader) {
{
ESLevent *arg1 = (ESLevent *) 0 ;
@@ -3658,6 +3770,8 @@ static swig_command_info swig_commands[] = {
{"ESLc::ESLevent_getType", _wrap_ESLevent_getType},
{"ESLc::ESLevent_addBody", _wrap_ESLevent_addBody},
{"ESLc::ESLevent_addHeader", _wrap_ESLevent_addHeader},
+{"ESLc::ESLevent_pushHeader", _wrap_ESLevent_pushHeader},
+{"ESLc::ESLevent_unshiftHeader", _wrap_ESLevent_unshiftHeader},
{"ESLc::ESLevent_delHeader", _wrap_ESLevent_delHeader},
{"ESLc::ESLevent_firstHeader", _wrap_ESLevent_firstHeader},
{"ESLc::ESLevent_nextHeader", _wrap_ESLevent_nextHeader},
diff --git a/libs/esl/php/ESL.php b/libs/esl/php/ESL.php
index 70ff62ac0d..0bc8c4e724 100644
--- a/libs/esl/php/ESL.php
+++ b/libs/esl/php/ESL.php
@@ -76,8 +76,8 @@ class ESLevent {
return $r;
}
- function getHeader($header_name) {
- return ESLevent_getHeader($this->_cPtr,$header_name);
+ function getHeader($header_name,$idx=-1) {
+ return ESLevent_getHeader($this->_cPtr,$header_name,$idx);
}
function getBody() {
@@ -96,6 +96,14 @@ class ESLevent {
return ESLevent_addHeader($this->_cPtr,$header_name,$value);
}
+ function pushHeader($header_name,$value) {
+ return ESLevent_pushHeader($this->_cPtr,$header_name,$value);
+ }
+
+ function unshiftHeader($header_name,$value) {
+ return ESLevent_unshiftHeader($this->_cPtr,$header_name,$value);
+ }
+
function delHeader($header_name) {
return ESLevent_delHeader($this->_cPtr,$header_name);
}
diff --git a/libs/esl/php/esl_wrap.cpp b/libs/esl/php/esl_wrap.cpp
index c38ea1fa62..9e49c7c080 100644
--- a/libs/esl/php/esl_wrap.cpp
+++ b/libs/esl/php/esl_wrap.cpp
@@ -1445,13 +1445,16 @@ fail:
ZEND_NAMED_FUNCTION(_wrap_ESLevent_getHeader) {
ESLevent *arg1 = (ESLevent *) 0 ;
char *arg2 = (char *) 0 ;
+ int arg3 = (int) -1 ;
char *result = 0 ;
- zval **args[2];
+ zval **args[3];
+ int arg_count;
SWIG_ResetError();
- if(ZEND_NUM_ARGS() != 2 || zend_get_parameters_array_ex(2, args) != SUCCESS) {
- WRONG_PARAM_COUNT;
- }
+ arg_count = ZEND_NUM_ARGS();
+ if(arg_count<2 || arg_count>3 ||
+ zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)
+ WRONG_PARAM_COUNT;
{
if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_ESLevent, 0) < 0) {
@@ -1465,7 +1468,14 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_getHeader) {
arg2 = (char *) Z_STRVAL_PP(args[1]);
/*@SWIG@*/;
- result = (char *)(arg1)->getHeader((char const *)arg2);
+ if(arg_count > 2) {
+ /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/
+ convert_to_long_ex(args[2]);
+ arg3 = (int) Z_LVAL_PP(args[2]);
+ /*@SWIG@*/;
+
+ }
+ result = (char *)(arg1)->getHeader((char const *)arg2,arg3);
{
if(!result) {
ZVAL_NULL(return_value);
@@ -1612,6 +1622,86 @@ fail:
}
+ZEND_NAMED_FUNCTION(_wrap_ESLevent_pushHeader) {
+ ESLevent *arg1 = (ESLevent *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) 0 ;
+ bool result;
+ zval **args[3];
+
+ SWIG_ResetError();
+ if(ZEND_NUM_ARGS() != 3 || zend_get_parameters_array_ex(3, args) != SUCCESS) {
+ WRONG_PARAM_COUNT;
+ }
+
+ {
+ if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_ESLevent, 0) < 0) {
+ SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of ESLevent_pushHeader. Expected SWIGTYPE_p_ESLevent");
+ }
+ }
+ if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+
+ /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/
+ convert_to_string_ex(args[1]);
+ arg2 = (char *) Z_STRVAL_PP(args[1]);
+ /*@SWIG@*/;
+
+
+ /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/
+ convert_to_string_ex(args[2]);
+ arg3 = (char *) Z_STRVAL_PP(args[2]);
+ /*@SWIG@*/;
+
+ result = (bool)(arg1)->pushHeader((char const *)arg2,(char const *)arg3);
+ {
+ ZVAL_BOOL(return_value,(result)?1:0);
+ }
+ return;
+fail:
+ zend_error(SWIG_ErrorCode(),SWIG_ErrorMsg());
+}
+
+
+ZEND_NAMED_FUNCTION(_wrap_ESLevent_unshiftHeader) {
+ ESLevent *arg1 = (ESLevent *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) 0 ;
+ bool result;
+ zval **args[3];
+
+ SWIG_ResetError();
+ if(ZEND_NUM_ARGS() != 3 || zend_get_parameters_array_ex(3, args) != SUCCESS) {
+ WRONG_PARAM_COUNT;
+ }
+
+ {
+ if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_ESLevent, 0) < 0) {
+ SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of ESLevent_unshiftHeader. Expected SWIGTYPE_p_ESLevent");
+ }
+ }
+ if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
+
+ /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/
+ convert_to_string_ex(args[1]);
+ arg2 = (char *) Z_STRVAL_PP(args[1]);
+ /*@SWIG@*/;
+
+
+ /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/
+ convert_to_string_ex(args[2]);
+ arg3 = (char *) Z_STRVAL_PP(args[2]);
+ /*@SWIG@*/;
+
+ result = (bool)(arg1)->unshiftHeader((char const *)arg2,(char const *)arg3);
+ {
+ ZVAL_BOOL(return_value,(result)?1:0);
+ }
+ return;
+fail:
+ zend_error(SWIG_ErrorCode(),SWIG_ErrorMsg());
+}
+
+
ZEND_NAMED_FUNCTION(_wrap_ESLevent_delHeader) {
ESLevent *arg1 = (ESLevent *) 0 ;
char *arg2 = (char *) 0 ;
@@ -2547,6 +2637,8 @@ static zend_function_entry ESL_functions[] = {
SWIG_ZEND_NAMED_FE(eslevent_gettype,_wrap_ESLevent_getType,NULL)
SWIG_ZEND_NAMED_FE(eslevent_addbody,_wrap_ESLevent_addBody,NULL)
SWIG_ZEND_NAMED_FE(eslevent_addheader,_wrap_ESLevent_addHeader,NULL)
+ SWIG_ZEND_NAMED_FE(eslevent_pushheader,_wrap_ESLevent_pushHeader,NULL)
+ SWIG_ZEND_NAMED_FE(eslevent_unshiftheader,_wrap_ESLevent_unshiftHeader,NULL)
SWIG_ZEND_NAMED_FE(eslevent_delheader,_wrap_ESLevent_delHeader,NULL)
SWIG_ZEND_NAMED_FE(eslevent_firstheader,_wrap_ESLevent_firstHeader,NULL)
SWIG_ZEND_NAMED_FE(eslevent_nextheader,_wrap_ESLevent_nextHeader,NULL)
diff --git a/libs/esl/php/php_ESL.h b/libs/esl/php/php_ESL.h
index 8c9dede981..eceac5dd70 100644
--- a/libs/esl/php/php_ESL.h
+++ b/libs/esl/php/php_ESL.h
@@ -46,6 +46,8 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_getBody);
ZEND_NAMED_FUNCTION(_wrap_ESLevent_getType);
ZEND_NAMED_FUNCTION(_wrap_ESLevent_addBody);
ZEND_NAMED_FUNCTION(_wrap_ESLevent_addHeader);
+ZEND_NAMED_FUNCTION(_wrap_ESLevent_pushHeader);
+ZEND_NAMED_FUNCTION(_wrap_ESLevent_unshiftHeader);
ZEND_NAMED_FUNCTION(_wrap_ESLevent_delHeader);
ZEND_NAMED_FUNCTION(_wrap_ESLevent_firstHeader);
ZEND_NAMED_FUNCTION(_wrap_ESLevent_nextHeader);
diff --git a/libs/esl/python/ESL.py b/libs/esl/python/ESL.py
index 8e52ea303f..6bb4216692 100644
--- a/libs/esl/python/ESL.py
+++ b/libs/esl/python/ESL.py
@@ -59,6 +59,8 @@ class ESLevent:
def getType(*args): return apply(_ESL.ESLevent_getType, args)
def addBody(*args): return apply(_ESL.ESLevent_addBody, args)
def addHeader(*args): return apply(_ESL.ESLevent_addHeader, args)
+ def pushHeader(*args): return apply(_ESL.ESLevent_pushHeader, args)
+ def unshiftHeader(*args): return apply(_ESL.ESLevent_unshiftHeader, args)
def delHeader(*args): return apply(_ESL.ESLevent_delHeader, args)
def firstHeader(*args): return apply(_ESL.ESLevent_firstHeader, args)
def nextHeader(*args): return apply(_ESL.ESLevent_nextHeader, args)
diff --git a/libs/esl/python/esl_wrap.cpp b/libs/esl/python/esl_wrap.cpp
index 3ef587561c..90f6ed2c79 100644
--- a/libs/esl/python/esl_wrap.cpp
+++ b/libs/esl/python/esl_wrap.cpp
@@ -3373,17 +3373,21 @@ SWIGINTERN PyObject *_wrap_ESLevent_getHeader(PyObject *SWIGUNUSEDPARM(self), Py
PyObject *resultobj = 0;
ESLevent *arg1 = (ESLevent *) 0 ;
char *arg2 = (char *) 0 ;
+ int arg3 = (int) -1 ;
char *result = 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
int res2 ;
char *buf2 = 0 ;
int alloc2 = 0 ;
+ int val3 ;
+ int ecode3 = 0 ;
PyObject * obj0 = 0 ;
PyObject * obj1 = 0 ;
+ PyObject * obj2 = 0 ;
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
- if (!PyArg_ParseTuple(args,(char *)"OO:ESLevent_getHeader",&obj0,&obj1)) SWIG_fail;
+ if (!PyArg_ParseTuple(args,(char *)"OO|O:ESLevent_getHeader",&obj0,&obj1,&obj2)) SWIG_fail;
res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ESLevent, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ESLevent_getHeader" "', argument " "1"" of type '" "ESLevent *""'");
@@ -3394,9 +3398,16 @@ SWIGINTERN PyObject *_wrap_ESLevent_getHeader(PyObject *SWIGUNUSEDPARM(self), Py
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ESLevent_getHeader" "', argument " "2"" of type '" "char const *""'");
}
arg2 = reinterpret_cast< char * >(buf2);
+ if (obj2) {
+ ecode3 = SWIG_AsVal_int(obj2, &val3);
+ if (!SWIG_IsOK(ecode3)) {
+ SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "ESLevent_getHeader" "', argument " "3"" of type '" "int""'");
+ }
+ arg3 = static_cast< int >(val3);
+ }
{
SWIG_PYTHON_THREAD_BEGIN_ALLOW;
- result = (char *)(arg1)->getHeader((char const *)arg2);
+ result = (char *)(arg1)->getHeader((char const *)arg2,arg3);
SWIG_PYTHON_THREAD_END_ALLOW;
}
resultobj = SWIG_FromCharPtr((const char *)result);
@@ -3562,6 +3573,112 @@ fail:
}
+SWIGINTERN PyObject *_wrap_ESLevent_pushHeader(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+ PyObject *resultobj = 0;
+ ESLevent *arg1 = (ESLevent *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) 0 ;
+ bool result;
+ void *argp1 = 0 ;
+ int res1 = 0 ;
+ int res2 ;
+ char *buf2 = 0 ;
+ int alloc2 = 0 ;
+ int res3 ;
+ char *buf3 = 0 ;
+ int alloc3 = 0 ;
+ PyObject * obj0 = 0 ;
+ PyObject * obj1 = 0 ;
+ PyObject * obj2 = 0 ;
+
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ if (!PyArg_ParseTuple(args,(char *)"OOO:ESLevent_pushHeader",&obj0,&obj1,&obj2)) SWIG_fail;
+ res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ESLevent, 0 | 0 );
+ if (!SWIG_IsOK(res1)) {
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ESLevent_pushHeader" "', argument " "1"" of type '" "ESLevent *""'");
+ }
+ arg1 = reinterpret_cast< ESLevent * >(argp1);
+ res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+ if (!SWIG_IsOK(res2)) {
+ SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ESLevent_pushHeader" "', argument " "2"" of type '" "char const *""'");
+ }
+ arg2 = reinterpret_cast< char * >(buf2);
+ res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
+ if (!SWIG_IsOK(res3)) {
+ SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "ESLevent_pushHeader" "', argument " "3"" of type '" "char const *""'");
+ }
+ arg3 = reinterpret_cast< char * >(buf3);
+ {
+ SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+ result = (bool)(arg1)->pushHeader((char const *)arg2,(char const *)arg3);
+ SWIG_PYTHON_THREAD_END_ALLOW;
+ }
+ resultobj = SWIG_From_bool(static_cast< bool >(result));
+ if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+ if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return resultobj;
+fail:
+ if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+ if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_ESLevent_unshiftHeader(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+ PyObject *resultobj = 0;
+ ESLevent *arg1 = (ESLevent *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) 0 ;
+ bool result;
+ void *argp1 = 0 ;
+ int res1 = 0 ;
+ int res2 ;
+ char *buf2 = 0 ;
+ int alloc2 = 0 ;
+ int res3 ;
+ char *buf3 = 0 ;
+ int alloc3 = 0 ;
+ PyObject * obj0 = 0 ;
+ PyObject * obj1 = 0 ;
+ PyObject * obj2 = 0 ;
+
+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
+ if (!PyArg_ParseTuple(args,(char *)"OOO:ESLevent_unshiftHeader",&obj0,&obj1,&obj2)) SWIG_fail;
+ res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ESLevent, 0 | 0 );
+ if (!SWIG_IsOK(res1)) {
+ SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ESLevent_unshiftHeader" "', argument " "1"" of type '" "ESLevent *""'");
+ }
+ arg1 = reinterpret_cast< ESLevent * >(argp1);
+ res2 = SWIG_AsCharPtrAndSize(obj1, &buf2, NULL, &alloc2);
+ if (!SWIG_IsOK(res2)) {
+ SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ESLevent_unshiftHeader" "', argument " "2"" of type '" "char const *""'");
+ }
+ arg2 = reinterpret_cast< char * >(buf2);
+ res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
+ if (!SWIG_IsOK(res3)) {
+ SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "ESLevent_unshiftHeader" "', argument " "3"" of type '" "char const *""'");
+ }
+ arg3 = reinterpret_cast< char * >(buf3);
+ {
+ SWIG_PYTHON_THREAD_BEGIN_ALLOW;
+ result = (bool)(arg1)->unshiftHeader((char const *)arg2,(char const *)arg3);
+ SWIG_PYTHON_THREAD_END_ALLOW;
+ }
+ resultobj = SWIG_From_bool(static_cast< bool >(result));
+ if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+ if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return resultobj;
+fail:
+ if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+ if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+ SWIG_PYTHON_THREAD_END_BLOCK;
+ return NULL;
+}
+
+
SWIGINTERN PyObject *_wrap_ESLevent_delHeader(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *resultobj = 0;
ESLevent *arg1 = (ESLevent *) 0 ;
@@ -4726,6 +4843,8 @@ static PyMethodDef SwigMethods[] = {
{ (char *)"ESLevent_getType", _wrap_ESLevent_getType, METH_VARARGS, NULL},
{ (char *)"ESLevent_addBody", _wrap_ESLevent_addBody, METH_VARARGS, NULL},
{ (char *)"ESLevent_addHeader", _wrap_ESLevent_addHeader, METH_VARARGS, NULL},
+ { (char *)"ESLevent_pushHeader", _wrap_ESLevent_pushHeader, METH_VARARGS, NULL},
+ { (char *)"ESLevent_unshiftHeader", _wrap_ESLevent_unshiftHeader, METH_VARARGS, NULL},
{ (char *)"ESLevent_delHeader", _wrap_ESLevent_delHeader, METH_VARARGS, NULL},
{ (char *)"ESLevent_firstHeader", _wrap_ESLevent_firstHeader, METH_VARARGS, NULL},
{ (char *)"ESLevent_nextHeader", _wrap_ESLevent_nextHeader, METH_VARARGS, NULL},
diff --git a/libs/esl/ruby/esl_wrap.cpp b/libs/esl/ruby/esl_wrap.cpp
index 3769b5bc24..5afce64cf9 100644
--- a/libs/esl/ruby/esl_wrap.cpp
+++ b/libs/esl/ruby/esl_wrap.cpp
@@ -2396,15 +2396,18 @@ SWIGINTERN VALUE
_wrap_ESLevent_getHeader(int argc, VALUE *argv, VALUE self) {
ESLevent *arg1 = (ESLevent *) 0 ;
char *arg2 = (char *) 0 ;
+ int arg3 = (int) -1 ;
char *result = 0 ;
void *argp1 = 0 ;
int res1 = 0 ;
int res2 ;
char *buf2 = 0 ;
int alloc2 = 0 ;
+ int val3 ;
+ int ecode3 = 0 ;
VALUE vresult = Qnil;
- if ((argc < 1) || (argc > 1)) {
+ if ((argc < 1) || (argc > 2)) {
rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)",argc); SWIG_fail;
}
res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_ESLevent, 0 | 0 );
@@ -2417,7 +2420,14 @@ _wrap_ESLevent_getHeader(int argc, VALUE *argv, VALUE self) {
SWIG_exception_fail(SWIG_ArgError(res2), Ruby_Format_TypeError( "", "char const *","getHeader", 2, argv[0] ));
}
arg2 = reinterpret_cast< char * >(buf2);
- result = (char *)(arg1)->getHeader((char const *)arg2);
+ if (argc > 1) {
+ ecode3 = SWIG_AsVal_int(argv[1], &val3);
+ if (!SWIG_IsOK(ecode3)) {
+ SWIG_exception_fail(SWIG_ArgError(ecode3), Ruby_Format_TypeError( "", "int","getHeader", 3, argv[1] ));
+ }
+ arg3 = static_cast< int >(val3);
+ }
+ result = (char *)(arg1)->getHeader((char const *)arg2,arg3);
vresult = SWIG_FromCharPtr((const char *)result);
if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
return vresult;
@@ -2556,6 +2566,98 @@ fail:
}
+SWIGINTERN VALUE
+_wrap_ESLevent_pushHeader(int argc, VALUE *argv, VALUE self) {
+ ESLevent *arg1 = (ESLevent *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) 0 ;
+ bool result;
+ void *argp1 = 0 ;
+ int res1 = 0 ;
+ int res2 ;
+ char *buf2 = 0 ;
+ int alloc2 = 0 ;
+ int res3 ;
+ char *buf3 = 0 ;
+ int alloc3 = 0 ;
+ VALUE vresult = Qnil;
+
+ if ((argc < 2) || (argc > 2)) {
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 2)",argc); SWIG_fail;
+ }
+ res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_ESLevent, 0 | 0 );
+ if (!SWIG_IsOK(res1)) {
+ SWIG_exception_fail(SWIG_ArgError(res1), Ruby_Format_TypeError( "", "ESLevent *","pushHeader", 1, self ));
+ }
+ arg1 = reinterpret_cast< ESLevent * >(argp1);
+ res2 = SWIG_AsCharPtrAndSize(argv[0], &buf2, NULL, &alloc2);
+ if (!SWIG_IsOK(res2)) {
+ SWIG_exception_fail(SWIG_ArgError(res2), Ruby_Format_TypeError( "", "char const *","pushHeader", 2, argv[0] ));
+ }
+ arg2 = reinterpret_cast< char * >(buf2);
+ res3 = SWIG_AsCharPtrAndSize(argv[1], &buf3, NULL, &alloc3);
+ if (!SWIG_IsOK(res3)) {
+ SWIG_exception_fail(SWIG_ArgError(res3), Ruby_Format_TypeError( "", "char const *","pushHeader", 3, argv[1] ));
+ }
+ arg3 = reinterpret_cast< char * >(buf3);
+ result = (bool)(arg1)->pushHeader((char const *)arg2,(char const *)arg3);
+ vresult = SWIG_From_bool(static_cast< bool >(result));
+ if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+ if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+ return vresult;
+fail:
+ if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+ if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+ return Qnil;
+}
+
+
+SWIGINTERN VALUE
+_wrap_ESLevent_unshiftHeader(int argc, VALUE *argv, VALUE self) {
+ ESLevent *arg1 = (ESLevent *) 0 ;
+ char *arg2 = (char *) 0 ;
+ char *arg3 = (char *) 0 ;
+ bool result;
+ void *argp1 = 0 ;
+ int res1 = 0 ;
+ int res2 ;
+ char *buf2 = 0 ;
+ int alloc2 = 0 ;
+ int res3 ;
+ char *buf3 = 0 ;
+ int alloc3 = 0 ;
+ VALUE vresult = Qnil;
+
+ if ((argc < 2) || (argc > 2)) {
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 2)",argc); SWIG_fail;
+ }
+ res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_ESLevent, 0 | 0 );
+ if (!SWIG_IsOK(res1)) {
+ SWIG_exception_fail(SWIG_ArgError(res1), Ruby_Format_TypeError( "", "ESLevent *","unshiftHeader", 1, self ));
+ }
+ arg1 = reinterpret_cast< ESLevent * >(argp1);
+ res2 = SWIG_AsCharPtrAndSize(argv[0], &buf2, NULL, &alloc2);
+ if (!SWIG_IsOK(res2)) {
+ SWIG_exception_fail(SWIG_ArgError(res2), Ruby_Format_TypeError( "", "char const *","unshiftHeader", 2, argv[0] ));
+ }
+ arg2 = reinterpret_cast< char * >(buf2);
+ res3 = SWIG_AsCharPtrAndSize(argv[1], &buf3, NULL, &alloc3);
+ if (!SWIG_IsOK(res3)) {
+ SWIG_exception_fail(SWIG_ArgError(res3), Ruby_Format_TypeError( "", "char const *","unshiftHeader", 3, argv[1] ));
+ }
+ arg3 = reinterpret_cast< char * >(buf3);
+ result = (bool)(arg1)->unshiftHeader((char const *)arg2,(char const *)arg3);
+ vresult = SWIG_From_bool(static_cast< bool >(result));
+ if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+ if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+ return vresult;
+fail:
+ if (alloc2 == SWIG_NEWOBJ) delete[] buf2;
+ if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
+ return Qnil;
+}
+
+
SWIGINTERN VALUE
_wrap_ESLevent_delHeader(int argc, VALUE *argv, VALUE self) {
ESLevent *arg1 = (ESLevent *) 0 ;
@@ -3835,6 +3937,8 @@ SWIGEXPORT void Init_ESL(void) {
rb_define_method(cESLevent.klass, "getType", VALUEFUNC(_wrap_ESLevent_getType), -1);
rb_define_method(cESLevent.klass, "addBody", VALUEFUNC(_wrap_ESLevent_addBody), -1);
rb_define_method(cESLevent.klass, "addHeader", VALUEFUNC(_wrap_ESLevent_addHeader), -1);
+ rb_define_method(cESLevent.klass, "pushHeader", VALUEFUNC(_wrap_ESLevent_pushHeader), -1);
+ rb_define_method(cESLevent.klass, "unshiftHeader", VALUEFUNC(_wrap_ESLevent_unshiftHeader), -1);
rb_define_method(cESLevent.klass, "delHeader", VALUEFUNC(_wrap_ESLevent_delHeader), -1);
rb_define_method(cESLevent.klass, "firstHeader", VALUEFUNC(_wrap_ESLevent_firstHeader), -1);
rb_define_method(cESLevent.klass, "nextHeader", VALUEFUNC(_wrap_ESLevent_nextHeader), -1);
diff --git a/libs/esl/src/esl.c b/libs/esl/src/esl.c
index bfdf58a625..ef8d7c1cb1 100644
--- a/libs/esl/src/esl.c
+++ b/libs/esl/src/esl.c
@@ -1088,7 +1088,11 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
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);
+ if (!strncmp(hval, "ARRAY::", 7)) {
+ esl_event_add_array(revent, hname, hval);
+ } else {
+ esl_event_add_header_string(revent, ESL_STACK_BOTTOM, hname, hval);
+ }
}
p = e;
@@ -1217,7 +1221,12 @@ ESL_DECLARE(esl_status_t) esl_recv_event(esl_handle_t *handle, int check_q, esl_
esl_event_del_header(handle->last_ievent, "event-name");
esl_name_event(hval, &handle->last_ievent->event_id);
}
- esl_event_add_header_string(handle->last_ievent, ESL_STACK_BOTTOM, hname, hval);
+
+ if (!strncmp(hval, "ARRAY::", 7)) {
+ esl_event_add_array(handle->last_ievent, hname, hval);
+ } else {
+ esl_event_add_header_string(handle->last_ievent, ESL_STACK_BOTTOM, hname, hval);
+ }
}
beg = c + 1;
@@ -1371,5 +1380,23 @@ ESL_DECLARE(esl_status_t) esl_send_recv_timed(esl_handle_t *handle, const char *
}
+ESL_DECLARE(unsigned int) esl_separate_string_string(char *buf, const char *delim, char **array, unsigned int arraylen)
+{
+ unsigned int count = 0;
+ char *d;
+ size_t dlen = strlen(delim);
+ array[count++] = buf;
+
+ while (count < arraylen && array[count - 1]) {
+ if ((d = strstr(array[count - 1], delim))) {
+ *d = '\0';
+ d += dlen;
+ array[count++] = d;
+ } else
+ break;
+ }
+
+ return count;
+}
diff --git a/libs/esl/src/esl_event.c b/libs/esl/src/esl_event.c
index 9bd78a838d..7aa12a8cd6 100644
--- a/libs/esl/src/esl_event.c
+++ b/libs/esl/src/esl_event.c
@@ -235,8 +235,7 @@ static unsigned int esl_ci_hashfunc_default(const char *char_key, esl_ssize_t *k
return hash;
}
-
-ESL_DECLARE(char *)esl_event_get_header(esl_event_t *event, const char *header_name)
+ESL_DECLARE(esl_event_header_t *) esl_event_get_header_ptr(esl_event_t *event, const char *header_name)
{
esl_event_header_t *hp;
esl_ssize_t hlen = -1;
@@ -244,18 +243,39 @@ ESL_DECLARE(char *)esl_event_get_header(esl_event_t *event, const char *header_n
esl_assert(event);
- if (!header_name) return NULL;
-
+ if (!header_name)
+ return NULL;
+
hash = esl_ci_hashfunc_default(header_name, &hlen);
-
+
for (hp = event->headers; hp; hp = hp->next) {
- if ((!hp->hash || hash == hp->hash) && !strcasecmp(hp->name, header_name) ) {
- return hp->value;
+ if ((!hp->hash || hash == hp->hash) && !strcasecmp(hp->name, header_name)) {
+ return hp;
}
}
return NULL;
}
+ESL_DECLARE(char *) esl_event_get_header_idx(esl_event_t *event, const char *header_name, int idx)
+{
+ esl_event_header_t *hp;
+
+ if ((hp = esl_event_get_header_ptr(event, header_name))) {
+ if (idx > -1) {
+ if (idx < hp->idx) {
+ return hp->array[idx];
+ } else {
+ return NULL;
+ }
+ }
+
+ return hp->value;
+
+ }
+
+ return NULL;
+}
+
ESL_DECLARE(char *)esl_event_get_body(esl_event_t *event)
{
return (event ? event->body : NULL);
@@ -264,7 +284,7 @@ ESL_DECLARE(char *)esl_event_get_body(esl_event_t *event)
ESL_DECLARE(esl_status_t) esl_event_del_header_val(esl_event_t *event, const char *header_name, const char *val)
{
esl_event_header_t *hp, *lp = NULL, *tp;
- esl_status_t status = ESL_FAIL;
+ esl_status_t status = ESL_FALSE;
int x = 0;
esl_ssize_t hlen = -1;
unsigned long hash = 0;
@@ -273,12 +293,12 @@ ESL_DECLARE(esl_status_t) esl_event_del_header_val(esl_event_t *event, const cha
while (tp) {
hp = tp;
tp = tp->next;
-
+
x++;
- esl_assert(x < 1000);
+ esl_assert(x < 1000000);
hash = esl_ci_hashfunc_default(header_name, &hlen);
- if (hp->name && (!hp->hash || hash == hp->hash) && !strcasecmp(header_name, hp->name) && (esl_strlen_zero(val) || !strcmp(hp->value, val))) {
+ if ((!hp->hash || hash == hp->hash) && (hp->name && !strcasecmp(header_name, hp->name)) && (esl_strlen_zero(val) || !strcmp(hp->value, val))) {
if (lp) {
lp->next = hp->next;
} else {
@@ -288,10 +308,27 @@ ESL_DECLARE(esl_status_t) esl_event_del_header_val(esl_event_t *event, const cha
event->last_header = lp;
}
FREE(hp->name);
- FREE(hp->value);
- memset(hp, 0, sizeof(*hp));
- FREE(hp);
+ if (hp->idx) {
+ int i = 0;
+ hp->value = NULL;
+
+ for (i = 0; i < hp->idx; i++) {
+ FREE(hp->array[i]);
+ }
+ FREE(hp->array);
+ }
+
+ FREE(hp->value);
+
+ memset(hp, 0, sizeof(*hp));
+#ifdef ESL_EVENT_RECYCLE
+ if (esl_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, hp) != ESL_SUCCESS) {
+ FREE(hp);
+ }
+#else
+ FREE(hp);
+#endif
status = ESL_SUCCESS;
} else {
lp = hp;
@@ -301,40 +338,245 @@ ESL_DECLARE(esl_status_t) esl_event_del_header_val(esl_event_t *event, const cha
return status;
}
-static esl_status_t esl_event_base_add_header(esl_event_t *event, esl_stack_t stack, const char *header_name, char *data)
+static esl_event_header_t *new_header(const char *header_name)
{
esl_event_header_t *header;
- esl_ssize_t hlen = -1;
-
- header = ALLOC(sizeof(*header));
- esl_assert(header);
- if ((event->flags & ESL_UNIQ_HEADERS)) {
- esl_event_del_header(event, header_name);
+#ifdef ESL_EVENT_RECYCLE
+ void *pop;
+ if (esl_queue_trypop(EVENT_HEADER_RECYCLE_QUEUE, &pop) == ESL_SUCCESS) {
+ header = (esl_event_header_t *) pop;
+ } else {
+#endif
+ header = ALLOC(sizeof(*header));
+ esl_assert(header);
+#ifdef ESL_EVENT_RECYCLE
+ }
+#endif
+
+ memset(header, 0, sizeof(*header));
+ header->name = DUP(header_name);
+
+ return header;
+
+}
+
+ESL_DECLARE(int) esl_event_add_array(esl_event_t *event, const char *var, const char *val)
+{
+ char *data;
+ char **array;
+ int max = 0;
+ int len;
+ const char *p;
+ int i;
+
+ if (strlen(val) < 8) {
+ return -1;
}
- memset(header, 0, sizeof(*header));
+ p = val + 7;
- header->name = DUP(header_name);
- header->value = data;
- header->hash = esl_ci_hashfunc_default(header->name, &hlen);
+ max = 1;
+
+ while((p = strstr(p, "|:"))) {
+ max++;
+ p += 2;
+ }
+
+ if (!max) {
+ return -2;
+ }
+
+ data = strdup(val + 7);
- if (stack == ESL_STACK_TOP) {
- header->next = event->headers;
- event->headers = header;
- if (!event->last_header) {
+ len = (sizeof(char *) * max) + 1;
+ array = malloc(len);
+ esl_assert(array);
+ memset(array, 0, len);
+
+ esl_separate_string_string(data, "|:", array, max);
+
+ for(i = 0; i < max; i++) {
+ esl_event_add_header_string(event, ESL_STACK_PUSH, var, array[i]);
+ }
+
+ free(array);
+ free(data);
+
+ return 0;
+}
+
+static esl_status_t esl_event_base_add_header(esl_event_t *event, esl_stack_t stack, const char *header_name, char *data)
+{
+ esl_event_header_t *header = NULL;
+ esl_ssize_t hlen = -1;
+ int exists = 0, fly = 0;
+ char *index_ptr;
+ int index = 0;
+ char *real_header_name = NULL;
+
+ if ((index_ptr = strchr(header_name, '['))) {
+ index_ptr++;
+ index = atoi(index_ptr);
+ real_header_name = DUP(header_name);
+ if ((index_ptr = strchr(real_header_name, '['))) {
+ *index_ptr++ = '\0';
+ }
+ header_name = real_header_name;
+ }
+
+ if (index_ptr || (stack & ESL_STACK_PUSH) || (stack & ESL_STACK_UNSHIFT)) {
+
+ if (!(header = esl_event_get_header_ptr(event, header_name)) && index_ptr) {
+
+ header = new_header(header_name);
+
+ if (esl_test_flag(event, ESL_EF_UNIQ_HEADERS)) {
+ esl_event_del_header(event, header_name);
+ }
+
+ fly++;
+ }
+
+ if ((header = esl_event_get_header_ptr(event, header_name))) {
+
+ if (index_ptr) {
+ if (index > -1 && index <= 4000) {
+ if (index < header->idx) {
+ FREE(header->array[index]);
+ header->array[index] = DUP(data);
+ } else {
+ int i;
+ char **m;
+
+ m = realloc(header->array, sizeof(char *) * (index + 1));
+ esl_assert(m);
+ header->array = m;
+ for (i = header->idx; i < index; i++) {
+ m[i] = DUP("");
+ }
+ m[index] = DUP(data);
+ header->idx = index + 1;
+ if (!fly) {
+ exists = 1;
+ }
+
+ goto redraw;
+ }
+ }
+ goto end;
+ } else {
+ if ((stack & ESL_STACK_PUSH) || (stack & ESL_STACK_UNSHIFT)) {
+ exists++;
+ stack &= ~(ESL_STACK_TOP | ESL_STACK_BOTTOM);
+ } else {
+ header = NULL;
+ }
+ }
+ }
+ }
+
+
+ if (!header) {
+
+ if (esl_strlen_zero(data)) {
+ esl_event_del_header(event, header_name);
+ FREE(data);
+ goto end;
+ }
+
+ if (esl_test_flag(event, ESL_EF_UNIQ_HEADERS)) {
+ esl_event_del_header(event, header_name);
+ }
+
+ if (strstr(data, "ARRAY::")) {
+ esl_event_add_array(event, header_name, data);
+ FREE(data);
+ goto end;
+ }
+
+
+ header = new_header(header_name);
+ }
+
+ if ((stack & ESL_STACK_PUSH) || (stack & ESL_STACK_UNSHIFT)) {
+ char **m = NULL;
+ esl_size_t len = 0;
+ char *hv;
+ int i = 0, j = 0;
+
+ if (header->value && !header->idx) {
+ m = malloc(sizeof(char *));
+ esl_assert(m);
+ m[0] = header->value;
+ header->value = NULL;
+ header->array = m;
+ header->idx++;
+ m = NULL;
+ }
+
+ i = header->idx + 1;
+ m = realloc(header->array, sizeof(char *) * i);
+ esl_assert(m);
+
+ if ((stack & ESL_STACK_PUSH)) {
+ m[header->idx] = data;
+ } else if ((stack & ESL_STACK_UNSHIFT)) {
+ for (j = header->idx; j > 0; j--) {
+ m[j] = m[j-1];
+ }
+ m[0] = data;
+ }
+
+ header->idx++;
+ header->array = m;
+
+ redraw:
+ len = 0;
+ for(j = 0; j < header->idx; j++) {
+ len += strlen(header->array[j]) + 2;
+ }
+
+ if (len) {
+ len += 8;
+ hv = realloc(header->value, len);
+ esl_assert(hv);
+ header->value = hv;
+
+ esl_snprintf(header->value, len, "ARRAY::");
+ for(j = 0; j < header->idx; j++) {
+ esl_snprintf(header->value + strlen(header->value), len - strlen(header->value), "%s%s", j == 0 ? "" : "|:", header->array[j]);
+ }
+ }
+
+ } else {
+ header->value = data;
+ }
+
+ if (!exists) {
+ header->hash = esl_ci_hashfunc_default(header->name, &hlen);
+
+ if ((stack & ESL_STACK_TOP)) {
+ header->next = event->headers;
+ event->headers = header;
+ if (!event->last_header) {
+ event->last_header = header;
+ }
+ } else {
+ if (event->last_header) {
+ event->last_header->next = header;
+ } else {
+ event->headers = header;
+ header->next = NULL;
+ }
event->last_header = header;
}
- } else {
- if (event->last_header) {
- event->last_header->next = header;
- } else {
- event->headers = header;
- header->next = NULL;
- }
- event->last_header = header;
}
+ end:
+
+ esl_safe_free(real_header_name);
+
return ESL_SUCCESS;
}
@@ -386,48 +628,98 @@ ESL_DECLARE(esl_status_t) esl_event_add_body(esl_event_t *event, const char *fmt
}
}
+
ESL_DECLARE(void) esl_event_destroy(esl_event_t **event)
{
- esl_event_t *ep = *event, *this_event;
- esl_event_header_t *hp, *this_header;
+ esl_event_t *ep = *event;
+ esl_event_header_t *hp, *this;
- for (ep = *event ; ep ;) {
- this_event = ep;
- ep = ep->next;
-
- for (hp = this_event->headers; hp;) {
- this_header = hp;
+ if (ep) {
+ for (hp = ep->headers; hp;) {
+ this = hp;
hp = hp->next;
- FREE(this_header->name);
- FREE(this_header->value);
- memset(this_header, 0, sizeof(*this_header));
- FREE(this_header);
+ FREE(this->name);
+
+ if (this->idx) {
+ int i = 0;
+ this->value = NULL;
+ for (i = 0; i < this->idx; i++) {
+ FREE(this->array[i]);
+ }
+ FREE(this->array);
+ }
+
+ FREE(this->value);
+
+
+#ifdef ESL_EVENT_RECYCLE
+ if (esl_queue_trypush(EVENT_HEADER_RECYCLE_QUEUE, this) != ESL_SUCCESS) {
+ FREE(this);
+ }
+#else
+ FREE(this);
+#endif
+
+
}
- FREE(this_event->body);
- FREE(this_event->subclass_name);
- memset(this_event, 0, sizeof(*this_event));
- FREE(this_event);
+ FREE(ep->body);
+ FREE(ep->subclass_name);
+#ifdef ESL_EVENT_RECYCLE
+ if (esl_queue_trypush(EVENT_RECYCLE_QUEUE, ep) != ESL_SUCCESS) {
+ FREE(ep);
+ }
+#else
+ FREE(ep);
+#endif
+
}
*event = NULL;
}
+ESL_DECLARE(void) esl_event_merge(esl_event_t *event, esl_event_t *tomerge)
+{
+ esl_event_header_t *hp;
+
+ esl_assert(tomerge && event);
+ for (hp = tomerge->headers; hp; hp = hp->next) {
+ if (hp->idx) {
+ int i;
+
+ for(i = 0; i < hp->idx; i++) {
+ esl_event_add_header_string(event, ESL_STACK_PUSH, hp->name, hp->array[i]);
+ }
+ } else {
+ esl_event_add_header_string(event, ESL_STACK_BOTTOM, hp->name, hp->value);
+ }
+ }
+}
ESL_DECLARE(esl_status_t) esl_event_dup(esl_event_t **event, esl_event_t *todup)
{
esl_event_header_t *hp;
if (esl_event_create_subclass(event, ESL_EVENT_CLONE, todup->subclass_name) != ESL_SUCCESS) {
- return ESL_FAIL;
+ return ESL_GENERR;
}
(*event)->event_id = todup->event_id;
-
(*event)->event_user_data = todup->event_user_data;
(*event)->bind_user_data = todup->bind_user_data;
-
+ (*event)->flags = todup->flags;
for (hp = todup->headers; hp; hp = hp->next) {
- esl_event_add_header_string(*event, ESL_STACK_BOTTOM, hp->name, hp->value);
+ if (todup->subclass_name && !strcmp(hp->name, "Event-Subclass")) {
+ continue;
+ }
+
+ if (hp->idx) {
+ int i;
+ for (i = 0; i < hp->idx; i++) {
+ esl_event_add_header_string(*event, ESL_STACK_PUSH, hp->name, hp->array[i]);
+ }
+ } else {
+ esl_event_add_header_string(*event, ESL_STACK_BOTTOM, hp->name, hp->value);
+ }
}
if (todup->body) {
@@ -439,97 +731,26 @@ ESL_DECLARE(esl_status_t) esl_event_dup(esl_event_t **event, esl_event_t *todup)
return ESL_SUCCESS;
}
-ESL_DECLARE(esl_status_t) esl_event_create_json(esl_event_t **event, const char *json)
-{
- esl_event_t *new_event;
- cJSON *cj, *cjp;
-
-
- if (!(cj = cJSON_Parse(json))) {
- return ESL_FAIL;
- }
-
- if (esl_event_create(&new_event, ESL_EVENT_CLONE) != ESL_SUCCESS) {
- cJSON_Delete(cj);
- return ESL_FAIL;
- }
-
- for (cjp = cj->child; cjp; cjp = cjp->next) {
- char *name = cjp->string;
- char *value = cjp->valuestring;
-
- if (name && value) {
- if (!strcasecmp(name, "_body")) {
- esl_event_add_body(new_event, value);
- } else {
- if (!strcasecmp(name, "event-name")) {
- esl_event_del_header(new_event, "event-name");
- }
-
- esl_name_event(value, &new_event->event_id);
- esl_event_add_header_string(new_event, ESL_STACK_BOTTOM, name, value);
- }
-
- }
- }
-
- cJSON_Delete(cj);
- *event = new_event;
- return ESL_SUCCESS;
-}
-
-ESL_DECLARE(esl_status_t) esl_event_serialize_json(esl_event_t *event, char **str)
-{
- esl_event_header_t *hp;
- cJSON *cj;
-
- *str = NULL;
-
- cj = cJSON_CreateObject();
-
- for (hp = event->headers; hp; hp = hp->next) {
- cJSON_AddItemToObject(cj, hp->name, cJSON_CreateString(hp->value));
- }
- if (event->body) {
- int blen = (int) strlen(event->body);
- char tmp[25];
-
- esl_snprintf(tmp, sizeof(tmp), "%d", blen);
-
- cJSON_AddItemToObject(cj, "Content-Length", cJSON_CreateString(tmp));
- cJSON_AddItemToObject(cj, "_body", cJSON_CreateString(event->body));
- }
-
- *str = cJSON_Print(cj);
- cJSON_Delete(cj);
-
- return ESL_SUCCESS;
-}
ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, esl_bool_t encode)
{
- size_t len = 0;
+ esl_size_t len = 0;
esl_event_header_t *hp;
- size_t llen = 0, dlen = 0, blocksize = 512, encode_len = 1536, new_len = 0;
+ esl_size_t llen = 0, dlen = 0, blocksize = 512, encode_len = 1536, new_len = 0;
char *buf;
char *encode_buf = NULL; /* used for url encoding of variables to make sure unsafe things stay out of the serialized copy */
- int clen = 0;
-
- if (!event || !event->headers)
- return ESL_FAIL;
*str = NULL;
dlen = blocksize * 2;
if (!(buf = malloc(dlen))) {
- return ESL_FAIL;
+ abort();
}
/* go ahead and give ourselves some space to work with, should save a few reallocs */
if (!(encode_buf = malloc(encode_len))) {
- esl_safe_free(buf);
- return ESL_FAIL;
+ abort();
}
/* esl_log_printf(ESL_CHANNEL_LOG, ESL_LOG_INFO, "hit serialized!.\n"); */
@@ -542,54 +763,54 @@ ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, es
* destroying loop.
*/
- if (!strcasecmp(hp->name, "content-length")) {
- clen++;
+ if (hp->idx) {
+ int i;
+ new_len = 0;
+ for(i = 0; i < hp->idx; i++) {
+ new_len += (strlen(hp->array[i]) * 3) + 1;
+ }
+ } else {
+ new_len = (strlen(hp->value) * 3) + 1;
}
-
- new_len = (strlen(hp->value) * 3) + 1;
-
if (encode_len < new_len) {
char *tmp;
- /* esl_log_printf(ESL_CHANNEL_LOG, ESL_LOG_INFO, "Allocing %d was %d.\n", ((strlen(hp->value) * 3) + 1), encode_len); */
- /* we can use realloc for initial alloc as well, if encode_buf is zero it treats it as a malloc */
/* keep track of the size of our allocation */
encode_len = new_len;
if (!(tmp = realloc(encode_buf, encode_len))) {
- /* oh boy, ram's gone, give back what little we grabbed and bail */
- esl_safe_free(buf);
- esl_safe_free(encode_buf);
- return ESL_FAIL;
+ abort();
}
encode_buf = tmp;
}
/* handle any bad things in the string like newlines : etc that screw up the serialized format */
+
+
if (encode) {
esl_url_encode(hp->value, encode_buf, encode_len);
} else {
- esl_snprintf(encode_buf, encode_len, "%s", hp->value);
+ esl_snprintf(encode_buf, encode_len, "[%s]", hp->value);
}
+
llen = strlen(hp->name) + strlen(encode_buf) + 8;
if ((len + llen) > dlen) {
char *m;
+ char *old = buf;
dlen += (blocksize + (len + llen));
if ((m = realloc(buf, dlen))) {
buf = m;
} else {
- /* we seem to be out of memory trying to resize the serialize string, give back what we already have and give up */
- esl_safe_free(buf);
- esl_safe_free(encode_buf);
- return ESL_FAIL;
+ buf = old;
+ abort();
}
}
- snprintf(buf + len, dlen - len, "%s: %s\n", hp->name, *encode_buf == '\0' ? "_undef_" : encode_buf);
+ esl_snprintf(buf + len, dlen - len, "%s: %s\n", hp->name, *encode_buf == '\0' ? "_undef_" : encode_buf);
len = strlen(buf);
}
@@ -608,33 +829,121 @@ ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, es
if ((len + llen) > dlen) {
char *m;
+ char *old = buf;
dlen += (blocksize + (len + llen));
if ((m = realloc(buf, dlen))) {
buf = m;
} else {
- esl_safe_free(buf);
- return ESL_FAIL;
+ buf = old;
+ abort();
}
}
-
+
if (blen) {
- if (clen) {
- snprintf(buf + len, dlen - len, "\n%s", event->body);
- } else {
- snprintf(buf + len, dlen - len, "Content-Length: %d\n\n%s", (int)strlen(event->body), event->body);
-
- }
+ esl_snprintf(buf + len, dlen - len, "Content-Length: %d\n\n%s", blen, event->body);
+ } else {
+ esl_snprintf(buf + len, dlen - len, "\n");
}
} else {
- snprintf(buf + len, dlen - len, "\n");
+ esl_snprintf(buf + len, dlen - len, "\n");
}
-
*str = buf;
return ESL_SUCCESS;
}
+ESL_DECLARE(esl_status_t) esl_event_create_json(esl_event_t **event, const char *json)
+{
+ esl_event_t *new_event;
+ cJSON *cj, *cjp;
+
+
+ if (!(cj = cJSON_Parse(json))) {
+ return ESL_FALSE;
+ }
+
+ if (esl_event_create(&new_event, ESL_EVENT_CLONE) != ESL_SUCCESS) {
+ cJSON_Delete(cj);
+ return ESL_FALSE;
+ }
+
+ for (cjp = cj->child; cjp; cjp = cjp->next) {
+ char *name = cjp->string;
+ char *value = cjp->valuestring;
+
+ if (name && value) {
+ if (!strcasecmp(name, "_body")) {
+ esl_event_add_body(new_event, value, ESL_VA_NONE);
+ } else {
+ if (!strcasecmp(name, "event-name")) {
+ esl_event_del_header(new_event, "event-name");
+ esl_name_event(value, &new_event->event_id);
+ }
+
+ esl_event_add_header_string(new_event, ESL_STACK_BOTTOM, name, value);
+ }
+
+ } else if (name) {
+ if (cjp->type == cJSON_Array) {
+ int i, x = cJSON_GetArraySize(cjp);
+
+ for (i = 0; i < x; i++) {
+ cJSON *item = cJSON_GetArrayItem(cjp, i);
+
+ if (item != NULL && item->type == cJSON_String && item->valuestring) {
+ esl_event_add_header_string(new_event, ESL_STACK_PUSH, name, item->valuestring);
+ }
+ }
+ }
+ }
+ }
+
+ cJSON_Delete(cj);
+ *event = new_event;
+ return ESL_SUCCESS;
+}
+
+ESL_DECLARE(esl_status_t) esl_event_serialize_json(esl_event_t *event, char **str)
+{
+ esl_event_header_t *hp;
+ cJSON *cj;
+
+ *str = NULL;
+
+ cj = cJSON_CreateObject();
+
+ for (hp = event->headers; hp; hp = hp->next) {
+ if (hp->idx) {
+ cJSON *a = cJSON_CreateArray();
+ int i;
+
+ for(i = 0; i < hp->idx; i++) {
+ cJSON_AddItemToArray(a, cJSON_CreateString(hp->array[i]));
+ }
+
+ cJSON_AddItemToObject(cj, hp->name, a);
+
+ } else {
+ cJSON_AddItemToObject(cj, hp->name, cJSON_CreateString(hp->value));
+ }
+ }
+
+ if (event->body) {
+ int blen = (int) strlen(event->body);
+ char tmp[25];
+
+ esl_snprintf(tmp, sizeof(tmp), "%d", blen);
+
+ cJSON_AddItemToObject(cj, "Content-Length", cJSON_CreateString(tmp));
+ cJSON_AddItemToObject(cj, "_body", cJSON_CreateString(event->body));
+ }
+
+ *str = cJSON_Print(cj);
+ cJSON_Delete(cj);
+
+ return ESL_SUCCESS;
+}
/* For Emacs:
* Local Variables:
diff --git a/libs/esl/src/esl_oop.cpp b/libs/esl/src/esl_oop.cpp
index 8ea3dfa4d3..0c4bbd6f90 100644
--- a/libs/esl/src/esl_oop.cpp
+++ b/libs/esl/src/esl_oop.cpp
@@ -390,12 +390,12 @@ bool ESLevent::setPriority(esl_priority_t priority)
return false;
}
-const char *ESLevent::getHeader(const char *header_name)
+const char *ESLevent::getHeader(const char *header_name, int idx)
{
this_check("");
if (event) {
- return esl_event_get_header(event, header_name);
+ return esl_event_get_header_idx(event, header_name, idx);
} else {
esl_log(ESL_LOG_ERROR, "Trying to getHeader an event that does not exist!\n");
}
@@ -415,6 +415,32 @@ bool ESLevent::addHeader(const char *header_name, const char *value)
return false;
}
+bool ESLevent::pushHeader(const char *header_name, const char *value)
+{
+ this_check(false);
+
+ if (event) {
+ return esl_event_add_header_string(event, ESL_STACK_PUSH, header_name, value) == ESL_SUCCESS ? true : false;
+ } else {
+ esl_log(ESL_LOG_ERROR, "Trying to addHeader an event that does not exist!\n");
+ }
+
+ return false;
+}
+
+bool ESLevent::unshiftHeader(const char *header_name, const char *value)
+{
+ this_check(false);
+
+ if (event) {
+ return esl_event_add_header_string(event, ESL_STACK_UNSHIFT, header_name, value) == ESL_SUCCESS ? true : false;
+ } else {
+ esl_log(ESL_LOG_ERROR, "Trying to addHeader an event that does not exist!\n");
+ }
+
+ return false;
+}
+
bool ESLevent::delHeader(const char *header_name)
{
this_check(false);
diff --git a/libs/esl/src/include/esl.h b/libs/esl/src/include/esl.h
index 17ebf26ee1..095e814a0e 100644
--- a/libs/esl/src/include/esl.h
+++ b/libs/esl/src/include/esl.h
@@ -42,6 +42,7 @@ extern "C" {
#define esl_copy_string(_x, _y, _z) strncpy(_x, _y, _z - 1)
#define esl_set_string(_x, _y) esl_copy_string(_x, _y, sizeof(_x))
+#define ESL_VA_NONE "%s", ""
typedef struct esl_event_header esl_event_header_t;
typedef struct esl_event esl_event_t;
@@ -262,7 +263,8 @@ typedef enum {
ESL_SUCCESS,
ESL_FAIL,
ESL_BREAK,
- ESL_DISCONNECTED
+ ESL_DISCONNECTED,
+ ESL_GENERR
} esl_status_t;
#define BUF_CHUNK 65536 * 50
@@ -309,6 +311,10 @@ typedef struct {
int destroyed;
} esl_handle_t;
+#define esl_test_flag(obj, flag) ((obj)->flags & flag)
+#define esl_set_flag(obj, flag) (obj)->flags |= (flag)
+#define esl_clear_flag(obj, flag) (obj)->flags &= ~(flag)
+
/*! \brief Used internally for truth test */
typedef enum {
ESL_TRUE = 1,
@@ -453,6 +459,8 @@ ESL_DECLARE(esl_status_t) esl_events(esl_handle_t *handle, esl_event_type_t etyp
ESL_DECLARE(int) esl_wait_sock(esl_socket_t sock, uint32_t ms, esl_poll_t flags);
+ESL_DECLARE(unsigned int) esl_separate_string_string(char *buf, const char *delim, char **array, unsigned int arraylen);
+
#define esl_recv(_h) esl_recv_event(_h, 0, NULL)
#define esl_recv_timed(_h, _ms) esl_recv_event_timed(_h, _ms, 0, NULL)
diff --git a/libs/esl/src/include/esl_event.h b/libs/esl/src/include/esl_event.h
index 7e619f4764..d6be0470e8 100644
--- a/libs/esl/src/include/esl_event.h
+++ b/libs/esl/src/include/esl_event.h
@@ -42,7 +42,9 @@ extern "C" {
typedef enum {
ESL_STACK_BOTTOM,
- ESL_STACK_TOP
+ ESL_STACK_TOP,
+ ESL_STACK_PUSH,
+ ESL_STACK_UNSHIFT
} esl_stack_t;
typedef enum {
@@ -141,6 +143,10 @@ typedef enum {
char *name;
/*! the header value */
char *value;
+ /*! array space */
+ char **array;
+ /*! array index */
+ int idx;
/*! hash of the header name */
unsigned long hash;
struct esl_event_header *next;
@@ -174,7 +180,7 @@ struct esl_event {
};
typedef enum {
- ESL_UNIQ_HEADERS = (1 << 0)
+ ESL_EF_UNIQ_HEADERS = (1 << 0)
} esl_event_flag_t;
@@ -203,7 +209,11 @@ ESL_DECLARE(esl_status_t) esl_event_set_priority(esl_event_t *event, esl_priorit
\param header_name the name of the header to read
\return the value of the requested header
*/
-ESL_DECLARE(char *)esl_event_get_header(esl_event_t *event, const char *header_name);
+
+
+ESL_DECLARE(esl_event_header_t *) esl_event_get_header_ptr(esl_event_t *event, const char *header_name);
+ESL_DECLARE(char *) esl_event_get_header_idx(esl_event_t *event, const char *header_name, int idx);
+#define esl_event_get_header(_e, _h) esl_event_get_header_idx(_e, _h, -1)
/*!
\brief Retrieve the body value from an event
@@ -223,6 +233,8 @@ ESL_DECLARE(char *)esl_event_get_body(esl_event_t *event);
ESL_DECLARE(esl_status_t) esl_event_add_header(esl_event_t *event, esl_stack_t stack,
const char *header_name, const char *fmt, ...); //PRINTF_FUNCTION(4, 5);
+ESL_DECLARE(int) esl_event_add_array(esl_event_t *event, const char *var, const char *val);
+
/*!
\brief Add a string header to an event
\param event the event to add the header to
@@ -250,6 +262,7 @@ ESL_DECLARE(void) esl_event_destroy(esl_event_t **event);
\return ESL_SUCCESS if the event was duplicated
*/
ESL_DECLARE(esl_status_t) esl_event_dup(esl_event_t **event, esl_event_t *todup);
+ESL_DECLARE(void) esl_event_merge(esl_event_t *event, esl_event_t *tomerge);
/*!
\brief Render the name of an event id enumeration
diff --git a/libs/esl/src/include/esl_oop.h b/libs/esl/src/include/esl_oop.h
index 3947d0cfb7..947fe453d7 100644
--- a/libs/esl/src/include/esl_oop.h
+++ b/libs/esl/src/include/esl_oop.h
@@ -56,11 +56,13 @@ class ESLevent {
virtual ~ESLevent();
const char *serialize(const char *format = NULL);
bool setPriority(esl_priority_t priority = ESL_PRIORITY_NORMAL);
- const char *getHeader(const char *header_name);
+ const char *getHeader(const char *header_name, int idx = -1);
char *getBody(void);
const char *getType(void);
bool addBody(const char *value);
bool addHeader(const char *header_name, const char *value);
+ bool pushHeader(const char *header_name, const char *value);
+ bool unshiftHeader(const char *header_name, const char *value);
bool delHeader(const char *header_name);
const char *firstHeader(void);
const char *nextHeader(void);
diff --git a/libs/freetdm/Makefile.am b/libs/freetdm/Makefile.am
index 6c2eae3ef8..b4eb76d6fd 100644
--- a/libs/freetdm/Makefile.am
+++ b/libs/freetdm/Makefile.am
@@ -90,7 +90,7 @@ library_include_HEADERS = \
$(SRC)/include/ftdm_dso.h
lib_LTLIBRARIES = libfreetdm.la
-libfreetdm_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
+libfreetdm_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS)
libfreetdm_la_LDFLAGS = -version-info 1:0:0 $(AM_LDFLAGS)
libfreetdm_la_LIBADD = $(LIBS)
@@ -104,39 +104,39 @@ noinst_PROGRAMS = testtones detect_tones detect_dtmf testpri testr2 testanalog
testapp_SOURCES = $(SRC)/testapp.c
testapp_LDADD = libfreetdm.la
-testapp_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
+testapp_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS)
testcid_SOURCES = $(SRC)/testcid.c
testcid_LDADD = libfreetdm.la
-testcid_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
+testcid_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS)
testtones_SOURCES = $(SRC)/testtones.c
testtones_LDADD = libfreetdm.la
-testtones_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
+testtones_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS)
detect_tones_SOURCES = $(SRC)/detect_tones.c
detect_tones_LDADD = libfreetdm.la
-detect_tones_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
+detect_tones_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS)
detect_dtmf_SOURCES = $(SRC)/detect_dtmf.c
detect_dtmf_LDADD = libfreetdm.la
-detect_dtmf_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
+detect_dtmf_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS)
#testisdn_SOURCES = $(SRC)/testisdn.c
#testisdn_LDADD = libfreetdm.la
-#testisdn_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
+#testisdn_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS)
testpri_SOURCES = $(SRC)/testpri.c
testpri_LDADD = libfreetdm.la
-testpri_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
+testpri_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS)
testr2_SOURCES = $(SRC)/testr2.c
testr2_LDADD = libfreetdm.la
-testr2_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
+testr2_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS)
testanalog_SOURCES = $(SRC)/testanalog.c
testanalog_LDADD = libfreetdm.la
-testanalog_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
+testanalog_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS)
#
# ftmod modules
@@ -144,22 +144,22 @@ testanalog_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
mod_LTLIBRARIES = ftmod_zt.la ftmod_skel.la ftmod_analog.la ftmod_analog_em.la
ftmod_zt_la_SOURCES = $(SRC)/ftmod/ftmod_zt/ftmod_zt.c
-ftmod_zt_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
+ftmod_zt_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS)
ftmod_zt_la_LDFLAGS = -shared -module -avoid-version
ftmod_zt_la_LIBADD = libfreetdm.la
ftmod_skel_la_SOURCES = $(SRC)/ftmod/ftmod_skel/ftmod_skel.c
-ftmod_skel_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
+ftmod_skel_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS)
ftmod_skel_la_LDFLAGS = -module -avoid-version
ftmod_skel_la_LIBADD = libfreetdm.la
ftmod_analog_la_SOURCES = $(SRC)/ftmod/ftmod_analog/ftmod_analog.c
-ftmod_analog_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
+ftmod_analog_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS)
ftmod_analog_la_LDFLAGS = -shared -module -avoid-version
ftmod_analog_la_LIBADD = libfreetdm.la
ftmod_analog_em_la_SOURCES = $(SRC)/ftmod/ftmod_analog_em/ftmod_analog_em.c
-ftmod_analog_em_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
+ftmod_analog_em_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS)
ftmod_analog_em_la_LDFLAGS = -shared -module -avoid-version
ftmod_analog_em_la_LIBADD = libfreetdm.la
@@ -168,7 +168,7 @@ 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, use FTDM_COMPAT_CFLAGS instead
-ftmod_wanpipe_la_CFLAGS = $(AM_CFLAGS) $(FTDM_COMPAT_CFLAGS) -D__LINUX__ -I/usr/include/wanpipe
+ftmod_wanpipe_la_CFLAGS = $(FTDM_COMPAT_CFLAGS) $(AM_CFLAGS) -D__LINUX__ -I/usr/include/wanpipe
ftmod_wanpipe_la_LDFLAGS = -shared -module -avoid-version -lsangoma
ftmod_wanpipe_la_LIBADD = libfreetdm.la
endif
@@ -176,7 +176,7 @@ endif
if HAVE_LIBISDN
mod_LTLIBRARIES += ftmod_isdn.la
ftmod_isdn_la_SOURCES = $(SRC)/ftmod/ftmod_isdn/ftmod_isdn.c
-ftmod_isdn_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) -D_GNU_SOURCE $(LIBISDN_CPPFLAGS) $(PCAP_CPPFLAGS)
+ftmod_isdn_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) -D_GNU_SOURCE $(LIBISDN_CPPFLAGS) $(PCAP_CPPFLAGS)
ftmod_isdn_la_LDFLAGS = -shared -module -avoid-version $(LIBISDN_LDFLAGS) $(PCAP_LDFLAGS)
ftmod_isdn_la_LIBADD = libfreetdm.la $(LIBISDN_LIBS) $(PCAP_LIBS)
endif
@@ -184,7 +184,7 @@ endif
if HAVE_LIBPRI
mod_LTLIBRARIES += ftmod_libpri.la
ftmod_libpri_la_SOURCES = $(SRC)/ftmod/ftmod_libpri/ftmod_libpri.c $(SRC)/ftmod/ftmod_libpri/lpwrap_pri.c
-ftmod_libpri_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
+ftmod_libpri_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS)
ftmod_libpri_la_LDFLAGS = -shared -module -avoid-version -lpri
ftmod_libpri_la_LIBADD = libfreetdm.la
endif
@@ -192,7 +192,7 @@ endif
if HAVE_PRITAP
mod_LTLIBRARIES += ftmod_pritap.la
ftmod_pritap_la_SOURCES = $(SRC)/ftmod/ftmod_pritap/ftmod_pritap.c
-ftmod_pritap_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
+ftmod_pritap_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS)
ftmod_pritap_la_LDFLAGS = -shared -module -avoid-version -lpri
ftmod_pritap_la_LIBADD = libfreetdm.la
endif
@@ -215,7 +215,7 @@ ftmod_sangoma_ss7_la_SOURCES = \
$(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c \
$(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_relay.c
-ftmod_sangoma_ss7_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) -D_GNU_SOURCE
+ftmod_sangoma_ss7_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) -D_GNU_SOURCE
ftmod_sangoma_ss7_la_LDFLAGS = -shared -module -avoid-version -lsng_ss7
ftmod_sangoma_ss7_la_LIBADD = libfreetdm.la
endif
@@ -235,7 +235,7 @@ ftmod_sangoma_isdn_la_SOURCES = \
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c \
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
-ftmod_sangoma_isdn_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS) -D_GNU_SOURCE
+ftmod_sangoma_isdn_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) -D_GNU_SOURCE
ftmod_sangoma_isdn_la_LDFLAGS = -shared -module -avoid-version -lsng_isdn
ftmod_sangoma_isdn_la_LIBADD = libfreetdm.la
endif
@@ -243,7 +243,7 @@ endif
if HAVE_OPENR2
mod_LTLIBRARIES += ftmod_r2.la
ftmod_r2_la_SOURCES = $(SRC)/ftmod/ftmod_r2/ftmod_r2.c $(SRC)/ftmod/ftmod_r2/ftmod_r2_io_mf_lib.c
-ftmod_r2_la_CFLAGS = $(AM_CFLAGS) $(FTDM_CFLAGS)
+ftmod_r2_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS)
ftmod_r2_la_LDFLAGS = -shared -module -avoid-version -lopenr2
ftmod_r2_la_LIBADD = libfreetdm.la
endif
diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c
index 731893a2f6..d4c85d3998 100755
--- a/libs/freetdm/mod_freetdm/mod_freetdm.c
+++ b/libs/freetdm/mod_freetdm/mod_freetdm.c
@@ -42,6 +42,9 @@
#define FREETDM_VAR_PREFIX "freetdm_"
#define FREETDM_VAR_PREFIX_LEN (sizeof(FREETDM_VAR_PREFIX)-1)
+/* How many consecutive IO errors before giving up */
+#define FTDM_MAX_READ_WRITE_ERRORS 10
+
SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_freetdm_shutdown);
SWITCH_MODULE_DEFINITION(mod_freetdm, mod_freetdm_load, mod_freetdm_shutdown, NULL);
@@ -110,7 +113,8 @@ struct private_object {
switch_mutex_t *mutex;
switch_mutex_t *flag_mutex;
ftdm_channel_t *ftdmchan;
- uint32_t wr_error;
+ uint32_t write_error;
+ uint32_t read_error;
};
/* private data attached to FTDM channels (only FXS for now) */
@@ -624,12 +628,11 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
ftdm_status_t status;
int total_to;
int chunk, do_break = 0;
-
+ uint32_t span_id, chan_id;
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
-
tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL);
@@ -638,6 +641,13 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
return SWITCH_STATUS_FALSE;
}
+ if (!tech_pvt->ftdmchan) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ span_id = ftdm_channel_get_span_id(tech_pvt->ftdmchan);
+ chan_id = ftdm_channel_get_id(tech_pvt->ftdmchan);
+
/* Digium Cards sometimes timeout several times in a row here.
Yes, we support digium cards, ain't we nice.......
6 double length intervals should compensate */
@@ -697,8 +707,13 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
len = tech_pvt->read_frame.buflen;
if (ftdm_channel_read(tech_pvt->ftdmchan, tech_pvt->read_frame.data, &len) != FTDM_SUCCESS) {
- ftdm_log(FTDM_LOG_WARNING, "failed to read from device\n");
- goto fail;
+ ftdm_log(FTDM_LOG_WARNING, "failed to read from device %d:%d\n", span_id, chan_id);
+ if (++tech_pvt->read_error > FTDM_MAX_READ_WRITE_ERRORS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "too many I/O read errors on device %d:%d!\n", span_id, chan_id);
+ goto fail;
+ }
+ } else {
+ tech_pvt->read_error = 0;
}
*frame = &tech_pvt->read_frame;
@@ -736,6 +751,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
ftdm_size_t len;
unsigned char data[SWITCH_RECOMMENDED_BUFFER_SIZE] = {0};
ftdm_wait_flag_t wflags = FTDM_WRITE;
+ uint32_t span_id, chan_id;
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
@@ -743,10 +759,6 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
tech_pvt = switch_core_session_get_private(session);
assert(tech_pvt != NULL);
- if (!tech_pvt->ftdmchan) {
- return SWITCH_STATUS_FALSE;
- }
-
if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
return SWITCH_STATUS_FALSE;
}
@@ -758,6 +770,14 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
goto fail;
}
+
+ if (!tech_pvt->ftdmchan) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ span_id = ftdm_channel_get_span_id(tech_pvt->ftdmchan);
+ chan_id = ftdm_channel_get_id(tech_pvt->ftdmchan);
+
if (switch_test_flag(frame, SFF_CNG)) {
frame->data = data;
@@ -779,12 +799,14 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
len = frame->datalen;
if (ftdm_channel_write(tech_pvt->ftdmchan, frame->data, frame->buflen, &len) != FTDM_SUCCESS) {
- if (++tech_pvt->wr_error > 10) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "too many I/O write errors!\n");
+ ftdm_log(FTDM_LOG_WARNING, "failed to write to device %d:%d\n", span_id, chan_id);
+ if (++tech_pvt->write_error > FTDM_MAX_READ_WRITE_ERRORS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG,
+ SWITCH_LOG_ERROR, "too many I/O write errors on device %d:%d!\n", span_id, chan_id);
goto fail;
}
} else {
- tech_pvt->wr_error = 0;
+ tech_pvt->write_error = 0;
}
return SWITCH_STATUS_SUCCESS;
@@ -1855,29 +1877,31 @@ static FIO_SIGNAL_CB_FUNCTION(on_common_signal)
break;
}
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-name", "%s", ftdm_channel_get_span_name(sigmsg->channel));
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-number", "%d", ftdm_channel_get_span_id(sigmsg->channel));
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "chan-number", "%d", ftdm_channel_get_id(sigmsg->channel));
+ if (event) {
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-name", "%s", ftdm_channel_get_span_name(sigmsg->channel));
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "span-number", "%d", ftdm_channel_get_span_id(sigmsg->channel));
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "chan-number", "%d", ftdm_channel_get_id(sigmsg->channel));
- if (alarmbits & FTDM_ALARM_RED) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "red");
+ if (alarmbits & FTDM_ALARM_RED) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "red");
+ }
+ if (alarmbits & FTDM_ALARM_YELLOW) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "yellow");
+ }
+ if (alarmbits & FTDM_ALARM_RAI) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "rai");
+ }
+ if (alarmbits & FTDM_ALARM_BLUE) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "blue");
+ }
+ if (alarmbits & FTDM_ALARM_AIS) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "ais");
+ }
+ if (alarmbits & FTDM_ALARM_GENERAL) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "general");
+ }
+ switch_event_fire(&event);
}
- if (alarmbits & FTDM_ALARM_YELLOW) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "yellow");
- }
- if (alarmbits & FTDM_ALARM_RAI) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "rai");
- }
- if (alarmbits & FTDM_ALARM_BLUE) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "blue");
- }
- if (alarmbits & FTDM_ALARM_AIS) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "ais");
- }
- if (alarmbits & FTDM_ALARM_GENERAL) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm", "general");
- }
- switch_event_fire(&event);
return FTDM_BREAK;
}
@@ -2483,10 +2507,10 @@ static uint32_t enable_analog_option(const char *str, uint32_t current_options)
}
-#define CONFIG_ERROR(...) do { \
+#define CONFIG_ERROR(...) { \
ftdm_log(FTDM_LOG_ERROR, __VA_ARGS__); \
globals.config_error = 1; \
- } while(0)
+ }
/* create ftdm_conf_node_t tree based on a fixed pattern XML configuration list
* last 2 args are for limited aka dumb recursivity
* */
@@ -2871,9 +2895,9 @@ static switch_status_t load_config(void)
} else if (!strcasecmp(var, "hold-music")) {
switch_set_string(globals.hold_music, val);
} else if (!strcasecmp(var, "crash-on-assert")) {
- globals.crash_on_assert = switch_true(val);
+ globals.crash_on_assert = (uint8_t)switch_true(val);
} else if (!strcasecmp(var, "fail-on-error")) {
- globals.fail_on_error = switch_true(val);
+ globals.fail_on_error = (uint8_t)switch_true(val);
} else if (!strcasecmp(var, "sip-headers")) {
globals.sip_headers = switch_true(val);
} else if (!strcasecmp(var, "enable-analog-option")) {
diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c
index 93729f0a50..f7b4bb9a1c 100644
--- a/libs/freetdm/src/ftdm_io.c
+++ b/libs/freetdm/src/ftdm_io.c
@@ -1549,6 +1549,7 @@ static ftdm_status_t _ftdm_channel_open_by_group(uint32_t group_id, ftdm_directi
int best_rate = 0;
uint32_t i = 0;
uint32_t count = 0;
+ uint32_t first_channel = 0;
if (group_id) {
ftdm_group_find(group_id, &group);
@@ -1573,6 +1574,7 @@ static ftdm_status_t _ftdm_channel_open_by_group(uint32_t group_id, ftdm_directi
i = 0;
} else if (direction == FTDM_RR_DOWN || direction == FTDM_RR_UP) {
i = rr_next(group->last_used_index, 0, group->chan_count - 1, direction);
+ first_channel = i;
} else {
i = group->chan_count-1;
}
@@ -1605,6 +1607,9 @@ static ftdm_status_t _ftdm_channel_open_by_group(uint32_t group_id, ftdm_directi
group->last_used_index = i;
}
i = rr_next(i, 0, group->chan_count - 1, direction);
+ if (first_channel == i) {
+ break;
+ }
} else {
if (i == 0) {
break;
@@ -1663,6 +1668,7 @@ static ftdm_status_t _ftdm_channel_open_by_span(uint32_t span_id, ftdm_direction
int best_rate = 0;
uint32_t i = 0;
uint32_t count = 0;
+ uint32_t first_channel = 0;
*ftdmchan = NULL;
@@ -1696,6 +1702,7 @@ static ftdm_status_t _ftdm_channel_open_by_span(uint32_t span_id, ftdm_direction
i = 1;
} else if (direction == FTDM_RR_DOWN || direction == FTDM_RR_UP) {
i = rr_next(span->last_used_index, 1, span->chan_count, direction);
+ first_channel = i;
} else {
i = span->chan_count;
}
@@ -1706,10 +1713,6 @@ static ftdm_status_t _ftdm_channel_open_by_span(uint32_t span_id, ftdm_direction
if (i > span->chan_count) {
break;
}
- } else if (direction == FTDM_RR_DOWN || direction == FTDM_RR_UP) {
- if (i == span->last_used_index) {
- break;
- }
} else {
if (i == 0) {
break;
@@ -1738,6 +1741,9 @@ static ftdm_status_t _ftdm_channel_open_by_span(uint32_t span_id, ftdm_direction
span->last_used_index = i;
}
i = rr_next(i, 1, span->chan_count, direction);
+ if (first_channel == i) {
+ break;
+ }
} else {
i--;
}
@@ -3583,7 +3589,7 @@ skipdebug:
return status;
}
-FIO_WRITE_FUNCTION(ftdm_raw_write)
+FT_DECLARE(ftdm_status_t) ftdm_raw_write (ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen)
{
int dlen = (int) *datalen;
@@ -3610,7 +3616,7 @@ FIO_WRITE_FUNCTION(ftdm_raw_write)
return ftdmchan->fio->write(ftdmchan, data, datalen);
}
-FIO_READ_FUNCTION(ftdm_raw_read)
+FT_DECLARE(ftdm_status_t) ftdm_raw_read (ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen)
{
ftdm_status_t status;
diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c
index 8093443986..5150890ec6 100644
--- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c
+++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c
@@ -1584,6 +1584,13 @@ static int on_dchan_down(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_
static int on_anything(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_event *pevent)
{
ftdm_log(FTDM_LOG_DEBUG, "-- Caught Event span %d %u (%s)\n", ftdm_span_get_id(spri->span), event_type, lpwrap_pri_event_str(event_type));
+ switch (pevent->e) {
+ case PRI_EVENT_CONFIG_ERR:
+ {
+ ftdm_log(FTDM_LOG_WARNING, "-- PRI error event: %s\n", pevent->err.err);
+ }
+ break;
+ }
return 0;
}
diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
index 1c15f992a2..8333a306c4 100755
--- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
+++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
@@ -436,6 +436,13 @@ static __inline openr2_calling_party_category_t ftdm_r2_ftdm_cpc_to_openr2_cpc(f
case FTDM_CPC_PAYPHONE:
return OR2_CALLING_PARTY_CATEGORY_PAY_PHONE;
+ case FTDM_CPC_OPERATOR_FRENCH:
+ case FTDM_CPC_OPERATOR_ENGLISH:
+ case FTDM_CPC_OPERATOR_GERMAN:
+ case FTDM_CPC_OPERATOR_RUSSIAN:
+ case FTDM_CPC_OPERATOR_SPANISH:
+ return OR2_CALLING_PARTY_CATEGORY_COLLECT_CALL;
+
case FTDM_CPC_INVALID:
return OR2_CALLING_PARTY_CATEGORY_UNKNOWN;
}
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2008.vcproj b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2008.vcproj
index 01395cb1db..f6263907e1 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2008.vcproj
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2008.vcproj
@@ -238,6 +238,10 @@
RelativePath=".\ftmod_sangoma_isdn_trace.c"
>
+
+
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj
index d7b75d8df4..7ec8fd3346 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.2010.vcxproj
@@ -189,6 +189,7 @@
+
@@ -199,4 +200,4 @@
-
\ No newline at end of file
+
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
index 2a0fa83706..d74a67b483 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
@@ -47,7 +47,6 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span);
static ftdm_status_t ftdm_sangoma_isdn_dtmf(ftdm_channel_t *ftdmchan, const char* dtmf);
ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event);
-static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span);
static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_event_t event);
static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan);
static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event);
@@ -59,8 +58,8 @@ static sng_isdn_event_interface_t g_sngisdn_event_interface;
ftdm_sngisdn_data_t g_sngisdn_data;
-FTDM_ENUM_NAMES(SNGISDN_TRANSFER_TYPE_NAMES, SNGISDN_TRANSFER_TYPE_STRINGS)
-FTDM_STR2ENUM(ftdm_str2sngisdn_transfer_type, sngisdn_transfer_type2str, sngisdn_transfer_type_t, SNGISDN_TRANSFER_TYPE_NAMES, SNGISDN_TRANSFER_INVALID)
+SNGISDN_ENUM_NAMES(SNGISDN_TRANSFER_TYPE_NAMES, SNGISDN_TRANSFER_TYPE_STRINGS)
+SNGISDN_STR2ENUM(ftdm_str2sngisdn_transfer_type, sngisdn_transfer_type2str, sngisdn_transfer_type_t, SNGISDN_TRANSFER_TYPE_NAMES, SNGISDN_TRANSFER_INVALID)
ftdm_state_map_t sangoma_isdn_state_map = {
{
@@ -313,28 +312,6 @@ static void ftdm_sangoma_isdn_process_phy_events(ftdm_span_t *span, ftdm_oob_eve
}
}
-static void ftdm_sangoma_isdn_poll_events(ftdm_span_t *span)
-{
- ftdm_status_t ret_status;
-
- ret_status = ftdm_span_poll_event(span, 0, NULL);
- switch(ret_status) {
- case FTDM_SUCCESS:
- {
- ftdm_event_t *event;
- while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) {
- ftdm_sangoma_isdn_process_phy_events(span, event->enum_id);
- }
- }
- break;
- case FTDM_TIMEOUT:
- /* No events pending */
- break;
- default:
- ftdm_log(FTDM_LOG_WARNING, "%s:Failed to poll span event\n", span->name);
- }
-}
-
static void ftdm_sangoma_isdn_dchan_set_queue_size(ftdm_channel_t *dchan)
{
ftdm_status_t ret_status;
@@ -365,7 +342,7 @@ static void ftdm_sangoma_isdn_wakeup_phy(ftdm_channel_t *dchan)
static void *ftdm_sangoma_isdn_io_run(ftdm_thread_t *me, void *obj)
{
uint8_t data[1000];
- unsigned i;
+ unsigned i = 0;
ftdm_status_t status = FTDM_SUCCESS;
ftdm_wait_flag_t wflags = FTDM_READ;
ftdm_span_t *span = (ftdm_span_t*) obj;
@@ -374,6 +351,7 @@ static void *ftdm_sangoma_isdn_io_run(ftdm_thread_t *me, void *obj)
unsigned waitms = 10000;
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *citer = NULL;
+ ftdm_event_t *event;
short *poll_events = ftdm_malloc(sizeof(short) * span->chan_count);
/* Initialize the d-channel */
@@ -394,6 +372,8 @@ static void *ftdm_sangoma_isdn_io_run(ftdm_thread_t *me, void *obj)
wflags = FTDM_READ;
memset(poll_events, 0, sizeof(short)*span->chan_count);
+ poll_events[i] |= FTDM_EVENTS;
+
for (i = 0, citer = ftdm_span_get_chan_iterator(span, chaniter); citer; citer = ftdm_iterator_next(citer), i++) {
ftdmchan = ftdm_iterator_current(citer);
@@ -416,6 +396,7 @@ static void *ftdm_sangoma_isdn_io_run(ftdm_thread_t *me, void *obj)
case FTDM_TIMEOUT:
break;
case FTDM_SUCCESS:
+ /* Check if there are any channels that have data available */
for (citer = ftdm_span_get_chan_iterator(span, chaniter); citer; citer = ftdm_iterator_next(citer)) {
len = 1000;
ftdmchan = ftdm_iterator_current(citer);
@@ -444,6 +425,12 @@ static void *ftdm_sangoma_isdn_io_run(ftdm_thread_t *me, void *obj)
}
}
}
+
+ /* Check if there are any channels that have events available */
+ while (ftdm_span_next_event(span, &event) == FTDM_SUCCESS) {
+ ftdm_sangoma_isdn_process_phy_events(span, event->enum_id);
+ }
+
break;
default:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Unhandled IO event\n");
@@ -487,7 +474,6 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
}
while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) {
-
/* Check if there are any timers to process */
ftdm_sched_run(signal_data->sched);
ftdm_span_trigger_signals(span);
@@ -525,9 +511,6 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
ftdm_log(FTDM_LOG_ERROR, "%s: ftdm_interrupt_wait returned with unknown code\n", span->name);
break;
}
-
- /* Poll for events, e.g HW DTMF */
- ftdm_sangoma_isdn_poll_events(span);
}
/* clear the IN_THREAD flag so that we know the thread is done */
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
index 9935b3e0ea..08adc6ef6b 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
@@ -177,7 +177,7 @@ typedef enum {
SNGISDN_TRANSFER_INVALID,
} sngisdn_transfer_type_t;
#define SNGISDN_TRANSFER_TYPE_STRINGS "NONE", "ATT_COURTESY_VRU", "ATT_COURTERY_VRU_DATA", "INVALID"
-FTDM_STR2ENUM_P(ftdm_str2sngisdn_transfer_type, sngisdn_transfer_type2str, sngisdn_transfer_type_t)
+SNGISDN_STR2ENUM_P(ftdm_str2sngisdn_transfer_type, sngisdn_transfer_type2str, sngisdn_transfer_type_t)
/* From section 4.2 of TR50075, max length of data is 100 when single UUI is sent */
#define COURTESY_TRANSFER_MAX_DATA_SIZE 100
@@ -251,7 +251,8 @@ typedef struct sngisdn_span_data {
uint8_t raw_trace_q931; /* TODO: combine with trace_flags */
uint8_t raw_trace_q921; /* TODO: combine with trace_flags */
uint8_t timer_t3;
- uint8_t restart_opt;
+ uint8_t restart_opt;
+ uint8_t force_sending_complete;
char* local_numbers[SNGISDN_NUM_LOCAL_NUMBERS];
ftdm_sched_t *sched;
ftdm_queue_t *event_queue;
@@ -323,6 +324,11 @@ typedef struct ftdm_sngisdn_data {
uint8_t num_dchan;
sngisdn_dchan_data_t dchans[MAX_L1_LINKS+1];
sngisdn_span_data_t *spans[MAX_L1_LINKS+1]; /* spans are indexed by link_id */
+
+#ifdef SANGOMA_ISDN_CHAN_ID_INVERT_BIT
+ /* Since this is a global configuration, place it here instead of sngisdn_span_data_t */
+ uint8_t chan_id_invert_extend_bit;
+#endif
}ftdm_sngisdn_data_t;
typedef struct ftdm2trillium
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c
index ec688eb2ba..66721eba0a 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c
@@ -286,7 +286,8 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
signal_data->restart_opt = SNGISDN_OPT_DEFAULT;
signal_data->link_id = span->span_id;
signal_data->transfer_timeout = 20000;
- signal_data->att_remove_dtmf = 1;
+ signal_data->att_remove_dtmf = SNGISDN_OPT_DEFAULT;
+ signal_data->force_sending_complete = SNGISDN_OPT_DEFAULT;
span->default_caller_data.dnis.plan = FTDM_NPI_INVALID;
span->default_caller_data.dnis.type = FTDM_TON_INVALID;
@@ -386,10 +387,18 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
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 if (!strcasecmp(var, "force-sending-complete")) {
+ parse_yesno(var, val, &signal_data->force_sending_complete);
} else if (!strcasecmp(var, "early-media-override")) {
if (parse_early_media(val, span) != FTDM_SUCCESS) {
return FTDM_FAIL;
}
+ } else if (!strcasecmp(var, "chan-id-invert-extend-bit")) {
+#ifdef SANGOMA_ISDN_CHAN_ID_INVERT_BIT
+ parse_yesno(var, val, &g_sngisdn_data.chan_id_invert_extend_bit);
+#else
+ ftdm_log(FTDM_LOG_WARNING, "chan-id-invert-extend-bit is not supported in your version of libsng_isdn\n");
+#endif
} else {
ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
}
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c
index 88aa9131b6..4288a4d615 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c
@@ -624,7 +624,7 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.tCbCfg = TRUE;
cfg.t.cfg.s.inDLSAP.tCbId = signal_data->cc_id;
-
+
if (signal_data->facility == SNGISDN_OPT_TRUE) {
cfg.t.cfg.s.inDLSAP.facilityHandling = IN_FACILITY_STANDRD;
} else {
@@ -720,6 +720,16 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
}
cfg.t.cfg.s.inDLSAP.useSubAdr = 0; /* call routing on subaddress */
+#ifdef SANGOMA_ISDN_CHAN_ID_INVERT_BIT
+ if (signal_data->switchtype == SNGISDN_SWITCH_DMS100 &&
+ g_sngisdn_data.chan_id_invert_extend_bit == SNGISDN_OPT_TRUE) {
+ /* Since this feature is not standard, we modified Trillium to check
+ the useSubAdr field and remove the extended bit if this is set, this
+ is a global configuration and once set, applies to all spans configured
+ as DMS 100 */
+ cfg.t.cfg.s.inDLSAP.useSubAdr = PRSNT_NODEF;
+ }
+#endif
cfg.t.cfg.s.inDLSAP.adrPref = 0; /* use of prefix for international calls */
cfg.t.cfg.s.inDLSAP.nmbPrefDig = 0; /* number of digits used for prefix */
for (i = 0; i < IN_MAXPREFDIG; i++)
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
index 0cb2b1401d..44538bba61 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
@@ -882,6 +882,12 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
uint8_t call_state = 0;
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
+
+ if (!suInstId && !spInstId) {
+ /* We already cleared this call */
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Dropping STATUS CONFIRM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
+ return;
+ }
if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) {
call_state = staEvnt->callSte.callGlblSte.val;
@@ -1137,7 +1143,7 @@ static ftdm_status_t sngisdn_force_down(ftdm_channel_t *ftdmchan)
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data;
ftdm_status_t status = FTDM_SUCCESS;
- ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Forcing channel to DOWN state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
+ ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Forcing channel to DOWN state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_DOWN:
/* Do nothing */
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
index 9a1e66fe51..a424313fc1 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
@@ -51,9 +51,10 @@ 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));
- if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) {
+ if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN || signal_data->force_sending_complete == SNGISDN_OPT_TRUE) {
conEvnt.sndCmplt.eh.pres = PRSNT_NODEF;
}
+
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
signal_data->signalling == SNGISDN_SIGNALING_NET) {
sngisdn_info->ces = CES_MNGMNT;
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c
index 879b1491a9..e2f93f0e86 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c
@@ -502,12 +502,16 @@ void sngisdn_rcv_sta_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, St
sngisdn_event_data_t *sngisdn_event = NULL;
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-
+
+ /* We sometimes receive a STA CFM after receiving a RELEASE/RELEASE COMPLETE, so we need to lock
+ here in case we are calling clear_call_data at the same time this function is called */
+
+ ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
- ftdm_assert(0, "Inconsistent call states\n");
+ ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
return;
}
@@ -526,6 +530,7 @@ void sngisdn_rcv_sta_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, St
memcpy(&sngisdn_event->event.staEvnt, staEvnt, sizeof(*staEvnt));
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
+ ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
index 30ee953c40..b0c3efe271 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
@@ -99,13 +99,14 @@ void clear_call_data(sngisdn_chan_data_t *sngisdn_info)
ftdm_mutex_lock(g_sngisdn_data.ccs[cc_id].mutex);
g_sngisdn_data.ccs[cc_id].active_spInstIds[sngisdn_info->spInstId]=NULL;
g_sngisdn_data.ccs[cc_id].active_suInstIds[sngisdn_info->suInstId]=NULL;
- ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].mutex);
-
+
sngisdn_info->suInstId = 0;
sngisdn_info->spInstId = 0;
sngisdn_info->globalFlg = 0;
sngisdn_info->flags = 0;
sngisdn_info->transfer_data.type = SNGISDN_TRANSFER_NONE;
+
+ ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].mutex);
return;
}
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_transfer.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_transfer.c
index f00087a061..4c0c9555dd 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_transfer.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_transfer.c
@@ -273,7 +273,7 @@ ftdm_status_t sngisdn_att_transfer_process_dtmf(ftdm_channel_t *ftdmchan, const
att_courtesy_transfer_complete(sngisdn_info, sngisdn_info->transfer_data.response);
}
- if (signal_data->att_remove_dtmf) {
+ if (signal_data->att_remove_dtmf != SNGISDN_OPT_FALSE) {
/* If we return FTDM_BREAK, dtmf event is not queue'ed to user */
status = FTDM_BREAK;
}
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
index 0520e9d163..6fb9c82895 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
@@ -584,6 +584,20 @@ ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circ
break;
/**************************************************************************/
+ case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
+
+ /* already hangup complete, just ignore it */
+ /*
+ * i.e. collision REL & ANM
+ * IAM ->
+ * <- ACM
+ * REL -> <- ANM (if REL gets processed first, ANM needs to be ignored)
+ * <- RLC
+ */
+ SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx ANM/CON Ignoring it because we already hung up\n", sngss7_info->circuit->cic);
+
+ break;
+ /**************************************************************************/
default: /* incorrect state...reset the CIC */
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx ANM/CON\n", sngss7_info->circuit->cic);
@@ -1267,7 +1281,7 @@ ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circu
/* confirm that the circuit is active on our side otherwise move to the next circuit */
if (!sngss7_test_flag(&g_ftdm_sngss7_data.cfg.isupCkt[i], SNGSS7_ACTIVE)) {
- SS7_ERROR("[CIC:%d]Circuit is not active yet, skipping!\n",g_ftdm_sngss7_data.cfg.isupCkt[i].cic);
+ ftdm_log(FTDM_LOG_DEBUG, "[CIC:%d]Circuit is not active yet, skipping!\n",g_ftdm_sngss7_data.cfg.isupCkt[i].cic);
i++;
continue;
}
diff --git a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c
index fa9f76cd3f..b66eb0bb6f 100644
--- a/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c
+++ b/libs/freetdm/src/ftmod/ftmod_zt/ftmod_zt.c
@@ -1072,16 +1072,20 @@ static __inline__ ftdm_status_t zt_channel_process_event(ftdm_channel_t *fchan,
break;
case ZT_EVENT_BADFCS:
{
- ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Bad frame checksum (ZT_EVENT_BADFCS)!\n");
- /* What else could we do? */
- *event_id = FTDM_OOB_NOOP;
+ ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Bad frame checksum (ZT_EVENT_BADFCS)\n");
+ *event_id = FTDM_OOB_NOOP; /* What else could we do? */
}
break;
case ZT_EVENT_OVERRUN:
{
- ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Driver overrun! (ZT_EVENT_OVERRUN)\n");
- /* What else could we do? */
- *event_id = FTDM_OOB_NOOP;
+ ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "HDLC frame overrun (ZT_EVENT_OVERRUN)\n");
+ *event_id = FTDM_OOB_NOOP; /* What else could we do? */
+ }
+ break;
+ case ZT_EVENT_ABORT:
+ {
+ ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "HDLC abort frame received (ZT_EVENT_ABORT)\n");
+ *event_id = FTDM_OOB_NOOP; /* What else could we do? */
}
break;
case ZT_EVENT_NONE:
diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h
index 96083430fc..67015c6fdf 100644
--- a/libs/freetdm/src/include/private/ftdm_core.h
+++ b/libs/freetdm/src/include/private/ftdm_core.h
@@ -599,8 +599,8 @@ FT_DECLARE(ftdm_iterator_t *) ftdm_get_iterator(ftdm_iterator_type_t type, ftdm_
FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen);
-FIO_WRITE_FUNCTION(ftdm_raw_write);
-FIO_READ_FUNCTION(ftdm_raw_read);
+FT_DECLARE(ftdm_status_t) ftdm_raw_read (ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen);
+FT_DECLARE(ftdm_status_t) ftdm_raw_write (ftdm_channel_t *ftdmchan, void *data, ftdm_size_t *datalen);
/*!
* \brief Retrieves an event from the span
diff --git a/libs/libdingaling/src/libdingaling.c b/libs/libdingaling/src/libdingaling.c
index bbf26ca5c9..76b19f118f 100644
--- a/libs/libdingaling/src/libdingaling.c
+++ b/libs/libdingaling/src/libdingaling.c
@@ -1908,6 +1908,8 @@ void ldl_handle_send_msg(ldl_handle_t *handle, char *from, char *to, const char
int on = 0;
int len = 0;
char *my_body = strdup(body);
+ char *my_body_base = my_body;
+
assert(handle != NULL);
assert(body != NULL);
@@ -1952,7 +1954,9 @@ void ldl_handle_send_msg(ldl_handle_t *handle, char *from, char *to, const char
free(bdup);
}
- free(my_body);
+ if (my_body_base) {
+ free(my_body_base);
+ }
apr_queue_push(handle->queue, msg);
msg = NULL;
diff --git a/libs/stfu/stfu.c b/libs/stfu/stfu.c
index a4c3bb78d3..75a659d894 100644
--- a/libs/stfu/stfu.c
+++ b/libs/stfu/stfu.c
@@ -231,7 +231,7 @@ void stfu_n_debug(stfu_instance_t *i, const char *name)
void stfu_n_report(stfu_instance_t *i, stfu_report_t *r)
{
- assert(i);
+ stfu_assert(i);
r->qlen = i->qlen;
r->packet_in_count = i->period_packet_in_count;
r->clean_count = i->period_clean_count;
@@ -580,7 +580,7 @@ static int stfu_n_find_any_frame(stfu_instance_t *in, stfu_queue_t *queue, stfu_
uint32_t i = 0;
stfu_frame_t *frame = NULL;
- assert(r_frame);
+ stfu_assert(r_frame);
*r_frame = NULL;
diff --git a/libs/stfu/stfu.h b/libs/stfu/stfu.h
index b802bbaef6..3e989b0a97 100644
--- a/libs/stfu/stfu.h
+++ b/libs/stfu/stfu.h
@@ -40,6 +40,13 @@ extern "C" {
#include
#include
+#if (_MSC_VER >= 1400) // VC8+
+#define stfu_assert(expr) assert(expr);__analysis_assume( expr )
+#endif
+
+#ifndef stfu_assert
+#define stfu_assert(_x) assert(_x)
+#endif
#ifdef _MSC_VER
#ifndef uint32_t
diff --git a/libs/unimrcp/.update b/libs/unimrcp/.update
index 2c9225f323..05e080f0c9 100644
--- a/libs/unimrcp/.update
+++ b/libs/unimrcp/.update
@@ -1 +1 @@
-Mon Feb 22 09:40:01 CST 2010
+Thu Jun 16 15:02:31 UTC 2011
diff --git a/libs/unimrcp/AUTHORS b/libs/unimrcp/AUTHORS
index d032c9e71a..6c7b0eee09 100644
--- a/libs/unimrcp/AUTHORS
+++ b/libs/unimrcp/AUTHORS
@@ -14,3 +14,4 @@ Contributor(s):
Carlos Pina Soares
Chaitanya Chokkareddy
Tomas Valenta
+ Danijel Korzinek
diff --git a/libs/unimrcp/Makefile.am b/libs/unimrcp/Makefile.am
index eeb00cecb4..0421198eb9 100644
--- a/libs/unimrcp/Makefile.am
+++ b/libs/unimrcp/Makefile.am
@@ -14,7 +14,7 @@ MAINTAINERCLEANFILES = Makefile.in aclocal.m4 configure $(AUX_DIST)
ACLOCAL = aclocal -I $(macrodir)
-SUBDIRS = conf data libs modules plugins platforms build
+SUBDIRS = build conf data libs modules plugins platforms
if TEST_SUITES
SUBDIRS += tests
endif
diff --git a/libs/unimrcp/NOTICE b/libs/unimrcp/NOTICE
index bcd5c17ac5..37f1bf3c01 100644
--- a/libs/unimrcp/NOTICE
+++ b/libs/unimrcp/NOTICE
@@ -1,5 +1,5 @@
The UniMRCP Project (http://www.unimrcp.org)
-Copyright (C) 2008 Arsen Chaloyan
+Copyright (C) 2008-2010 Arsen Chaloyan
Licensed under the Apache License, Version 2.0 (the "License").
This product includes a number of subcomponents with
diff --git a/libs/unimrcp/acinclude.m4 b/libs/unimrcp/acinclude.m4
index 46eb391ab8..7a487f7046 100644
--- a/libs/unimrcp/acinclude.m4
+++ b/libs/unimrcp/acinclude.m4
@@ -3,7 +3,6 @@ m4_include([build/acmacros/apu.m4])
m4_include([build/acmacros/find_apr.m4])
m4_include([build/acmacros/find_apu.m4])
m4_include([build/acmacros/sofia-sip.m4])
-m4_include([build/acmacros/swift.m4])
m4_include([build/acmacros/sphinxbase.m4])
m4_include([build/acmacros/pocketsphinx.m4])
m4_include([build/acmacros/flite.m4])
diff --git a/libs/unimrcp/build/Makefile.am b/libs/unimrcp/build/Makefile.am
index dfacd94fc1..822c9173c8 100644
--- a/libs/unimrcp/build/Makefile.am
+++ b/libs/unimrcp/build/Makefile.am
@@ -1,5 +1,9 @@
MAINTAINERCLEANFILES = Makefile.in
+CLEANFILES = uni_revision.h
-SUBDIRS = pkgconfig
+SUBDIRS = pkgconfig svnrev
-include_HEADERS = uni_version.h
+include_HEADERS = uni_version.h uni_revision.h
+
+uni_revision.h :
+ svnrev/svnrev -rsvnrev/svnrev.input -p../ -ouni_revision.h
diff --git a/libs/unimrcp/build/acmacros/flite.m4 b/libs/unimrcp/build/acmacros/flite.m4
index a1991bc16b..5585e963b4 100644
--- a/libs/unimrcp/build/acmacros/flite.m4
+++ b/libs/unimrcp/build/acmacros/flite.m4
@@ -13,21 +13,28 @@ AC_DEFUN([UNIMRCP_CHECK_FLITE],
found_flite="no"
- flite_libdir="build/libs"
+ flite_config="config/config"
for dir in $flite_path ; do
cd $dir && flite_dir=`pwd` && cd - > /dev/null
- if test -d "$dir/$flite_libdir"; then
- found_flite="yes"
- UNIMRCP_FLITE_INCLUDES="-I$flite_dir/include"
- UNIMRCP_FLITE_LIBS="$dir/$flite_libdir/libflite_cmu_us_awb.a \
- $dir/$flite_libdir/libflite_cmu_us_kal.a \
- $dir/$flite_libdir/libflite_cmu_us_rms.a \
- $dir/$flite_libdir/libflite_cmu_us_slt.a \
- $dir/$flite_libdir/libflite_cmulex.a \
- $dir/$flite_libdir/libflite_usenglish.a \
- $dir/$flite_libdir/libflite.a"
- break
- fi
+ if test -f "$flite_dir/$flite_config"; then
+ target_os=`grep TARGET_OS "$flite_dir/$flite_config" | sed "s/^.*= //"` ;\
+ target_cpu=`grep TARGET_CPU "$flite_dir/$flite_config" | sed "s/^.*= //"` ;\
+ flite_libdir=$flite_dir/build/$target_cpu-$target_os/lib
+ if test -d "$flite_libdir"; then
+ UNIMRCP_FLITE_INCLUDES="-I$flite_dir/include"
+ UNIMRCP_FLITE_LIBS="$flite_libdir/libflite_cmu_us_awb.a \
+ $flite_libdir/libflite_cmu_us_kal.a \
+ $flite_libdir/libflite_cmu_us_rms.a \
+ $flite_libdir/libflite_cmu_us_slt.a \
+ $flite_libdir/libflite_cmulex.a \
+ $flite_libdir/libflite_usenglish.a \
+ $flite_libdir/libflite.a"
+ found_flite="yes"
+ break
+ else
+ AC_MSG_WARN(Cannot find Flite lib dir: $flite_libdir)
+ fi
+ fi
done
if test x_$found_flite != x_yes; then
diff --git a/libs/unimrcp/build/acmacros/swift.m4 b/libs/unimrcp/build/acmacros/swift.m4
deleted file mode 100644
index b9049767a4..0000000000
--- a/libs/unimrcp/build/acmacros/swift.m4
+++ /dev/null
@@ -1,28 +0,0 @@
-dnl UNIMRCP_CHECK_SWIFT
-
-AC_DEFUN([UNIMRCP_CHECK_SWIFT],
-[
- AC_MSG_NOTICE([Cepstral Swift library configuration])
-
- AC_MSG_CHECKING([for Swift])
- AC_ARG_WITH(swift,
- [ --with-swift=PATH prefix for installed Swift],
- [swift_path=$withval],
- [swift_path="/opt/swift"]
- )
-
- if test -d "$swift_path"; then
- found_swift="yes"
- UNIMRCP_SWIFT_INCLUDES="-I$swift_path/include"
- UNIMRCP_SWIFT_LIBS="-lswift -lceplex_us -lceplang_en -lm"
- UNIMRCP_SWIFT_LDFLAGS="-L$swift_path/lib/ -R$swift_path/lib/"
-
- AC_SUBST(UNIMRCP_SWIFT_INCLUDES)
- AC_SUBST(UNIMRCP_SWIFT_LIBS)
- AC_SUBST(UNIMRCP_SWIFT_LDFLAGS)
-
- AC_MSG_RESULT($swift_path)
- else
- AC_MSG_WARN([not found - looked for $swift_path])
- fi
-])
diff --git a/libs/unimrcp/build/init.d/unimrcp-server b/libs/unimrcp/build/init.d/unimrcp-server
new file mode 100755
index 0000000000..29be4f3653
--- /dev/null
+++ b/libs/unimrcp/build/init.d/unimrcp-server
@@ -0,0 +1,271 @@
+#!/bin/sh
+#
+# unimrcp-server This shell script takes care of starting and stopping the UniMRCP server.
+#
+# chkconfig: 2345 65 35
+# description: UniMRCP is an open source MRCP v1 & v2 server
+
+# Some global variables
+
+# Application
+APP_NAME="unimrcpserver"
+APP_LONG_NAME="unimrcpserver"
+UNIMRCP_DIR="/usr/local/unimrcp/"
+
+EXEC="${UNIMRCP_DIR}bin/${APP_NAME} -d -o 2 -r ${UNIMRCP_DIR}"
+
+# sudo user
+USERNAME=root
+
+# Priority at which to run the server. See "man nice" for valid priorities.
+# nice is only used if a priority is specified.
+PRIORITY=
+
+# Location of the pid file.
+PIDDIR="/var/run/"
+pid=
+
+LOG="/var/log/${APP_NAME}.log"
+
+if [ -e $PIDDIR ]; then
+echo
+else
+mkdir $PIDDIR
+fi
+
+# Allow configuration overrides in /etc/sysconfig/$APP_NAME
+CONFIGFILE=/etc/sysconfig/$APP_NAME
+
+[ -x $CONFIGFILE ] && . $CONFIGFILE
+
+# Do not modify anything beyond this point
+#-----------------------------------------------------------------------------
+
+# Get the fully qualified path to the script
+case $0 in
+ /*)
+ SCRIPT="$0"
+ ;;
+ *)
+ PWD=`pwd`
+ SCRIPT="$PWD/$0"
+ ;;
+esac
+
+# Change spaces to ":" so the tokens can be parsed.
+SCRIPT=`echo $SCRIPT | sed -e 's; ;:;g'`
+# Get the real path to this script, resolving any symbolic links
+TOKENS=`echo $SCRIPT | sed -e 's;/; ;g'`
+REALPATH=
+for C in $TOKENS; do
+REALPATH="$REALPATH/$C"
+ while [ -h "$REALPATH" ] ; do
+LS="`ls -ld "$REALPATH"`"
+ LINK="`expr "$LS" : '.*-> \(.*\)$'`"
+ if expr "$LINK" : '/.*' > /dev/null; then
+REALPATH="$LINK"
+ else
+REALPATH="`dirname "$REALPATH"`""/$LINK"
+ fi
+done
+done
+# Change ":" chars back to spaces.
+REALPATH=`echo $REALPATH | sed -e 's;:; ;g'`
+
+# Change the current directory to the location of the script
+cd "`dirname "$REALPATH"`"
+
+chown $USERNAME $PIDDIR
+
+# Process ID
+PIDFILE="$PIDDIR/$APP_NAME.pid"
+
+# Resolve the location of the 'ps' command
+PSEXE="/usr/bin/ps"
+if [ ! -x $PSEXE ]
+then
+PSEXE="/bin/ps"
+ if [ ! -x $PSEXE ]
+ then
+echo "Unable to locate 'ps'."
+ echo "Please report this with the location on your system."
+ exit 1
+ fi
+fi
+
+# Build the nice clause
+if [ "X$PRIORITY" = "X" ]
+then
+CMDNICE=""
+else
+CMDNICE="nice -$PRIORITY"
+fi
+
+getpid() {
+ if [ -f $PIDFILE ]
+ then
+if [ -r $PIDFILE ]
+ then
+pid=`cat $PIDFILE`
+ if [ "X$pid" != "X" ]
+ then
+ # Verify that a process with this pid is still running.
+ pid=`$PSEXE -p $pid | grep $pid | grep -v grep | awk '{print $1}' | tail -1`
+ if [ "X$pid" = "X" ]
+ then
+ # This is a stale pid file.
+ rm -f $PIDFILE
+ echo "Removed stale pid file: $PIDFILE"
+ fi
+fi
+else
+echo "Cannot read $PIDFILE."
+ exit 1
+ fi
+fi
+}
+
+testpid() {
+ pid=`$PSEXE -p $pid | grep $pid | grep -v grep | awk '{print $1}' | tail -1`
+ if [ "X$pid" = "X" ]
+ then
+ # Process is gone so remove the pid file.
+ rm -f $PIDFILE
+ fi
+}
+
+console() {
+ echo "Running $APP_LONG_NAME..."
+ getpid
+ if [ "X$pid" = "X" ]
+ then
+exec sudo -u $USERNAME $CMDNICE $EXEC
+ else
+echo "$APP_LONG_NAME is already running."
+ exit 1
+ fi
+}
+
+start() {
+ echo "Starting $APP_LONG_NAME..."
+ getpid
+ if [ "X$pid" = "X" ]
+ then
+sudo -u $USERNAME $CMDNICE $EXEC
+ pid=`$PSEXE -C $APP_NAME -o pid=`
+echo $pid
+echo $pid > $PIDFILE
+ else
+echo "$APP_LONG_NAME is already running."
+ exit 1
+ fi
+}
+
+stopit() {
+ echo "Stopping $APP_LONG_NAME..."
+ getpid
+ if [ "X$pid" = "X" ]
+ then
+echo "$APP_LONG_NAME was not running."
+ else
+ # Running so try to stop it.
+ sudo -u $USERNAME kill $pid
+ if [ $? -ne 0 ]
+ then
+ # An explanation for the failure should have been given
+ echo "Unable to stop $APP_LONG_NAME."
+ exit 1
+ fi
+
+ # We can not predict how long it will take for the wrapper to
+ # actually stop as it depends on settings in wrapper.conf.
+ # Loop until it does.
+ savepid=$pid
+ CNT=0
+ TOTCNT=0
+ while [ "X$pid" != "X" ]
+ do
+ # Loop for up to 5 minutes
+ if [ "$TOTCNT" -lt "300" ]
+ then
+if [ "$CNT" -lt "5" ]
+ then
+CNT=`expr $CNT + 1`
+ else
+echo "Waiting for $APP_LONG_NAME to exit..."
+ CNT=0
+ fi
+TOTCNT=`expr $TOTCNT + 1`
+
+ sleep 1
+
+ testpid
+ else
+pid=
+ fi
+done
+
+pid=$savepid
+ testpid
+ if [ "X$pid" != "X" ]
+ then
+echo "Timed out waiting for $APP_LONG_NAME to exit."
+ echo " Attempting a forced exit..."
+ kill -9 $pid
+ fi
+
+pid=$savepid
+ testpid
+ if [ "X$pid" != "X" ]
+ then
+echo "Failed to stop $APP_LONG_NAME."
+ exit 1
+ else
+echo "Stopped $APP_LONG_NAME."
+ fi
+fi
+}
+
+status() {
+ getpid
+ if [ "X$pid" = "X" ]
+ then
+echo "$APP_LONG_NAME is not running."
+ exit 1
+ else
+echo "$APP_LONG_NAME is running ($pid)."
+ exit 0
+ fi
+}
+
+case "$1" in
+
+ 'console')
+ console
+ ;;
+
+ 'start')
+ start
+ ;;
+
+ 'stop')
+ stopit
+ ;;
+
+ 'restart')
+ stopit
+ start
+ ;;
+
+ 'status')
+ status
+ ;;
+
+ *)
+ echo "Usage: $0 { console | start | stop | restart | status }"
+ exit 1
+ ;;
+esac
+
+exit 0
+
diff --git a/libs/unimrcp/build/svnrev/Makefile.am b/libs/unimrcp/build/svnrev/Makefile.am
new file mode 100644
index 0000000000..5ce3ff2644
--- /dev/null
+++ b/libs/unimrcp/build/svnrev/Makefile.am
@@ -0,0 +1,10 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = $(UNIMRCP_APR_INCLUDES) $(UNIMRCP_APU_INCLUDES)
+
+noinst_PROGRAMS = svnrev
+svnrev_LDADD = $(UNIMRCP_APR_LIBS) $(UNIMRCP_APU_LIBS)
+svnrev_SOURCES = svnrev.c
+
+rev:
+ ./svnrev -rsvnrev.input -p../../ -o../uni_revision.h
diff --git a/libs/unimrcp/build/svnrev/svnrev.c b/libs/unimrcp/build/svnrev/svnrev.c
new file mode 100644
index 0000000000..154b07ef3f
--- /dev/null
+++ b/libs/unimrcp/build/svnrev/svnrev.c
@@ -0,0 +1,381 @@
+/* SvnRev
+ *
+ * This utility retrieves the highest number that follows the "$Id: $" keyword
+ * or a combination of the $Rev: $ and $Date: $ keywords. The Subversion
+ * version control system expands these keywords and keeps them up to date.
+ * For an example of the tag, see the end of this comment.
+ *
+ * Details on the usage and the operation of this utility is available on-line
+ * at http://www.compuphase.com/svnrev.htm.
+ *
+ *
+ * Acknowledgements
+ *
+ * The support for .java files is contributed by Tom McCann (tommc@spoken.com).
+ * The option for prefixing and/or suffixing the build number (in the string
+ * constant SVN_REVSTR) was suggested by Robert Nitzel.
+ *
+ *
+ * License
+ *
+ * Copyright (c) 2005-2009, ITB CompuPhase (www.compuphase.com).
+ *
+ * This software is provided "as-is", without any express or implied warranty.
+ * In no event will the authors be held liable for any damages arising from
+ * the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software in
+ * a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * Version: $Id: svnrev.c 1497 2010-02-12 17:20:21Z achaloyan $
+ */
+
+#include
+#include
+#include
+
+#include
+#include
+
+
+#if defined __WIN32__ || defined _Win32 || defined _WIN32
+ #define DIRSEP '\\'
+#elif defined macintosh
+ #define DIRSEP ':'
+#else
+ /* assume Linux/Unix */
+ #define DIRSEP '/'
+#endif
+
+#define MAX_LINELENGTH 512
+#define MAX_SYMBOLLENGTH 32
+
+static void about(void)
+{
+ printf("svnrev 1.7.\n\n");
+ printf("Usage: svnrev [options] [input [...]]\n\n"
+ "Options:\n"
+ "-ofilename\tOutput filename for the file with the build number. When no\n"
+ "\t\tfilename follows \"-o\", the result is written to stdout. The\n"
+ "\t\tdefault filename is \"svnrev.h\" for C/C++ and \"VersionInfo.java\"\n"
+ "\t\tfor Java.\n\n"
+ "-fpattern\tFormat: Adds text before or after the build number in the\n"
+ "\t\tconstant SVN_REVSTR. The pattern has the form \"text#text\"\n"
+ "\t\t(without the quotes) where \"text\" is arbitrary text and \"#\"\n"
+ "\t\twill be replaced by the build number.\n\n"
+ "-i\t\tIncremental: this option should be used when the list of input\n"
+ "\t\tfiles is a subset of all files in the project. When -i is\n"
+ "\t\tpresent, svnrev also scans the output file that was generated\n"
+ "\t\ton a previous run.\n\n"
+ "-jname\t\tJava: this option writes a java package file instead of a C/C++\n"
+ "\t\theader file. The name of the Java package must follow the\n"
+ "\t\toption (this is not the filename).\n\n"
+ "-v\t\tVerbose: prints the names of files that are modified since the\n"
+ "\t\tlast commit (into version control) to stderr.\n");
+ exit(1);
+}
+
+static void processfile(const char *name, int failsilent,
+ int *max_build, int *accum_build,
+ int *max_year, int *max_month, int *max_day,
+ int *ismodified)
+
+{
+ char str[MAX_LINELENGTH], str_base[MAX_LINELENGTH];
+ char name_base[MAX_LINELENGTH];
+ char *p1;
+ FILE *fp, *fp_base;
+ int build, maj_build;
+ int year, month, day;
+ int cnt;
+ char modchar;
+
+ /* since we also want to verify whether the file is modified in version
+ * control, get the path to the working copy name
+ * for every source file "\, the "working copy" base can
+ * be found in "\.svn\text-base\.svn-base"
+ */
+ if ((p1 = strrchr(name, DIRSEP)) != NULL) {
+ ++p1; /* skip directory separator character ('\' in Windows, '/' in Linux) */
+ strncpy(name_base, name, (int)(p1 - name));
+ name_base[(int)(p1 - name)] = '\0';
+ } else {
+ name_base[0] = '\0';
+ p1 = (char*)name;
+ } /* if */
+ sprintf(name_base + strlen(name_base), ".svn%ctext-base%c%s.svn-base",
+ DIRSEP, DIRSEP, p1);
+
+ /* first extract the revision keywords */
+ fp = fopen(name, "r");
+ if (fp == NULL) {
+ if (!failsilent)
+ fprintf(stderr, "Failed to open input file '%s'\n", name);
+ return;
+ } /* if */
+ fp_base = fopen(name_base, "r"); /* fail silently */
+ build = 0;
+ maj_build = 0; /* RCS / CVS */
+ year = month = day = 0;
+
+ while (fgets(str, sizeof str, fp) != NULL) {
+ if (fp_base == NULL || fgets(str_base, sizeof str_base, fp_base) == NULL)
+ str_base[0] = '\0';
+ if ((p1 = strstr(str, "$Id:")) != NULL && strchr(p1+1, '$') != NULL) {
+ if (sscanf(p1, "$Id: %*s %d %d-%d-%d", &build, &year, &month, &day) < 4
+ && sscanf(p1, "$Id: %*s %d %d/%d/%d", &build, &year, &month, &day) < 4)
+ if (sscanf(p1, "$Id: %*s %d.%d %d-%d-%d", &maj_build, &build, &year, &month, &day) < 5)
+ sscanf(p1, "$Id: %*s %d.%d %d/%d/%d", &maj_build, &build, &year, &month, &day);
+ } else if ((p1 = strstr(str, "$Rev:")) != NULL && strchr(p1+1, '$') != NULL) {
+ if (sscanf(p1, "$Rev: %d.%d", &maj_build, &build) < 2) {
+ sscanf(p1, "$Rev: %d", &build);
+ maj_build = 0;
+ } /* if */
+ } else if ((p1 = strstr(str, "$Revision:")) != NULL && strchr(p1+1, '$') != NULL) {
+ if (sscanf(p1, "$Revision: %d.%d", &maj_build, &build) < 2) {
+ /* SvnRev also writes this keyword in its own generated file; read it
+ * back for partial updates
+ */
+ cnt = sscanf(p1, "$Revision: %d%c", &build, &modchar);
+ if (cnt == 2 && modchar == 'M' && ismodified != NULL)
+ *ismodified = 1;
+ maj_build = 0;
+ } /* if */
+ } else if ((p1 = strstr(str, "$Date:")) != NULL && strchr(p1+1, '$') != NULL) {
+ if (sscanf(p1, "$Date: %d-%d-%d", &year, &month, &day) < 3)
+ sscanf(p1, "$Date: %d/%d/%d", &year, &month, &day);
+ } else if (ismodified != NULL && *ismodified == 0 && fp_base != NULL) {
+ /* no keyword present, compare the lines for equivalence */
+ *ismodified = strcmp(str, str_base) != 0;
+ } /* if */
+
+ if (maj_build)
+ *accum_build += build; /* RCS / CVS */
+ else if (build > *max_build)
+ *max_build = build; /* Subversion */
+ if (year > *max_year
+ || (year == *max_year && month > *max_month)
+ || (year == *max_year && month == *max_month && day > *max_day))
+ {
+ *max_year = year;
+ *max_month = month;
+ *max_day = day;
+ } /* if */
+ if (build > 0 && year > 0 && (fp_base == NULL || ismodified == NULL || *ismodified != 0))
+ break; /* both build # and date found, not comparing or modification
+ * already found => no need to search further */
+
+ } /* while */
+ fclose(fp);
+ if (fp_base != NULL)
+ fclose(fp_base);
+}
+
+int main(int argc, char *argv[])
+{
+ char *outname = NULL;
+ FILE *fp;
+ FILE *input_file;
+ char *input_file_name = NULL;
+ char *path_prefix = NULL;
+ int index;
+ int process_self = 0;
+ int verbose = 0;
+ int max_build, accum_build;
+ int max_year, max_month, max_day;
+ int ismodified, filemodified;
+ char prefix[MAX_SYMBOLLENGTH], suffix[MAX_SYMBOLLENGTH];
+ char modified_suffix[2];
+ int write_java = 0; /* flag for Java output, 0=.h output, 1=.java output */
+ /* java package to put revision info in.
+ * REVIEW - I assume if you want Java output you will specify a package. */
+ char *java_package = NULL;
+
+ if (argc <= 1)
+ about();
+
+ /* collect the options */
+ prefix[0] = '\0';
+ suffix[0] = '\0';
+
+ for (index = 1; index < argc; index++) {
+ /* check for options */
+ if (argv[index][0] == '-'
+#if defined __WIN32__ || defined _Win32 || defined _WIN32
+ || argv[index][0] == '/'
+#endif
+ )
+ {
+ switch (argv[index][1]) {
+ case 'f': {
+ int len;
+ char *ptr = strchr(&argv[index][2], '#');
+ len = (ptr != NULL) ? (int)(ptr - &argv[index][2]) : (int)strlen(&argv[index][2]);
+ if (len >= MAX_SYMBOLLENGTH)
+ len = MAX_SYMBOLLENGTH - 1;
+ strncpy(prefix, &argv[index][2], len);
+ prefix[len] = '\0';
+ ptr = (ptr != NULL) ? ptr + 1 : strchr(argv[index], '\0');
+ len = (int)strlen(ptr);
+ if (len >= MAX_SYMBOLLENGTH)
+ len = MAX_SYMBOLLENGTH - 1;
+ strncpy(suffix, ptr, len);
+ suffix[len] = '\0';
+ break;
+ } /* case */
+ case 'i':
+ process_self = 1;
+ break;
+ case 'j':
+ write_java=1;
+ java_package = &argv[index][2];
+ break;
+ case 'o':
+ outname = &argv[index][2];
+ break;
+ case 'r':
+ input_file_name = &argv[index][2];
+ break;
+ case 'p':
+ path_prefix = &argv[index][2];
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ fprintf(stderr, "Invalid option '%s'\n", argv[index]);
+ about();
+ } /* switch */
+ } /* if */
+ } /* for */
+
+ if (outname == NULL)
+ outname = write_java ? "SvnRevision.java" : "uni_revision.h";
+ if (!process_self && *outname != '\0')
+ remove(outname);
+
+ /* phase 1: scan through all files and get the highest build number */
+
+ max_build = 0;
+ accum_build = 0; /* for RCS / CVS */
+ max_year = max_month = max_day = 0;
+ ismodified = 0;
+
+ if(input_file_name) {
+ input_file = fopen(input_file_name, "r");
+ if (input_file != NULL) {
+ apr_dir_t *dir;
+ apr_finfo_t finfo;
+ apr_status_t rv;
+ apr_pool_t *pool;
+ char *file_path;
+ char dir_path[256]; /* line */
+ int offset = 0;
+ if(path_prefix)
+ offset = sprintf(dir_path, "%s", path_prefix);
+ else
+ offset = sprintf(dir_path, "../../");
+
+ apr_initialize();
+ apr_pool_create(&pool,NULL);
+ while (fgets(dir_path + offset, sizeof(dir_path) - offset, input_file) != NULL ) { /* read a line */
+ size_t len = strlen(dir_path)-1;
+ if(dir_path[len] == '\n')
+ dir_path[len] = 0;
+ rv = apr_dir_open(&dir,dir_path,pool);
+ if(rv == APR_SUCCESS) {
+ while (apr_dir_read(&finfo, APR_FINFO_NAME, dir) == APR_SUCCESS) { /* get next file */
+ if(finfo.filetype != APR_REG) continue;
+
+ apr_filepath_merge(&file_path,dir_path,finfo.name,0,pool);
+
+ filemodified = 0;
+ if (strcasecmp(file_path, outname)!=0)
+ processfile(file_path, 0, &max_build, &accum_build, &max_year, &max_month, &max_day, &filemodified);
+ if (filemodified && verbose)
+ fprintf(stderr, "\tNotice: modified file '%s'\n", file_path);
+ ismodified = ismodified || filemodified;
+ }
+ apr_dir_close(dir);
+ }
+ else {
+ fprintf(stderr, "No such directory '%s'\n", dir_path);
+ }
+ }
+ fclose (input_file);
+ apr_pool_destroy(pool);
+ apr_terminate();
+ }
+ else {
+ fprintf(stderr, "No such input file '%s'\n", input_file_name);
+ }
+ }
+ else {
+ for (index = 1; index < argc; index++) {
+ /* skip the options (already handled) */
+ if (argv[index][0] == '-'
+#if defined __WIN32__ || defined _Win32 || defined _WIN32
+ || argv[index][0] == '/'
+#endif
+ )
+ continue;
+
+ filemodified = 0;
+ if (strcasecmp(argv[index], outname)!=0)
+ processfile(argv[index], 0, &max_build, &accum_build, &max_year, &max_month, &max_day, &filemodified);
+ if (filemodified && verbose)
+ fprintf(stderr, "\tNotice: modified file '%s'\n", argv[index]);
+ ismodified = ismodified || filemodified;
+ } /* for */
+ }
+
+ /* also run over the existing header file, if any */
+ if (process_self && *outname != '\0')
+ processfile(outname, 1, &max_build, &accum_build, &max_year, &max_month, &max_day, NULL/*&ismodified*/);
+
+ if (accum_build > max_build)
+ max_build = accum_build;
+ modified_suffix[0] = ismodified ? 'M' : '\0';
+ modified_suffix[1] = '\0';
+
+ /* phase 2: write a file with this highest build number */
+ if (*outname == '\0') {
+ fp = stdout;
+ } else if ((fp = fopen(outname, "w")) == NULL) {
+ fprintf(stderr, "Failed to create output file '%s'\n", outname);
+ return 2;
+ } /* if */
+ if (*outname != '\0') {
+ /* don't print the comments to stdout */
+ fprintf(fp, "/* This file was generated by the \"svnrev\" utility\n"
+ " * (http://www.compuphase.com/svnrev.htm).\n"
+ " * You should not modify it manually, as it may be re-generated.\n"
+ " *\n"
+ " * $Revision: %d%s$\n"
+ " * $Date: %04d-%02d-%02d$\n"
+ " */\n\n", max_build, modified_suffix, max_year, max_month, max_day);
+ } /* if */
+
+ fprintf(fp, "#ifndef UNI_REVISION_H\n");
+ fprintf(fp, "#define UNI_REVISION_H\n\n");
+ fprintf(fp, "#define UNI_REVISION\t\t%d\n", max_build);
+ fprintf(fp, "#define UNI_REVISION_STRING\t\"%s%d%s%s\"\n", prefix, max_build, modified_suffix, suffix);
+ fprintf(fp, "#define UNI_REVISION_DATE\t\"%04d-%02d-%02d\"\n", max_year, max_month, max_day);
+ fprintf(fp, "#define UNI_REVISION_STAMP\t%04d%02d%02dL\n", max_year, max_month, max_day);
+ fprintf(fp, "#define UNI_REVISION_MODIFIED\t%d\n", ismodified);
+ fprintf(fp, "\n#endif /* UNI_REVISION_H */\n");
+
+ if (*outname != '\0')
+ fclose(fp);
+
+ return 0;
+}
diff --git a/libs/unimrcp/build/svnrev/svnrev.input b/libs/unimrcp/build/svnrev/svnrev.input
new file mode 100644
index 0000000000..1f73eb847e
--- /dev/null
+++ b/libs/unimrcp/build/svnrev/svnrev.input
@@ -0,0 +1,32 @@
+build
+libs/apr-toolkit/include
+libs/apr-toolkit/src
+libs/mpf/include
+libs/mpf/src
+libs/mrcp/control/include
+libs/mrcp/control/src
+libs/mrcp/include
+libs/mrcp/message/include
+libs/mrcp/message/src
+libs/mrcp/resources/include
+libs/mrcp/resources/src
+libs/mrcp-client/include
+libs/mrcp-client/src
+libs/mrcp-server/include
+libs/mrcp-server/src
+libs/mrcp-engine/include
+libs/mrcp-engine/src
+libs/mrcp-signaling/include
+libs/mrcp-signaling/src
+libs/mrcpv2-transport/include
+libs/mrcpv2-transport/src
+libs/uni-rtsp/include
+libs/uni-rtsp/src
+modules/mrcp-sofiasip/include
+modules/mrcp-sofiasip/src
+modules/mrcp-unirtsp/include
+modules/mrcp-unirtsp/src
+platforms/libunimrcp-client/include
+platforms/libunimrcp-client/src
+platforms/libunimrcp-server/include
+platforms/libunimrcp-server/src
\ No newline at end of file
diff --git a/libs/unimrcp/build/svnrev/svnrev.vcproj b/libs/unimrcp/build/svnrev/svnrev.vcproj
new file mode 100644
index 0000000000..44259880b7
--- /dev/null
+++ b/libs/unimrcp/build/svnrev/svnrev.vcproj
@@ -0,0 +1,345 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/unimrcp/build/tools/prepare.2008.vcproj b/libs/unimrcp/build/tools/prepare.2008.vcproj
deleted file mode 100644
index d19d002f7e..0000000000
--- a/libs/unimrcp/build/tools/prepare.2008.vcproj
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/build/tools/prepare.vcproj b/libs/unimrcp/build/tools/prepare.vcproj
index 370cabb3f6..4fec72ee99 100644
--- a/libs/unimrcp/build/tools/prepare.vcproj
+++ b/libs/unimrcp/build/tools/prepare.vcproj
@@ -28,7 +28,7 @@
>
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/build/tools/unimrcp_service.c b/libs/unimrcp/build/tools/unimrcp_service.c
index b8a1bd7a2d..c76459fa19 100644
--- a/libs/unimrcp/build/tools/unimrcp_service.c
+++ b/libs/unimrcp/build/tools/unimrcp_service.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: unimrcp_service.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include
diff --git a/libs/unimrcp/build/tools/unimrcpservice.2008.vcproj b/libs/unimrcp/build/tools/unimrcpservice.2008.vcproj
deleted file mode 100644
index 2ae65f7c05..0000000000
--- a/libs/unimrcp/build/tools/unimrcpservice.2008.vcproj
+++ /dev/null
@@ -1,158 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/build/tools/unimrcpservice.vcproj b/libs/unimrcp/build/tools/unimrcpservice.vcproj
index 0b3f899e18..1c0b13840f 100644
--- a/libs/unimrcp/build/tools/unimrcpservice.vcproj
+++ b/libs/unimrcp/build/tools/unimrcpservice.vcproj
@@ -51,7 +51,7 @@
/>
-
/** major version
* Major API changes that could cause compatibility problems for older
* programs such as structure size changes. No binary compatibility is
* possible across a change in the major version.
*/
-#define UNI_MAJOR_VERSION 0
+#define UNI_MAJOR_VERSION 1
/** minor version
* Minor API changes that do not cause binary compatibility problems.
* Reset to 0 when upgrading UNI_MAJOR_VERSION
*/
-#define UNI_MINOR_VERSION 9
+#define UNI_MINOR_VERSION 0
/** patch level
* The Patch Level never includes API changes, simply bug fixes.
@@ -57,10 +57,40 @@
|| ((major) == UNI_MAJOR_VERSION && (minor) < UNI_MINOR_VERSION) \
|| ((major) == UNI_MAJOR_VERSION && (minor) == UNI_MINOR_VERSION && (patch) <= UNI_PATCH_VERSION))
+
+/** Properly quote a value as a string in the C preprocessor */
+#define UNI_STRINGIFY(n) UNI_STRINGIFY_HELPER(n)
+/** Helper macro for UNI_STRINGIFY */
+#define UNI_STRINGIFY_HELPER(n) #n
+
/** The formatted string of UniMRCP's version */
#define UNI_VERSION_STRING \
- APR_STRINGIFY(UNI_MAJOR_VERSION) "." \
- APR_STRINGIFY(UNI_MINOR_VERSION) "." \
- APR_STRINGIFY(UNI_PATCH_VERSION)
+ UNI_STRINGIFY(UNI_MAJOR_VERSION) "." \
+ UNI_STRINGIFY(UNI_MINOR_VERSION) "." \
+ UNI_STRINGIFY(UNI_PATCH_VERSION)
-#endif /* __UNI_VERSION_H__ */
+/** An alternative formatted string of UniMRCP's version
+ macro for Win32 .rc files using numeric csv representation */
+#define UNI_VERSION_STRING_CSV UNI_MAJOR_VERSION ##, \
+ ##UNI_MINOR_VERSION ##, \
+ ##UNI_PATCH_VERSION
+
+/** The Copyright */
+#define UNI_COPYRIGHT "Copyright 2008-2010 Arsen Chaloyan"
+
+/** The License */
+#define UNI_LICENSE \
+ "Licensed under the Apache License, Version 2.0 (the ""License"");" \
+ "you may not use this file except in compliance with the License." \
+ "You may obtain a copy of the License at" \
+ "" \
+ " http://www.apache.org/licenses/LICENSE-2.0" \
+ "" \
+ "Unless required by applicable law or agreed to in writing, software" \
+ "distributed under the License is distributed on an ""AS IS"" BASIS," \
+ "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied." \
+ "See the License for the specific language governing permissions and" \
+ "limitations under the License."
+
+
+#endif /* UNI_VERSION_H */
diff --git a/libs/unimrcp/build/vsprops/apr.props b/libs/unimrcp/build/vsprops/apr.props
deleted file mode 100644
index 660a970181..0000000000
--- a/libs/unimrcp/build/vsprops/apr.props
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
- $(LibRootDir)libs\apr
- $(LibRootDir)libs\apr-util
- $(LibRootDir)libs\apr-iconv
-
-
- <_ProjectFileVersion>10.0.30319.1
-
-
-
- $(AprDir)\include;$(AprUtilDir)\include;%(AdditionalIncludeDirectories)
-
-
-
-
- $(AprDir)
-
-
- $(AprUtilDir)
-
-
- $(AprIconvDir)
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/build/vsprops/apt.props b/libs/unimrcp/build/vsprops/apt.props
deleted file mode 100644
index 8ede1684dc..0000000000
--- a/libs/unimrcp/build/vsprops/apt.props
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
-
-
-
- $(ProjectRootDir)libs\apr-toolkit\include;%(AdditionalIncludeDirectories)
- APT_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/build/vsprops/cepstral.vsprops b/libs/unimrcp/build/vsprops/cepstral.vsprops
deleted file mode 100644
index 8df44eba0f..0000000000
--- a/libs/unimrcp/build/vsprops/cepstral.vsprops
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
diff --git a/libs/unimrcp/build/vsprops/mpf.props b/libs/unimrcp/build/vsprops/mpf.props
deleted file mode 100644
index ff68ceaef2..0000000000
--- a/libs/unimrcp/build/vsprops/mpf.props
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
-
-
-
- $(ProjectRootDir)libs\mpf\include;%(AdditionalIncludeDirectories)
- MPF_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/build/vsprops/mrcp.props b/libs/unimrcp/build/vsprops/mrcp.props
deleted file mode 100644
index fa4ee3539b..0000000000
--- a/libs/unimrcp/build/vsprops/mrcp.props
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
-
-
-
- $(ProjectRootDir)libs\mrcp\include;$(ProjectRootDir)libs\mrcp\message\include;$(ProjectRootDir)libs\mrcp\control\include;$(ProjectRootDir)libs\mrcp\resources\include;%(AdditionalIncludeDirectories)
- MRCP_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/build/vsprops/mrcpclient.props b/libs/unimrcp/build/vsprops/mrcpclient.props
deleted file mode 100644
index b650e07d91..0000000000
--- a/libs/unimrcp/build/vsprops/mrcpclient.props
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
-
-
-
- $(ProjectRootDir)libs\mrcp-client\include;%(AdditionalIncludeDirectories)
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/build/vsprops/mrcpsignaling.props b/libs/unimrcp/build/vsprops/mrcpsignaling.props
deleted file mode 100644
index 5e0c884a9f..0000000000
--- a/libs/unimrcp/build/vsprops/mrcpsignaling.props
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
-
-
-
- $(ProjectRootDir)libs\mrcp-signaling\include;%(AdditionalIncludeDirectories)
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/build/vsprops/mrcpv2transport.props b/libs/unimrcp/build/vsprops/mrcpv2transport.props
deleted file mode 100644
index c71836559b..0000000000
--- a/libs/unimrcp/build/vsprops/mrcpv2transport.props
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
-
-
-
- $(ProjectRootDir)libs\mrcpv2-transport\include;%(AdditionalIncludeDirectories)
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/build/vsprops/sofiasip.props b/libs/unimrcp/build/vsprops/sofiasip.props
deleted file mode 100644
index 3714d30977..0000000000
--- a/libs/unimrcp/build/vsprops/sofiasip.props
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
- $(LibRootDir)libs\sofia-sip
-
-
- <_ProjectFileVersion>10.0.30319.1
-
-
-
- $(SofiaDir)\win32;$(SofiaDir)\libsofia-sip-ua\su;$(SofiaDir)\libsofia-sip-ua\nua;$(SofiaDir)\libsofia-sip-ua\url;$(SofiaDir)\libsofia-sip-ua\sip;$(SofiaDir)\libsofia-sip-ua\msg;$(SofiaDir)\libsofia-sip-ua\sdp;$(SofiaDir)\libsofia-sip-ua\nta;$(SofiaDir)\libsofia-sip-ua\nea;$(SofiaDir)\libsofia-sip-ua\soa;$(SofiaDir)\libsofia-sip-ua\iptsec;$(SofiaDir)\libsofia-sip-ua\bnf;$(SofiaDir)\libsofia-sip-ua\features;%(AdditionalIncludeDirectories)
-
-
-
-
- $(SofiaDir)
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/build/vsprops/unibase.props b/libs/unimrcp/build/vsprops/unibase.props
deleted file mode 100644
index 097e8596ab..0000000000
--- a/libs/unimrcp/build/vsprops/unibase.props
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
- $(ProjectDir)..\..\
- $(SolutionDir)
-
-
- <_ProjectFileVersion>10.0.30319.1
-
-
-
- WIN32;%(PreprocessorDefinitions)
- Level4
- true
- 4100;%(DisableSpecificWarnings)
-
-
-
-
- $(ProjectRootDir)
-
-
- $(LibRootDir)
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/build/vsprops/unidebug.props b/libs/unimrcp/build/vsprops/unidebug.props
deleted file mode 100644
index e9778995ab..0000000000
--- a/libs/unimrcp/build/vsprops/unidebug.props
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
-
-
-
- Disabled
- _DEBUG;%(PreprocessorDefinitions)
- true
- EnableFastChecks
- MultiThreadedDebugDLL
-
-
- ProgramDatabase
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/build/vsprops/unimrcpclient.vsprops b/libs/unimrcp/build/vsprops/unimrcpclient.vsprops
index 613b2ff02f..8f1edceebd 100644
--- a/libs/unimrcp/build/vsprops/unimrcpclient.vsprops
+++ b/libs/unimrcp/build/vsprops/unimrcpclient.vsprops
@@ -11,6 +11,6 @@
/>
diff --git a/libs/unimrcp/build/vsprops/unimrcpplugin.vsprops b/libs/unimrcp/build/vsprops/unimrcpplugin.vsprops
deleted file mode 100644
index 53c6857dfd..0000000000
--- a/libs/unimrcp/build/vsprops/unimrcpplugin.vsprops
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
diff --git a/libs/unimrcp/build/vsprops/unimrcpserver.vsprops b/libs/unimrcp/build/vsprops/unimrcpserver.vsprops
index 0a44b670dd..8f812676ea 100644
--- a/libs/unimrcp/build/vsprops/unimrcpserver.vsprops
+++ b/libs/unimrcp/build/vsprops/unimrcpserver.vsprops
@@ -11,6 +11,6 @@
/>
diff --git a/libs/unimrcp/build/vsprops/unirelease.props b/libs/unimrcp/build/vsprops/unirelease.props
deleted file mode 100644
index 8081506815..0000000000
--- a/libs/unimrcp/build/vsprops/unirelease.props
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
-
-
-
- NDEBUG;%(PreprocessorDefinitions)
- MultiThreadedDLL
-
-
- ProgramDatabase
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/build/vsprops/unirtsp.props b/libs/unimrcp/build/vsprops/unirtsp.props
deleted file mode 100644
index 7ed01cb9a8..0000000000
--- a/libs/unimrcp/build/vsprops/unirtsp.props
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
-
-
-
- $(ProjectRootDir)libs\uni-rtsp\include;%(AdditionalIncludeDirectories)
- RTSP_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/conf/Makefile.am b/libs/unimrcp/conf/Makefile.am
index 9241bbe561..d317e66ecb 100644
--- a/libs/unimrcp/conf/Makefile.am
+++ b/libs/unimrcp/conf/Makefile.am
@@ -2,10 +2,17 @@ MAINTAINERCLEANFILES = Makefile.in
def-conf:
test -d $(confdir) || $(mkinstalldirs) $(confdir)
- for conffile in `find ./ -name \*.xml` ; do \
+ for conffile in `find ./ -maxdepth 1 -name \*.xml -o -name \*.xsd` ; do \
filename=`echo $$conffile | sed -e 's|^.*/||'`; \
$(INSTALL) -m 644 $$filename $(confdir); \
done
+ test -d $(confdir)/client-profiles || $(mkinstalldirs) $(confdir)/client-profiles
+ for conffile in `find ./client-profiles/ -maxdepth 1 -name \*.xml -o -name \*.xsd` ; do \
+ filename=`echo $$conffile | sed -e 's|^.*/||'`; \
+ $(INSTALL) -m 644 client-profiles/$$filename $(confdir)/client-profiles; \
+ done
+
+
install-data-local:
test -d $(confdir) || $(MAKE) def-conf
diff --git a/libs/unimrcp/conf/client-profiles/lumenvox.xml b/libs/unimrcp/conf/client-profiles/lumenvox.xml
new file mode 100644
index 0000000000..4b592a5450
--- /dev/null
+++ b/libs/unimrcp/conf/client-profiles/lumenvox.xml
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+ 5060
+
+
+
+
+
+
+
+ 554
+
+
+
+
+
+
+
+
+
+
+
+ SIP-Agent-1
+ MRCPv2-Agent-1
+ Media-Engine-1
+ RTP-Factory-1
+ LumenVox-SIP-Settings
+ RTP-Settings-1
+
+
+
+
+ RTSP-Agent-1
+ Media-Engine-1
+ RTP-Factory-1
+ LumenVox-RTSP-Settings
+ RTP-Settings-1
+
+
+
+
+
diff --git a/libs/unimrcp/conf/client-profiles/nuance.xml b/libs/unimrcp/conf/client-profiles/nuance.xml
new file mode 100644
index 0000000000..083f0cf8c4
--- /dev/null
+++ b/libs/unimrcp/conf/client-profiles/nuance.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+ 5060
+
+
+
+
+
+
+
+
+ 4900
+
+ media
+
+
+
+
+
+
+
+
+
+ 50
+ 200
+
+ 20
+ PCMU PCMA L16/96/8000 telephone-event/101/8000
+
+
+
+ 2
+
+ 5000
+
+ 1000
+
+
+
+
+
+
+
+
+ SIP-Agent-1
+ MRCPv2-Agent-1
+ Media-Engine-1
+ RTP-Factory-1
+ Nuance-SIP-Settings
+ Nuance-RTP-Settings
+
+
+
+
+ RTSP-Agent-1
+ Media-Engine-1
+ RTP-Factory-1
+ Nuance-RTSP-Settings
+ Nuance-RTP-Settings
+
+
+
+
+
diff --git a/libs/unimrcp/conf/client-profiles/speechpro.xml b/libs/unimrcp/conf/client-profiles/speechpro.xml
new file mode 100644
index 0000000000..9f765bef61
--- /dev/null
+++ b/libs/unimrcp/conf/client-profiles/speechpro.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+ 8000
+
+
+
+
+
+
+
+
+
+
+
+
+ RTSP-Agent-1
+ Media-Engine-1
+ RTP-Factory-1
+ SpeechPro-RTSP-Settings
+ RTP-Settings-1
+
+
+
+
+
diff --git a/libs/unimrcp/conf/client-profiles/unimrcp.xml b/libs/unimrcp/conf/client-profiles/unimrcp.xml
new file mode 100644
index 0000000000..e29d8784fd
--- /dev/null
+++ b/libs/unimrcp/conf/client-profiles/unimrcp.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+ 8060
+
+
+
+
+
+
+
+ 1554
+
+ media
+
+
+
+
+
+
+
+
+
+
+ SIP-Agent-1
+ MRCPv2-Agent-1
+ Media-Engine-1
+ RTP-Factory-1
+ UniMRCP-SIP-Settings
+ RTP-Settings-1
+
+
+
+
+ RTSP-Agent-1
+ Media-Engine-1
+ RTP-Factory-1
+ UniMRCP-RTSP-Settings
+ RTP-Settings-1
+
+
+
+
+
diff --git a/libs/unimrcp/conf/logger.xml b/libs/unimrcp/conf/logger.xml
new file mode 100644
index 0000000000..73ae9b5cac
--- /dev/null
+++ b/libs/unimrcp/conf/logger.xml
@@ -0,0 +1,38 @@
+
+
+
+
+ INFO
+
+
+
+
+
+ DATE,TIME,PRIORITY
+
+
+ NONE
+
diff --git a/libs/unimrcp/conf/umcscenarios.xml b/libs/unimrcp/conf/umcscenarios.xml
index a9f1ce67cb..d5c713e201 100644
--- a/libs/unimrcp/conf/umcscenarios.xml
+++ b/libs/unimrcp/conf/umcscenarios.xml
@@ -1,3 +1,4 @@
+
-
+
@@ -33,7 +35,7 @@ For instance,
-->
-
+
@@ -55,7 +57,7 @@ For instance,
-->
-
+
@@ -72,7 +74,7 @@ For instance,
-->
-
+
-->
@@ -89,8 +91,24 @@ For instance,
-->
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 8062
+ udp
+ UniMRCP SofiaSIP
+ UniMRCPClient
+
+
+
+
+
+
+
+
+ 100
+
+ UniMRCPClient
+
+
+
+
+ 100
+ false
+ 1024
+ 1024
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+ 4000
+ 5000
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ 50
+ 200
+
+ 20
+ PCMU PCMA L16/96/8000 telephone-event/101/8000
+
+
+
+
-
+ 1
-
+ 5000
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ 1000
+
+
+
diff --git a/libs/unimrcp/conf/unimrcpclient.xsd b/libs/unimrcp/conf/unimrcpclient.xsd
new file mode 100644
index 0000000000..349cae4252
--- /dev/null
+++ b/libs/unimrcp/conf/unimrcpclient.xsd
@@ -0,0 +1,266 @@
+
+
+
+
+ UniMRCP client document
+
+
+
+
+
+ Generic properties
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Common components
+
+
+
+
+
+ Factory of MRCP resources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SIP signaling agent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ RTSP signaling agent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MRCPv2 connection agent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Media processing engine
+
+
+
+
+
+
+
+
+
+
+
+ Factory of RTP terminations
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Settings
+
+
+
+
+
+ SIP settings
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ RTSP settings
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ RTP settings
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Profiles
+
+
+
+
+
+ MRCPv2 profile
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MRCPv1 profile
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libs/unimrcp/conf/unimrcpserver.xml b/libs/unimrcp/conf/unimrcpserver.xml
index b48e58a6e8..29189a8d03 100644
--- a/libs/unimrcp/conf/unimrcpserver.xml
+++ b/libs/unimrcp/conf/unimrcpserver.xml
@@ -1,103 +1,157 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 8060
+ udp,tcp
+
+ UniMRCP SofiaSIP
+ UniMRCPServer
+
+
+
+
+
+
+
+
+
+
+
+ 1554
+
+
+
+
+
+ 100
+ UniMRCPServer
+
+
+
+
+
+
+ 1544
+ 100
+ false
+ 1024
+ 1024
+
+
+
+
+ 1
+
+
+
+
+
+
+
+ 5000
+ 6000
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+ 50
+ 200
+
+ 20
+ PCMU PCMA L16/96/8000 telephone-event/101/8000
+
+
+
+
-
-
-
+ 1
+
+ 5000
-
-
-
-
-
-
-
-
-
-
-
-
-
+ 1000
+
+
-
+
-
-
-
-
-
-
+
+ SIP-Agent-1
+ MRCPv2-Agent-1
+ Media-Engine-1
+ RTP-Factory-1
+ RTP-Settings-1
+
+
+
+
-
-
-
-
-
+
+ RTSP-Agent-1
+ Media-Engine-1
+ RTP-Factory-1
+ RTP-Settings-1
+
diff --git a/libs/unimrcp/conf/unimrcpserver.xsd b/libs/unimrcp/conf/unimrcpserver.xsd
new file mode 100644
index 0000000000..920e5072f8
--- /dev/null
+++ b/libs/unimrcp/conf/unimrcpserver.xsd
@@ -0,0 +1,266 @@
+
+
+
+
+ UniMRCP server document
+
+
+
+
+
+ Generic properties
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Common components
+
+
+
+
+
+ Factory of MRCP resources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SIP signaling agent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ RTSP signaling agent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MRCPv2 connection agent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Media processing engine
+
+
+
+
+
+
+
+
+
+
+
+ Factory of RTP terminations
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Factory of plugins (MRCP engines)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Settings
+
+
+
+
+
+ RTP settings
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Profiles
+
+
+
+
+
+ MRCPv2 profile
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MRCPv1 profile
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/unimrcp/configure.ac b/libs/unimrcp/configure.ac
index 1ba581189b..f0fa56f737 100644
--- a/libs/unimrcp/configure.ac
+++ b/libs/unimrcp/configure.ac
@@ -3,14 +3,11 @@
AC_PREREQ(2.57)
-AC_INIT([unimrcp],[0.9.0])
+AC_INIT([unimrcp],[1.0.0])
AC_CONFIG_AUX_DIR([build])
AC_CONFIG_MACRO_DIR([build/acmacros])
AC_PREFIX_DEFAULT(/usr/local/unimrcp)
-CFLAGS="$CFLAGS $CONFIGURE_CFLAGS"
-CXXFLAGS="$CXXFLAGS $CONFIGURE_CXXFLAGS"
-LDFLAGS="$LDFLAGS $CONFIGURE_LDFLAGS"
plugindir='${prefix}/plugin'
confdir='${prefix}/conf'
@@ -120,6 +117,15 @@ AC_ARG_ENABLE(demorecog-plugin,
AM_CONDITIONAL([DEMORECOG_PLUGIN],[test "${enable_demorecog_plugin}" = "yes"])
+#Enable demo verifier plugin
+AC_ARG_ENABLE(demoverifier-plugin,
+ [AC_HELP_STRING([--disable-demoverifier-plugin ],[exclude demo verifier plugin from build])],
+ [enable_demoverifier_plugin="$enableval"],
+ [enable_demoverifier_plugin="yes"])
+
+AM_CONDITIONAL([DEMOVERIFIER_PLUGIN],[test "${enable_demoverifier_plugin}" = "yes"])
+
+
#Enable recorder plugin
AC_ARG_ENABLE(recorder-plugin,
[AC_HELP_STRING([--disable-recorder-plugin ],[exclude recorder plugin from build])],
@@ -129,20 +135,6 @@ AC_ARG_ENABLE(recorder-plugin,
AM_CONDITIONAL([RECORDER_PLUGIN],[test "${enable_recorder_plugin}" = "yes"])
-#Enable Cepstral Swift plugin
-AC_ARG_ENABLE(cepstral-plugin,
- [AC_HELP_STRING([--disable-cepstral-plugin ],[exclude cepstral plugin from build])],
- [enable_cepstral_plugin="$enableval"],
- [enable_cepstral_plugin="yes"])
-
-if test "${enable_cepstral_plugin}" != "no"; then
- UNIMRCP_CHECK_SWIFT
-fi
-
-AM_CONDITIONAL([CEPSTRAL_PLUGIN],[test "${enable_cepstral_plugin}" = "yes" &&\
- test "${found_swift}" = "yes"])
-
-
#Enable PocketSphinx plugin
AC_ARG_ENABLE(pocketsphinx-plugin,
[AC_HELP_STRING([--enable-pocketsphinx-plugin ],[enable pocketsphinx plugin])],
@@ -191,12 +183,12 @@ AC_CONFIG_FILES([
modules/mrcp-sofiasip/Makefile
modules/mrcp-unirtsp/Makefile
plugins/Makefile
- plugins/mrcp-cepstral/Makefile
plugins/mrcp-pocketsphinx/Makefile
plugins/mrcp-flite/Makefile
plugins/mrcp-recorder/Makefile
plugins/demo-synth/Makefile
plugins/demo-recog/Makefile
+ plugins/demo-verifier/Makefile
platforms/Makefile
platforms/libunimrcp-server/Makefile
platforms/libunimrcp-client/Makefile
@@ -216,8 +208,10 @@ AC_CONFIG_FILES([
build/pkgconfig/unimrcpclient.pc
build/pkgconfig/unimrcpserver.pc
build/pkgconfig/unimrcpplugin.pc
+ build/svnrev/Makefile
conf/Makefile
data/Makefile
+ docs/doxygen.conf
])
AC_OUTPUT
@@ -231,6 +225,7 @@ AC_MSG_NOTICE([ Sofia-SIP: $sofia_version])
AC_MSG_NOTICE([Plugins:])
AC_MSG_NOTICE([ Demo Synthesizer: $enable_demosynth_plugin])
AC_MSG_NOTICE([ Demo Recognizer: $enable_demorecog_plugin])
-AC_MSG_NOTICE([ Cepstral: $enable_cepstral_plugin])
+AC_MSG_NOTICE([ Demo Verifier: $enable_demoverifier_plugin])
+AC_MSG_NOTICE([ Recorder: $enable_recorder_plugin])
AC_MSG_NOTICE([ PocketSphinx: $enable_pocketsphinx_plugin])
AC_MSG_NOTICE([ Flite: $enable_flite_plugin])
diff --git a/libs/unimrcp/data/demo-16kHz.pcm b/libs/unimrcp/data/demo-16kHz.pcm
index 01ace40952..5341461c25 100644
Binary files a/libs/unimrcp/data/demo-16kHz.pcm and b/libs/unimrcp/data/demo-16kHz.pcm differ
diff --git a/libs/unimrcp/data/demo-8kHz.pcm b/libs/unimrcp/data/demo-8kHz.pcm
index 7c5bf2720b..5121fdc483 100644
Binary files a/libs/unimrcp/data/demo-8kHz.pcm and b/libs/unimrcp/data/demo-8kHz.pcm differ
diff --git a/libs/unimrcp/data/grammar.mixed b/libs/unimrcp/data/grammar.mixed
new file mode 100644
index 0000000000..2f706e7632
--- /dev/null
+++ b/libs/unimrcp/data/grammar.mixed
@@ -0,0 +1,19 @@
+
+--break
+Content-Type:text/uri-list
+Content-Length: 22
+
+builtin:grammar/digits
+
+--break
+Content-Type:application/srgs+xml
+Content-Length: 230
+
+
+
+
+ - one two three four five
+
+
+--break--
\ No newline at end of file
diff --git a/libs/unimrcp/data/johnsmith-16kHz.pcm b/libs/unimrcp/data/johnsmith-16kHz.pcm
new file mode 100644
index 0000000000..235338077d
Binary files /dev/null and b/libs/unimrcp/data/johnsmith-16kHz.pcm differ
diff --git a/libs/unimrcp/data/johnsmith-8kHz.pcm b/libs/unimrcp/data/johnsmith-8kHz.pcm
new file mode 100644
index 0000000000..8332f40732
Binary files /dev/null and b/libs/unimrcp/data/johnsmith-8kHz.pcm differ
diff --git a/libs/unimrcp/data/result-verification.xml b/libs/unimrcp/data/result-verification.xml
new file mode 100644
index 0000000000..fa0c8ceef3
--- /dev/null
+++ b/libs/unimrcp/data/result-verification.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+ 500
+ cellular-phone
+ male
+ accepted
+ 0.85
+
+
+ 1500
+ cellular-phone
+ male
+ accepted
+ 0.75
+
+
+
+
\ No newline at end of file
diff --git a/libs/unimrcp/data/speak.txt b/libs/unimrcp/data/speak.txt
index 3245b20dc9..894d43a75f 100644
--- a/libs/unimrcp/data/speak.txt
+++ b/libs/unimrcp/data/speak.txt
@@ -1 +1 @@
-Hello World.
\ No newline at end of file
+Welcome to Uni MRCP.
\ No newline at end of file
diff --git a/libs/unimrcp/data/speak.xml b/libs/unimrcp/data/speak.xml
index e9a9ec3ebd..c64e8dfb31 100644
--- a/libs/unimrcp/data/speak.xml
+++ b/libs/unimrcp/data/speak.xml
@@ -1,6 +1,6 @@
-
-
- Hello World.
-
+
+
+ Welcome to Uni MRCP.
+
\ No newline at end of file
diff --git a/libs/unimrcp/docs/doxygen.conf b/libs/unimrcp/docs/doxygen.conf.in
similarity index 91%
rename from libs/unimrcp/docs/doxygen.conf
rename to libs/unimrcp/docs/doxygen.conf.in
index 8b375cefd9..b405be48f0 100644
--- a/libs/unimrcp/docs/doxygen.conf
+++ b/libs/unimrcp/docs/doxygen.conf.in
@@ -1,6 +1,7 @@
PROJECT_NAME="UniMRCP"
+PROJECT_NUMBER = @VERSION@
-INPUT=.
+INPUT=. docs/mainpage.docs
QUIET=YES
RECURSIVE=YES
FILE_PATTERNS=*.h
diff --git a/libs/unimrcp/docs/mainpage.docs b/libs/unimrcp/docs/mainpage.docs
new file mode 100644
index 0000000000..8961b43da3
--- /dev/null
+++ b/libs/unimrcp/docs/mainpage.docs
@@ -0,0 +1,92 @@
+/**
+@mainpage UniMRCP
+
+
+@section Introduction
+
+UniMRCP is an open source cross-platform MRCP project, which provides everything required for MRCP client and server side deployment.
+
+UniMRCP encapsulates SIP/MRCPv2, RTSP, SDP and RTP/RTCP stacks inside and provides MRCP version independent user level interface for the integration.
+
+
+@section Source Tree Structure
+
+
+Libraries
+
+* apr-toolkit - set of utilities built on top of APR and APR-Util libraries (task abstraction, logging, etc)
+
+* mpf - media processing framework
+
+* mrcp - implementation of MRCP basics (message, parser, resources)
+
+* mrcpv2-transport - implementation of MRCPv2 transport layer
+
+* mrcp-signaling - abstract MRCP signaling (session management) interface
+
+* mrcp-engine - abstract resource engine interface
+
+* mrcp-client - implementation of MRCP client stack based on abstract signaling interface
+
+* mrcp-server - implementation of MRCP server stack based on abstract signaling and engine interfaces
+
+* uni-rtsp - implementation of minimal RTSP stack required for MRCPv1
+
+
+
+Modules
+
+* mrcp-sofiasip - implementation of abstract signaling interface using SofiaSIP library
+
+* mrcp-unirtsp - implementation of abstract signaling interface using UniRTSP library
+
+
+
+
+Plugins
+
+* demo-synth - simulation of actual synthesizer engine
+
+* demo-recog - simulation of actual recognizer engine
+
+* mrcp-recorder - implementation of recorder resource
+
+* mrcp-flite - implementation of synthesizer resource using open source Flite engine
+
+* mrcp-pocketsphinx - implementation of recognizer resource using open source PocketSphinx engine
+
+
+Platforms
+
+* libunimrcpclient - unimrcp client stack based on libraries and modules above
+
+* libunimrcpserver - unimrcp server stack based on libraries, modules and plugins above
+
+* unimrcpclient - sample C application based on unimrcp client stack
+
+* umc - sample C++ application based on unimrcp client stack
+
+* unimrcpserver - final unimrcp server application
+
+
+@section Dependencies
+
+ APR - Apache Portable Runtime
+
+ Sofia-SIP - SIP User Agent Library
+
+
+@section Project Links
+
+ Website
+
+ Downloads
+
+ Wiki
+
+ Issue Tracker
+
+ Discussion Group
+
+
+*/
diff --git a/libs/unimrcp/libs/apr-toolkit/Makefile.am b/libs/unimrcp/libs/apr-toolkit/Makefile.am
index e887e398c2..0647143824 100644
--- a/libs/unimrcp/libs/apr-toolkit/Makefile.am
+++ b/libs/unimrcp/libs/apr-toolkit/Makefile.am
@@ -8,38 +8,43 @@ noinst_LTLIBRARIES = libaprtoolkit.la
include_HEADERS = include/apt.h \
include/apt_obj_list.h \
include/apt_cyclic_queue.h \
+ include/apt_dir_layout.h \
include/apt_task.h \
include/apt_task_msg.h \
include/apt_consumer_task.h \
- include/apt_net_server_task.h \
- include/apt_net_client_task.h \
include/apt_pollset.h \
+ include/apt_poller_task.h \
include/apt_pool.h \
include/apt_log.h \
include/apt_pair.h \
include/apt_string.h \
include/apt_string_table.h \
+ include/apt_header_field.h \
include/apt_text_stream.h \
+ include/apt_text_message.h \
include/apt_net.h \
include/apt_nlsml_doc.h \
- include/apt_dir_layout.h \
+ include/apt_multipart_content.h \
+ include/apt_timer_queue.h \
include/apt_test_suite.h
libaprtoolkit_la_SOURCES = src/apt_obj_list.c \
src/apt_cyclic_queue.c \
+ src/apt_dir_layout.c \
src/apt_task.c \
src/apt_task_msg.c \
src/apt_consumer_task.c \
- src/apt_net_server_task.c \
- src/apt_net_client_task.c \
src/apt_pollset.c \
+ src/apt_poller_task.c \
src/apt_pool.c \
src/apt_log.c \
src/apt_pair.c \
src/apt_string_table.c \
+ src/apt_header_field.c \
src/apt_text_stream.c \
+ src/apt_text_message.c \
src/apt_net.c \
src/apt_nlsml_doc.c \
- src/apt_dir_layout.c \
+ src/apt_multipart_content.c \
+ src/apt_timer_queue.c \
src/apt_test_suite.c
-
diff --git a/libs/unimrcp/libs/apr-toolkit/aprtoolkit.2008.vcproj b/libs/unimrcp/libs/apr-toolkit/aprtoolkit.2008.vcproj
deleted file mode 100644
index d77441afa5..0000000000
--- a/libs/unimrcp/libs/apr-toolkit/aprtoolkit.2008.vcproj
+++ /dev/null
@@ -1,409 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/libs/apr-toolkit/aprtoolkit.2010.vcxproj b/libs/unimrcp/libs/apr-toolkit/aprtoolkit.2010.vcxproj
deleted file mode 100644
index 9288736c40..0000000000
--- a/libs/unimrcp/libs/apr-toolkit/aprtoolkit.2010.vcxproj
+++ /dev/null
@@ -1,157 +0,0 @@
-
-
-
-
- Debug
- Win32
-
-
- Debug
- x64
-
-
- Release
- Win32
-
-
- Release
- x64
-
-
-
- aprtoolkit
- {13DEECA0-BDD4-4744-A1A2-8EB0A44DF3D2}
- aprtoolkit
- Win32Proj
-
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
-
-
-
- APT_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- APT_STATIC_LIB;%(PreprocessorDefinitions)
- ProgramDatabase
-
-
-
-
- APT_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- APT_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {f057da7f-79e5-4b00-845c-ef446ef055e3}
- false
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/libs/apr-toolkit/aprtoolkit.2010.vcxproj.filters b/libs/unimrcp/libs/apr-toolkit/aprtoolkit.2010.vcxproj.filters
deleted file mode 100644
index db0b3156b3..0000000000
--- a/libs/unimrcp/libs/apr-toolkit/aprtoolkit.2010.vcxproj.filters
+++ /dev/null
@@ -1,125 +0,0 @@
-
-
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hpp;hxx;hm;inl;inc;xsd
-
-
- {4c2fadb2-8996-43e3-9db1-e3fc3eccee30}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/libs/apr-toolkit/aprtoolkit.vcproj b/libs/unimrcp/libs/apr-toolkit/aprtoolkit.vcproj
index 9ea77e93a6..bb2746e815 100644
--- a/libs/unimrcp/libs/apr-toolkit/aprtoolkit.vcproj
+++ b/libs/unimrcp/libs/apr-toolkit/aprtoolkit.vcproj
@@ -253,22 +253,22 @@
RelativePath=".\include\apt_dir_layout.h"
>
+
+
+
+
-
-
-
-
@@ -281,6 +281,10 @@
RelativePath=".\include\apt_pair.h"
>
+
+
@@ -309,10 +313,18 @@
RelativePath=".\include\apt_test_suite.h"
>
+
+
+
+
+
+
+
+
-
-
-
-
@@ -358,6 +370,10 @@
RelativePath=".\src\apt_pair.c"
>
+
+
@@ -382,10 +398,18 @@
RelativePath=".\src\apt_test_suite.c"
>
+
+
+
+
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt.h b/libs/unimrcp/libs/apr-toolkit/include/apt.h
index 2c0353161e..963b28b65a 100644
--- a/libs/unimrcp/libs/apr-toolkit/include/apt.h
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __APT_H__
-#define __APT_H__
+#ifndef APT_H
+#define APT_H
/**
* @file apt.h
@@ -56,4 +58,4 @@
/** Boolean value */
typedef int apt_bool_t;
-#endif /*__APT_H__*/
+#endif /* APT_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_consumer_task.h b/libs/unimrcp/libs/apr-toolkit/include/apt_consumer_task.h
index 59eff4015f..9085f0c3ba 100644
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_consumer_task.h
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_consumer_task.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_consumer_task.h 1708 2010-05-24 17:03:25Z achaloyan $
*/
-#ifndef __APT_CONSUMER_TASK_H__
-#define __APT_CONSUMER_TASK_H__
+#ifndef APT_CONSUMER_TASK_H
+#define APT_CONSUMER_TASK_H
/**
* @file apt_consumer_task.h
@@ -44,7 +46,7 @@ APT_DECLARE(apt_consumer_task_t*) apt_consumer_task_create(
* Get task base.
* @param task the consumer task to get base for
*/
-APT_DECLARE(apt_task_t*) apt_consumer_task_base_get(apt_consumer_task_t *task);
+APT_DECLARE(apt_task_t*) apt_consumer_task_base_get(const apt_consumer_task_t *task);
/**
* Get task vtable.
@@ -56,8 +58,8 @@ APT_DECLARE(apt_task_vtable_t*) apt_consumer_task_vtable_get(apt_consumer_task_t
* Get consumer task object.
* @param task the consumer task to get object from
*/
-APT_DECLARE(void*) apt_consumer_task_object_get(apt_consumer_task_t *task);
+APT_DECLARE(void*) apt_consumer_task_object_get(const apt_consumer_task_t *task);
APT_END_EXTERN_C
-#endif /*__APT_CONSUMER_TASK_H__*/
+#endif /* APT_CONSUMER_TASK_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_cyclic_queue.h b/libs/unimrcp/libs/apr-toolkit/include/apt_cyclic_queue.h
index 7c6ea3ab08..b0500855d6 100644
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_cyclic_queue.h
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_cyclic_queue.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_cyclic_queue.h 1708 2010-05-24 17:03:25Z achaloyan $
*/
-#ifndef __APT_CYCLIC_QUEUE_H__
-#define __APT_CYCLIC_QUEUE_H__
+#ifndef APT_CYCLIC_QUEUE_H
+#define APT_CYCLIC_QUEUE_H
/**
* @file apt_cyclic_queue.h
@@ -69,9 +71,9 @@ APT_DECLARE(void) apt_cyclic_queue_clear(apt_cyclic_queue_t *queue);
* @param queue the queue to query
* @return TRUE if empty, otherwise FALSE
*/
-APT_DECLARE(apt_bool_t) apt_cyclic_queue_is_empty(apt_cyclic_queue_t *queue);
+APT_DECLARE(apt_bool_t) apt_cyclic_queue_is_empty(const apt_cyclic_queue_t *queue);
APT_END_EXTERN_C
-#endif /*__APT_CYCLIC_QUEUE_H__*/
+#endif /* APT_CYCLIC_QUEUE_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_dir_layout.h b/libs/unimrcp/libs/apr-toolkit/include/apt_dir_layout.h
index 497265d381..6adda9fab8 100644
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_dir_layout.h
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_dir_layout.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_dir_layout.h 1524 2010-02-15 20:44:16Z achaloyan $
*/
-#ifndef __APT_DIR_LAYOUT_H__
-#define __APT_DIR_LAYOUT_H__
+#ifndef APT_DIR_LAYOUT_H
+#define APT_DIR_LAYOUT_H
/**
* @file apt_dir_layout.h
@@ -56,12 +58,13 @@ APT_DECLARE(apt_dir_layout_t*) apt_custom_dir_layout_create(
const char *data_dir_path,
apr_pool_t *pool);
-/**
- * Construct file path with the given file name relative to data dir.
- */
+/** Construct file path relative to data dir using the file name specified. */
APT_DECLARE(char*) apt_datadir_filepath_get(const apt_dir_layout_t *dir_layout, const char *file_name, apr_pool_t *pool);
+/** Construct file path relative to conf dir using the file name specified. */
+APT_DECLARE(char*) apt_confdir_filepath_get(const apt_dir_layout_t *dir_layout, const char *file_name, apr_pool_t *pool);
+
APT_END_EXTERN_C
-#endif /*__APT_DIR_LAYOUT_H__*/
+#endif /* APT_DIR_LAYOUT_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_header_field.h b/libs/unimrcp/libs/apr-toolkit/include/apt_header_field.h
new file mode 100644
index 0000000000..72932059dd
--- /dev/null
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_header_field.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: apt_header_field.h 1719 2010-05-31 21:09:51Z achaloyan $
+ */
+
+#ifndef APT_HEADER_FIELD_H
+#define APT_HEADER_FIELD_H
+
+/**
+ * @file apt_header_field.h
+ * @brief Header Field Declaration (RFC5322)
+ */
+
+#ifdef WIN32
+#pragma warning(disable: 4127)
+#endif
+#include
+#include "apt_string.h"
+
+APT_BEGIN_EXTERN_C
+
+/** Header field declaration */
+typedef struct apt_header_field_t apt_header_field_t;
+/** Header section declaration */
+typedef struct apt_header_section_t apt_header_section_t;
+
+/** Header field */
+struct apt_header_field_t {
+ /** Ring entry */
+ APR_RING_ENTRY(apt_header_field_t) link;
+
+ /** Name of the header field */
+ apt_str_t name;
+ /** Value of the header field */
+ apt_str_t value;
+
+ /** Numeric identifier associated with name */
+ apr_size_t id;
+};
+
+/**
+ * Header section
+ * @remark The header section is a collection of header fields.
+ * The header fields are stored in both a ring and an array.
+ * The goal is to ensure efficient access and manipulation on the header fields.
+ */
+struct apt_header_section_t {
+ /** List of header fields (name-value pairs) */
+ APR_RING_HEAD(apt_head_t, apt_header_field_t) ring;
+ /** Array of pointers to header fields */
+ apt_header_field_t **arr;
+ /** Max number of header fields */
+ apr_size_t arr_size;
+};
+
+
+/**
+ * Allocate an empty header field.
+ * @param pool the pool to allocate memory from
+ */
+APT_DECLARE(apt_header_field_t*) apt_header_field_alloc(apr_pool_t *pool);
+
+/**
+ * Create a header field using given name and value APT strings.
+ * @param name the name of the header field
+ * @param value the value of the header field
+ * @param pool the pool to allocate memory from
+ */
+APT_DECLARE(apt_header_field_t*) apt_header_field_create(const apt_str_t *name, const apt_str_t *value, apr_pool_t *pool);
+
+/**
+ * Create a header field using given name and value C strings.
+ * @param name the name of the header field
+ * @param value the value of the header field
+ * @param pool the pool to allocate memory from
+ */
+APT_DECLARE(apt_header_field_t*) apt_header_field_create_c(const char *name, const char *value, apr_pool_t *pool);
+
+/**
+ * Create a header field from entire text line consisting of a name and value pair.
+ * @param line the text line, which consists of a name and value pair
+ * @param separator the name and value separator
+ * @param pool the pool to allocate memory from
+ */
+APT_DECLARE(apt_header_field_t*) apt_header_field_create_from_line(const apt_str_t *line, char separator, apr_pool_t *pool);
+
+/**
+ * Copy specified header field.
+ * @param src_header_field the header field to copy
+ * @param pool the pool to allocate memory from
+ */
+APT_DECLARE(apt_header_field_t*) apt_header_field_copy(const apt_header_field_t *src_header_field, apr_pool_t *pool);
+
+/**
+ * Initialize header section (collection of header fields).
+ * @param header the header section to initialize
+ */
+APT_DECLARE(void) apt_header_section_init(apt_header_section_t *header);
+
+/**
+ * Allocate header section to set/get header fields by numeric identifiers.
+ * @param header the header section to allocate
+ * @param max_field_count the max number of header fields in the section (protocol dependent)
+ * @param pool the pool to allocate memory from
+ */
+APT_DECLARE(apt_bool_t) apt_header_section_array_alloc(apt_header_section_t *header, apr_size_t max_field_count, apr_pool_t *pool);
+
+/**
+ * Add (append) header field to header section.
+ * @param header the header section to add field to
+ * @param header_field the header field to add
+ */
+APT_DECLARE(apt_bool_t) apt_header_section_field_add(apt_header_section_t *header, apt_header_field_t *header_field);
+
+/**
+ * Insert header field to header section based on numreic identifier if specified.
+ * @param header the header section to insert field into
+ * @param header_field the header field to insert
+ */
+APT_DECLARE(apt_bool_t) apt_header_section_field_insert(apt_header_section_t *header, apt_header_field_t *header_field);
+
+/**
+ * Set header field in the array of header fields using associated numeric identifier.
+ * @param header the header section to set field for
+ * @param header_field the header field to set
+ * @remark Typically, the header field should be already added to the header section using apt_header_section_field_add()
+ */
+APT_DECLARE(apt_bool_t) apt_header_section_field_set(apt_header_section_t *header, apt_header_field_t *header_field);
+
+/**
+ * Remove header field from header section.
+ * @param header the header section to remove field from
+ * @param header_field the header field to remove
+ */
+APT_DECLARE(apt_bool_t) apt_header_section_field_remove(apt_header_section_t *header, apt_header_field_t *header_field);
+
+/**
+ * Check whether specified header field is set.
+ * @param header the header section to use
+ * @param id the identifier associated with the header_field to check
+ */
+static APR_INLINE apt_bool_t apt_header_section_field_check(const apt_header_section_t *header, apr_size_t id)
+{
+ if(id < header->arr_size) {
+ return header->arr[id] ? TRUE : FALSE;
+ }
+ return FALSE;
+}
+
+/**
+ * Get header field by specified identifier.
+ * @param header the header section to use
+ * @param id the identifier associated with the header_field
+ */
+static APR_INLINE apt_header_field_t* apt_header_section_field_get(const apt_header_section_t *header, apr_size_t id)
+{
+ if(id < header->arr_size) {
+ return header->arr[id];
+ }
+ return NULL;
+}
+
+APT_END_EXTERN_C
+
+#endif /* APT_HEADER_FIELD_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_log.h b/libs/unimrcp/libs/apr-toolkit/include/apt_log.h
index ea2c561331..4d7c1bc5ed 100644
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_log.h
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_log.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_log.h 1792 2011-01-10 21:08:52Z achaloyan $
*/
-#ifndef __APT_LOG_H__
-#define __APT_LOG_H__
+#ifndef APT_LOG_H
+#define APT_LOG_H
/**
* @file apt_log.h
@@ -44,8 +46,10 @@ APT_BEGIN_EXTERN_C
#define APT_SIDRES_FMT "<%s@%s>"
/** Format to log pointers and identifiers */
#define APT_PTRSID_FMT APT_PTR_FMT" "APT_SID_FMT
-/** Format to log pointers, identifiers and resources */
-#define APT_PTRSIDRES_FMT APT_PTR_FMT" "APT_SIDRES_FMT
+/** Format to log pointers and identifiers */
+#define APT_NAMESID_FMT "%s "APT_SID_FMT
+/** Format to log names, identifiers and resources */
+#define APT_NAMESIDRES_FMT "%s "APT_SIDRES_FMT
/** Priority of log messages ordered from highest priority to lowest (rfc3164) */
@@ -69,22 +73,30 @@ typedef enum {
APT_LOG_HEADER_TIME = 0x02, /**< enable time output */
APT_LOG_HEADER_PRIORITY = 0x04, /**< enable priority name output */
APT_LOG_HEADER_MARK = 0x08, /**< enable file:line mark output */
+ APT_LOG_HEADER_THREAD = 0x10, /**< enable thread identifier output */
APT_LOG_HEADER_DEFAULT = APT_LOG_HEADER_DATE | APT_LOG_HEADER_TIME | APT_LOG_HEADER_PRIORITY
} apt_log_header_e;
-/** Log output modes */
+/** Mode of log output */
typedef enum {
APT_LOG_OUTPUT_NONE = 0x00, /**< disable logging */
APT_LOG_OUTPUT_CONSOLE = 0x01, /**< enable console output */
APT_LOG_OUTPUT_FILE = 0x02 /**< enable log file output */
} apt_log_output_e;
+/** Masking mode of private data */
+typedef enum {
+ APT_LOG_MASKING_NONE, /**< log everything as is */
+ APT_LOG_MASKING_COMPLETE, /**< mask private data completely */
+ APT_LOG_MASKING_ENCRYPTED /**< encrypt private data */
+} apt_log_masking_e;
+
/** Opaque logger declaration */
typedef struct apt_logger_t apt_logger_t;
/** Prototype of extended log handler function */
-typedef apt_bool_t (*apt_log_ext_handler_f)(const char *file, int line, const char *id,
+typedef apt_bool_t (*apt_log_ext_handler_f)(const char *file, int line, const char *obj,
apt_log_priority_e priority, const char *format, va_list arg_ptr);
/**
@@ -95,6 +107,13 @@ typedef apt_bool_t (*apt_log_ext_handler_f)(const char *file, int line, const ch
*/
APT_DECLARE(apt_bool_t) apt_log_instance_create(apt_log_output_e mode, apt_log_priority_e priority, apr_pool_t *pool);
+/**
+ * Create and load the singleton instance of the logger.
+ * @param config_file the path to configuration file to load settings from
+ * @param pool the memory pool to use
+ */
+APT_DECLARE(apt_bool_t) apt_log_instance_load(const char *config_file, apr_pool_t *pool);
+
/**
* Destroy the singleton instance of the logger.
*/
@@ -116,13 +135,15 @@ APT_DECLARE(apt_bool_t) apt_log_instance_set(apt_logger_t *logger);
* @param file_name the name of the log file
* @param max_file_size the max size of the log file
* @param max_file_count the max number of files used in log rotation
+ * @param append whether to append or to truncate (start over) the log file
* @param pool the memory pool to use
*/
APT_DECLARE(apt_bool_t) apt_log_file_open(
- const char *dir_path,
- const char *file_name,
- apr_size_t max_file_size,
- apr_size_t max_file_count,
+ const char *dir_path,
+ const char *file_name,
+ apr_size_t max_file_size,
+ apr_size_t max_file_count,
+ apt_bool_t append,
apr_pool_t *pool);
/**
@@ -131,23 +152,73 @@ APT_DECLARE(apt_bool_t) apt_log_file_open(
APT_DECLARE(apt_bool_t) apt_log_file_close(void);
/**
- * Set the logging output.
+ * Set the logging output mode.
* @param mode the mode to set
*/
APT_DECLARE(apt_bool_t) apt_log_output_mode_set(apt_log_output_e mode);
+/**
+ * Check the logging output mode to be enabled (set) or not.
+ * @param mode the mode to check
+ */
+APT_DECLARE(apt_bool_t) apt_log_output_mode_check(apt_log_output_e mode);
+
+/**
+ * Translate the output mode string to bitmask of apt_log_output_e values.
+ * @param str the string to translate
+ */
+APT_DECLARE(int) apt_log_output_mode_translate(char *str);
+
/**
* Set the logging priority (log level).
* @param priority the priority to set
*/
APT_DECLARE(apt_bool_t) apt_log_priority_set(apt_log_priority_e priority);
+/**
+ * Translate the priority (log level) string to enum.
+ * @param str the string to translate
+ */
+APT_DECLARE(apt_log_priority_e) apt_log_priority_translate(const char *str);
+
/**
* Set the header (format) for log messages.
* @param header the header to set (used as bitmask)
*/
APT_DECLARE(apt_bool_t) apt_log_header_set(int header);
+/**
+ * Translate the header string to bitmask of apt_log_header_e values.
+ * @param str the string to translate
+ */
+APT_DECLARE(int) apt_log_header_translate(char *str);
+
+/**
+ * Set the masking mode of private data.
+ * @param masking the masking mode to set
+ */
+APT_DECLARE(apt_bool_t) apt_log_masking_set(apt_log_masking_e masking);
+
+/**
+ * Get the current masking mode of private data.
+ */
+APT_DECLARE(apt_log_masking_e) apt_log_masking_get();
+
+/**
+ * Translate the masking mode string to enum.
+ * @param str the string to translate
+ */
+APT_DECLARE(apt_log_masking_e) apt_log_masking_translate(const char *str);
+
+/**
+ * Mask private data based on the masking mode
+ * @param data_in the data to mask
+ * @param length the length of the data to mask on input, the length of the masked data on output
+ * @param pool the memory pool to use if needed
+ * @return The masked data.
+ */
+APT_DECLARE(const char*) apt_log_data_mask(const char *data_in, apr_size_t *length, apr_pool_t *pool);
+
/**
* Set the extended external log handler.
* @param handler the handler to pass log events to
@@ -165,6 +236,16 @@ APT_DECLARE(apt_bool_t) apt_log_ext_handler_set(apt_log_ext_handler_f handler);
*/
APT_DECLARE(apt_bool_t) apt_log(const char *file, int line, apt_log_priority_e priority, const char *format, ...);
+/**
+ * Do logging.
+ * @param file the file name log entry is generated from
+ * @param line the line number log entry is generated from
+ * @param priority the priority of the entire log entry
+ * @param obj the associated object
+ * @param format the format of the entire log entry
+ */
+APT_DECLARE(apt_bool_t) apt_obj_log(const char *file, int line, apt_log_priority_e priority, void *obj, const char *format, ...);
+
APT_END_EXTERN_C
-#endif /*__APT_LOG_H__*/
+#endif /* APT_LOG_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_multipart_content.h b/libs/unimrcp/libs/apr-toolkit/include/apt_multipart_content.h
new file mode 100644
index 0000000000..c3f2dd8de2
--- /dev/null
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_multipart_content.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: apt_multipart_content.h 1722 2010-06-01 08:40:35Z achaloyan $
+ */
+
+#ifndef APT_MULTIPART_CONTENT_H
+#define APT_MULTIPART_CONTENT_H
+
+/**
+ * @file apt_multipart_content.h
+ * @brief Multipart Content Routine
+ */
+
+#include "apt_header_field.h"
+
+APT_BEGIN_EXTERN_C
+
+/** Opaque multipart content declaration */
+typedef struct apt_multipart_content_t apt_multipart_content_t;
+
+/** Content part declaration */
+typedef struct apt_content_part_t apt_content_part_t;
+
+/** Content part */
+struct apt_content_part_t {
+ /** Header section */
+ apt_header_section_t header;
+ /** Body */
+ apt_str_t body;
+
+ /** Pointer to parsed content-type header field */
+ apt_str_t *type;
+ /** Pointer to parsed content-id header field */
+ apt_str_t *id;
+ /** Pointer to parsed content-length header field */
+ apt_str_t *length;
+};
+
+/**
+ * Create an empty multipart content
+ * @param max_content_size the max size of the content (body)
+ * @param boundary the boundary to separate content parts
+ * @param pool the pool to allocate memory from
+ * @return an empty multipart content
+ */
+APT_DECLARE(apt_multipart_content_t*) apt_multipart_content_create(apr_size_t max_content_size, const apt_str_t *boundary, apr_pool_t *pool);
+
+/**
+ * Add content part to multipart content
+ * @param multipart_content the multipart content to add content part to
+ * @param content_part the content part to add
+ * @return TRUE on success
+ */
+APT_DECLARE(apt_bool_t) apt_multipart_content_add(apt_multipart_content_t *multipart_content, const apt_content_part_t *content_part);
+
+/**
+ * Add content part to multipart content by specified header fields and body
+ * @param multipart_content the multipart content to add content part to
+ * @param content_type the type of content part
+ * @param content_id the identifier of content part
+ * @param body the body of content part
+ * @return TRUE on success
+ */
+APT_DECLARE(apt_bool_t) apt_multipart_content_add2(apt_multipart_content_t *multipart_content, const apt_str_t *content_type, const apt_str_t *content_id, const apt_str_t *body);
+
+/**
+ * Finalize multipart content generation
+ * @param multipart_content the multipart content to finalize
+ * @return generated multipart content
+ */
+APT_DECLARE(apt_str_t*) apt_multipart_content_finalize(apt_multipart_content_t *multipart_content);
+
+
+/**
+ * Assign body to multipart content to get (parse) each content part from
+ * @param body the body of multipart content to parse
+ * @param boundary the boundary to separate content parts
+ * @param pool the pool to allocate memory from
+ * @return multipart content with assigned body
+ */
+APT_DECLARE(apt_multipart_content_t*) apt_multipart_content_assign(const apt_str_t *body, const apt_str_t *boundary, apr_pool_t *pool);
+
+/**
+ * Get the next content part
+ * @param multipart_content the multipart content to get the next content part from
+ * @param content_part the parsed content part
+ * @param is_final indicates the final boundary is reached
+ * @return TRUE on success
+ */
+APT_DECLARE(apt_bool_t) apt_multipart_content_get(apt_multipart_content_t *multipart_content, apt_content_part_t *content_part, apt_bool_t *is_final);
+
+
+APT_END_EXTERN_C
+
+#endif /* APT_MULTIPART_CONTENT_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_net.h b/libs/unimrcp/libs/apr-toolkit/include/apt_net.h
index 7c9d109851..d413c7f871 100644
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_net.h
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_net.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_net.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __APT_NET_H__
-#define __APT_NET_H__
+#ifndef APT_NET_H
+#define APT_NET_H
/**
* @file apt_net.h
@@ -43,4 +45,4 @@ void apt_ntp_time_get(apr_uint32_t *sec, apr_uint32_t *frac);
APT_END_EXTERN_C
-#endif /*__APT_NET_H__*/
+#endif /* APT_NET_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_net_client_task.h b/libs/unimrcp/libs/apr-toolkit/include/apt_net_client_task.h
deleted file mode 100644
index 0cd9466f6a..0000000000
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_net_client_task.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright 2008 Arsen Chaloyan
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __APT_NET_CLIENT_TASK_H__
-#define __APT_NET_CLIENT_TASK_H__
-
-/**
- * @file apt_net_client_task.h
- * @brief Network Client Task Base
- */
-
-#include
-#include "apt_task.h"
-
-APT_BEGIN_EXTERN_C
-
-/** Opaque network client task declaration */
-typedef struct apt_net_client_task_t apt_net_client_task_t;
-/** Network client connection declaration */
-typedef struct apt_net_client_connection_t apt_net_client_connection_t;
-/** Virtual table of network client events */
-typedef struct apt_net_client_vtable_t apt_net_client_vtable_t;
-
-/** Network client connection */
-struct apt_net_client_connection_t {
- /** Memory pool */
- apr_pool_t *pool;
- /** External object */
- void *obj;
- /** Connected socket */
- apr_socket_t *sock;
- /** Socket poll descriptor */
- apr_pollfd_t sock_pfd;
- /** String identifier used for traces */
- const char *id;
-};
-
-/** Virtual table of network client events */
-struct apt_net_client_vtable_t {
- /** Message receive handler */
- apt_bool_t (*on_receive)(apt_net_client_task_t *task, apt_net_client_connection_t *connection);
-};
-
-
-/**
- * Create network client task.
- * @param max_connection_count the number of max connections
- * @param obj the external object
- * @param client_vtable the table of virtual methods of the net client task
- * @param msg_pool the pool of task messages
- * @param pool the pool to allocate memory from
- */
-APT_DECLARE(apt_net_client_task_t*) apt_net_client_task_create(
- apr_size_t max_connection_count,
- void *obj,
- const apt_net_client_vtable_t *client_vtable,
- apt_task_msg_pool_t *msg_pool,
- apr_pool_t *pool);
-
-/**
- * Destroy network client task.
- * @param task the task to destroy
- */
-APT_DECLARE(apt_bool_t) apt_net_client_task_destroy(apt_net_client_task_t *task);
-
-/**
- * Start network client task and wait for incoming requests.
- * @param task the task to start
- */
-APT_DECLARE(apt_bool_t) apt_net_client_task_start(apt_net_client_task_t *task);
-
-/**
- * Terminate connection task.
- * @param task the task to terminate
- */
-APT_DECLARE(apt_bool_t) apt_net_client_task_terminate(apt_net_client_task_t *task);
-
-/**
- * Get task base.
- * @param task the network client task to get task base from
- */
-APT_DECLARE(apt_task_t*) apt_net_client_task_base_get(apt_net_client_task_t *task);
-
-/**
- * Get task vtable.
- * @param task the network client task to get vtable from
- */
-APT_DECLARE(apt_task_vtable_t*) apt_net_client_task_vtable_get(apt_net_client_task_t *task);
-
-/**
- * Get external object.
- * @param task the task to get object from
- */
-APT_DECLARE(void*) apt_net_client_task_object_get(apt_net_client_task_t *task);
-
-/**
- * Create connection.
- */
-APT_DECLARE(apt_net_client_connection_t*) apt_net_client_connect(apt_net_client_task_t *task, const char *ip, apr_port_t port);
-
-/**
- * Close connection.
- */
-APT_DECLARE(apt_bool_t) apt_net_client_connection_close(apt_net_client_task_t *task, apt_net_client_connection_t *connection);
-
-/**
- * Close and destroy connection.
- */
-APT_DECLARE(apt_bool_t) apt_net_client_disconnect(apt_net_client_task_t *task, apt_net_client_connection_t *connection);
-
-
-APT_END_EXTERN_C
-
-#endif /*__APT_NET_CLIENT_TASK_H__*/
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_net_server_task.h b/libs/unimrcp/libs/apr-toolkit/include/apt_net_server_task.h
deleted file mode 100644
index fa97836463..0000000000
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_net_server_task.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright 2008 Arsen Chaloyan
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __APT_NET_SERVER_TASK_H__
-#define __APT_NET_SERVER_TASK_H__
-
-/**
- * @file apt_net_server_task.h
- * @brief Network Server Task Base
- */
-
-#include
-#include "apt_task.h"
-
-APT_BEGIN_EXTERN_C
-
-/** Opaque network server task declaration */
-typedef struct apt_net_server_task_t apt_net_server_task_t;
-/** Network server connection declaration */
-typedef struct apt_net_server_connection_t apt_net_server_connection_t;
-/** Virtual table of network server events */
-typedef struct apt_net_server_vtable_t apt_net_server_vtable_t;
-
-/** Network server connection */
-struct apt_net_server_connection_t {
- /** Memory pool */
- apr_pool_t *pool;
- /** External object */
- void *obj;
- /** Client IP address */
- char *client_ip;
- /** Accepted socket */
- apr_socket_t *sock;
- /** Socket poll descriptor */
- apr_pollfd_t sock_pfd;
- /** String identifier used for traces */
- const char *id;
-};
-
-/** Virtual table of network server events */
-struct apt_net_server_vtable_t {
- /** Connect event handler */
- apt_bool_t (*on_connect)(apt_net_server_task_t *task, apt_net_server_connection_t *connection);
- /** Disconnect event handler */
- apt_bool_t (*on_disconnect)(apt_net_server_task_t *task, apt_net_server_connection_t *connection);
- /** Message receive handler */
- apt_bool_t (*on_receive)(apt_net_server_task_t *task, apt_net_server_connection_t *connection);
-};
-
-
-/**
- * Create network server task.
- * @param listen_ip the listen IP address
- * @param listen_port the listen port
- * @param max_connection_count the number of max connections to accept
- * @param obj the external object
- * @param server_vtable the table of virtual methods of the net server task
- * @param msg_pool the pool of task messages
- * @param pool the pool to allocate memory from
- */
-APT_DECLARE(apt_net_server_task_t*) apt_net_server_task_create(
- const char *listen_ip,
- apr_port_t listen_port,
- apr_size_t max_connection_count,
- void *obj,
- const apt_net_server_vtable_t *server_vtable,
- apt_task_msg_pool_t *msg_pool,
- apr_pool_t *pool);
-
-/**
- * Destroy network server task.
- * @param task the task to destroy
- */
-APT_DECLARE(apt_bool_t) apt_net_server_task_destroy(apt_net_server_task_t *task);
-
-/**
- * Start network server task and wait for incoming requests.
- * @param task the task to start
- */
-APT_DECLARE(apt_bool_t) apt_net_server_task_start(apt_net_server_task_t *task);
-
-/**
- * Terminate connection task.
- * @param task the task to terminate
- */
-APT_DECLARE(apt_bool_t) apt_net_server_task_terminate(apt_net_server_task_t *task);
-
-/**
- * Get task base.
- * @param task the network server task to get task base from
- */
-APT_DECLARE(apt_task_t*) apt_net_server_task_base_get(apt_net_server_task_t *task);
-
-/**
- * Get task vtable.
- * @param task the network server task to get vtable from
- */
-APT_DECLARE(apt_task_vtable_t*) apt_net_server_task_vtable_get(apt_net_server_task_t *task);
-
-/**
- * Get external object.
- * @param task the task to get object from
- */
-APT_DECLARE(void*) apt_net_server_task_object_get(apt_net_server_task_t *task);
-
-/**
- * Close connection.
- */
-APT_DECLARE(apt_bool_t) apt_net_server_connection_close(apt_net_server_task_t *task, apt_net_server_connection_t *connection);
-
-/**
- * Destroy connection.
- */
-APT_DECLARE(void) apt_net_server_connection_destroy(apt_net_server_connection_t *connection);
-
-
-APT_END_EXTERN_C
-
-#endif /*__APT_NET_SERVER_TASK_H__*/
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_nlsml_doc.h b/libs/unimrcp/libs/apr-toolkit/include/apt_nlsml_doc.h
index ab8724598f..ca29a07ad8 100644
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_nlsml_doc.h
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_nlsml_doc.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_nlsml_doc.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __APT_NLSML_DOC_H__
-#define __APT_NLSML_DOC_H__
+#ifndef APT_NLSML_DOC_H
+#define APT_NLSML_DOC_H
/**
* @file apt_nlsml_doc.h
@@ -45,4 +47,4 @@ APT_DECLARE(const char *) nlsml_input_attrib_get(const apr_xml_elem *input, cons
APT_END_EXTERN_C
-#endif /*__APT_NLSML_DOC_H__*/
+#endif /* APT_NLSML_DOC_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_obj_list.h b/libs/unimrcp/libs/apr-toolkit/include/apt_obj_list.h
index ed3359567d..3d17a81595 100644
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_obj_list.h
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_obj_list.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_obj_list.h 1708 2010-05-24 17:03:25Z achaloyan $
*/
-#ifndef __APT_OBJ_LIST_H__
-#define __APT_OBJ_LIST_H__
+#ifndef APT_OBJ_LIST_H
+#define APT_OBJ_LIST_H
/**
* @file apt_obj_list.h
@@ -65,40 +67,40 @@ APT_DECLARE(void*) apt_list_pop_front(apt_obj_list_t *list);
* Retrieve object of the first element in the list.
* @param list the list to retrieve from
*/
-APT_DECLARE(void*) apt_list_head(apt_obj_list_t *list);
+APT_DECLARE(void*) apt_list_head(const apt_obj_list_t *list);
/**
* Retrieve object of the last element in the list.
* @param list the list to retrieve from
*/
-APT_DECLARE(void*) apt_obj_list_tail(apt_obj_list_t *list);
+APT_DECLARE(void*) apt_obj_list_tail(const apt_obj_list_t *list);
/**
* Retrieve the first element of the list.
* @param list the list to retrieve from
*/
-APT_DECLARE(apt_list_elem_t*) apt_list_first_elem_get(apt_obj_list_t *list);
+APT_DECLARE(apt_list_elem_t*) apt_list_first_elem_get(const apt_obj_list_t *list);
/**
* Retrieve the last element of the list.
* @param list the list to retrieve from
*/
-APT_DECLARE(apt_list_elem_t*) apt_list_last_elem_get(apt_obj_list_t *list);
+APT_DECLARE(apt_list_elem_t*) apt_list_last_elem_get(const apt_obj_list_t *list);
/**
* Retrieve the next element of the list.
* @param list the list to retrieve from
* @param elem the element to retrieve next element from
*/
-APT_DECLARE(apt_list_elem_t*) apt_list_next_elem_get(apt_obj_list_t *list, apt_list_elem_t *elem);
+APT_DECLARE(apt_list_elem_t*) apt_list_next_elem_get(const apt_obj_list_t *list, apt_list_elem_t *elem);
/**
* Retrieve the prev element of the list.
* @param list the list to retrieve from
* @param elem the element to retrieve prev element from
*/
-APT_DECLARE(apt_list_elem_t*) apt_list_prev_elem_get(apt_obj_list_t *list, apt_list_elem_t *elem);
+APT_DECLARE(apt_list_elem_t*) apt_list_prev_elem_get(const apt_obj_list_t *list, apt_list_elem_t *elem);
/**
* Insert element to the list.
@@ -123,15 +125,15 @@ APT_DECLARE(apt_list_elem_t*) apt_list_elem_remove(apt_obj_list_t *list, apt_lis
* @param list the list to query
* @return TRUE if empty, otherwise FALSE
*/
-APT_DECLARE(apt_bool_t) apt_list_is_empty(apt_obj_list_t *list);
+APT_DECLARE(apt_bool_t) apt_list_is_empty(const apt_obj_list_t *list);
/**
* Retrieve the object associated with element.
* @param elem the element to retrieve object from
*/
-APT_DECLARE(void*) apt_list_elem_object_get(apt_list_elem_t *elem);
+APT_DECLARE(void*) apt_list_elem_object_get(const apt_list_elem_t *elem);
APT_END_EXTERN_C
-#endif /*__APT_OBJ_LIST_H__*/
+#endif /* APT_OBJ_LIST_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_pair.h b/libs/unimrcp/libs/apr-toolkit/include/apt_pair.h
index 36b74dfbaa..4f3d8c55d6 100644
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_pair.h
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_pair.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_pair.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __APT_PAIR_H__
-#define __APT_PAIR_H__
+#ifndef APT_PAIR_H
+#define APT_PAIR_H
/**
* @file apt_pair.h
@@ -70,4 +72,4 @@ APT_DECLARE(const apt_pair_t*) apt_pair_array_get(const apt_pair_arr_t *arr, int
APT_END_EXTERN_C
-#endif /*__APT_PAIR_H__*/
+#endif /* APT_PAIR_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_poller_task.h b/libs/unimrcp/libs/apr-toolkit/include/apt_poller_task.h
new file mode 100644
index 0000000000..e1a3c6a655
--- /dev/null
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_poller_task.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: apt_poller_task.h 1708 2010-05-24 17:03:25Z achaloyan $
+ */
+
+#ifndef APT_POLLER_TASK_H
+#define APT_POLLER_TASK_H
+
+/**
+ * @file apt_poller_task.h
+ * @brief Poller Task
+ */
+
+#include "apt_pollset.h"
+#include "apt_task.h"
+#include "apt_timer_queue.h"
+
+APT_BEGIN_EXTERN_C
+
+/** Opaque poller task declaration */
+typedef struct apt_poller_task_t apt_poller_task_t;
+
+/** Function prototype to handle signalled descripors */
+typedef apt_bool_t (*apt_poll_signal_f)(void *obj, const apr_pollfd_t *descriptor);
+
+
+/**
+ * Create poller task.
+ * @param max_pollset_size the maximum number of descriptors pollset can hold
+ * @param signal_handler the handler of signalled descriptors
+ * @param obj the external object to pass to callback
+ * @param msg_pool the pool of task messages
+ * @param pool the pool to allocate memory from
+ */
+APT_DECLARE(apt_poller_task_t*) apt_poller_task_create(
+ apr_size_t max_pollset_size,
+ apt_poll_signal_f signal_handler,
+ void *obj,
+ apt_task_msg_pool_t *msg_pool,
+ apr_pool_t *pool);
+
+/**
+ * Destroy poller task.
+ * @param task the task to destroy
+ */
+APT_DECLARE(apt_bool_t) apt_poller_task_destroy(apt_poller_task_t *task);
+
+/**
+ * Cleanup poller task.
+ * @param task the task to cleanup
+ *
+ * @remark This function should be considered in protected scope.
+ * It will be called on task destroy unless you override the behavior.
+ */
+APT_DECLARE(void) apt_poller_task_cleanup(apt_poller_task_t *task);
+
+/**
+ * Start poller task and wait for incoming messages.
+ * @param task the task to start
+ */
+APT_DECLARE(apt_bool_t) apt_poller_task_start(apt_poller_task_t *task);
+
+/**
+ * Terminate poller task.
+ * @param task the task to terminate
+ */
+APT_DECLARE(apt_bool_t) apt_poller_task_terminate(apt_poller_task_t *task);
+
+/**
+ * Get task base.
+ * @param task the poller task to get task base from
+ */
+APT_DECLARE(apt_task_t*) apt_poller_task_base_get(const apt_poller_task_t *task);
+
+/**
+ * Get task vtable.
+ * @param task the poller task to get vtable from
+ */
+APT_DECLARE(apt_task_vtable_t*) apt_poller_task_vtable_get(apt_poller_task_t *task);
+
+/**
+ * Get external object.
+ * @param task the poller task to get object from
+ */
+APT_DECLARE(void*) apt_poller_task_object_get(const apt_poller_task_t *task);
+
+/**
+ * Get pollset.
+ * @param task the poller task to get pollset from
+ */
+APT_DECLARE(apt_pollset_t*) apt_poller_task_pollset_get(const apt_poller_task_t *task);
+
+/**
+ * Create timer.
+ * @param task the poller task to create timer in the scope of
+ * @param proc the timer callback
+ * @param obj the object to pass to callback
+ * @param pool the pool to allocate memory from
+ */
+APT_DECLARE(apt_timer_t*) apt_poller_task_timer_create(
+ apt_poller_task_t *task,
+ apt_timer_proc_f proc,
+ void *obj,
+ apr_pool_t *pool);
+
+
+APT_END_EXTERN_C
+
+#endif /* APT_POLLER_TASK_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_pollset.h b/libs/unimrcp/libs/apr-toolkit/include/apt_pollset.h
index 05ba559bd3..3f7d56527b 100644
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_pollset.h
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_pollset.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_pollset.h 1565 2010-03-06 07:13:04Z achaloyan $
*/
-#ifndef __APT_POLLSET_H__
-#define __APT_POLLSET_H__
+#ifndef APT_POLLSET_H
+#define APT_POLLSET_H
/**
* @file apt_pollset.h
@@ -39,7 +41,7 @@ APT_BEGIN_EXTERN_C
typedef struct apt_pollset_t apt_pollset_t;
/**
- * Create interruptable pollset on top of APR pollset
+ * Create interruptable pollset on top of APR pollset.
* @param size the maximum number of descriptors pollset can hold
* @param pool the pool to allocate memory from
*/
@@ -69,7 +71,7 @@ APT_DECLARE(apt_bool_t) apt_pollset_remove(apt_pollset_t *pollset, const apr_pol
* Block for activity on the descriptor(s) in a pollset.
* @param pollset the pollset to use
* @param timeout the timeout in microseconds
- * @param num nthe umber of signalled descriptors (output parameter)
+ * @param num the number of signalled descriptors (output parameter)
* @param descriptors the array of signalled descriptors (output parameter)
*/
APT_DECLARE(apr_status_t) apt_pollset_poll(
@@ -93,4 +95,4 @@ APT_DECLARE(apt_bool_t) apt_pollset_is_wakeup(apt_pollset_t *pollset, const apr_
APT_END_EXTERN_C
-#endif /*__APT_POLLSET_H__*/
+#endif /* APT_POLLSET_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_pool.h b/libs/unimrcp/libs/apr-toolkit/include/apt_pool.h
index b2bff52688..7f1aabaf2b 100644
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_pool.h
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_pool.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_pool.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __APT_POOL_H__
-#define __APT_POOL_H__
+#ifndef APT_POOL_H
+#define APT_POOL_H
/**
* @file apt_pool.h
@@ -44,4 +46,4 @@ APT_DECLARE(apr_pool_t*) apt_subpool_create(apr_pool_t *parent);
APT_END_EXTERN_C
-#endif /*__APT_POOL_H__*/
+#endif /* APT_POOL_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_string.h b/libs/unimrcp/libs/apr-toolkit/include/apt_string.h
index 31dd72c0b4..23be9655d4 100644
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_string.h
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_string.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_string.h 1531 2010-02-20 14:19:53Z achaloyan $
*/
-#ifndef __APT_STRING_H__
-#define __APT_STRING_H__
+#ifndef APT_STRING_H
+#define APT_STRING_H
/**
* @file apt_string.h
@@ -65,7 +67,7 @@ static APR_INLINE apr_size_t apt_string_length_get(const apt_str_t *str)
/** Check whether string is empty. */
static APR_INLINE apr_size_t apt_string_is_empty(const apt_str_t *str)
{
- return str->length ? TRUE : FALSE;
+ return str->length ? FALSE : TRUE;
}
/**
@@ -140,4 +142,4 @@ static APR_INLINE apt_bool_t apt_string_compare(const apt_str_t *str1, const apt
APT_END_EXTERN_C
-#endif /*__APT_STRING_H__*/
+#endif /* APT_STRING_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_string_table.h b/libs/unimrcp/libs/apr-toolkit/include/apt_string_table.h
index 112bd6bffc..3ba927f44e 100644
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_string_table.h
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_string_table.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_string_table.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __APT_STRING_TABLE_H__
-#define __APT_STRING_TABLE_H__
+#ifndef APT_STRING_TABLE_H
+#define APT_STRING_TABLE_H
/**
* @file apt_string_table.h
@@ -60,4 +62,4 @@ APT_DECLARE(apr_size_t) apt_string_table_id_find(const apt_str_table_item_t tabl
APT_END_EXTERN_C
-#endif /*__APT_STRING_TABLE_H__*/
+#endif /* APT_STRING_TABLE_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_task.h b/libs/unimrcp/libs/apr-toolkit/include/apt_task.h
index 29c2dea399..031eff6af8 100644
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_task.h
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_task.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_task.h 1696 2010-05-20 15:44:16Z achaloyan $
*/
-#ifndef __APT_TASK_H__
-#define __APT_TASK_H__
+#ifndef APT_TASK_H
+#define APT_TASK_H
/**
* @file apt_task.h
@@ -124,19 +126,19 @@ APT_DECLARE(apt_bool_t) apt_task_msg_process(apt_task_t *task, apt_task_msg_t *m
* Get parent (master) task.
* @param task the task to get parent from
*/
-APT_DECLARE(apt_task_t*) apt_task_parent_get(apt_task_t *task);
+APT_DECLARE(apt_task_t*) apt_task_parent_get(const apt_task_t *task);
/**
* Get memory pool associated with task.
* @param task the task to get pool from
*/
-APT_DECLARE(apr_pool_t*) apt_task_pool_get(apt_task_t *task);
+APT_DECLARE(apr_pool_t*) apt_task_pool_get(const apt_task_t *task);
/**
* Get external object associated with the task.
* @param task the task to get object from
*/
-APT_DECLARE(void*) apt_task_object_get(apt_task_t *task);
+APT_DECLARE(void*) apt_task_object_get(const apt_task_t *task);
/**
* Get task vtable.
@@ -155,7 +157,7 @@ APT_DECLARE(void) apt_task_name_set(apt_task_t *task, const char *name);
* Get task name.
* @param task the task to get name from
*/
-APT_DECLARE(const char*) apt_task_name_get(apt_task_t *task);
+APT_DECLARE(const char*) apt_task_name_get(const apt_task_t *task);
/**
* Enable/disable auto ready mode.
@@ -170,6 +172,36 @@ APT_DECLARE(void) apt_task_auto_ready_set(apt_task_t *task, apt_bool_t auto_read
*/
APT_DECLARE(apt_bool_t) apt_task_ready(apt_task_t *task);
+/**
+ * Get the running flag.
+ * @param task the task
+ */
+APT_DECLARE(apt_bool_t*) apt_task_running_flag_get(apt_task_t *task);
+
+/**
+ * Add start request.
+ * @param task the task
+ */
+APT_DECLARE(apt_bool_t) apt_task_start_request_add(apt_task_t *task);
+
+/**
+ * Remove start request.
+ * @param task the task
+ */
+APT_DECLARE(apt_bool_t) apt_task_start_request_remove(apt_task_t *task);
+
+/**
+ * Add termination request.
+ * @param task the task
+ */
+APT_DECLARE(apt_bool_t) apt_task_terminate_request_add(apt_task_t *task);
+
+/**
+ * Remove termination request.
+ * @param task the task
+ */
+APT_DECLARE(apt_bool_t) apt_task_terminate_request_remove(apt_task_t *task);
+
/**
* Hold task execution.
* @param msec the time to hold
@@ -197,26 +229,16 @@ struct apt_task_vtable_t {
apt_task_event_f on_pre_run;
/** Virtual post-run event handler */
apt_task_event_f on_post_run;
+ /** Virtual start-request event handler */
+ apt_task_event_f on_start_request;
/** Virtual start-complete event handler */
apt_task_event_f on_start_complete;
+ /** Virtual terminate-request event handler */
+ apt_task_event_f on_terminate_request;
/** Virtual terminate-complete event handler */
apt_task_event_f on_terminate_complete;
};
-static APR_INLINE void apt_task_vtable_reset(apt_task_vtable_t *vtable)
-{
- vtable->destroy = NULL;
- vtable->start = NULL;
- vtable->terminate = NULL;
- vtable->run = NULL;
- vtable->signal_msg = NULL;
- vtable->process_msg = NULL;
- vtable->on_pre_run = NULL;
- vtable->on_post_run = NULL;
- vtable->on_start_complete = NULL;
- vtable->on_terminate_complete = NULL;
-}
-
APT_END_EXTERN_C
-#endif /*__APT_TASK_H__*/
+#endif /* APT_TASK_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_task_msg.h b/libs/unimrcp/libs/apr-toolkit/include/apt_task_msg.h
index 4d43ee5ca3..8680bf4491 100644
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_task_msg.h
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_task_msg.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_task_msg.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __APT_TASK_MSG_H__
-#define __APT_TASK_MSG_H__
+#ifndef APT_TASK_MSG_H
+#define APT_TASK_MSG_H
/**
* @file apt_task_msg.h
@@ -77,4 +79,4 @@ APT_DECLARE(void) apt_task_msg_release(apt_task_msg_t *task_msg);
APT_END_EXTERN_C
-#endif /*__APT_TASK_MSG_H__*/
+#endif /* APT_TASK_MSG_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_test_suite.h b/libs/unimrcp/libs/apr-toolkit/include/apt_test_suite.h
index 3e1b2cbeca..ce19f477c7 100644
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_test_suite.h
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_test_suite.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_test_suite.h 1708 2010-05-24 17:03:25Z achaloyan $
*/
-#ifndef __APT_TEST_SUITE_H__
-#define __APT_TEST_SUITE_H__
+#ifndef APT_TEST_SUITE_H
+#define APT_TEST_SUITE_H
/**
* @file apt_test_suite.h
@@ -92,8 +94,8 @@ APT_DECLARE(apt_bool_t) apt_test_framework_run(apt_test_framework_t *framework,
* Retrieve the memory pool.
* @param framework the test framework to retrieve memory pool from
*/
-APT_DECLARE(apr_pool_t*) apt_test_framework_pool_get(apt_test_framework_t *framework);
+APT_DECLARE(apr_pool_t*) apt_test_framework_pool_get(const apt_test_framework_t *framework);
APT_END_EXTERN_C
-#endif /*__APT_TEST_SUITE_H__*/
+#endif /* APT_TEST_SUITE_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_text_message.h b/libs/unimrcp/libs/apr-toolkit/include/apt_text_message.h
new file mode 100644
index 0000000000..40edf0af50
--- /dev/null
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_text_message.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: apt_text_message.h 1722 2010-06-01 08:40:35Z achaloyan $
+ */
+
+#ifndef APT_TEXT_MESSAGE_H
+#define APT_TEXT_MESSAGE_H
+
+/**
+ * @file apt_text_message.h
+ * @brief Text Message Interface (RFC5322)
+ */
+
+#include "apt_header_field.h"
+#include "apt_text_stream.h"
+
+APT_BEGIN_EXTERN_C
+
+/** Status of text message processing (parsing/generation) */
+typedef enum {
+ APT_MESSAGE_STATUS_COMPLETE,
+ APT_MESSAGE_STATUS_INCOMPLETE,
+ APT_MESSAGE_STATUS_INVALID
+} apt_message_status_e;
+
+
+/** Opaque text message parser */
+typedef struct apt_message_parser_t apt_message_parser_t;
+/** Vtable of text message parser */
+typedef struct apt_message_parser_vtable_t apt_message_parser_vtable_t;
+
+/** Opaque text message generator */
+typedef struct apt_message_generator_t apt_message_generator_t;
+/** Vtable of text message generator */
+typedef struct apt_message_generator_vtable_t apt_message_generator_vtable_t;
+
+/** Temporary context associated with message and used for its parsing or generation */
+typedef struct apt_message_context_t apt_message_context_t;
+
+/** Create message parser */
+APT_DECLARE(apt_message_parser_t*) apt_message_parser_create(void *obj, const apt_message_parser_vtable_t *vtable, apr_pool_t *pool);
+
+/** Parse message by raising corresponding event handlers */
+APT_DECLARE(apt_message_status_e) apt_message_parser_run(apt_message_parser_t *parser, apt_text_stream_t *stream, void **message);
+
+/** Get external object associated with parser */
+APT_DECLARE(void*) apt_message_parser_object_get(apt_message_parser_t *parser);
+
+/** Set verbose mode for the parser */
+APT_DECLARE(void) apt_message_parser_verbose_set(apt_message_parser_t *parser, apt_bool_t verbose);
+
+
+/** Create message generator */
+APT_DECLARE(apt_message_generator_t*) apt_message_generator_create(void *obj, const apt_message_generator_vtable_t *vtable, apr_pool_t *pool);
+
+/** Generate message */
+APT_DECLARE(apt_message_status_e) apt_message_generator_run(apt_message_generator_t *generator, void *message, apt_text_stream_t *stream);
+
+/** Get external object associated with generator */
+APT_DECLARE(void*) apt_message_generator_object_get(apt_message_generator_t *generator);
+
+/** Set verbose mode for the parser */
+APT_DECLARE(void) apt_message_generator_verbose_set(apt_message_generator_t *generator, apt_bool_t verbose);
+
+
+/** Parse individual header field (name-value pair) */
+APT_DECLARE(apt_header_field_t*) apt_header_field_parse(apt_text_stream_t *stream, apr_pool_t *pool);
+
+/** Generate individual header field (name-value pair) */
+APT_DECLARE(apt_bool_t) apt_header_field_generate(const apt_header_field_t *header_field, apt_text_stream_t *stream);
+
+/** Parse header section */
+APT_DECLARE(apt_bool_t) apt_header_section_parse(apt_header_section_t *header, apt_text_stream_t *stream, apr_pool_t *pool);
+
+/** Generate header section */
+APT_DECLARE(apt_bool_t) apt_header_section_generate(const apt_header_section_t *header, apt_text_stream_t *stream);
+
+
+/** Temporary context associated with message and used for its parsing or generation */
+struct apt_message_context_t {
+ /** Context or ptotocol specific message */
+ void *message;
+ /** Header section of the message */
+ apt_header_section_t *header;
+ /** Body or content of the message */
+ apt_str_t *body;
+};
+
+/** Vtable of text message parser */
+struct apt_message_parser_vtable_t {
+ /** Start new message parsing by associating corresponding context and reading its start-line if applicable */
+ apt_bool_t (*on_start)(apt_message_parser_t *parser, apt_message_context_t *context, apt_text_stream_t *stream, apr_pool_t *pool);
+ /** Header section handler is invoked when entire header section has been read and parsed into header fields */
+ apt_bool_t (*on_header_complete)(apt_message_parser_t *parser, apt_message_context_t *context);
+ /** Body handler is invoked when entire body has been read */
+ apt_bool_t (*on_body_complete)(apt_message_parser_t *parser, apt_message_context_t *context);
+};
+
+/** Vtable of text message generator */
+struct apt_message_generator_vtable_t {
+ /** Start message generation by associating corresponding context and generating message start-line if applicable */
+ apt_bool_t (*on_start)(apt_message_generator_t *generator, apt_message_context_t *context, apt_text_stream_t *stream);
+ /** Header section handler is invoked to notify header section has been generated */
+ apt_bool_t (*on_header_complete)(apt_message_generator_t *generator, apt_message_context_t *context, apt_text_stream_t *stream);
+ /** Body handler is invoked to notify body has been generated */
+ apt_bool_t (*on_body_complete)(apt_message_generator_t *generator, apt_message_context_t *context, apt_text_stream_t *stream);
+};
+
+
+APT_END_EXTERN_C
+
+#endif /* APT_TEXT_MESSAGE_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_text_stream.h b/libs/unimrcp/libs/apr-toolkit/include/apt_text_stream.h
index e9e40cad5b..3df2565145 100644
--- a/libs/unimrcp/libs/apr-toolkit/include/apt_text_stream.h
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_text_stream.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,25 +12,27 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_text_stream.h 1672 2010-04-28 20:37:22Z achaloyan $
*/
-#ifndef __APT_TEXT_STREAM_H__
-#define __APT_TEXT_STREAM_H__
+#ifndef APT_TEXT_STREAM_H
+#define APT_TEXT_STREAM_H
/**
* @file apt_text_stream.h
* @brief Text Stream Parse/Generate Routine
*/
-#include "apt_string.h"
+#include "apt_string_table.h"
#include "apt_pair.h"
APT_BEGIN_EXTERN_C
-/** Named tokens */
-
/** Space */
-#define APT_TOKEN_SP ' '
+#define APT_TOKEN_SP 0x20
+/** Horizontal tab */
+#define APT_TOKEN_HTAB 0x09
/** Carrige return */
#define APT_TOKEN_CR 0x0D
/** Line feed */
@@ -52,73 +54,77 @@ struct apt_text_stream_t {
apt_bool_t is_eos;
};
+
/**
- * Navigate through the lines of the text stream (message).
- * @param stream the text stream to navigate
+ * Read entire line of the text stream.
+ * @param stream the text stream to navigate on
* @param line the read line to return
* @return TRUE if the line is successfully read, otherwise FALSE
+ * @remark To be used to navigate through the lines of the text stream (message).
*/
APT_DECLARE(apt_bool_t) apt_text_line_read(apt_text_stream_t *stream, apt_str_t *line);
/**
- * Navigate through the headers (name:value pairs) of the text stream (message).
+ * Read header field (name-value pair) of the text stream by scanning entire line.
* @param stream the text stream to navigate
* @param pair the read pair to return
* @return TRUE if the header is successfully read, otherwise FALSE
+ * @remark To be used to navigate through the lines and read header fields
+ * (name:value pairs) of the text stream (message).
*/
APT_DECLARE(apt_bool_t) apt_text_header_read(apt_text_stream_t *stream, apt_pair_t *pair);
/**
- * Navigate through the fields of the line.
+ * Read the field terminated with specified separator.
* @param stream the text stream to navigate
* @param separator the field separator
* @param skip_spaces whether to skip spaces or not
* @param field the read field to return
- * @return TRUE if the length of the field > 0, otherwise FALSE
+ * @return TRUE if the read field isn't empty, otherwise FALSE
+ * @remark To be used to navigate through the fields of the text stream (message).
*/
APT_DECLARE(apt_bool_t) apt_text_field_read(apt_text_stream_t *stream, char separator, apt_bool_t skip_spaces, apt_str_t *field);
+/** Generate name-value pair line */
+APT_DECLARE(apt_bool_t) apt_text_name_value_insert(apt_text_stream_t *stream, const apt_str_t *name, const apt_str_t *value);
-
-/** Generate header */
-APT_DECLARE(apt_bool_t) apt_text_header_generate(const apt_pair_t *pair, apt_text_stream_t *text_stream);
-
-/** Generate only the name ("name:") of the header */
-APT_DECLARE(apt_bool_t) apt_text_header_name_generate(const apt_str_t *name, apt_text_stream_t *text_stream);
+/** Generate only the name ("name:") of the header field */
+APT_DECLARE(apt_bool_t) apt_text_header_name_insert(apt_text_stream_t *stream, const apt_str_t *name);
/** Parse array of name-value pairs */
APT_DECLARE(apt_bool_t) apt_pair_array_parse(apt_pair_arr_t *arr, const apt_str_t *value, apr_pool_t *pool);
/** Generate array of name-value pairs */
-APT_DECLARE(apt_bool_t) apt_pair_array_generate(apt_pair_arr_t *arr, apt_text_stream_t *text_stream);
+APT_DECLARE(apt_bool_t) apt_pair_array_generate(const apt_pair_arr_t *arr, apt_str_t *str, apr_pool_t *pool);
+
+/** Insert array of name-value pairs */
+APT_DECLARE(apt_bool_t) apt_text_pair_array_insert(apt_text_stream_t *stream, const apt_pair_arr_t *arr);
/** Parse boolean-value */
APT_DECLARE(apt_bool_t) apt_boolean_value_parse(const apt_str_t *str, apt_bool_t *value);
+/** Generate apr_size_t value from pool (buffer is allocated from pool) */
+APT_DECLARE(apt_bool_t) apt_boolean_value_generate(apt_bool_t value, apt_str_t *str, apr_pool_t *pool);
-/** Generate boolean-value */
-APT_DECLARE(apt_bool_t) apt_boolean_value_generate(apt_bool_t value, apt_text_stream_t *str);
+/** Insert boolean-value */
+APT_DECLARE(apt_bool_t) apt_text_boolean_value_insert(apt_text_stream_t *stream, apt_bool_t value);
-/** Parse size_t value */
+/** Parse apr_size_t value */
APT_DECLARE(apr_size_t) apt_size_value_parse(const apt_str_t *str);
+/** Generate apr_size_t value from pool (buffer is allocated from pool) */
+APT_DECLARE(apt_bool_t) apt_size_value_generate(apr_size_t value, apt_str_t *str, apr_pool_t *pool);
-/** Generate apr_size_t value */
-APT_DECLARE(apt_bool_t) apt_size_value_generate(apr_size_t value, apt_text_stream_t *stream);
+/** Insert apr_size_t value */
+APT_DECLARE(apt_bool_t) apt_text_size_value_insert(apt_text_stream_t *stream, apr_size_t value);
/** Parse float value */
APT_DECLARE(float) apt_float_value_parse(const apt_str_t *str);
+/** Generate float value (buffer is allocated from pool) */
+APT_DECLARE(apt_bool_t) apt_float_value_generate(float value, apt_str_t *str, apr_pool_t *pool);
-/** Generate float value */
-APT_DECLARE(apt_bool_t) apt_float_value_generate(float value, apt_text_stream_t *stream);
-
-/** Generate string value */
-static APR_INLINE apt_bool_t apt_string_value_generate(const apt_str_t *str, apt_text_stream_t *stream)
-{
- if(str->length) {
- memcpy(stream->pos,str->buf,str->length);
- stream->pos += str->length;
- }
- return TRUE;
-}
+/** Insert float value */
+APT_DECLARE(apt_bool_t) apt_text_float_value_insert(apt_text_stream_t *stream, float value);
+/** Insert string value */
+APT_DECLARE(apt_bool_t) apt_text_string_insert(apt_text_stream_t *stream, const apt_str_t *str);
/** Reset navigation related data of the text stream */
static APR_INLINE void apt_text_stream_reset(apt_text_stream_t *stream)
@@ -137,36 +143,74 @@ static APR_INLINE void apt_text_stream_init(apt_text_stream_t *stream, char *buf
}
/** Insert end of the line symbol(s) */
-static APR_INLINE void apt_text_eol_insert(apt_text_stream_t *stream)
+static APR_INLINE apt_bool_t apt_text_eol_insert(apt_text_stream_t *stream)
{
- *stream->pos++ = APT_TOKEN_CR;
- *stream->pos++ = APT_TOKEN_LF;
+ if(stream->pos + 2 < stream->end) {
+ *stream->pos++ = APT_TOKEN_CR;
+ *stream->pos++ = APT_TOKEN_LF;
+ return TRUE;
+ }
+ return FALSE;
}
/** Insert character */
-static APR_INLINE void apt_text_char_insert(apt_text_stream_t *stream, char ch)
+static APR_INLINE apt_bool_t apt_text_char_insert(apt_text_stream_t *stream, char ch)
{
- *stream->pos++ = ch;
+ if(stream->pos + 1 < stream->end) {
+ *stream->pos++ = ch;
+ return TRUE;
+ }
+ return FALSE;
}
/** Insert space */
-static APR_INLINE void apt_text_space_insert(apt_text_stream_t *stream)
+static APR_INLINE apt_bool_t apt_text_space_insert(apt_text_stream_t *stream)
{
- *stream->pos++ = APT_TOKEN_SP;
+ return apt_text_char_insert(stream,APT_TOKEN_SP);
}
-/** Skip spaces */
+/** Insert space */
+static APR_INLINE apt_bool_t apt_text_htab_insert(apt_text_stream_t *stream)
+{
+ return apt_text_char_insert(stream,APT_TOKEN_HTAB);
+}
+
+/** Check whether specified character is a white space (WSP = SP / HTAB) */
+static APR_INLINE apt_bool_t apt_text_is_wsp(char ch)
+{
+ return (ch == APT_TOKEN_SP || ch == APT_TOKEN_HTAB) ? TRUE : FALSE;
+}
+
+/** Skip sequence of spaces */
static APR_INLINE void apt_text_spaces_skip(apt_text_stream_t *stream)
{
- const char *end = stream->text.buf + stream->text.length;
- while(stream->pos < end && *stream->pos == APT_TOKEN_SP) stream->pos++;
+ while(stream->pos < stream->end && *stream->pos == APT_TOKEN_SP)
+ stream->pos++;
+}
+
+/** Skip sequence of white spaces (WSP = SP / HTAB) */
+static APR_INLINE void apt_text_white_spaces_skip(apt_text_stream_t *stream)
+{
+ while(stream->pos < stream->end && apt_text_is_wsp(*stream->pos) == TRUE)
+ stream->pos++;
}
/** Skip specified character */
static APR_INLINE void apt_text_char_skip(apt_text_stream_t *stream, char ch)
{
- const char *end = stream->text.buf + stream->text.length;
- if(stream->pos < end && *stream->pos == ch) stream->pos++;
+ if(stream->pos < stream->end && *stream->pos == ch) stream->pos++;
+}
+
+/** Skip sequence of specified characters */
+static APR_INLINE void apt_text_chars_skip(apt_text_stream_t *stream, char ch)
+{
+ while(stream->pos < stream->end && *stream->pos == ch) stream->pos++;
+}
+
+/** Skip to specified character */
+static APR_INLINE void apt_text_skip_to_char(apt_text_stream_t *stream, char ch)
+{
+ while(stream->pos < stream->end && *stream->pos != ch) stream->pos++;
}
/** Check whether end of stream is reached */
@@ -180,13 +224,14 @@ APT_DECLARE(apt_bool_t) apt_text_stream_scroll(apt_text_stream_t *stream);
/** Parse id at resource string */
APT_DECLARE(apt_bool_t) apt_id_resource_parse(const apt_str_t *str, char separator, apt_str_t *id, apt_str_t *resource, apr_pool_t *pool);
-
/** Generate id at resource string */
APT_DECLARE(apt_bool_t) apt_id_resource_generate(const apt_str_t *id, const apt_str_t *resource, char separator, apt_str_t *str, apr_pool_t *pool);
/** Generate value plus the length (number of digits) of the value itself */
APT_DECLARE(apt_bool_t) apt_var_length_value_generate(apr_size_t *value, apr_size_t max_count, apt_str_t *str);
+/** Generate completion-cause */
+APT_DECLARE(apt_bool_t) apt_completion_cause_generate(const apt_str_table_item_t table[], apr_size_t size, apr_size_t cause, apt_str_t *str, apr_pool_t *pool);
/**
* Generate unique identifier (hex string)
@@ -199,4 +244,4 @@ APT_DECLARE(apt_bool_t) apt_unique_id_generate(apt_str_t *id, apr_size_t length,
APT_END_EXTERN_C
-#endif /*__APT_TEXT_STREAM_H__*/
+#endif /* APT_TEXT_STREAM_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/include/apt_timer_queue.h b/libs/unimrcp/libs/apr-toolkit/include/apt_timer_queue.h
new file mode 100644
index 0000000000..0536e94a8d
--- /dev/null
+++ b/libs/unimrcp/libs/apr-toolkit/include/apt_timer_queue.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: apt_timer_queue.h 1642 2010-04-08 13:37:57Z achaloyan $
+ */
+
+#ifndef APT_TIMER_QUEUE_H
+#define APT_TIMER_QUEUE_H
+
+/**
+ * @file apt_timer_queue.h
+ * @brief Timer Queue
+ */
+
+#include "apt.h"
+
+APT_BEGIN_EXTERN_C
+
+/** Opaque timer declaration */
+typedef struct apt_timer_t apt_timer_t;
+/** Opaque timer queue declaration */
+typedef struct apt_timer_queue_t apt_timer_queue_t;
+
+/** Prototype of timer callback */
+typedef void (*apt_timer_proc_f)(apt_timer_t *timer, void *obj);
+
+
+/** Create timer queue */
+APT_DECLARE(apt_timer_queue_t*) apt_timer_queue_create(apr_pool_t *pool);
+
+/** Destroy timer queue */
+APT_DECLARE(void) apt_timer_queue_destroy(apt_timer_queue_t *timer_queue);
+
+/** Advance scheduled timers */
+APT_DECLARE(void) apt_timer_queue_advance(apt_timer_queue_t *timer_queue, apr_uint32_t elapsed_time);
+
+/** Is timer queue empty */
+APT_DECLARE(apt_bool_t) apt_timer_queue_is_empty(const apt_timer_queue_t *timer_queue);
+
+/** Get current timeout */
+APT_DECLARE(apt_bool_t) apt_timer_queue_timeout_get(const apt_timer_queue_t *timer_queue, apr_uint32_t *timeout);
+
+
+/** Create timer */
+APT_DECLARE(apt_timer_t*) apt_timer_create(apt_timer_queue_t *timer_queue, apt_timer_proc_f proc, void *obj, apr_pool_t *pool);
+
+/** Set one-shot timer */
+APT_DECLARE(apt_bool_t) apt_timer_set(apt_timer_t *timer, apr_uint32_t timeout);
+
+/** Kill timer */
+APT_DECLARE(apt_bool_t) apt_timer_kill(apt_timer_t *timer);
+
+
+APT_END_EXTERN_C
+
+#endif /* APT_TIMER_QUEUE_H */
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_consumer_task.c b/libs/unimrcp/libs/apr-toolkit/src/apt_consumer_task.c
index ceb9320d98..28c691a274 100644
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_consumer_task.c
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_consumer_task.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_consumer_task.c 1708 2010-05-24 17:03:25Z achaloyan $
*/
#include
@@ -54,7 +56,7 @@ APT_DECLARE(apt_consumer_task_t*) apt_consumer_task_create(
return consumer_task;
}
-APT_DECLARE(apt_task_t*) apt_consumer_task_base_get(apt_consumer_task_t *task)
+APT_DECLARE(apt_task_t*) apt_consumer_task_base_get(const apt_consumer_task_t *task)
{
return task->base;
}
@@ -64,7 +66,7 @@ APT_DECLARE(apt_task_vtable_t*) apt_consumer_task_vtable_get(apt_consumer_task_t
return apt_task_vtable_get(task->base);
}
-APT_DECLARE(void*) apt_consumer_task_object_get(apt_consumer_task_t *task)
+APT_DECLARE(void*) apt_consumer_task_object_get(const apt_consumer_task_t *task)
{
return task->obj;
}
@@ -79,22 +81,25 @@ static apt_bool_t apt_consumer_task_run(apt_task_t *task)
{
apr_status_t rv;
void *msg;
- apt_bool_t running = TRUE;
+ apt_bool_t *running;
apt_consumer_task_t *consumer_task;
consumer_task = apt_task_object_get(task);
if(!consumer_task) {
return FALSE;
}
- while(running) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Wait for Task Messages [%s]",apt_task_name_get(task));
+ running = apt_task_running_flag_get(task);
+ if(!running) {
+ return FALSE;
+ }
+
+ while(*running) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Wait for Messages [%s]",apt_task_name_get(task));
rv = apr_queue_pop(consumer_task->msg_queue,&msg);
if(rv == APR_SUCCESS) {
if(msg) {
apt_task_msg_t *task_msg = msg;
- if(apt_task_msg_process(consumer_task->base,task_msg) == FALSE) {
- running = FALSE;
- }
+ apt_task_msg_process(consumer_task->base,task_msg);
}
}
}
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_cyclic_queue.c b/libs/unimrcp/libs/apr-toolkit/src/apt_cyclic_queue.c
index fff7de514f..2ac36c4dbb 100644
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_cyclic_queue.c
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_cyclic_queue.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_cyclic_queue.c 1708 2010-05-24 17:03:25Z achaloyan $
*/
#include
@@ -78,7 +80,7 @@ APT_DECLARE(void) apt_cyclic_queue_clear(apt_cyclic_queue_t *queue)
queue->head = queue->tail = 0;
}
-APT_DECLARE(apt_bool_t) apt_cyclic_queue_is_empty(apt_cyclic_queue_t *queue)
+APT_DECLARE(apt_bool_t) apt_cyclic_queue_is_empty(const apt_cyclic_queue_t *queue)
{
return queue->actual_size ? TRUE : FALSE;
}
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_dir_layout.c b/libs/unimrcp/libs/apr-toolkit/src/apt_dir_layout.c
index 9a527b63b0..2e651863d8 100644
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_dir_layout.c
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_dir_layout.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_dir_layout.c 1524 2010-02-15 20:44:16Z achaloyan $
*/
#include
@@ -72,3 +74,14 @@ APT_DECLARE(char*) apt_datadir_filepath_get(const apt_dir_layout_t *dir_layout,
}
return NULL;
}
+
+APT_DECLARE(char*) apt_confdir_filepath_get(const apt_dir_layout_t *dir_layout, const char *file_name, apr_pool_t *pool)
+{
+ if(dir_layout && dir_layout->conf_dir_path && file_name) {
+ char *file_path = NULL;
+ if(apr_filepath_merge(&file_path,dir_layout->conf_dir_path,file_name,0,pool) == APR_SUCCESS) {
+ return file_path;
+ }
+ }
+ return NULL;
+}
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_header_field.c b/libs/unimrcp/libs/apr-toolkit/src/apt_header_field.c
new file mode 100644
index 0000000000..9cf814549f
--- /dev/null
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_header_field.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: apt_header_field.c 1685 2010-05-06 05:34:54Z achaloyan $
+ */
+
+#include "apt_header_field.h"
+#include "apt_text_stream.h"
+
+#define UNKNOWN_HEADER_FIELD_ID (apr_size_t)-1
+
+/** Allocate an empty header field */
+APT_DECLARE(apt_header_field_t*) apt_header_field_alloc(apr_pool_t *pool)
+{
+ apt_header_field_t *header_field = apr_palloc(pool,sizeof(apt_header_field_t));
+ apt_string_reset(&header_field->name);
+ apt_string_reset(&header_field->value);
+ header_field->id = UNKNOWN_HEADER_FIELD_ID;
+ APR_RING_ELEM_INIT(header_field,link);
+ return header_field;
+}
+
+/** Create a header field using given name and value APT strings */
+APT_DECLARE(apt_header_field_t*) apt_header_field_create(const apt_str_t *name, const apt_str_t *value, apr_pool_t *pool)
+{
+ apt_header_field_t *header_field;
+ if(!name || !value) {
+ return NULL;
+ }
+ header_field = apr_palloc(pool,sizeof(apt_header_field_t));
+ apt_string_copy(&header_field->name,name,pool);
+ apt_string_copy(&header_field->value,value,pool);
+ header_field->id = UNKNOWN_HEADER_FIELD_ID;
+ APR_RING_ELEM_INIT(header_field,link);
+ return header_field;
+}
+
+/** Create a header field using given name and value C strings */
+APT_DECLARE(apt_header_field_t*) apt_header_field_create_c(const char *name, const char *value, apr_pool_t *pool)
+{
+ apt_header_field_t *header_field;
+ if(!name || !value) {
+ return NULL;
+ }
+ header_field = apr_palloc(pool,sizeof(apt_header_field_t));
+ apt_string_assign(&header_field->name,name,pool);
+ apt_string_assign(&header_field->value,value,pool);
+ header_field->id = UNKNOWN_HEADER_FIELD_ID;
+ APR_RING_ELEM_INIT(header_field,link);
+ return header_field;
+}
+
+/* Create a header field from entire text line consisting of a name and value pair */
+APT_DECLARE(apt_header_field_t*) apt_header_field_create_from_line(const apt_str_t *line, char separator, apr_pool_t *pool)
+{
+ apt_str_t item;
+ apt_text_stream_t stream;
+ apt_header_field_t *header_field;
+ if(!line) {
+ return NULL;
+ }
+
+ header_field = apr_palloc(pool,sizeof(apt_header_field_t));
+ stream.text = *line;
+ apt_text_stream_reset(&stream);
+
+ /* read name */
+ if(apt_text_field_read(&stream,separator,TRUE,&item) == FALSE) {
+ return NULL;
+ }
+ apt_string_copy(&header_field->name,&item,pool);
+
+ /* read value */
+ apt_text_field_read(&stream,0,TRUE,&item);
+ apt_string_copy(&header_field->value,&item,pool);
+
+ header_field->id = UNKNOWN_HEADER_FIELD_ID;
+ APR_RING_ELEM_INIT(header_field,link);
+ return header_field;
+}
+
+/** Copy specified header field */
+APT_DECLARE(apt_header_field_t*) apt_header_field_copy(const apt_header_field_t *src_header_field, apr_pool_t *pool)
+{
+ apt_header_field_t *header_field = apr_palloc(pool,sizeof(apt_header_field_t));
+ apt_string_copy(&header_field->name,&src_header_field->name,pool);
+ apt_string_copy(&header_field->value,&src_header_field->value,pool);
+ header_field->id = src_header_field->id;
+ APR_RING_ELEM_INIT(header_field,link);
+ return header_field;
+}
+
+/** Initialize header section (collection of header fields) */
+APT_DECLARE(void) apt_header_section_init(apt_header_section_t *header)
+{
+ APR_RING_INIT(&header->ring, apt_header_field_t, link);
+ header->arr = NULL;
+ header->arr_size = 0;
+}
+
+/** Allocate header section to set/get header fields by numeric identifiers */
+APT_DECLARE(apt_bool_t) apt_header_section_array_alloc(apt_header_section_t *header, apr_size_t max_field_count, apr_pool_t *pool)
+{
+ if(!max_field_count) {
+ return FALSE;
+ }
+
+ header->arr = (apt_header_field_t**)apr_pcalloc(pool,sizeof(apt_header_field_t*) * max_field_count);
+ header->arr_size = max_field_count;
+ return TRUE;
+}
+
+/** Add (append) header field to header section */
+APT_DECLARE(apt_bool_t) apt_header_section_field_add(apt_header_section_t *header, apt_header_field_t *header_field)
+{
+ if(header_field->id < header->arr_size) {
+ if(header->arr[header_field->id]) {
+ return FALSE;
+ }
+ header->arr[header_field->id] = header_field;
+ }
+ APR_RING_INSERT_TAIL(&header->ring,header_field,apt_header_field_t,link);
+ return TRUE;
+}
+
+/** Insert header field to header section based on numreic identifier if specified */
+APT_DECLARE(apt_bool_t) apt_header_section_field_insert(apt_header_section_t *header, apt_header_field_t *header_field)
+{
+ apt_header_field_t *it;
+ if(header_field->id < header->arr_size) {
+ if(header->arr[header_field->id]) {
+ return FALSE;
+ }
+ header->arr[header_field->id] = header_field;
+
+ for(it = APR_RING_FIRST(&header->ring);
+ it != APR_RING_SENTINEL(&header->ring, apt_header_field_t, link);
+ it = APR_RING_NEXT(it, link)) {
+ if(header_field->id < it->id) {
+ APR_RING_INSERT_BEFORE(it,header_field,link);
+ return TRUE;
+ }
+ }
+ }
+
+ APR_RING_INSERT_TAIL(&header->ring,header_field,apt_header_field_t,link);
+ return TRUE;
+}
+
+/** Set header field in the array of header fields using associated numeric identifier */
+APT_DECLARE(apt_bool_t) apt_header_section_field_set(apt_header_section_t *header, apt_header_field_t *header_field)
+{
+ if(header_field->id >= header->arr_size) {
+ return FALSE;
+ }
+ if(header->arr[header_field->id]) {
+ return FALSE;
+ }
+ header->arr[header_field->id] = header_field;
+ return TRUE;
+}
+
+/** Remove header field from header section */
+APT_DECLARE(apt_bool_t) apt_header_section_field_remove(apt_header_section_t *header, apt_header_field_t *header_field)
+{
+ if(header_field->id < header->arr_size) {
+ header->arr[header_field->id] = NULL;
+ }
+ APR_RING_REMOVE(header_field,link);
+ return TRUE;
+}
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_log.c b/libs/unimrcp/libs/apr-toolkit/src/apt_log.c
index 4ad91a996b..10b374d957 100644
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_log.c
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_log.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,14 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_log.c 1792 2011-01-10 21:08:52Z achaloyan $
*/
#include
#include
+#include
+#include
#include "apt_log.h"
#define MAX_LOG_ENTRY_SIZE 4096
@@ -43,6 +47,7 @@ struct apt_log_file_data_t {
apr_size_t max_size;
apr_size_t cur_file_index;
apr_size_t max_file_count;
+ apt_bool_t append;
apr_thread_mutex_t *mutex;
apr_pool_t *pool;
};
@@ -53,6 +58,7 @@ struct apt_logger_t {
int header;
apt_log_ext_handler_f ext_handler;
apt_log_file_data_t *file_data;
+ apt_log_masking_e masking;
};
static apt_logger_t *apt_logger = NULL;
@@ -61,19 +67,83 @@ static apt_bool_t apt_do_log(const char *file, int line, apt_log_priority_e prio
static const char* apt_log_file_path_make(apt_log_file_data_t *file_data);
static apt_bool_t apt_log_file_dump(apt_log_file_data_t *file_data, const char *log_entry, apr_size_t size);
+static apr_xml_doc* apt_log_doc_parse(const char *file_path, apr_pool_t *pool);
+static apr_size_t apt_log_file_get_size(apt_log_file_data_t *file_data);
+static apr_byte_t apt_log_file_exist(apt_log_file_data_t *file_data);
+static apt_logger_t* apt_log_instance_alloc(apr_pool_t *pool)
+{
+ apt_logger_t *logger = apr_palloc(pool,sizeof(apt_logger_t));
+ logger->mode = APT_LOG_OUTPUT_CONSOLE;
+ logger->priority = APT_PRIO_INFO;
+ logger->header = APT_LOG_HEADER_DEFAULT;
+ logger->ext_handler = NULL;
+ logger->file_data = NULL;
+ logger->masking = APT_LOG_MASKING_NONE;
+ return logger;
+}
APT_DECLARE(apt_bool_t) apt_log_instance_create(apt_log_output_e mode, apt_log_priority_e priority, apr_pool_t *pool)
{
if(apt_logger) {
return FALSE;
}
- apt_logger = apr_palloc(pool,sizeof(apt_logger_t));
+ apt_logger = apt_log_instance_alloc(pool);
apt_logger->mode = mode;
apt_logger->priority = priority;
- apt_logger->header = APT_LOG_HEADER_DEFAULT;
- apt_logger->ext_handler = NULL;
- apt_logger->file_data = NULL;
+ return TRUE;
+}
+
+APT_DECLARE(apt_bool_t) apt_log_instance_load(const char *config_file, apr_pool_t *pool)
+{
+ apr_xml_doc *doc;
+ const apr_xml_elem *elem;
+ const apr_xml_elem *root;
+ char *text;
+
+ if(apt_logger) {
+ return FALSE;
+ }
+ apt_logger = apt_log_instance_alloc(pool);
+
+ /* Parse XML document */
+ doc = apt_log_doc_parse(config_file,pool);
+ if(!doc) {
+ return FALSE;
+ }
+
+ root = doc->root;
+
+ /* Match document name */
+ if(!root || strcasecmp(root->name,"aptlogger") != 0) {
+ /* Unknown document */
+ return FALSE;
+ }
+
+ /* Navigate through document */
+ for(elem = root->first_child; elem; elem = elem->next) {
+ if(!elem->first_cdata.first || !elem->first_cdata.first->text)
+ continue;
+
+ text = apr_pstrdup(pool,elem->first_cdata.first->text);
+ apr_collapse_spaces(text,text);
+
+ if(strcasecmp(elem->name,"priority") == 0) {
+ apt_logger->priority = apt_log_priority_translate(text);
+ }
+ else if(strcasecmp(elem->name,"output") == 0) {
+ apt_logger->mode = apt_log_output_mode_translate(text);
+ }
+ else if(strcasecmp(elem->name,"headers") == 0) {
+ apt_logger->header = apt_log_header_translate(text);
+ }
+ else if(strcasecmp(elem->name,"masking") == 0) {
+ apt_logger->masking = apt_log_masking_translate(text);
+ }
+ else {
+ /* Unknown element */
+ }
+ }
return TRUE;
}
@@ -104,7 +174,13 @@ APT_DECLARE(apt_bool_t) apt_log_instance_set(apt_logger_t *logger)
return TRUE;
}
-APT_DECLARE(apt_bool_t) apt_log_file_open(const char *dir_path, const char *file_name, apr_size_t max_file_size, apr_size_t max_file_count, apr_pool_t *pool)
+APT_DECLARE(apt_bool_t) apt_log_file_open(
+ const char *dir_path,
+ const char *file_name,
+ apr_size_t max_file_size,
+ apr_size_t max_file_count,
+ apt_bool_t append,
+ apr_pool_t *pool)
{
const char *log_file_path;
apt_log_file_data_t *file_data;
@@ -117,29 +193,55 @@ APT_DECLARE(apt_bool_t) apt_log_file_open(const char *dir_path, const char *file
}
file_data = apr_palloc(pool,sizeof(apt_log_file_data_t));
- file_data->log_dir_path = dir_path;
- file_data->log_file_name = file_name;
+ file_data->log_dir_path = apr_pstrdup(pool,dir_path);
+ file_data->log_file_name = apr_pstrdup(pool,file_name);
file_data->cur_file_index = 0;
file_data->cur_size = 0;
file_data->max_file_count = max_file_count;
file_data->max_size = max_file_size;
+ file_data->append = append;
file_data->mutex = NULL;
file_data->pool = pool;
if(!file_data->max_size) {
- file_data->max_file_count = MAX_LOG_FILE_SIZE;
+ file_data->max_size = MAX_LOG_FILE_SIZE;
}
if(!file_data->max_file_count) {
file_data->max_file_count = MAX_LOG_FILE_COUNT;
}
+ if(file_data->append == TRUE) {
+ /* iteratively find the last created file */
+ while(file_data->cur_file_indexmax_file_count)
+ {
+ if(apt_log_file_exist(file_data) == 0)
+ {
+ if(file_data->cur_file_index > 0)
+ file_data->cur_file_index--;
+ file_data->cur_size = apt_log_file_get_size(file_data);
+ break;
+ }
+ file_data->cur_file_index++;
+ }
+
+ /* if all the files have been created start rewriting from beginning */
+ if(file_data->cur_file_index>=file_data->max_file_count)
+ {
+ file_data->cur_file_index=0;
+ file_data->cur_size=0;
+ log_file_path = apt_log_file_path_make(file_data);
+ file_data->file = fopen(log_file_path,"wb"); /* truncate the first file to zero length */
+ fclose(file_data->file);
+ }
+ }
+
/* create mutex */
if(apr_thread_mutex_create(&file_data->mutex,APR_THREAD_MUTEX_DEFAULT,pool) != APR_SUCCESS) {
return FALSE;
}
/* open log file */
log_file_path = apt_log_file_path_make(file_data);
- file_data->file = fopen(log_file_path,"wb");
+ file_data->file = fopen(log_file_path,file_data->append == TRUE ? "ab" : "wb");
if(!file_data->file) {
apr_thread_mutex_destroy(file_data->mutex);
return FALSE;
@@ -177,6 +279,31 @@ APT_DECLARE(apt_bool_t) apt_log_output_mode_set(apt_log_output_e mode)
return TRUE;
}
+APT_DECLARE(apt_bool_t) apt_log_output_mode_check(apt_log_output_e mode)
+{
+ if(!apt_logger) {
+ return FALSE;
+ }
+ return (apt_logger->mode | mode) ? TRUE : FALSE;
+}
+
+APT_DECLARE(int) apt_log_output_mode_translate(char *str)
+{
+ int mode = APT_LOG_OUTPUT_NONE;
+ char *name;
+ char *last;
+ name = apr_strtok(str, ",", &last);
+ while(name) {
+ if(strcasecmp(name, "CONSOLE") == 0)
+ mode |= APT_LOG_OUTPUT_CONSOLE;
+ else if(strcasecmp(name, "FILE") == 0)
+ mode |= APT_LOG_OUTPUT_FILE;
+
+ name = apr_strtok(NULL, ",", &last);
+ }
+ return mode;
+}
+
APT_DECLARE(apt_bool_t) apt_log_priority_set(apt_log_priority_e priority)
{
if(!apt_logger || priority >= APT_PRIO_COUNT) {
@@ -186,6 +313,28 @@ APT_DECLARE(apt_bool_t) apt_log_priority_set(apt_log_priority_e priority)
return TRUE;
}
+APT_DECLARE(apt_log_priority_e) apt_log_priority_translate(const char *str)
+{
+ if(strcasecmp(str, "EMERGENCY") == 0)
+ return APT_PRIO_EMERGENCY;
+ else if(strcasecmp(str, "ALERT") == 0)
+ return APT_PRIO_ALERT;
+ else if(strcasecmp(str, "CRITICAL") == 0)
+ return APT_PRIO_CRITICAL;
+ else if(strcasecmp(str, "ERROR") == 0)
+ return APT_PRIO_ERROR;
+ else if(strcasecmp(str, "WARNING") == 0)
+ return APT_PRIO_WARNING;
+ else if(strcasecmp(str, "NOTICE") == 0)
+ return APT_PRIO_NOTICE;
+ else if(strcasecmp(str, "INFO") == 0)
+ return APT_PRIO_INFO;
+ else if(strcasecmp(str, "DEBUG") == 0)
+ return APT_PRIO_DEBUG;
+
+ return APT_PRIO_DEBUG;
+}
+
APT_DECLARE(apt_bool_t) apt_log_header_set(int header)
{
if(!apt_logger) {
@@ -195,6 +344,69 @@ APT_DECLARE(apt_bool_t) apt_log_header_set(int header)
return TRUE;
}
+APT_DECLARE(int) apt_log_header_translate(char *str)
+{
+ int header = APT_LOG_OUTPUT_NONE;
+ char *name;
+ char *last;
+ name = apr_strtok(str, ",", &last);
+ while(name) {
+ if(strcasecmp(name, "DATE") == 0)
+ header |= APT_LOG_HEADER_DATE;
+ else if(strcasecmp(name, "TIME") == 0)
+ header |= APT_LOG_HEADER_TIME;
+ else if(strcasecmp(name, "PRIORITY") == 0)
+ header |= APT_LOG_HEADER_PRIORITY;
+ else if(strcasecmp(name, "MARK") == 0)
+ header |= APT_LOG_HEADER_MARK;
+ else if(strcasecmp(name, "THREAD") == 0)
+ header |= APT_LOG_HEADER_THREAD;
+
+ name = apr_strtok(NULL, ",", &last);
+ }
+ return header;
+}
+
+APT_DECLARE(apt_bool_t) apt_log_masking_set(apt_log_masking_e masking)
+{
+ if(!apt_logger) {
+ return FALSE;
+ }
+ apt_logger->masking = masking;
+ return TRUE;
+}
+
+APT_DECLARE(apt_log_masking_e) apt_log_masking_get()
+{
+ if(!apt_logger) {
+ return APT_LOG_MASKING_NONE;
+ }
+ return apt_logger->masking;
+}
+
+APT_DECLARE(apt_log_masking_e) apt_log_masking_translate(const char *str)
+{
+ if(strcasecmp(str, "COMPLETE") == 0)
+ return APT_LOG_MASKING_COMPLETE;
+ else if(strcasecmp(str, "ENCRYPTED") == 0)
+ return APT_LOG_MASKING_ENCRYPTED;
+ return APT_LOG_MASKING_NONE;
+}
+
+#define APT_MASKED_CONTENT "*** masked ***"
+
+APT_DECLARE(const char*) apt_log_data_mask(const char *data_in, apr_size_t *length, apr_pool_t *pool)
+{
+ if(!apt_logger) {
+ return NULL;
+ }
+ if(apt_logger->masking == APT_LOG_MASKING_COMPLETE) {
+ *length = sizeof(APT_MASKED_CONTENT) - 1;
+ return APT_MASKED_CONTENT;
+ }
+ return data_in;
+}
+
APT_DECLARE(apt_bool_t) apt_log_ext_handler_set(apt_log_ext_handler_f handler)
{
if(!apt_logger) {
@@ -224,6 +436,35 @@ APT_DECLARE(apt_bool_t) apt_log(const char *file, int line, apt_log_priority_e p
return status;
}
+APT_DECLARE(apt_bool_t) apt_obj_log(const char *file, int line, apt_log_priority_e priority, void *obj, const char *format, ...)
+{
+ apt_bool_t status = TRUE;
+ if(!apt_logger) {
+ return FALSE;
+ }
+ if(priority <= apt_logger->priority) {
+ va_list arg_ptr;
+ va_start(arg_ptr, format);
+ if(apt_logger->ext_handler) {
+ status = apt_logger->ext_handler(file,line,obj,priority,format,arg_ptr);
+ }
+ else {
+ status = apt_do_log(file,line,priority,format,arg_ptr);
+ }
+ va_end(arg_ptr);
+ }
+ return status;
+}
+
+static APR_INLINE unsigned long apt_thread_id_get()
+{
+#ifdef WIN32
+ return (unsigned long) GetCurrentThreadId();
+#else
+ return (unsigned long) apr_os_thread_current();
+#endif
+}
+
static apt_bool_t apt_do_log(const char *file, int line, apt_log_priority_e priority, const char *format, va_list arg_ptr)
{
char log_entry[MAX_LOG_ENTRY_SIZE];
@@ -249,6 +490,9 @@ static apt_bool_t apt_do_log(const char *file, int line, apt_log_priority_e prio
if(apt_logger->header & APT_LOG_HEADER_MARK) {
offset += apr_snprintf(log_entry+offset,max_size-offset,"%s:%03d ",file,line);
}
+ if(apt_logger->header & APT_LOG_HEADER_THREAD) {
+ offset += apr_snprintf(log_entry+offset,max_size-offset,"%05lu ",apt_thread_id_get());
+ }
if(apt_logger->header & APT_LOG_HEADER_PRIORITY) {
memcpy(log_entry+offset,priority_snames[priority],MAX_PRIORITY_NAME_LENGTH);
offset += MAX_PRIORITY_NAME_LENGTH;
@@ -275,6 +519,40 @@ static const char* apt_log_file_path_make(apt_log_file_data_t *file_data)
return log_file_path;
}
+static apr_size_t apt_log_file_get_size(apt_log_file_data_t *file_data)
+{
+ FILE* fp;
+ const char *log_file_path;
+ apr_size_t ret;
+
+ log_file_path = apt_log_file_path_make(file_data);
+ fp = fopen(log_file_path,"rb");
+
+ if(!fp) return 0;
+
+ fseek(fp,0,SEEK_END);
+ ret = ftell(fp);
+
+ fclose(fp);
+
+ return ret;
+}
+
+static apr_byte_t apt_log_file_exist(apt_log_file_data_t *file_data)
+{
+ FILE* fp;
+ const char *log_file_path;
+
+ log_file_path = apt_log_file_path_make(file_data);
+ fp = fopen(log_file_path,"rb");
+
+ if(!fp) return 0;
+
+ fclose(fp);
+
+ return 1;
+}
+
static apt_bool_t apt_log_file_dump(apt_log_file_data_t *file_data, const char *log_entry, apr_size_t size)
{
apr_thread_mutex_lock(file_data->mutex);
@@ -303,3 +581,24 @@ static apt_bool_t apt_log_file_dump(apt_log_file_data_t *file_data, const char *
apr_thread_mutex_unlock(file_data->mutex);
return TRUE;
}
+
+static apr_xml_doc* apt_log_doc_parse(const char *file_path, apr_pool_t *pool)
+{
+ apr_xml_parser *parser = NULL;
+ apr_xml_doc *xml_doc = NULL;
+ apr_file_t *fd = NULL;
+ apr_status_t rv;
+
+ rv = apr_file_open(&fd,file_path,APR_READ|APR_BINARY,0,pool);
+ if(rv != APR_SUCCESS) {
+ return NULL;
+ }
+
+ rv = apr_xml_parse_file(pool,&parser,&xml_doc,fd,2000);
+ if(rv != APR_SUCCESS) {
+ xml_doc = NULL;
+ }
+
+ apr_file_close(fd);
+ return xml_doc;
+}
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_multipart_content.c b/libs/unimrcp/libs/apr-toolkit/src/apt_multipart_content.c
new file mode 100644
index 0000000000..3f3690ff7a
--- /dev/null
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_multipart_content.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: apt_multipart_content.c 1673 2010-04-28 20:45:47Z achaloyan $
+ */
+
+#include
+#include "apt_multipart_content.h"
+#include "apt_text_stream.h"
+#include "apt_text_message.h"
+
+#define CONTENT_LENGTH_HEADER "Content-Length"
+#define CONTENT_TYPE_HEADER "Content-Type"
+#define CONTENT_ID_HEADER "Content-Id"
+
+#define DEFAULT_BOUNDARY "break"
+#define DEFAULT_HYPHENS "--"
+
+#define DEFAULT_MULTIPART_CONTENT_SIZE 4096
+
+/** Multipart content */
+struct apt_multipart_content_t {
+ apr_pool_t *pool;
+ apt_text_stream_t stream;
+
+ apt_str_t boundary;
+ apt_str_t hyphens;
+};
+
+/** Create an empty multipart content */
+APT_DECLARE(apt_multipart_content_t*) apt_multipart_content_create(apr_size_t max_content_size, const apt_str_t *boundary, apr_pool_t *pool)
+{
+ char *buffer;
+ apt_multipart_content_t *multipart_content = apr_palloc(pool,sizeof(apt_multipart_content_t));
+ multipart_content->pool = pool;
+
+ if(max_content_size == 0) {
+ max_content_size = DEFAULT_MULTIPART_CONTENT_SIZE;
+ }
+
+ if(boundary) {
+ multipart_content->boundary = *boundary;
+ }
+ else {
+ multipart_content->boundary.buf = DEFAULT_BOUNDARY;
+ multipart_content->boundary.length = sizeof(DEFAULT_BOUNDARY)-1;
+ }
+
+ multipart_content->hyphens.buf = DEFAULT_HYPHENS;
+ multipart_content->hyphens.length = sizeof(DEFAULT_HYPHENS)-1;
+
+ buffer = apr_palloc(pool,max_content_size+1);
+ apt_text_stream_init(&multipart_content->stream,buffer,max_content_size);
+ return multipart_content;
+}
+
+/** Initialize content part generation */
+static apt_bool_t apt_multipart_content_initialize(apt_multipart_content_t *multipart_content)
+{
+ /* insert preceding end-of-line */
+ if(apt_text_eol_insert(&multipart_content->stream) == FALSE) {
+ return FALSE;
+ }
+ /* insert hyphens */
+ if(apt_text_string_insert(&multipart_content->stream,&multipart_content->hyphens) == FALSE) {
+ return FALSE;
+ }
+ /* insert boundary */
+ if(apt_text_string_insert(&multipart_content->stream,&multipart_content->boundary) == FALSE) {
+ return FALSE;
+ }
+ return apt_text_eol_insert(&multipart_content->stream);
+}
+
+/** Add content part to multipart content */
+APT_DECLARE(apt_bool_t) apt_multipart_content_add(apt_multipart_content_t *multipart_content, const apt_content_part_t *content_part)
+{
+ if(!content_part) {
+ return FALSE;
+ }
+
+ /* insert preceding eol, hyppens and boudnary */
+ if(apt_multipart_content_initialize(multipart_content) == FALSE) {
+ return FALSE;
+ }
+
+ /* insert header fields */
+ if(apt_header_section_generate(&content_part->header,&multipart_content->stream) == FALSE) {
+ return FALSE;
+ }
+
+ /* insert body */
+ return apt_text_string_insert(&multipart_content->stream,&content_part->body);
+}
+
+/** Add content part to multipart content by specified header fields and body */
+APT_DECLARE(apt_bool_t) apt_multipart_content_add2(apt_multipart_content_t *multipart_content, const apt_str_t *content_type, const apt_str_t *content_id, const apt_str_t *body)
+{
+ /* insert preceding eol, hyppens and boudnary */
+ if(apt_multipart_content_initialize(multipart_content) == FALSE) {
+ return FALSE;
+ }
+
+ /* insert content-type */
+ if(content_type) {
+ apt_str_t name = {CONTENT_TYPE_HEADER,sizeof(CONTENT_TYPE_HEADER)-1};
+ if(apt_text_name_value_insert(&multipart_content->stream,&name,content_type) == FALSE) {
+ return FALSE;
+ }
+ }
+
+ /* insert content-id */
+ if(content_id) {
+ apt_str_t name = {CONTENT_ID_HEADER,sizeof(CONTENT_ID_HEADER)-1};
+ if(apt_text_name_value_insert(&multipart_content->stream,&name,content_id) == FALSE) {
+ return FALSE;
+ }
+ }
+
+ /* insert content-length */
+ if(body) {
+ apt_str_t name = {CONTENT_LENGTH_HEADER,sizeof(CONTENT_LENGTH_HEADER)-1};
+ if(apt_text_header_name_insert(&multipart_content->stream,&name) == FALSE) {
+ return FALSE;
+ }
+ if(apt_text_size_value_insert(&multipart_content->stream,body->length) == FALSE) {
+ return FALSE;
+ }
+ if(apt_text_eol_insert(&multipart_content->stream) == FALSE) {
+ return FALSE;
+ }
+ }
+
+ /* insert empty line */
+ if(apt_text_eol_insert(&multipart_content->stream) == FALSE) {
+ return FALSE;
+ }
+
+ /* insert body */
+ if(body) {
+ if(apt_text_string_insert(&multipart_content->stream,body) == FALSE) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+/** Finalize multipart content generation */
+APT_DECLARE(apt_str_t*) apt_multipart_content_finalize(apt_multipart_content_t *multipart_content)
+{
+ apt_text_stream_t *stream = &multipart_content->stream;
+ /* insert preceding end-of-line */
+ if(apt_text_eol_insert(&multipart_content->stream) == FALSE) {
+ return NULL;
+ }
+ /* insert hyphens */
+ if(apt_text_string_insert(&multipart_content->stream,&multipart_content->hyphens) == FALSE) {
+ return NULL;
+ }
+ /* insert boundary */
+ if(apt_text_string_insert(&multipart_content->stream,&multipart_content->boundary) == FALSE) {
+ return NULL;
+ }
+ /* insert final hyphens */
+ if(apt_text_string_insert(&multipart_content->stream,&multipart_content->hyphens) == FALSE) {
+ return NULL;
+ }
+ if(apt_text_eol_insert(&multipart_content->stream) == FALSE) {
+ return NULL;
+ }
+
+ stream->text.length = stream->pos - stream->text.buf;
+ stream->text.buf[stream->text.length] = '\0';
+ return &stream->text;
+}
+
+
+/** Assign body to multipart content to get (parse) each content part from */
+APT_DECLARE(apt_multipart_content_t*) apt_multipart_content_assign(const apt_str_t *body, const apt_str_t *boundary, apr_pool_t *pool)
+{
+ apt_multipart_content_t *multipart_content = apr_palloc(pool,sizeof(apt_multipart_content_t));
+ multipart_content->pool = pool;
+
+ if(!body) {
+ return FALSE;
+ }
+
+ if(boundary) {
+ multipart_content->boundary = *boundary;
+ }
+ else {
+ apt_string_reset(&multipart_content->boundary);
+ }
+
+ apt_string_reset(&multipart_content->hyphens);
+ apt_text_stream_init(&multipart_content->stream,body->buf,body->length);
+ return multipart_content;
+}
+
+static APR_INLINE void apt_content_part_reset(apt_content_part_t *content_part)
+{
+ apt_header_section_init(&content_part->header);
+ apt_string_reset(&content_part->body);
+ content_part->type = NULL;
+ content_part->id = NULL;
+ content_part->length = NULL;
+}
+
+/** Get the next content part */
+APT_DECLARE(apt_bool_t) apt_multipart_content_get(apt_multipart_content_t *multipart_content, apt_content_part_t *content_part, apt_bool_t *is_final)
+{
+ apt_str_t boundary;
+ apt_header_field_t *header_field;
+ apt_text_stream_t *stream = &multipart_content->stream;
+
+ if(!content_part || !is_final) {
+ return FALSE;
+ }
+ *is_final = FALSE;
+ apt_content_part_reset(content_part);
+
+ /* skip preamble */
+ apt_text_skip_to_char(stream,'-');
+ if(apt_text_is_eos(stream) == TRUE) {
+ return FALSE;
+ }
+
+ /* skip initial hyphens */
+ apt_text_chars_skip(stream,'-');
+ if(apt_text_is_eos(stream) == TRUE) {
+ return FALSE;
+ }
+
+ /* read line and the boundary */
+ if(apt_text_line_read(stream,&boundary) == FALSE) {
+ return FALSE;
+ }
+
+ /* remove optional trailing spaces */
+ while(boundary.length && boundary.buf[boundary.length-1] == APT_TOKEN_SP) boundary.length--;
+
+ /* check whether this is the final boundary */
+ if(boundary.length >= 2) {
+ if(boundary.buf[boundary.length-1] == '-' && boundary.buf[boundary.length-2] == '-') {
+ /* final boundary */
+ boundary.length -= 2;
+ *is_final = TRUE;
+ }
+ }
+
+ /* compare boundaries */
+ if(apt_string_is_empty(&multipart_content->boundary) == TRUE) {
+ /* no boundary was specified from user space,
+ learn boundary from the content */
+ multipart_content->boundary = boundary;
+ }
+ else {
+ if(apt_string_compare(&multipart_content->boundary,&boundary) == FALSE) {
+ /* invalid boundary */
+ return FALSE;
+ }
+ }
+
+ if(*is_final == TRUE) {
+ /* final boundary => return TRUE, content remains empty */
+ return TRUE;
+ }
+
+ /* read header fields */
+ if(apt_header_section_parse(&content_part->header,stream,multipart_content->pool) == FALSE) {
+ return FALSE;
+ }
+
+ for(header_field = APR_RING_FIRST(&content_part->header.ring);
+ header_field != APR_RING_SENTINEL(&content_part->header.ring, apt_header_field_t, link);
+ header_field = APR_RING_NEXT(header_field, link)) {
+ if(strncmp(header_field->name.buf,CONTENT_LENGTH_HEADER,header_field->name.length) == 0) {
+ content_part->length = &header_field->value;
+ }
+ else if(strncmp(header_field->name.buf,CONTENT_TYPE_HEADER,header_field->name.length) == 0) {
+ content_part->type = &header_field->value;
+ }
+ else if(strncmp(header_field->name.buf,CONTENT_ID_HEADER,header_field->name.length) == 0) {
+ content_part->id = &header_field->value;
+ }
+ }
+
+ if(content_part->length && apt_string_is_empty(content_part->length) == FALSE) {
+ apr_size_t length = atoi(content_part->length->buf);
+ if(length + stream->pos > stream->end) {
+ return FALSE;
+ }
+
+ /* read content */
+ apt_string_assign_n(&content_part->body,stream->pos,length,multipart_content->pool);
+ stream->pos += length;
+ }
+
+ return TRUE;
+}
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_net.c b/libs/unimrcp/libs/apr-toolkit/src/apt_net.c
index 733f0e20bc..e8da32a5b4 100644
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_net.c
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_net.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_net.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_net_client_task.c b/libs/unimrcp/libs/apr-toolkit/src/apt_net_client_task.c
deleted file mode 100644
index 6effe42f3c..0000000000
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_net_client_task.c
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright 2008 Arsen Chaloyan
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "apt_net_client_task.h"
-#include "apt_task.h"
-#include "apt_pool.h"
-#include "apt_pollset.h"
-#include "apt_cyclic_queue.h"
-#include "apt_log.h"
-
-
-/** Network client task */
-struct apt_net_client_task_t {
- apr_pool_t *pool;
- apt_task_t *base;
- void *obj;
-
- apr_size_t max_connection_count;
-
- apr_thread_mutex_t *guard;
- apt_cyclic_queue_t *msg_queue;
- apt_pollset_t *pollset;
-
- const apt_net_client_vtable_t *client_vtable;
-};
-
-static apt_bool_t apt_net_client_task_msg_signal(apt_task_t *task, apt_task_msg_t *msg);
-static apt_bool_t apt_net_client_task_run(apt_task_t *task);
-static apt_bool_t apt_net_client_task_on_destroy(apt_task_t *task);
-
-/** Create connection task */
-APT_DECLARE(apt_net_client_task_t*) apt_net_client_task_create(
- apr_size_t max_connection_count,
- void *obj,
- const apt_net_client_vtable_t *client_vtable,
- apt_task_msg_pool_t *msg_pool,
- apr_pool_t *pool)
-{
- apt_task_vtable_t *vtable;
- apt_net_client_task_t *task;
-
- task = apr_palloc(pool,sizeof(apt_net_client_task_t));
- task->pool = pool;
- task->obj = obj;
- task->pollset = NULL;
- task->max_connection_count = max_connection_count;
-
- if(!client_vtable || !client_vtable->on_receive) {
- return NULL;
- }
- task->client_vtable = client_vtable;
-
- task->base = apt_task_create(task,msg_pool,pool);
- if(!task->base) {
- return NULL;
- }
-
- vtable = apt_task_vtable_get(task->base);
- if(vtable) {
- vtable->run = apt_net_client_task_run;
- vtable->destroy = apt_net_client_task_on_destroy;
- vtable->signal_msg = apt_net_client_task_msg_signal;
- }
- apt_task_auto_ready_set(task->base,FALSE);
-
- task->msg_queue = apt_cyclic_queue_create(CYCLIC_QUEUE_DEFAULT_SIZE);
- apr_thread_mutex_create(&task->guard,APR_THREAD_MUTEX_UNNESTED,pool);
- return task;
-}
-
-/** Virtual destroy handler */
-static apt_bool_t apt_net_client_task_on_destroy(apt_task_t *base)
-{
- apt_net_client_task_t *task = apt_task_object_get(base);
- if(task->guard) {
- apr_thread_mutex_destroy(task->guard);
- task->guard = NULL;
- }
- if(task->msg_queue) {
- apt_cyclic_queue_destroy(task->msg_queue);
- task->msg_queue = NULL;
- }
- return TRUE;
-}
-
-/** Destroy connection task. */
-APT_DECLARE(apt_bool_t) apt_net_client_task_destroy(apt_net_client_task_t *task)
-{
- return apt_task_destroy(task->base);
-}
-
-/** Start connection task. */
-APT_DECLARE(apt_bool_t) apt_net_client_task_start(apt_net_client_task_t *task)
-{
- return apt_task_start(task->base);
-}
-
-/** Terminate connection task. */
-APT_DECLARE(apt_bool_t) apt_net_client_task_terminate(apt_net_client_task_t *task)
-{
- return apt_task_terminate(task->base,TRUE);
-}
-
-/** Get task */
-APT_DECLARE(apt_task_t*) apt_net_client_task_base_get(apt_net_client_task_t *task)
-{
- return task->base;
-}
-
-/** Get task vtable */
-APT_DECLARE(apt_task_vtable_t*) apt_net_client_task_vtable_get(apt_net_client_task_t *task)
-{
- return apt_task_vtable_get(task->base);
-}
-
-/** Get external object */
-APT_DECLARE(void*) apt_net_client_task_object_get(apt_net_client_task_t *task)
-{
- return task->obj;
-}
-
-/** Create connection */
-APT_DECLARE(apt_net_client_connection_t*) apt_net_client_connect(apt_net_client_task_t *task, const char *ip, apr_port_t port)
-{
- char *local_ip = NULL;
- char *remote_ip = NULL;
- apr_sockaddr_t *l_sockaddr = NULL;
- apr_sockaddr_t *r_sockaddr = NULL;
- apt_net_client_connection_t *connection;
- apr_pool_t *pool = apt_pool_create();
- if(!pool) {
- return NULL;
- }
-
- connection = apr_palloc(pool,sizeof(apt_net_client_connection_t));
- connection->pool = pool;
- connection->obj = NULL;
- connection->sock = NULL;
-
- if(apr_sockaddr_info_get(&r_sockaddr,ip,APR_INET,port,0,connection->pool) != APR_SUCCESS) {
- apr_pool_destroy(pool);
- return NULL;
- }
-
- if(apr_socket_create(&connection->sock,r_sockaddr->family,SOCK_STREAM,APR_PROTO_TCP,connection->pool) != APR_SUCCESS) {
- apr_pool_destroy(pool);
- return NULL;
- }
-
- apr_socket_opt_set(connection->sock, APR_SO_NONBLOCK, 0);
- apr_socket_timeout_set(connection->sock, -1);
- apr_socket_opt_set(connection->sock, APR_SO_REUSEADDR, 1);
-
- if(apr_socket_connect(connection->sock,r_sockaddr) != APR_SUCCESS) {
- apr_socket_close(connection->sock);
- apr_pool_destroy(pool);
- return NULL;
- }
-
- if(apr_socket_addr_get(&l_sockaddr,APR_LOCAL,connection->sock) != APR_SUCCESS) {
- apr_socket_close(connection->sock);
- apr_pool_destroy(pool);
- return NULL;
- }
-
- apr_sockaddr_ip_get(&local_ip,l_sockaddr);
- apr_sockaddr_ip_get(&remote_ip,r_sockaddr);
- connection->id = apr_psprintf(pool,"%s:%hu <-> %s:%hu",
- local_ip,l_sockaddr->port,
- remote_ip,r_sockaddr->port);
-
- memset(&connection->sock_pfd,0,sizeof(apr_pollfd_t));
- connection->sock_pfd.desc_type = APR_POLL_SOCKET;
- connection->sock_pfd.reqevents = APR_POLLIN;
- connection->sock_pfd.desc.s = connection->sock;
- connection->sock_pfd.client_data = connection;
- if(apt_pollset_add(task->pollset,&connection->sock_pfd) != TRUE) {
- apr_socket_close(connection->sock);
- apr_pool_destroy(pool);
- return NULL;
- }
-
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Established TCP Connection %s",connection->id);
- return connection;
-}
-
-/** Close connection */
-APT_DECLARE(apt_bool_t) apt_net_client_connection_close(apt_net_client_task_t *task, apt_net_client_connection_t *connection)
-{
- if(connection->sock) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Close TCP Connection %s",connection->id);
- apt_pollset_remove(task->pollset,&connection->sock_pfd);
- apr_socket_close(connection->sock);
- connection->sock = NULL;
- }
- return TRUE;
-}
-
-/** Close and destroy connection */
-APT_DECLARE(apt_bool_t) apt_net_client_disconnect(apt_net_client_task_t *task, apt_net_client_connection_t *connection)
-{
- apt_net_client_connection_close(task,connection);
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Destroy TCP Connection %s",connection->id);
- apr_pool_destroy(connection->pool);
- return TRUE;
-}
-
-/** Create the pollset */
-static apt_bool_t apt_net_client_task_pollset_create(apt_net_client_task_t *task)
-{
- /* create pollset */
- task->pollset = apt_pollset_create((apr_uint32_t)task->max_connection_count, task->pool);
- if(!task->pollset) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Pollset");
- return FALSE;
- }
-
- return TRUE;
-}
-
-/** Destroy the pollset */
-static void apt_net_client_task_pollset_destroy(apt_net_client_task_t *task)
-{
- if(task->pollset) {
- apt_pollset_destroy(task->pollset);
- task->pollset = NULL;
- }
-}
-
-static apt_bool_t apt_net_client_task_process(apt_net_client_task_t *task)
-{
- apt_bool_t status = TRUE;
- apt_bool_t running = TRUE;
- apt_task_msg_t *msg;
-
- do {
- apr_thread_mutex_lock(task->guard);
- msg = apt_cyclic_queue_pop(task->msg_queue);
- apr_thread_mutex_unlock(task->guard);
- if(msg) {
- status = apt_task_msg_process(task->base,msg);
- }
- else {
- running = FALSE;
- }
- }
- while(running == TRUE);
- return status;
-}
-
-static apt_bool_t apt_net_client_task_run(apt_task_t *base)
-{
- apt_net_client_task_t *task = apt_task_object_get(base);
- apt_bool_t running = TRUE;
- apr_status_t status;
- apr_int32_t num;
- const apr_pollfd_t *ret_pfd;
- int i;
-
- if(!task) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Start Network Client Task");
- return FALSE;
- }
-
- if(apt_net_client_task_pollset_create(task) == FALSE) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Pollset");
- return FALSE;
- }
-
- /* explicitly indicate task is ready to process messages */
- apt_task_ready(task->base);
-
- while(running) {
- status = apt_pollset_poll(task->pollset, -1, &num, &ret_pfd);
- if(status != APR_SUCCESS) {
- continue;
- }
- for(i = 0; i < num; i++) {
- if(apt_pollset_is_wakeup(task->pollset,&ret_pfd[i])) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Process Control Message");
- if(apt_net_client_task_process(task) == FALSE) {
- running = FALSE;
- break;
- }
- continue;
- }
-
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Process Message");
- task->client_vtable->on_receive(task,ret_pfd[i].client_data);
- }
- }
-
- apt_net_client_task_pollset_destroy(task);
- return TRUE;
-}
-
-static apt_bool_t apt_net_client_task_msg_signal(apt_task_t *base, apt_task_msg_t *msg)
-{
- apt_bool_t status;
- apt_net_client_task_t *task = apt_task_object_get(base);
- apr_thread_mutex_lock(task->guard);
- status = apt_cyclic_queue_push(task->msg_queue,msg);
- apr_thread_mutex_unlock(task->guard);
- if(apt_pollset_wakeup(task->pollset) != TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Signal Control Message");
- status = FALSE;
- }
- return status;
-}
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_net_server_task.c b/libs/unimrcp/libs/apr-toolkit/src/apt_net_server_task.c
deleted file mode 100644
index 93cc9f5d69..0000000000
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_net_server_task.c
+++ /dev/null
@@ -1,393 +0,0 @@
-/*
- * Copyright 2008 Arsen Chaloyan
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "apt_net_server_task.h"
-#include "apt_task.h"
-#include "apt_pool.h"
-#include "apt_pollset.h"
-#include "apt_cyclic_queue.h"
-#include "apt_log.h"
-
-
-/** Network server task */
-struct apt_net_server_task_t {
- apr_pool_t *pool;
- apt_task_t *base;
- void *obj;
-
- apr_size_t max_connection_count;
-
- apr_thread_mutex_t *guard;
- apt_cyclic_queue_t *msg_queue;
- apt_pollset_t *pollset;
-
- /* Listening socket descriptor */
- apr_sockaddr_t *sockaddr;
- apr_socket_t *listen_sock;
- apr_pollfd_t listen_sock_pfd;
-
- const apt_net_server_vtable_t *server_vtable;
-};
-
-static apt_bool_t apt_net_server_task_msg_signal(apt_task_t *task, apt_task_msg_t *msg);
-static apt_bool_t apt_net_server_task_run(apt_task_t *task);
-static apt_bool_t apt_net_server_task_on_destroy(apt_task_t *task);
-
-/** Create connection task */
-APT_DECLARE(apt_net_server_task_t*) apt_net_server_task_create(
- const char *listen_ip,
- apr_port_t listen_port,
- apr_size_t max_connection_count,
- void *obj,
- const apt_net_server_vtable_t *server_vtable,
- apt_task_msg_pool_t *msg_pool,
- apr_pool_t *pool)
-{
- apt_task_vtable_t *vtable;
- apt_net_server_task_t *task;
-
- task = apr_palloc(pool,sizeof(apt_net_server_task_t));
- task->pool = pool;
- task->obj = obj;
- task->sockaddr = NULL;
- task->listen_sock = NULL;
- task->pollset = NULL;
- task->max_connection_count = max_connection_count;
-
- apr_sockaddr_info_get(&task->sockaddr,listen_ip,APR_INET,listen_port,0,task->pool);
- if(!task->sockaddr) {
- return NULL;
- }
-
- if(!server_vtable || !server_vtable->on_connect ||
- !server_vtable->on_disconnect || !server_vtable->on_receive) {
- return NULL;
- }
- task->server_vtable = server_vtable;
-
- task->base = apt_task_create(task,msg_pool,pool);
- if(!task->base) {
- return NULL;
- }
-
- vtable = apt_task_vtable_get(task->base);
- if(vtable) {
- vtable->run = apt_net_server_task_run;
- vtable->destroy = apt_net_server_task_on_destroy;
- vtable->signal_msg = apt_net_server_task_msg_signal;
- }
- apt_task_auto_ready_set(task->base,FALSE);
-
- task->msg_queue = apt_cyclic_queue_create(CYCLIC_QUEUE_DEFAULT_SIZE);
- apr_thread_mutex_create(&task->guard,APR_THREAD_MUTEX_UNNESTED,pool);
- return task;
-}
-
-/** Virtual destroy handler */
-static apt_bool_t apt_net_server_task_on_destroy(apt_task_t *base)
-{
- apt_net_server_task_t *task = apt_task_object_get(base);
- if(task->guard) {
- apr_thread_mutex_destroy(task->guard);
- task->guard = NULL;
- }
- if(task->msg_queue) {
- apt_cyclic_queue_destroy(task->msg_queue);
- task->msg_queue = NULL;
- }
- return TRUE;
-}
-
-/** Destroy connection task. */
-APT_DECLARE(apt_bool_t) apt_net_server_task_destroy(apt_net_server_task_t *task)
-{
- return apt_task_destroy(task->base);
-}
-
-/** Start connection task. */
-APT_DECLARE(apt_bool_t) apt_net_server_task_start(apt_net_server_task_t *task)
-{
- return apt_task_start(task->base);
-}
-
-/** Terminate connection task. */
-APT_DECLARE(apt_bool_t) apt_net_server_task_terminate(apt_net_server_task_t *task)
-{
- return apt_task_terminate(task->base,TRUE);
-}
-
-/** Get task */
-APT_DECLARE(apt_task_t*) apt_net_server_task_base_get(apt_net_server_task_t *task)
-{
- return task->base;
-}
-
-/** Get task vtable */
-APT_DECLARE(apt_task_vtable_t*) apt_net_server_task_vtable_get(apt_net_server_task_t *task)
-{
- return apt_task_vtable_get(task->base);
-}
-
-/** Get external object */
-APT_DECLARE(void*) apt_net_server_task_object_get(apt_net_server_task_t *task)
-{
- return task->obj;
-}
-
-
-/** Create listening socket and add to pollset */
-static apt_bool_t apt_net_server_task_listen_socket_create(apt_net_server_task_t *task)
-{
- apr_status_t status;
- if(!task->sockaddr) {
- return FALSE;
- }
-
- /* create listening socket */
- status = apr_socket_create(&task->listen_sock, task->sockaddr->family, SOCK_STREAM, APR_PROTO_TCP, task->pool);
- if(status != APR_SUCCESS) {
- return FALSE;
- }
-
- apr_socket_opt_set(task->listen_sock, APR_SO_NONBLOCK, 0);
- apr_socket_timeout_set(task->listen_sock, -1);
- apr_socket_opt_set(task->listen_sock, APR_SO_REUSEADDR, 1);
-
- status = apr_socket_bind(task->listen_sock, task->sockaddr);
- if(status != APR_SUCCESS) {
- apr_socket_close(task->listen_sock);
- task->listen_sock = NULL;
- return FALSE;
- }
- status = apr_socket_listen(task->listen_sock, SOMAXCONN);
- if(status != APR_SUCCESS) {
- apr_socket_close(task->listen_sock);
- task->listen_sock = NULL;
- return FALSE;
- }
-
- memset(&task->listen_sock_pfd,0,sizeof(apr_pollfd_t));
- task->listen_sock_pfd.desc_type = APR_POLL_SOCKET;
- task->listen_sock_pfd.reqevents = APR_POLLIN;
- task->listen_sock_pfd.desc.s = task->listen_sock;
- task->listen_sock_pfd.client_data = task->listen_sock;
- if(apt_pollset_add(task->pollset, &task->listen_sock_pfd) != TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Add Listen Socket to Pollset");
- apr_socket_close(task->listen_sock);
- task->listen_sock = NULL;
- }
-
- return TRUE;
-}
-
-/** Remove from pollset and destroy listening socket */
-static void apt_net_server_task_listen_socket_destroy(apt_net_server_task_t *task)
-{
- apt_pollset_remove(task->pollset,&task->listen_sock_pfd);
-
- if(task->listen_sock) {
- apr_socket_close(task->listen_sock);
- task->listen_sock = NULL;
- }
-}
-
-/** Create the pollset */
-static apt_bool_t apt_net_server_task_pollset_create(apt_net_server_task_t *task)
-{
- /* create pollset */
- task->pollset = apt_pollset_create((apr_uint32_t)task->max_connection_count + 1, task->pool);
- if(!task->pollset) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Pollset");
- return FALSE;
- }
-
- /* create listening socket */
- if(apt_net_server_task_listen_socket_create(task) != TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Listen Socket");
- }
-
- return TRUE;
-}
-
-/** Destroy the pollset */
-static void apt_net_server_task_pollset_destroy(apt_net_server_task_t *task)
-{
- apt_net_server_task_listen_socket_destroy(task);
- if(task->pollset) {
- apt_pollset_destroy(task->pollset);
- task->pollset = NULL;
- }
-}
-
-static apt_bool_t apt_net_server_task_process(apt_net_server_task_t *task)
-{
- apt_bool_t status = TRUE;
- apt_bool_t running = TRUE;
- apt_task_msg_t *msg;
-
- do {
- apr_thread_mutex_lock(task->guard);
- msg = apt_cyclic_queue_pop(task->msg_queue);
- apr_thread_mutex_unlock(task->guard);
- if(msg) {
- status = apt_task_msg_process(task->base,msg);
- }
- else {
- running = FALSE;
- }
- }
- while(running == TRUE);
- return status;
-}
-
-static apt_bool_t apt_net_server_task_accept(apt_net_server_task_t *task)
-{
- char *local_ip = NULL;
- char *remote_ip = NULL;
- apr_sockaddr_t *l_sockaddr = NULL;
- apr_sockaddr_t *r_sockaddr = NULL;
- apt_net_server_connection_t *connection;
- apr_pool_t *pool = apt_pool_create();
- if(!pool) {
- return FALSE;
- }
-
- connection = apr_palloc(pool,sizeof(apt_net_server_connection_t));
- connection->pool = pool;
- connection->obj = NULL;
- connection->sock = NULL;
- connection->client_ip = NULL;
-
- if(apr_socket_accept(&connection->sock,task->listen_sock,connection->pool) != APR_SUCCESS) {
- apr_pool_destroy(pool);
- return FALSE;
- }
-
- if(apr_socket_addr_get(&l_sockaddr,APR_LOCAL,connection->sock) != APR_SUCCESS ||
- apr_socket_addr_get(&r_sockaddr,APR_REMOTE,connection->sock) != APR_SUCCESS) {
- apr_pool_destroy(pool);
- return FALSE;
- }
-
- apr_sockaddr_ip_get(&local_ip,l_sockaddr);
- apr_sockaddr_ip_get(&remote_ip,r_sockaddr);
- connection->client_ip = remote_ip;
- connection->id = apr_psprintf(pool,"%s:%hu <-> %s:%hu",
- local_ip,l_sockaddr->port,
- remote_ip,r_sockaddr->port);
-
- memset(&connection->sock_pfd,0,sizeof(apr_pollfd_t));
- connection->sock_pfd.desc_type = APR_POLL_SOCKET;
- connection->sock_pfd.reqevents = APR_POLLIN;
- connection->sock_pfd.desc.s = connection->sock;
- connection->sock_pfd.client_data = connection;
- if(apt_pollset_add(task->pollset,&connection->sock_pfd) != TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Add to Pollset");
- apr_socket_close(connection->sock);
- apr_pool_destroy(pool);
- return FALSE;
- }
-
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Accepted TCP Connection %s",connection->id);
- task->server_vtable->on_connect(task,connection);
- return TRUE;
-}
-
-static apt_bool_t apt_net_server_task_run(apt_task_t *base)
-{
- apt_net_server_task_t *task = apt_task_object_get(base);
- apt_bool_t running = TRUE;
- apr_status_t status;
- apr_int32_t num;
- const apr_pollfd_t *ret_pfd;
- int i;
-
- if(!task) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Start Network Server Task");
- return FALSE;
- }
-
- if(apt_net_server_task_pollset_create(task) == FALSE) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Pollset");
- return FALSE;
- }
-
- /* explicitly indicate task is ready to process messages */
- apt_task_ready(task->base);
-
- while(running) {
- status = apt_pollset_poll(task->pollset, -1, &num, &ret_pfd);
- if(status != APR_SUCCESS) {
- continue;
- }
- for(i = 0; i < num; i++) {
- if(ret_pfd[i].desc.s == task->listen_sock) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Accept Connection");
- apt_net_server_task_accept(task);
- continue;
- }
- if(apt_pollset_is_wakeup(task->pollset,&ret_pfd[i])) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Process Control Message");
- if(apt_net_server_task_process(task) == FALSE) {
- running = FALSE;
- break;
- }
- continue;
- }
-
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Process Message");
- task->server_vtable->on_receive(task,ret_pfd[i].client_data);
- }
- }
-
- apt_net_server_task_pollset_destroy(task);
- return TRUE;
-}
-
-static apt_bool_t apt_net_server_task_msg_signal(apt_task_t *base, apt_task_msg_t *msg)
-{
- apt_bool_t status;
- apt_net_server_task_t *task = apt_task_object_get(base);
- apr_thread_mutex_lock(task->guard);
- status = apt_cyclic_queue_push(task->msg_queue,msg);
- apr_thread_mutex_unlock(task->guard);
- if(apt_pollset_wakeup(task->pollset) != TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Signal Control Message");
- status = FALSE;
- }
- return status;
-}
-
-
-/** Close connection */
-APT_DECLARE(apt_bool_t) apt_net_server_connection_close(apt_net_server_task_t *task, apt_net_server_connection_t *connection)
-{
- if(connection->sock) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Close TCP Connection %s",connection->id);
- apt_pollset_remove(task->pollset,&connection->sock_pfd);
- apr_socket_close(connection->sock);
- connection->sock = NULL;
- task->server_vtable->on_disconnect(task,connection);
- }
- return TRUE;
-}
-
-/** Destroy connection */
-APT_DECLARE(void) apt_net_server_connection_destroy(apt_net_server_connection_t *connection)
-{
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Destroy TCP Connection %s",connection->id);
- apr_pool_destroy(connection->pool);
-}
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_nlsml_doc.c b/libs/unimrcp/libs/apr-toolkit/src/apt_nlsml_doc.c
index 4e4ae82124..af46ab7342 100644
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_nlsml_doc.c
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_nlsml_doc.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,9 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_nlsml_doc.c 1655 2010-04-16 18:36:27Z achaloyan $
*/
#include "apt_nlsml_doc.h"
+#include "apt_log.h"
/** Load NLSML document */
APT_DECLARE(apr_xml_doc*) nlsml_doc_load(const apt_str_t *data, apr_pool_t *pool)
@@ -26,21 +29,25 @@ APT_DECLARE(apr_xml_doc*) nlsml_doc_load(const apt_str_t *data, apr_pool_t *pool
/* create XML parser */
parser = apr_xml_parser_create(pool);
if(apr_xml_parser_feed(parser,data->buf,data->length) != APR_SUCCESS) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to feed NLSML input to the parser");
return NULL;
}
/* done with XML tree creation */
if(apr_xml_parser_done(parser,&doc) != APR_SUCCESS) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to terminate NLSML parsing");
return NULL;
}
if(!doc || !doc->root) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No NLSML root element");
return NULL;
}
root = doc->root;
/* NLSML validity check: root element must be */
if(strcmp(root->name,"result") != 0) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unexpected NLSML root element <%s>",root->name);
return NULL;
}
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_obj_list.c b/libs/unimrcp/libs/apr-toolkit/src/apt_obj_list.c
index a1d320a8aa..69f006adee 100644
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_obj_list.c
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_obj_list.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_obj_list.c 1708 2010-05-24 17:03:25Z achaloyan $
*/
#ifdef WIN32
@@ -65,7 +67,7 @@ APT_DECLARE(void*) apt_list_pop_front(apt_obj_list_t *list)
return elem->obj;
}
-APT_DECLARE(void*) apt_list_head(apt_obj_list_t *list)
+APT_DECLARE(void*) apt_list_head(const apt_obj_list_t *list)
{
apt_list_elem_t *elem;
if(APR_RING_EMPTY(&list->head,apt_list_elem_t,link)) {
@@ -75,7 +77,7 @@ APT_DECLARE(void*) apt_list_head(apt_obj_list_t *list)
return elem->obj;
}
-APT_DECLARE(void*) apt_obj_list_tail(apt_obj_list_t *list)
+APT_DECLARE(void*) apt_obj_list_tail(const apt_obj_list_t *list)
{
apt_list_elem_t *elem;
if(APR_RING_EMPTY(&list->head,apt_list_elem_t,link)) {
@@ -85,7 +87,7 @@ APT_DECLARE(void*) apt_obj_list_tail(apt_obj_list_t *list)
return elem->obj;
}
-APT_DECLARE(apt_list_elem_t*) apt_list_first_elem_get(apt_obj_list_t *list)
+APT_DECLARE(apt_list_elem_t*) apt_list_first_elem_get(const apt_obj_list_t *list)
{
if(APR_RING_EMPTY(&list->head,apt_list_elem_t,link)) {
return NULL;
@@ -93,7 +95,7 @@ APT_DECLARE(apt_list_elem_t*) apt_list_first_elem_get(apt_obj_list_t *list)
return APR_RING_FIRST(&list->head);
}
-APT_DECLARE(apt_list_elem_t*) apt_list_last_elem_get(apt_obj_list_t *list)
+APT_DECLARE(apt_list_elem_t*) apt_list_last_elem_get(const apt_obj_list_t *list)
{
if(APR_RING_EMPTY(&list->head,apt_list_elem_t,link)) {
return NULL;
@@ -101,7 +103,7 @@ APT_DECLARE(apt_list_elem_t*) apt_list_last_elem_get(apt_obj_list_t *list)
return APR_RING_LAST(&list->head);
}
-APT_DECLARE(apt_list_elem_t*) apt_list_next_elem_get(apt_obj_list_t *list, apt_list_elem_t *elem)
+APT_DECLARE(apt_list_elem_t*) apt_list_next_elem_get(const apt_obj_list_t *list, apt_list_elem_t *elem)
{
apt_list_elem_t *next_elem = APR_RING_NEXT(elem,link);
if(next_elem == APR_RING_SENTINEL(&list->head,apt_list_elem_t,link)) {
@@ -110,7 +112,7 @@ APT_DECLARE(apt_list_elem_t*) apt_list_next_elem_get(apt_obj_list_t *list, apt_l
return next_elem;
}
-APT_DECLARE(apt_list_elem_t*) apt_list_prev_elem_get(apt_obj_list_t *list, apt_list_elem_t *elem)
+APT_DECLARE(apt_list_elem_t*) apt_list_prev_elem_get(const apt_obj_list_t *list, apt_list_elem_t *elem)
{
apt_list_elem_t *prev_elem = APR_RING_PREV(elem,link);
if(prev_elem == APR_RING_SENTINEL(&list->head,apt_list_elem_t,link)) {
@@ -137,7 +139,7 @@ APT_DECLARE(apt_list_elem_t*) apt_list_elem_remove(apt_obj_list_t *list, apt_lis
return next_elem;
}
-APT_DECLARE(apt_bool_t) apt_list_is_empty(apt_obj_list_t *list)
+APT_DECLARE(apt_bool_t) apt_list_is_empty(const apt_obj_list_t *list)
{
if(APR_RING_EMPTY(&list->head,apt_list_elem_t,link)) {
return TRUE;
@@ -145,7 +147,7 @@ APT_DECLARE(apt_bool_t) apt_list_is_empty(apt_obj_list_t *list)
return FALSE;
}
-APT_DECLARE(void*) apt_list_elem_object_get(apt_list_elem_t *elem)
+APT_DECLARE(void*) apt_list_elem_object_get(const apt_list_elem_t *elem)
{
return elem->obj;
}
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_pair.c b/libs/unimrcp/libs/apr-toolkit/src/apt_pair.c
index 29eb60e4d9..05c05c9e7e 100644
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_pair.c
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_pair.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_pair.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "apt_pair.h"
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_poller_task.c b/libs/unimrcp/libs/apr-toolkit/src/apt_poller_task.c
new file mode 100644
index 0000000000..99a581667b
--- /dev/null
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_poller_task.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: apt_poller_task.c 1708 2010-05-24 17:03:25Z achaloyan $
+ */
+
+#include "apt_poller_task.h"
+#include "apt_task.h"
+#include "apt_pool.h"
+#include "apt_cyclic_queue.h"
+#include "apt_log.h"
+
+
+/** Poller task */
+struct apt_poller_task_t {
+ apr_pool_t *pool;
+ apt_task_t *base;
+
+ void *obj;
+ apt_poll_signal_f signal_handler;
+
+ apr_thread_mutex_t *guard;
+ apt_cyclic_queue_t *msg_queue;
+ apt_pollset_t *pollset;
+ apt_timer_queue_t *timer_queue;
+};
+
+static apt_bool_t apt_poller_task_msg_signal(apt_task_t *task, apt_task_msg_t *msg);
+static apt_bool_t apt_poller_task_run(apt_task_t *task);
+static apt_bool_t apt_poller_task_on_destroy(apt_task_t *task);
+
+
+/** Create poller task */
+APT_DECLARE(apt_poller_task_t*) apt_poller_task_create(
+ apr_size_t max_pollset_size,
+ apt_poll_signal_f signal_handler,
+ void *obj,
+ apt_task_msg_pool_t *msg_pool,
+ apr_pool_t *pool)
+{
+ apt_task_vtable_t *vtable;
+ apt_poller_task_t *task;
+
+ if(!signal_handler) {
+ return NULL;
+ }
+
+ task = apr_palloc(pool,sizeof(apt_poller_task_t));
+ task->pool = pool;
+ task->obj = obj;
+ task->pollset = NULL;
+ task->signal_handler = signal_handler;
+
+ task->pollset = apt_pollset_create((apr_uint32_t)max_pollset_size,pool);
+ if(!task->pollset) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Pollset");
+ return NULL;
+ }
+
+ task->base = apt_task_create(task,msg_pool,pool);
+ if(!task->base) {
+ apt_pollset_destroy(task->pollset);
+ return NULL;
+ }
+
+ vtable = apt_task_vtable_get(task->base);
+ if(vtable) {
+ vtable->run = apt_poller_task_run;
+ vtable->destroy = apt_poller_task_on_destroy;
+ vtable->signal_msg = apt_poller_task_msg_signal;
+ }
+ apt_task_auto_ready_set(task->base,FALSE);
+
+ task->msg_queue = apt_cyclic_queue_create(CYCLIC_QUEUE_DEFAULT_SIZE);
+ apr_thread_mutex_create(&task->guard,APR_THREAD_MUTEX_UNNESTED,pool);
+
+ task->timer_queue = apt_timer_queue_create(pool);
+ return task;
+}
+
+/** Destroy poller task */
+APT_DECLARE(apt_bool_t) apt_poller_task_destroy(apt_poller_task_t *task)
+{
+ return apt_task_destroy(task->base);
+}
+
+/** Cleanup poller task */
+APT_DECLARE(void) apt_poller_task_cleanup(apt_poller_task_t *task)
+{
+ if(task->pollset) {
+ apt_pollset_destroy(task->pollset);
+ task->pollset = NULL;
+ }
+ if(task->guard) {
+ apr_thread_mutex_destroy(task->guard);
+ task->guard = NULL;
+ }
+ if(task->msg_queue) {
+ apt_cyclic_queue_destroy(task->msg_queue);
+ task->msg_queue = NULL;
+ }
+}
+
+/** Virtual destroy handler */
+static apt_bool_t apt_poller_task_on_destroy(apt_task_t *base)
+{
+ apt_poller_task_t *task = apt_task_object_get(base);
+ apt_poller_task_cleanup(task);
+ return TRUE;
+}
+
+
+/** Start poller task */
+APT_DECLARE(apt_bool_t) apt_poller_task_start(apt_poller_task_t *task)
+{
+ return apt_task_start(task->base);
+}
+
+/** Terminate poller task */
+APT_DECLARE(apt_bool_t) apt_poller_task_terminate(apt_poller_task_t *task)
+{
+ return apt_task_terminate(task->base,TRUE);
+}
+
+/** Get task */
+APT_DECLARE(apt_task_t*) apt_poller_task_base_get(const apt_poller_task_t *task)
+{
+ return task->base;
+}
+
+/** Get task vtable */
+APT_DECLARE(apt_task_vtable_t*) apt_poller_task_vtable_get(apt_poller_task_t *task)
+{
+ return apt_task_vtable_get(task->base);
+}
+
+/** Get external object */
+APT_DECLARE(void*) apt_poller_task_object_get(const apt_poller_task_t *task)
+{
+ return task->obj;
+}
+
+/** Get pollset */
+APT_DECLARE(apt_pollset_t*) apt_poller_task_pollset_get(const apt_poller_task_t *task)
+{
+ return task->pollset;
+}
+
+/** Create timer */
+APT_DECLARE(apt_timer_t*) apt_poller_task_timer_create(
+ apt_poller_task_t *task,
+ apt_timer_proc_f proc,
+ void *obj,
+ apr_pool_t *pool)
+{
+ return apt_timer_create(task->timer_queue,proc,obj,pool);
+}
+
+static apt_bool_t apt_poller_task_wakeup_process(apt_poller_task_t *task)
+{
+ apt_bool_t running = TRUE;
+ apt_task_msg_t *msg;
+
+ do {
+ apr_thread_mutex_lock(task->guard);
+ msg = apt_cyclic_queue_pop(task->msg_queue);
+ apr_thread_mutex_unlock(task->guard);
+ if(msg) {
+ apt_task_msg_process(task->base,msg);
+ }
+ else {
+ running = FALSE;
+ }
+ }
+ while(running == TRUE);
+ return TRUE;
+}
+
+static apt_bool_t apt_poller_task_run(apt_task_t *base)
+{
+ apt_poller_task_t *task = apt_task_object_get(base);
+ apt_bool_t *running;
+ apr_status_t status;
+ apr_int32_t num;
+ const apr_pollfd_t *ret_pfd;
+ apr_interval_time_t timeout;
+ apr_uint32_t queue_timeout;
+ apr_time_t time_now, time_last = 0;
+ int i;
+ const char *task_name;
+
+ if(!task) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Start Poller Task");
+ return FALSE;
+ }
+ task_name = apt_task_name_get(task->base),
+
+ running = apt_task_running_flag_get(task->base);
+ if(!running) {
+ return FALSE;
+ }
+
+ /* explicitly indicate task is ready to process messages */
+ apt_task_ready(task->base);
+
+ while(*running) {
+ if(apt_timer_queue_timeout_get(task->timer_queue,&queue_timeout) == TRUE) {
+ timeout = queue_timeout * 1000;
+ time_last = apr_time_now();
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Wait for Messages [%s] timeout [%u]",
+ task_name, queue_timeout);
+ }
+ else {
+ timeout = -1;
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Wait for Messages [%s]",task_name);
+ }
+ status = apt_pollset_poll(task->pollset, timeout, &num, &ret_pfd);
+ if(status != APR_SUCCESS && status != APR_TIMEUP) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Poll [%s] status: %d",task_name,status);
+ continue;
+ }
+ for(i = 0; i < num; i++) {
+ if(apt_pollset_is_wakeup(task->pollset,&ret_pfd[i])) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Process Poller Wakeup [%s]",task_name);
+ apt_poller_task_wakeup_process(task);
+ if(*running == FALSE) {
+ break;
+ }
+ continue;
+ }
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Process Signalled Descriptor [%s]",task_name);
+ task->signal_handler(task->obj,&ret_pfd[i]);
+ }
+
+ if(timeout != -1) {
+ time_now = apr_time_now();
+ if(time_now > time_last) {
+ apt_timer_queue_advance(task->timer_queue,(apr_uint32_t)((time_now - time_last)/1000));
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+static apt_bool_t apt_poller_task_msg_signal(apt_task_t *base, apt_task_msg_t *msg)
+{
+ apt_bool_t status;
+ apt_poller_task_t *task = apt_task_object_get(base);
+ apr_thread_mutex_lock(task->guard);
+ status = apt_cyclic_queue_push(task->msg_queue,msg);
+ apr_thread_mutex_unlock(task->guard);
+ if(apt_pollset_wakeup(task->pollset) != TRUE) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Signal Control Message");
+ status = FALSE;
+ }
+ return status;
+}
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_pollset.c b/libs/unimrcp/libs/apr-toolkit/src/apt_pollset.c
index 87db7f8c04..7592aff663 100644
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_pollset.c
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_pollset.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_pollset.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_pool.c b/libs/unimrcp/libs/apr-toolkit/src/apt_pool.c
index 8f75400836..8cbe247b9b 100644
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_pool.c
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_pool.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_pool.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "apt_pool.h"
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_string_table.c b/libs/unimrcp/libs/apr-toolkit/src/apt_string_table.c
index cc0c6be73b..bc96c51c49 100644
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_string_table.c
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_string_table.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_string_table.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_task.c b/libs/unimrcp/libs/apr-toolkit/src/apt_task.c
index 9d7014d592..5ce74e137f 100644
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_task.c
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_task.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_task.c 1696 2010-05-20 15:44:16Z achaloyan $
*/
#include
@@ -23,10 +25,10 @@
/** Internal states of the task */
typedef enum {
TASK_STATE_IDLE, /**< no task activity */
- TASK_STATE_START_REQUESTED, /**< task start is requested and is in progress */
+ TASK_STATE_START_REQUESTED, /**< start of the task has been requested, but it's not running yet */
TASK_STATE_RUNNING, /**< task is running */
- TASK_STATE_TERMINATE_REQUESTED /**< task termination is requested and is in progress */
-} apt_task_state_t;
+ TASK_STATE_TERMINATE_REQUESTED /**< termination of the task has been requested, but it's still running */
+} apt_task_state_e;
struct apt_task_t {
void *obj; /* external object associated with the task */
@@ -34,18 +36,22 @@ struct apt_task_t {
apt_task_msg_pool_t *msg_pool; /* message pool to allocate task messages from */
apr_thread_mutex_t *data_guard; /* mutex to protect task data */
apr_thread_t *thread_handle; /* thread handle */
- apt_task_state_t state; /* current task state */
+ apt_task_state_e state; /* current task state */
apt_task_vtable_t vtable; /* table of virtual methods */
apt_task_t *parent_task; /* parent (master) task */
apt_obj_list_t *child_tasks; /* list of the child (slave) tasks */
apr_size_t pending_start; /* number of pending start requests */
apr_size_t pending_term; /* number of pending terminate requests */
+ apt_bool_t running; /* task is running (TRUE if even terminate has already been requested) */
apt_bool_t auto_ready; /* if TRUE, task is implicitly ready to process messages */
const char *name; /* name of the task */
};
static void* APR_THREAD_FUNC apt_task_run(apr_thread_t *thread_handle, void *data);
+static APR_INLINE void apt_task_vtable_reset(apt_task_vtable_t *vtable);
static apt_bool_t apt_task_terminate_request(apt_task_t *task);
+static void apt_task_start_complete_raise(apt_task_t *task);
+static void apt_task_terminate_complete_raise(apt_task_t *task);
APT_DECLARE(apt_task_t*) apt_task_create(
@@ -98,7 +104,7 @@ APT_DECLARE(apt_bool_t) apt_task_destroy(apt_task_t *task)
apt_task_wait_till_complete(task);
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Destroy %s",task->name);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Destroy Task [%s]",task->name);
if(task->vtable.destroy) {
task->vtable.destroy(task);
}
@@ -120,7 +126,7 @@ APT_DECLARE(apt_bool_t) apt_task_start(apt_task_t *task)
if(task->state == TASK_STATE_IDLE) {
apr_status_t rv;
task->state = TASK_STATE_START_REQUESTED;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Start %s",task->name);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Start Task [%s]",task->name);
if(task->vtable.start) {
/* raise virtual start method */
task->vtable.start(task);
@@ -152,7 +158,7 @@ APT_DECLARE(apt_bool_t) apt_task_terminate(apt_task_t *task, apt_bool_t wait_til
if(task->state == TASK_STATE_TERMINATE_REQUESTED) {
/* raise virtual terminate method */
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Terminate %s",task->name);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Terminate Task [%s]",task->name);
if(task->vtable.terminate) {
status = task->vtable.terminate(task);
}
@@ -180,17 +186,17 @@ APT_DECLARE(void) apt_task_delay(apr_size_t msec)
apr_sleep(1000*msec);
}
-APT_DECLARE(apt_task_t*) apt_task_parent_get(apt_task_t *task)
+APT_DECLARE(apt_task_t*) apt_task_parent_get(const apt_task_t *task)
{
return task->parent_task;
}
-APT_DECLARE(apr_pool_t*) apt_task_pool_get(apt_task_t *task)
+APT_DECLARE(apr_pool_t*) apt_task_pool_get(const apt_task_t *task)
{
return task->pool;
}
-APT_DECLARE(void*) apt_task_object_get(apt_task_t *task)
+APT_DECLARE(void*) apt_task_object_get(const apt_task_t *task)
{
return task->obj;
}
@@ -205,7 +211,7 @@ APT_DECLARE(void) apt_task_name_set(apt_task_t *task, const char *name)
task->name = name;
}
-APT_DECLARE(const char*) apt_task_name_get(apt_task_t *task)
+APT_DECLARE(const char*) apt_task_name_get(const apt_task_t *task)
{
return task->name;
}
@@ -220,6 +226,8 @@ APT_DECLARE(apt_task_msg_t*) apt_task_msg_get(apt_task_t *task)
APT_DECLARE(apt_bool_t) apt_task_msg_signal(apt_task_t *task, apt_task_msg_t *msg)
{
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Signal Message to [%s] [%d;%d]",
+ task->name, msg->type, msg->sub_type);
if(task->vtable.signal_msg) {
return task->vtable.signal_msg(task,msg);
}
@@ -238,74 +246,48 @@ APT_DECLARE(apt_bool_t) apt_task_msg_parent_signal(apt_task_t *task, apt_task_ms
}
-APT_DECLARE(apt_bool_t) apt_core_task_msg_process(apt_task_t *task, apt_task_msg_t *msg)
+static apt_bool_t apt_core_task_msg_process(apt_task_t *task, apt_task_msg_t *msg)
{
- apt_bool_t running = TRUE;
switch(msg->sub_type) {
- case CORE_TASK_MSG_START_COMPLETE:
+ case CORE_TASK_MSG_START_COMPLETE:
{
- if(!task->pending_start) {
- /* error case, no pending start */
- break;
- }
- task->pending_start--;
- if(!task->pending_start) {
- if(task->vtable.on_start_complete) {
- task->vtable.on_start_complete(task);
- }
- if(task->parent_task) {
- /* signal start-complete message */
- apt_task_msg_signal(task->parent_task,msg);
- }
- }
+ apt_task_start_request_remove(task);
break;
}
case CORE_TASK_MSG_TERMINATE_REQUEST:
{
apt_task_child_terminate(task);
if(!task->pending_term) {
- running = FALSE;
+ task->running = FALSE;
}
break;
}
case CORE_TASK_MSG_TERMINATE_COMPLETE:
{
- if(!task->pending_term) {
- /* error case, no pending terminate */
- break;
- }
- task->pending_term--;
- if(!task->pending_term) {
- if(task->vtable.on_terminate_complete) {
- task->vtable.on_terminate_complete(task);
- }
- if(task->parent_task) {
- /* signal terminate-complete message */
- apt_task_msg_signal(task->parent_task,msg);
- }
- running = FALSE;
- }
+ apt_task_terminate_request_remove(task);
break;
}
default: break;
}
- return running;
+ return TRUE;
}
APT_DECLARE(apt_bool_t) apt_task_msg_process(apt_task_t *task, apt_task_msg_t *msg)
{
- apt_bool_t running = TRUE;
+ apt_bool_t status = FALSE;
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Process Message [%s] [%d;%d]",
+ task->name, msg->type, msg->sub_type);
if(msg->type == TASK_MSG_CORE) {
- running = apt_core_task_msg_process(task,msg);
+ status = apt_core_task_msg_process(task,msg);
}
else {
if(task->vtable.process_msg) {
- task->vtable.process_msg(task,msg);
+ status = task->vtable.process_msg(task,msg);
}
}
apt_task_msg_release(msg);
- return running;
+ return status;
}
static apt_bool_t apt_task_terminate_request(apt_task_t *task)
@@ -325,6 +307,9 @@ APT_DECLARE(apt_bool_t) apt_task_child_start(apt_task_t *task)
apt_task_t *child_task = NULL;
apt_list_elem_t *elem = apt_list_first_elem_get(task->child_tasks);
task->pending_start = 0;
+ if(task->vtable.on_start_request) {
+ task->vtable.on_start_request(task);
+ }
/* walk through the list of the child tasks and start them */
while(elem) {
child_task = apt_list_elem_object_get(elem);
@@ -338,18 +323,7 @@ APT_DECLARE(apt_bool_t) apt_task_child_start(apt_task_t *task)
if(!task->pending_start) {
/* no child task to start, just raise start-complete event */
- if(task->vtable.on_start_complete) {
- task->vtable.on_start_complete(task);
- }
- if(task->parent_task) {
- if(task->msg_pool) {
- apt_task_msg_t *msg = apt_task_msg_acquire(task->msg_pool);
- /* signal start-complete message */
- msg->type = TASK_MSG_CORE;
- msg->sub_type = CORE_TASK_MSG_START_COMPLETE;
- apt_task_msg_signal(task->parent_task,msg);
- }
- }
+ apt_task_start_complete_raise(task);
}
return TRUE;
}
@@ -359,6 +333,9 @@ APT_DECLARE(apt_bool_t) apt_task_child_terminate(apt_task_t *task)
apt_task_t *child_task = NULL;
apt_list_elem_t *elem = apt_list_first_elem_get(task->child_tasks);
task->pending_term = 0;
+ if(task->vtable.on_terminate_request) {
+ task->vtable.on_terminate_request(task);
+ }
/* walk through the list of the child tasks and terminate them */
while(elem) {
child_task = apt_list_elem_object_get(elem);
@@ -380,20 +357,7 @@ APT_DECLARE(apt_bool_t) apt_task_child_terminate(apt_task_t *task)
if(!task->pending_term) {
/* no child task to terminate, just raise terminate-complete event */
- if(task->vtable.on_terminate_complete) {
- task->vtable.on_terminate_complete(task);
- }
-#ifdef ENABLE_SIMULT_TASK_TERMINATION
- if(task->parent_task) {
- if(task->msg_pool) {
- apt_task_msg_t *msg = apt_task_msg_acquire(task->msg_pool);
- /* signal terminate-complete message */
- msg->type = TASK_MSG_CORE;
- msg->sub_type = CORE_TASK_MSG_TERMINATE_COMPLETE;
- apt_task_msg_signal(task->parent_task,msg);
- }
- }
-#endif
+ apt_task_terminate_complete_raise(task);
}
return TRUE;
}
@@ -414,6 +378,85 @@ APT_DECLARE(apt_bool_t) apt_task_ready(apt_task_t *task)
return TRUE;
}
+APT_DECLARE(apt_bool_t*) apt_task_running_flag_get(apt_task_t *task)
+{
+ return &task->running;
+}
+
+APT_DECLARE(apt_bool_t) apt_task_start_request_add(apt_task_t *task)
+{
+ task->pending_start++;
+ return TRUE;
+}
+
+APT_DECLARE(apt_bool_t) apt_task_start_request_remove(apt_task_t *task)
+{
+ if(!task->pending_start) {
+ /* error case, no pending start */
+ return FALSE;
+ }
+ task->pending_start--;
+ if(!task->pending_start) {
+ apt_task_start_complete_raise(task);
+ }
+ return TRUE;
+}
+
+APT_DECLARE(apt_bool_t) apt_task_terminate_request_add(apt_task_t *task)
+{
+ task->pending_term++;
+ return TRUE;
+}
+
+APT_DECLARE(apt_bool_t) apt_task_terminate_request_remove(apt_task_t *task)
+{
+ if(!task->pending_term) {
+ /* error case, no pending terminate */
+ return FALSE;
+ }
+ task->pending_term--;
+ if(!task->pending_term) {
+ apt_task_terminate_complete_raise(task);
+ task->running = FALSE;
+ }
+ return TRUE;
+}
+
+static void apt_task_start_complete_raise(apt_task_t *task)
+{
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Task Started [%s]",task->name);
+ if(task->vtable.on_start_complete) {
+ task->vtable.on_start_complete(task);
+ }
+ if(task->parent_task) {
+ if(task->msg_pool) {
+ apt_task_msg_t *msg = apt_task_msg_acquire(task->msg_pool);
+ /* signal start-complete message */
+ msg->type = TASK_MSG_CORE;
+ msg->sub_type = CORE_TASK_MSG_START_COMPLETE;
+ apt_task_msg_signal(task->parent_task,msg);
+ }
+ }
+}
+
+static void apt_task_terminate_complete_raise(apt_task_t *task)
+{
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Task Terminated [%s]",task->name);
+ if(task->vtable.on_terminate_complete) {
+ task->vtable.on_terminate_complete(task);
+ }
+#ifdef ENABLE_SIMULT_TASK_TERMINATION
+ if(task->parent_task) {
+ if(task->msg_pool) {
+ apt_task_msg_t *msg = apt_task_msg_acquire(task->msg_pool);
+ /* signal terminate-complete message */
+ msg->type = TASK_MSG_CORE;
+ msg->sub_type = CORE_TASK_MSG_TERMINATE_COMPLETE;
+ apt_task_msg_signal(task->parent_task,msg);
+ }
+ }
+#endif
+}
static void* APR_THREAD_FUNC apt_task_run(apr_thread_t *thread_handle, void *data)
{
@@ -425,6 +468,7 @@ static void* APR_THREAD_FUNC apt_task_run(apr_thread_t *thread_handle, void *dat
}
apr_thread_mutex_lock(task->data_guard);
task->state = TASK_STATE_RUNNING;
+ task->running = TRUE;
apr_thread_mutex_unlock(task->data_guard);
if(task->auto_ready == TRUE) {
@@ -439,6 +483,7 @@ static void* APR_THREAD_FUNC apt_task_run(apr_thread_t *thread_handle, void *dat
apr_thread_mutex_lock(task->data_guard);
task->state = TASK_STATE_IDLE;
+ task->running = FALSE;
apr_thread_mutex_unlock(task->data_guard);
/* raise post-run event */
if(task->vtable.on_post_run) {
@@ -448,3 +493,19 @@ static void* APR_THREAD_FUNC apt_task_run(apr_thread_t *thread_handle, void *dat
apr_thread_exit(thread_handle,APR_SUCCESS);
return NULL;
}
+
+static APR_INLINE void apt_task_vtable_reset(apt_task_vtable_t *vtable)
+{
+ vtable->destroy = NULL;
+ vtable->start = NULL;
+ vtable->terminate = NULL;
+ vtable->run = NULL;
+ vtable->signal_msg = NULL;
+ vtable->process_msg = NULL;
+ vtable->on_pre_run = NULL;
+ vtable->on_post_run = NULL;
+ vtable->on_start_request = NULL;
+ vtable->on_start_complete = NULL;
+ vtable->on_terminate_request = NULL;
+ vtable->on_terminate_complete = NULL;
+}
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_task_msg.c b/libs/unimrcp/libs/apr-toolkit/src/apt_task_msg.c
index fdff519fb1..bb64cea6ef 100644
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_task_msg.c
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_task_msg.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_task_msg.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_test_suite.c b/libs/unimrcp/libs/apr-toolkit/src/apt_test_suite.c
index 6a5d18ad7d..afaf29f0ce 100644
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_test_suite.c
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_test_suite.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_test_suite.c 1708 2010-05-24 17:03:25Z achaloyan $
*/
#include "apt_pool.h"
@@ -61,7 +63,7 @@ APT_DECLARE(apt_bool_t) apt_test_framework_suite_add(apt_test_framework_t *frame
return (apt_list_push_back(framework->suites,suite,suite->pool) ? TRUE : FALSE);
}
-APT_DECLARE(apr_pool_t*) apt_test_framework_pool_get(apt_test_framework_t *framework)
+APT_DECLARE(apr_pool_t*) apt_test_framework_pool_get(const apt_test_framework_t *framework)
{
return framework->pool;
}
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_text_message.c b/libs/unimrcp/libs/apr-toolkit/src/apt_text_message.c
new file mode 100644
index 0000000000..1e0d901b43
--- /dev/null
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_text_message.c
@@ -0,0 +1,448 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: apt_text_message.c 1671 2010-04-28 19:50:29Z achaloyan $
+ */
+
+#include "apt_text_message.h"
+#include "apt_log.h"
+
+/** Stage of text message processing (parsing/generation) */
+typedef enum {
+ APT_MESSAGE_STAGE_START_LINE,
+ APT_MESSAGE_STAGE_HEADER,
+ APT_MESSAGE_STAGE_BODY
+} apt_message_stage_e;
+
+
+/** Text message parser */
+struct apt_message_parser_t {
+ const apt_message_parser_vtable_t *vtable;
+ void *obj;
+ apr_pool_t *pool;
+ apt_message_context_t context;
+ apr_size_t content_length;
+ apt_message_stage_e stage;
+ apt_bool_t skip_lf;
+ apt_bool_t verbose;
+};
+
+/** Text message generator */
+struct apt_message_generator_t {
+ const apt_message_generator_vtable_t *vtable;
+ void *obj;
+ apr_pool_t *pool;
+ apt_message_context_t context;
+ apr_size_t content_length;
+ apt_message_stage_e stage;
+ apt_bool_t verbose;
+};
+
+/** Parse individual header field (name-value pair) */
+APT_DECLARE(apt_header_field_t*) apt_header_field_parse(apt_text_stream_t *stream, apr_pool_t *pool)
+{
+ apr_size_t folding_length = 0;
+ apr_array_header_t *folded_lines = NULL;
+ apt_header_field_t *header_field;
+ apt_str_t *line;
+ apt_pair_t pair;
+ /* read name-value pair */
+ if(apt_text_header_read(stream,&pair) == FALSE) {
+ return NULL;
+ }
+
+ /* check folding lines (value spanning multiple lines) */
+ while(stream->pos < stream->end) {
+ if(apt_text_is_wsp(*stream->pos) == FALSE) {
+ break;
+ }
+
+ stream->pos++;
+
+ /* skip further white spaces (if any) */
+ apt_text_white_spaces_skip(stream);
+
+ if(!folded_lines) {
+ folded_lines = apr_array_make(pool,1,sizeof(apt_str_t));
+ }
+ line = apr_array_push(folded_lines);
+ apt_text_line_read(stream,line);
+ folding_length += line->length;
+ };
+
+ header_field = apt_header_field_alloc(pool);
+ /* copy parsed name of the header field */
+ header_field->name.length = pair.name.length;
+ header_field->name.buf = apr_palloc(pool, pair.name.length + 1);
+ if(pair.name.length) {
+ memcpy(header_field->name.buf, pair.name.buf, pair.name.length);
+ }
+ header_field->name.buf[header_field->name.length] = '\0';
+
+ /* copy parsed value of the header field */
+ header_field->value.length = pair.value.length + folding_length;
+ header_field->value.buf = apr_palloc(pool, header_field->value.length + 1);
+ if(pair.value.length) {
+ memcpy(header_field->value.buf, pair.value.buf, pair.value.length);
+ }
+
+ if(folding_length) {
+ int i;
+ char *pos = header_field->value.buf + pair.value.length;
+ /* copy parsed folding lines */
+ for(i=0; inelts; i++) {
+ line = &APR_ARRAY_IDX(folded_lines,i,apt_str_t);
+
+ memcpy(pos,line->buf,line->length);
+ pos += line->length;
+ }
+ }
+ header_field->value.buf[header_field->value.length] = '\0';
+
+ return header_field;
+}
+
+/** Generate individual header field (name-value pair) */
+APT_DECLARE(apt_bool_t) apt_header_field_generate(const apt_header_field_t *header_field, apt_text_stream_t *stream)
+{
+ return apt_text_name_value_insert(stream,&header_field->name,&header_field->value);
+}
+
+/** Parse header section */
+APT_DECLARE(apt_bool_t) apt_header_section_parse(apt_header_section_t *header, apt_text_stream_t *stream, apr_pool_t *pool)
+{
+ apt_header_field_t *header_field;
+ apt_bool_t result = FALSE;
+
+ do {
+ header_field = apt_header_field_parse(stream,pool);
+ if(header_field) {
+ if(apt_string_is_empty(&header_field->name) == FALSE) {
+ /* normal header */
+ apt_header_section_field_add(header,header_field);
+ }
+ else {
+ /* empty header => exit */
+ result = TRUE;
+ break;
+ }
+ }
+ else {
+ /* malformed header => skip to the next one */
+ }
+ }
+ while(apt_text_is_eos(stream) == FALSE);
+
+ return result;
+}
+
+/** Generate header section */
+APT_DECLARE(apt_bool_t) apt_header_section_generate(const apt_header_section_t *header, apt_text_stream_t *stream)
+{
+ apt_header_field_t *header_field;
+ for(header_field = APR_RING_FIRST(&header->ring);
+ header_field != APR_RING_SENTINEL(&header->ring, apt_header_field_t, link);
+ header_field = APR_RING_NEXT(header_field, link)) {
+ apt_header_field_generate(header_field,stream);
+ }
+
+ return apt_text_eol_insert(stream);
+}
+
+static apt_bool_t apt_message_body_read(apt_message_parser_t *parser, apt_text_stream_t *stream)
+{
+ apt_bool_t status = TRUE;
+ apt_str_t *body = parser->context.body;
+ if(body->buf) {
+ /* stream length available to read */
+ apr_size_t stream_length = stream->text.length - (stream->pos - stream->text.buf);
+ /* required/remaining length to read */
+ apr_size_t required_length = parser->content_length - body->length;
+ if(required_length > stream_length) {
+ required_length = stream_length;
+ /* incomplete */
+ status = FALSE;
+ }
+ memcpy(body->buf + body->length, stream->pos, required_length);
+ body->length += required_length;
+ stream->pos += required_length;
+ if(parser->verbose == TRUE) {
+ apr_size_t length = required_length;
+ const char *masked_data = apt_log_data_mask(stream->pos,&length,parser->pool);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Parsed Message Body [%"APR_SIZE_T_FMT" bytes]\n%.*s",
+ required_length, length, masked_data);
+ }
+ }
+
+ return status;
+}
+
+static apt_bool_t apt_message_body_write(apt_message_generator_t *generator, apt_text_stream_t *stream)
+{
+ apt_bool_t status = TRUE;
+ apt_str_t *body = generator->context.body;
+ if(body && body->length < generator->content_length) {
+ /* stream length available to write */
+ apr_size_t stream_length = stream->text.length - (stream->pos - stream->text.buf);
+ /* required/remaining length to write */
+ apr_size_t required_length = generator->content_length - body->length;
+ if(required_length > stream_length) {
+ required_length = stream_length;
+ /* incomplete */
+ status = FALSE;
+ }
+
+ memcpy(stream->pos, body->buf + body->length, required_length);
+
+ if(generator->verbose == TRUE) {
+ apr_size_t length = required_length;
+ const char *masked_data = apt_log_data_mask(stream->pos,&length,generator->pool);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Generated Message Body [%"APR_SIZE_T_FMT" bytes]\n%.*s",
+ required_length, length, masked_data);
+ }
+
+ body->length += required_length;
+ stream->pos += required_length;
+ }
+
+ return status;
+}
+
+
+/** Create message parser */
+APT_DECLARE(apt_message_parser_t*) apt_message_parser_create(void *obj, const apt_message_parser_vtable_t *vtable, apr_pool_t *pool)
+{
+ apt_message_parser_t *parser = apr_palloc(pool,sizeof(apt_message_parser_t));
+ parser->obj = obj;
+ parser->vtable = vtable;
+ parser->pool = pool;
+ parser->context.message = NULL;
+ parser->context.body = NULL;
+ parser->context.header = NULL;
+ parser->content_length = 0;
+ parser->stage = APT_MESSAGE_STAGE_START_LINE;
+ parser->skip_lf = FALSE;
+ parser->verbose = FALSE;
+ return parser;
+}
+
+static APR_INLINE void apt_crlf_segmentation_test(apt_message_parser_t *parser, apt_text_stream_t *stream)
+{
+ /* in the worst case message segmentation may occur between and */
+ if(stream->pos == stream->end && *(stream->pos-1)== APT_TOKEN_CR) {
+ /* if this is the case be prepared to skip with the next attempt */
+ parser->skip_lf = TRUE;
+ }
+}
+
+/** Parse message by raising corresponding event handlers */
+APT_DECLARE(apt_message_status_e) apt_message_parser_run(apt_message_parser_t *parser, apt_text_stream_t *stream, void **message)
+{
+ const char *pos;
+ apt_message_status_e status = APT_MESSAGE_STATUS_INCOMPLETE;
+ if(parser->skip_lf == TRUE) {
+ /* skip occurred as a result of message segmentation between and */
+ apt_text_char_skip(stream,APT_TOKEN_LF);
+ parser->skip_lf = FALSE;
+ }
+ if(message) {
+ *message = NULL;
+ }
+
+ do {
+ pos = stream->pos;
+ if(parser->stage == APT_MESSAGE_STAGE_START_LINE) {
+ if(parser->vtable->on_start(parser,&parser->context,stream,parser->pool) == FALSE) {
+ if(apt_text_is_eos(stream) == FALSE) {
+ status = APT_MESSAGE_STATUS_INVALID;
+ }
+ break;
+ }
+
+ apt_crlf_segmentation_test(parser,stream);
+
+ parser->stage = APT_MESSAGE_STAGE_HEADER;
+ }
+
+ if(parser->stage == APT_MESSAGE_STAGE_HEADER) {
+ /* read header section */
+ apt_bool_t res = apt_header_section_parse(parser->context.header,stream,parser->pool);
+ if(parser->verbose == TRUE) {
+ apr_size_t length = stream->pos - pos;
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Parsed Message Header [%"APR_SIZE_T_FMT" bytes]\n%.*s",
+ length, length, pos);
+ }
+
+ apt_crlf_segmentation_test(parser,stream);
+
+ if(res == FALSE) {
+ break;
+ }
+
+ if(parser->vtable->on_header_complete) {
+ if(parser->vtable->on_header_complete(parser,&parser->context) == FALSE) {
+ status = APT_MESSAGE_STATUS_INVALID;
+ break;
+ }
+ }
+
+ if(parser->context.body && parser->context.body->length) {
+ apt_str_t *body = parser->context.body;
+ parser->content_length = body->length;
+ body->buf = apr_palloc(parser->pool,parser->content_length+1);
+ body->buf[parser->content_length] = '\0';
+ body->length = 0;
+ parser->stage = APT_MESSAGE_STAGE_BODY;
+ }
+ else {
+ status = APT_MESSAGE_STATUS_COMPLETE;
+ if(message) {
+ *message = parser->context.message;
+ }
+ parser->stage = APT_MESSAGE_STAGE_START_LINE;
+ break;
+ }
+ }
+
+ if(parser->stage == APT_MESSAGE_STAGE_BODY) {
+ if(apt_message_body_read(parser,stream) == FALSE) {
+ break;
+ }
+
+ if(parser->vtable->on_body_complete) {
+ parser->vtable->on_body_complete(parser,&parser->context);
+ }
+ status = APT_MESSAGE_STATUS_COMPLETE;
+ if(message) {
+ *message = parser->context.message;
+ }
+ parser->stage = APT_MESSAGE_STAGE_START_LINE;
+ break;
+ }
+ }
+ while(apt_text_is_eos(stream) == FALSE);
+
+ return status;
+}
+
+/** Get external object associated with parser */
+APT_DECLARE(void*) apt_message_parser_object_get(apt_message_parser_t *parser)
+{
+ return parser->obj;
+}
+
+/** Set verbose mode for the parser */
+APT_DECLARE(void) apt_message_parser_verbose_set(apt_message_parser_t *parser, apt_bool_t verbose)
+{
+ parser->verbose = verbose;
+}
+
+
+/** Create message generator */
+APT_DECLARE(apt_message_generator_t*) apt_message_generator_create(void *obj, const apt_message_generator_vtable_t *vtable, apr_pool_t *pool)
+{
+ apt_message_generator_t *generator = apr_palloc(pool,sizeof(apt_message_generator_t));
+ generator->obj = obj;
+ generator->vtable = vtable;
+ generator->pool = pool;
+ generator->context.message = NULL;
+ generator->context.header = NULL;
+ generator->context.body = NULL;
+ generator->content_length = 0;
+ generator->stage = APT_MESSAGE_STAGE_START_LINE;
+ generator->verbose = FALSE;
+ return generator;
+}
+
+static apt_message_status_e apt_message_generator_break(apt_message_generator_t *generator, apt_text_stream_t *stream)
+{
+ /* failed to generate message */
+ if(apt_text_is_eos(stream) == TRUE) {
+ /* end of stream reached */
+ return APT_MESSAGE_STATUS_INCOMPLETE;
+ }
+
+ /* error case */
+ return APT_MESSAGE_STATUS_INVALID;
+}
+
+/** Generate message */
+APT_DECLARE(apt_message_status_e) apt_message_generator_run(apt_message_generator_t *generator, void *message, apt_text_stream_t *stream)
+{
+ if(!message) {
+ return APT_MESSAGE_STATUS_INVALID;
+ }
+
+ if(message != generator->context.message) {
+ generator->stage = APT_MESSAGE_STAGE_START_LINE;
+ generator->context.message = message;
+ generator->context.header = NULL;
+ generator->context.body = NULL;
+ }
+
+ if(generator->stage == APT_MESSAGE_STAGE_START_LINE) {
+ /* generate start-line */
+ if(generator->vtable->on_start(generator,&generator->context,stream) == FALSE) {
+ return apt_message_generator_break(generator,stream);
+ }
+
+ if(!generator->context.header || !generator->context.body) {
+ return APT_MESSAGE_STATUS_INVALID;
+ }
+
+ /* generate header */
+ if(apt_header_section_generate(generator->context.header,stream) == FALSE) {
+ return apt_message_generator_break(generator,stream);
+ }
+
+ if(generator->vtable->on_header_complete) {
+ generator->vtable->on_header_complete(generator,&generator->context,stream);
+ }
+ if(generator->verbose == TRUE) {
+ apr_size_t length = stream->pos - stream->text.buf;
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Generated Message Header [%"APR_SIZE_T_FMT" bytes]\n%.*s",
+ length, length, stream->text.buf);
+ }
+
+ generator->stage = APT_MESSAGE_STAGE_START_LINE;
+ generator->content_length = generator->context.body->length;
+ if(generator->content_length) {
+ generator->context.body->length = 0;
+ generator->stage = APT_MESSAGE_STAGE_BODY;
+ }
+ }
+
+ if(generator->stage == APT_MESSAGE_STAGE_BODY) {
+ if(apt_message_body_write(generator,stream) == FALSE) {
+ return apt_message_generator_break(generator,stream);
+ }
+
+ generator->stage = APT_MESSAGE_STAGE_START_LINE;
+ }
+
+ return APT_MESSAGE_STATUS_COMPLETE;
+}
+
+/** Get external object associated with generator */
+APT_DECLARE(void*) apt_message_generator_object_get(apt_message_generator_t *generator)
+{
+ return generator->obj;
+}
+
+/** Set verbose mode for the parser */
+APT_DECLARE(void) apt_message_generator_verbose_set(apt_message_generator_t *generator, apt_bool_t verbose)
+{
+ generator->verbose = verbose;
+}
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_text_stream.c b/libs/unimrcp/libs/apr-toolkit/src/apt_text_stream.c
index 5617dff6fa..a15bbdb3cf 100644
--- a/libs/unimrcp/libs/apr-toolkit/src/apt_text_stream.c
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_text_stream.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: apt_text_stream.c 1793 2011-01-10 21:46:14Z achaloyan $
*/
#include
@@ -61,19 +63,20 @@ APT_DECLARE(apt_bool_t) apt_text_line_read(apt_text_stream_t *stream, apt_str_t
else {
/* end of stream is reached, do not advance stream pos, but set is_eos flag */
stream->is_eos = TRUE;
+ line->length = pos - line->buf;
}
return status;
}
-/** Navigate through the headers (name:value pairs) of the text stream (message)
- Valid headers are:
+/** To be used to navigate through the header fields (name:value pairs) of the text stream (message)
+ Valid header fields are:
name:value
name: value
name: value
name: value
name: (only name, no value)
(empty header)
- Malformed headers are:
+ Malformed header fields are:
name:value (missing end of line )
name (missing separator ':')
*/
@@ -109,8 +112,8 @@ APT_DECLARE(apt_bool_t) apt_text_header_read(apt_text_stream_t *stream, apt_pair
break;
}
else if(!pair->name.length) {
- /* skip initial spaces and read name */
- if(!pair->name.buf && *pos != APT_TOKEN_SP) {
+ /* skip preceding white spaces (SHOULD NOT be any WSP, though) and read name */
+ if(!pair->name.buf && apt_text_is_wsp(*pos) == FALSE) {
pair->name.buf = pos;
}
if(*pos == ':') {
@@ -119,8 +122,8 @@ APT_DECLARE(apt_bool_t) apt_text_header_read(apt_text_stream_t *stream, apt_pair
}
}
else if(!pair->value.length) {
- /* skip initial spaces and read value */
- if(!pair->value.buf && *pos != APT_TOKEN_SP) {
+ /* skip preceding white spaces and read value */
+ if(!pair->value.buf && apt_text_is_wsp(*pos) == FALSE) {
pair->value.buf = pos;
}
}
@@ -170,14 +173,19 @@ APT_DECLARE(apt_bool_t) apt_text_field_read(apt_text_stream_t *stream, char sepa
/** Scroll text stream */
APT_DECLARE(apt_bool_t) apt_text_stream_scroll(apt_text_stream_t *stream)
{
- apr_size_t remaining_length = stream->text.buf + stream->text.length - stream->pos;
- if(!remaining_length || remaining_length == stream->text.length) {
- stream->pos = stream->text.buf + remaining_length;
- return FALSE;
+ if(stream->pos == stream->end) {
+ stream->pos = stream->text.buf;
+ }
+ else {
+ apr_size_t remaining_length = stream->text.buf + stream->text.length - stream->pos;
+ if(!remaining_length || remaining_length == stream->text.length) {
+ stream->pos = stream->text.buf + remaining_length;
+ return FALSE;
+ }
+ memmove(stream->text.buf,stream->pos,remaining_length);
+ stream->pos = stream->text.buf + remaining_length;
+ stream->text.length = remaining_length;
}
- memmove(stream->text.buf,stream->pos,remaining_length);
- stream->pos = stream->text.buf + remaining_length;
- stream->text.length = remaining_length;
*stream->pos = '\0';
return TRUE;
}
@@ -216,14 +224,36 @@ APT_DECLARE(apt_bool_t) apt_id_resource_generate(const apt_str_t *id, const apt_
return TRUE;
}
-/** Generate only the name ("name":) of the header */
-APT_DECLARE(apt_bool_t) apt_text_header_name_generate(const apt_str_t *name, apt_text_stream_t *stream)
+/** Generate name-value pair line */
+APT_DECLARE(apt_bool_t) apt_text_name_value_insert(apt_text_stream_t *stream, const apt_str_t *name, const apt_str_t *value)
{
char *pos = stream->pos;
+ if(pos + name->length + value->length + 2 >= stream->end) {
+ return FALSE;
+ }
memcpy(pos,name->buf,name->length);
pos += name->length;
*pos++ = ':';
- *pos++ = ' ';
+ *pos++ = APT_TOKEN_SP;
+ if(apt_string_is_empty(value) == FALSE) {
+ memcpy(pos,value->buf,value->length);
+ pos += value->length;
+ }
+ stream->pos = pos;
+ return apt_text_eol_insert(stream);
+}
+
+/** Generate only the name ("name":) of the header field */
+APT_DECLARE(apt_bool_t) apt_text_header_name_insert(apt_text_stream_t *stream, const apt_str_t *name)
+{
+ char *pos = stream->pos;
+ if(pos + name->length + 2 >= stream->end) {
+ return FALSE;
+ }
+ memcpy(pos,name->buf,name->length);
+ pos += name->length;
+ *pos++ = ':';
+ *pos++ = APT_TOKEN_SP;
stream->pos = pos;
return TRUE;
}
@@ -269,7 +299,21 @@ APT_DECLARE(apt_bool_t) apt_pair_array_parse(apt_pair_arr_t *arr, const apt_str_
}
/** Generate array of name-value pairs */
-APT_DECLARE(apt_bool_t) apt_pair_array_generate(apt_pair_arr_t *arr, apt_text_stream_t *stream)
+APT_DECLARE(apt_bool_t) apt_pair_array_generate(const apt_pair_arr_t *arr, apt_str_t *str, apr_pool_t *pool)
+{
+ char buf[512];
+ apt_text_stream_t stream;
+ apt_text_stream_init(&stream,buf,sizeof(buf));
+ if(apt_text_pair_array_insert(&stream,arr) == FALSE) {
+ return FALSE;
+ }
+ apt_string_assign_n(str, stream.text.buf, stream.pos - stream.text.buf, pool);
+ return TRUE;
+}
+
+
+/** Insert array of name-value pairs */
+APT_DECLARE(apt_bool_t) apt_text_pair_array_insert(apt_text_stream_t *stream, const apt_pair_arr_t *arr)
{
int i;
apt_pair_t *pair;
@@ -314,30 +358,61 @@ APT_DECLARE(apt_bool_t) apt_boolean_value_parse(const apt_str_t *str, apt_bool_t
return FALSE;
}
-/** Generate boolean-value */
-APT_DECLARE(apt_bool_t) apt_boolean_value_generate(apt_bool_t value, apt_text_stream_t *stream)
+/** Generate apr_size_t value from pool (buffer is allocated from pool) */
+APT_DECLARE(apt_bool_t) apt_boolean_value_generate(apt_bool_t value, apt_str_t *str, apr_pool_t *pool)
{
if(value == TRUE) {
+ str->length = TOKEN_TRUE_LENGTH;
+ str->buf = apr_palloc(pool,str->length);
+ memcpy(str->buf,TOKEN_TRUE,str->length);
+ }
+ else {
+ str->length = TOKEN_FALSE_LENGTH;
+ str->buf = apr_palloc(pool,str->length);
+ memcpy(str->buf,TOKEN_FALSE,str->length);
+ }
+ return TRUE;
+}
+
+/** Generate boolean-value */
+APT_DECLARE(apt_bool_t) apt_boolean_value_insert(apt_text_stream_t *stream, apt_bool_t value)
+{
+ if(value == TRUE) {
+ if(stream->pos + TOKEN_TRUE_LENGTH >= stream->end) {
+ return FALSE;
+ }
memcpy(stream->pos,TOKEN_TRUE,TOKEN_TRUE_LENGTH);
stream->pos += TOKEN_TRUE_LENGTH;
}
else {
+ if(stream->pos + TOKEN_FALSE_LENGTH >= stream->end) {
+ return FALSE;
+ }
memcpy(stream->pos,TOKEN_FALSE,TOKEN_FALSE_LENGTH);
stream->pos += TOKEN_FALSE_LENGTH;
}
return TRUE;
}
+
/** Parse size_t value */
APT_DECLARE(apr_size_t) apt_size_value_parse(const apt_str_t *str)
{
return str->buf ? atol(str->buf) : 0;
}
-/** Generate apr_size_t value */
-APT_DECLARE(apt_bool_t) apt_size_value_generate(apr_size_t value, apt_text_stream_t *stream)
+/** Generate apr_size_t value (buffer is allocated from pool) */
+APT_DECLARE(apt_bool_t) apt_size_value_generate(apr_size_t value, apt_str_t *str, apr_pool_t *pool)
{
- int length = sprintf(stream->pos, "%"APR_SIZE_T_FMT, value);
+ str->buf = apr_psprintf(pool, "%"APR_SIZE_T_FMT, value);
+ str->length = strlen(str->buf);
+ return TRUE;
+}
+
+/** Insert apr_size_t value */
+APT_DECLARE(apt_bool_t) apt_text_size_value_insert(apt_text_stream_t *stream, apr_size_t value)
+{
+ int length = apr_snprintf(stream->pos, stream->end - stream->pos, "%"APR_SIZE_T_FMT, value);
if(length <= 0) {
return FALSE;
}
@@ -345,29 +420,58 @@ APT_DECLARE(apt_bool_t) apt_size_value_generate(apr_size_t value, apt_text_strea
return TRUE;
}
+
/** Parse float value */
APT_DECLARE(float) apt_float_value_parse(const apt_str_t *str)
{
return str->buf ? (float)atof(str->buf) : 0;
}
-/** Generate float value */
-APT_DECLARE(apt_bool_t) apt_float_value_generate(float value, apt_text_stream_t *stream)
+/** Generate float value (buffer is allocated from pool) */
+APT_DECLARE(apt_bool_t) apt_float_value_generate(float value, apt_str_t *str, apr_pool_t *pool)
{
char *end;
- int length = sprintf(stream->pos,"%f",value);
+ str->buf = apr_psprintf(pool,"%f",value);
+ str->length = strlen(str->buf);
+
+ /* remove trailing 0s (if any) */
+ end = str->buf + str->length - 1;
+ while(*end == 0x30 && end != str->buf && *(end - 1) != '.') end--;
+
+ str->length = end - str->buf + 1;
+ return TRUE;
+}
+
+/** Generate float value */
+APT_DECLARE(apt_bool_t) apt_text_float_value_insert(apt_text_stream_t *stream, float value)
+{
+ char *end;
+ int length = apr_snprintf(stream->pos, stream->end - stream->pos, "%f", value);
if(length <= 0) {
return FALSE;
}
/* remove trailing 0s (if any) */
end = stream->pos + length - 1;
- while(*end == 0x30 && end != stream->pos) end--;
+ while(*end == 0x30 && end != stream->pos && *(end - 1) != '.') end--;
stream->pos = end + 1;
return TRUE;
}
+/** Insert string value */
+APT_DECLARE(apt_bool_t) apt_text_string_insert(apt_text_stream_t *stream, const apt_str_t *str)
+{
+ if(stream->pos + str->length >= stream->end) {
+ return FALSE;
+ }
+ if(str->length) {
+ memcpy(stream->pos,str->buf,str->length);
+ stream->pos += str->length;
+ }
+ return TRUE;
+}
+
/** Generate value plus the length (number of digits) of the value itself. */
APT_DECLARE(apt_bool_t) apt_var_length_value_generate(apr_size_t *value, apr_size_t max_count, apt_str_t *str)
{
@@ -405,6 +509,25 @@ APT_DECLARE(apt_bool_t) apt_var_length_value_generate(apr_size_t *value, apr_siz
return TRUE;
}
+/** Generate completion-cause */
+APT_DECLARE(apt_bool_t) apt_completion_cause_generate(const apt_str_table_item_t table[], apr_size_t size, apr_size_t cause, apt_str_t *str, apr_pool_t *pool)
+{
+ char buf[256];
+ int length;
+ const apt_str_t *name = apt_string_table_str_get(table,size,cause);
+ if(!name) {
+ return FALSE;
+ }
+ length = sprintf(buf,"%03"APR_SIZE_T_FMT" ",cause);
+ if(length <= 0) {
+ return FALSE;
+ }
+
+ memcpy(buf+length,name->buf,name->length);
+ apt_string_assign_n(str,buf,name->length + length,pool);
+ return TRUE;
+}
+
/** Generate unique identifier (hex string) */
APT_DECLARE(apt_bool_t) apt_unique_id_generate(apt_str_t *id, apr_size_t length, apr_pool_t *pool)
diff --git a/libs/unimrcp/libs/apr-toolkit/src/apt_timer_queue.c b/libs/unimrcp/libs/apr-toolkit/src/apt_timer_queue.c
new file mode 100644
index 0000000000..8d1b007b8c
--- /dev/null
+++ b/libs/unimrcp/libs/apr-toolkit/src/apt_timer_queue.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: apt_timer_queue.c 1665 2010-04-25 05:03:26Z achaloyan $
+ */
+
+#ifdef WIN32
+#pragma warning(disable: 4127)
+#endif
+#include
+#include "apt_timer_queue.h"
+#include "apt_log.h"
+
+/** Timer queue */
+struct apt_timer_queue_t {
+ /** Ring head */
+ APR_RING_HEAD(apt_timer_head_t, apt_timer_t) head;
+
+ /** Elapsed time */
+ apr_uint32_t elapsed_time;
+};
+
+/** Timer */
+struct apt_timer_t {
+ /** Ring entry */
+ APR_RING_ENTRY(apt_timer_t) link;
+
+ /** Back pointer to queue */
+ apt_timer_queue_t *queue;
+ /** Time next report is scheduled at */
+ apr_uint32_t scheduled_time;
+
+ /** Timer proc */
+ apt_timer_proc_f proc;
+ /** Timer object */
+ void *obj;
+};
+
+static void apt_timers_reschedule(apt_timer_queue_t *timer_queue);
+
+/** Create timer queue */
+APT_DECLARE(apt_timer_queue_t*) apt_timer_queue_create(apr_pool_t *pool)
+{
+ apt_timer_queue_t *timer_queue = apr_palloc(pool,sizeof(apt_timer_queue_t));
+ APR_RING_INIT(&timer_queue->head, apt_timer_t, link);
+ timer_queue->elapsed_time = 0;
+ return timer_queue;
+}
+
+/** Destroy timer queue */
+APT_DECLARE(void) apt_timer_queue_destroy(apt_timer_queue_t *timer_queue)
+{
+}
+
+/** Advance scheduled timers */
+APT_DECLARE(void) apt_timer_queue_advance(apt_timer_queue_t *timer_queue, apr_uint32_t elapsed_time)
+{
+ apt_timer_t *timer;
+
+ if(APR_RING_EMPTY(&timer_queue->head, apt_timer_t, link)) {
+ /* just return, nothing to do */
+ return;
+ }
+
+ /* increment elapsed time */
+ timer_queue->elapsed_time += elapsed_time;
+ if(timer_queue->elapsed_time >= 0xFFFF) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Reschedule Timers [%u]",timer_queue->elapsed_time);
+ apt_timers_reschedule(timer_queue);
+ }
+
+ /* process timers */
+ do {
+ /* get first node (timer) */
+ timer = APR_RING_FIRST(&timer_queue->head);
+
+ if(timer->scheduled_time > timer_queue->elapsed_time) {
+ /* scheduled time is not elapsed yet */
+ break;
+ }
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Timer Elapsed 0x%x [%u]",timer,timer->scheduled_time);
+ /* remove the elapsed timer from the list */
+ APR_RING_REMOVE(timer, link);
+ timer->scheduled_time = 0;
+ /* process the elapsed timer */
+ timer->proc(timer,timer->obj);
+ }
+ while(!APR_RING_EMPTY(&timer_queue->head, apt_timer_t, link));
+}
+
+/** Is timer queue empty */
+APT_DECLARE(apt_bool_t) apt_timer_queue_is_empty(const apt_timer_queue_t *timer_queue)
+{
+ return APR_RING_EMPTY(&timer_queue->head, apt_timer_t, link) ? TRUE : FALSE;
+}
+
+/** Get current timeout */
+APT_DECLARE(apt_bool_t) apt_timer_queue_timeout_get(const apt_timer_queue_t *timer_queue, apr_uint32_t *timeout)
+{
+ apt_timer_t *timer;
+ /* is queue empty */
+ if(APR_RING_EMPTY(&timer_queue->head, apt_timer_t, link)) {
+ return FALSE;
+ }
+
+ /* get first node (timer) */
+ timer = APR_RING_FIRST(&timer_queue->head);
+ if(!timer) {
+ return FALSE;
+ }
+
+ *timeout = timer->scheduled_time - timer_queue->elapsed_time;
+ return TRUE;
+}
+
+
+/** Create timer */
+APT_DECLARE(apt_timer_t*) apt_timer_create(apt_timer_queue_t *timer_queue, apt_timer_proc_f proc, void *obj, apr_pool_t *pool)
+{
+ apt_timer_t *timer = apr_palloc(pool,sizeof(apt_timer_t));
+ timer->queue = timer_queue;
+ timer->scheduled_time = 0;
+ timer->proc = proc;
+ timer->obj = obj;
+ return timer;
+}
+
+static APR_INLINE apt_bool_t apt_timer_insert(apt_timer_queue_t *timer_queue, apt_timer_t *timer)
+{
+ apt_timer_t *it;
+ for(it = APR_RING_LAST(&timer_queue->head);
+ it != APR_RING_SENTINEL(&timer_queue->head, apt_timer_t, link);
+ it = APR_RING_PREV(it, link)) {
+
+ if(it->scheduled_time <= timer->scheduled_time) {
+ APR_RING_INSERT_AFTER(it,timer,link);
+ return TRUE;
+ }
+ }
+ APR_RING_INSERT_HEAD(&timer_queue->head,timer,apt_timer_t,link);
+ return TRUE;
+}
+
+/** Set one-shot timer */
+APT_DECLARE(apt_bool_t) apt_timer_set(apt_timer_t *timer, apr_uint32_t timeout)
+
+{
+ apt_timer_queue_t *queue = timer->queue;
+
+ if(timeout <= 0 || !timer->proc) {
+ return FALSE;
+ }
+
+ /* calculate time to elapse */
+ timer->scheduled_time = queue->elapsed_time + timeout;
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Set Timer 0x%x [%u]",timer,timer->scheduled_time);
+
+ if(APR_RING_EMPTY(&queue->head, apt_timer_t, link)) {
+ APR_RING_INSERT_TAIL(&queue->head,timer,apt_timer_t,link);
+ return TRUE;
+ }
+
+ /* insert new node (timer) to sorted by scheduled time list */
+ return apt_timer_insert(queue,timer);
+}
+
+/** Kill timer */
+APT_DECLARE(apt_bool_t) apt_timer_kill(apt_timer_t *timer)
+{
+ apt_timer_queue_t *queue = timer->queue;
+
+ if(!timer->scheduled_time) {
+ return FALSE;
+ }
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Kill Timer 0x%x [%u]",timer,timer->scheduled_time);
+ /* remove node (timer) from the list */
+ APR_RING_REMOVE(timer,link);
+ timer->scheduled_time = 0;
+
+ if(APR_RING_EMPTY(&queue->head, apt_timer_t, link)) {
+ /* reset elapsed time if no timers set */
+ queue->elapsed_time = 0;
+ }
+ return TRUE;
+}
+
+static void apt_timers_reschedule(apt_timer_queue_t *queue)
+{
+ apt_timer_t *it;
+ for(it = APR_RING_LAST(&queue->head);
+ it != APR_RING_SENTINEL(&queue->head, apt_timer_t, link);
+ it = APR_RING_PREV(it, link)) {
+
+ it->scheduled_time -= queue->elapsed_time;
+ }
+ queue->elapsed_time = 0;
+}
diff --git a/libs/unimrcp/libs/mpf/Makefile.am b/libs/unimrcp/libs/mpf/Makefile.am
index d153905278..0e904a46ed 100644
--- a/libs/unimrcp/libs/mpf/Makefile.am
+++ b/libs/unimrcp/libs/mpf/Makefile.am
@@ -35,7 +35,6 @@ include_HEADERS = codecs/g711/g711.h \
include/mpf_rtp_termination_factory.h \
include/mpf_file_termination_factory.h \
include/mpf_scheduler.h \
- include/mpf_timer_manager.h \
include/mpf_types.h \
include/mpf_encoder.h \
include/mpf_decoder.h \
@@ -72,7 +71,6 @@ libmpf_la_SOURCES = codecs/g711/g711.c \
src/mpf_file_termination_factory.c \
src/mpf_frame_buffer.c \
src/mpf_scheduler.c \
- src/mpf_timer_manager.c \
src/mpf_encoder.c \
src/mpf_decoder.c \
src/mpf_jitter_buffer.c \
diff --git a/libs/unimrcp/libs/mpf/include/mpf.h b/libs/unimrcp/libs/mpf/include/mpf.h
index 7edc0da71b..66fbc37460 100644
--- a/libs/unimrcp/libs/mpf/include/mpf.h
+++ b/libs/unimrcp/libs/mpf/include/mpf.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_H__
-#define __MPF_H__
+#ifndef MPF_H
+#define MPF_H
/**
* @file mpf.h
@@ -39,4 +41,4 @@
#define MPF_DECLARE(type) type
#endif
-#endif /*__MPF_H__*/
+#endif /* MPF_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_activity_detector.h b/libs/unimrcp/libs/mpf/include/mpf_activity_detector.h
index 1b90b558d5..3bb17f64f9 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_activity_detector.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_activity_detector.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_activity_detector.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_ACTIVITY_DETECTOR_H__
-#define __MPF_ACTIVITY_DETECTOR_H__
+#ifndef MPF_ACTIVITY_DETECTOR_H
+#define MPF_ACTIVITY_DETECTOR_H
/**
* @file mpf_activity_detector.h
@@ -63,4 +65,4 @@ MPF_DECLARE(mpf_detector_event_e) mpf_activity_detector_process(mpf_activity_det
APT_END_EXTERN_C
-#endif /*__MPF_ACTIVITY_DETECTOR_H__*/
+#endif /* MPF_ACTIVITY_DETECTOR_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_audio_file_descriptor.h b/libs/unimrcp/libs/mpf/include/mpf_audio_file_descriptor.h
index 0d9c439c4c..df1aa1fbcb 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_audio_file_descriptor.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_audio_file_descriptor.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_audio_file_descriptor.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_AUDIO_FILE_DESCRIPTOR_H__
-#define __MPF_AUDIO_FILE_DESCRIPTOR_H__
+#ifndef MPF_AUDIO_FILE_DESCRIPTOR_H
+#define MPF_AUDIO_FILE_DESCRIPTOR_H
/**
* @file mpf_audio_file_descriptor.h
@@ -51,4 +53,4 @@ struct mpf_audio_file_descriptor_t {
APT_END_EXTERN_C
-#endif /*__MPF_AUDIO_FILE_DESCRIPTOR_H__*/
+#endif /* MPF_AUDIO_FILE_DESCRIPTOR_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_audio_file_stream.h b/libs/unimrcp/libs/mpf/include/mpf_audio_file_stream.h
index f117fbfbb6..0f936baddd 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_audio_file_stream.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_audio_file_stream.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_audio_file_stream.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_AUDIO_FILE_STREAM_H__
-#define __MPF_AUDIO_FILE_STREAM_H__
+#ifndef MPF_AUDIO_FILE_STREAM_H
+#define MPF_AUDIO_FILE_STREAM_H
/**
* @file mpf_audio_file_stream.h
@@ -43,4 +45,4 @@ MPF_DECLARE(apt_bool_t) mpf_file_stream_modify(mpf_audio_stream_t *stream, mpf_a
APT_END_EXTERN_C
-#endif /*__MPF_AUDIO_FILE_STREAM_H__*/
+#endif /* MPF_AUDIO_FILE_STREAM_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_bridge.h b/libs/unimrcp/libs/mpf/include/mpf_bridge.h
index 395aaa966a..3988e0bf3e 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_bridge.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_bridge.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_bridge.h 1693 2010-05-16 18:33:07Z achaloyan $
*/
-#ifndef __MPF_BRIDGE_H__
-#define __MPF_BRIDGE_H__
+#ifndef MPF_BRIDGE_H
+#define MPF_BRIDGE_H
/**
* @file mpf_bridge.h
@@ -31,15 +33,17 @@ APT_BEGIN_EXTERN_C
* @param source the source audio stream
* @param sink the sink audio stream
* @param codec_manager the codec manager
+ * @param name the informative name used for debugging
* @param pool the pool to allocate memory from
*/
MPF_DECLARE(mpf_object_t*) mpf_bridge_create(
mpf_audio_stream_t *source,
mpf_audio_stream_t *sink,
const mpf_codec_manager_t *codec_manager,
+ const char *name,
apr_pool_t *pool);
APT_END_EXTERN_C
-#endif /*__MPF_BRIDGE_H__*/
+#endif /* MPF_BRIDGE_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_buffer.h b/libs/unimrcp/libs/mpf/include/mpf_buffer.h
index 6dd22f3f42..ee0cc0121c 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_buffer.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_buffer.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_buffer.h 1709 2010-05-24 17:12:11Z achaloyan $
*/
-#ifndef __MPF_BUFFER_H__
-#define __MPF_BUFFER_H__
+#ifndef MPF_BUFFER_H
+#define MPF_BUFFER_H
/**
* @file mpf_buffer.h
@@ -49,8 +51,8 @@ apt_bool_t mpf_buffer_event_write(mpf_buffer_t *buffer, mpf_frame_type_e event_t
apt_bool_t mpf_buffer_frame_read(mpf_buffer_t *buffer, mpf_frame_t *media_frame);
/** Get size of buffer **/
-apr_size_t mpf_buffer_get_size(mpf_buffer_t *buffer);
+apr_size_t mpf_buffer_get_size(const mpf_buffer_t *buffer);
APT_END_EXTERN_C
-#endif /*__MPF_BUFFER_H__*/
+#endif /* MPF_BUFFER_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_codec.h b/libs/unimrcp/libs/mpf/include/mpf_codec.h
index 04d9b27079..817e1540ce 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_codec.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_codec.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_codec.h 1686 2010-05-08 18:46:08Z achaloyan $
*/
-#ifndef __MPF_CODEC_H__
-#define __MPF_CODEC_H__
+#ifndef MPF_CODEC_H
+#define MPF_CODEC_H
/**
* @file mpf_codec.h
@@ -55,6 +57,9 @@ struct mpf_codec_vtable_t {
/** Virtual dissect method */
apt_bool_t (*dissect)(mpf_codec_t *codec, void **buffer, apr_size_t *size, mpf_codec_frame_t *frame);
+
+ /** Virtual initialize method */
+ apt_bool_t (*initialize)(mpf_codec_t *codec, mpf_codec_frame_t *frame_out);
};
/**
@@ -154,6 +159,19 @@ static APR_INLINE apt_bool_t mpf_codec_dissect(mpf_codec_t *codec, void **buffer
return rv;
}
+/** Initialize (fill) codec frame with silence */
+static APR_INLINE apt_bool_t mpf_codec_initialize(mpf_codec_t *codec, mpf_codec_frame_t *frame_out)
+{
+ apt_bool_t rv = TRUE;
+ if(codec->vtable->initialize) {
+ rv = codec->vtable->initialize(codec,frame_out);
+ }
+ else {
+ memset(frame_out->buffer,0,frame_out->size);
+ }
+ return rv;
+}
+
APT_END_EXTERN_C
-#endif /*__MPF_CODEC_H__*/
+#endif /* MPF_CODEC_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_codec_descriptor.h b/libs/unimrcp/libs/mpf/include/mpf_codec_descriptor.h
index 9f3a6ea1d7..4958cada57 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_codec_descriptor.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_codec_descriptor.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_codec_descriptor.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_CODEC_DESCRIPTOR_H__
-#define __MPF_CODEC_DESCRIPTOR_H__
+#ifndef MPF_CODEC_DESCRIPTOR_H
+#define MPF_CODEC_DESCRIPTOR_H
/**
* @file mpf_codec_descriptor.h
@@ -278,4 +280,4 @@ MPF_DECLARE(int) mpf_sample_rate_mask_get(apr_uint16_t sampling_rate);
APT_END_EXTERN_C
-#endif /*__MPF_CODEC_DESCRIPTOR_H__*/
+#endif /* MPF_CODEC_DESCRIPTOR_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_codec_manager.h b/libs/unimrcp/libs/mpf/include/mpf_codec_manager.h
index 2b14070b52..44aaf2cfca 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_codec_manager.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_codec_manager.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_codec_manager.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_CODEC_MANAGER_H__
-#define __MPF_CODEC_MANAGER_H__
+#ifndef MPF_CODEC_MANAGER_H
+#define MPF_CODEC_MANAGER_H
/**
* @file mpf_codec_manager.h
@@ -50,4 +52,4 @@ MPF_DECLARE(const mpf_codec_t*) mpf_codec_manager_codec_find(const mpf_codec_man
APT_END_EXTERN_C
-#endif /*__MPF_CODEC_MANAGER_H__*/
+#endif /* MPF_CODEC_MANAGER_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_context.h b/libs/unimrcp/libs/mpf/include/mpf_context.h
index d9a20bf9ad..9190970a39 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_context.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_context.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_context.h 1709 2010-05-24 17:12:11Z achaloyan $
*/
-#ifndef __MPF_CONTEXT_H__
-#define __MPF_CONTEXT_H__
+#ifndef MPF_CONTEXT_H
+#define MPF_CONTEXT_H
/**
* @file mpf_context.h
@@ -47,12 +49,14 @@ MPF_DECLARE(apt_bool_t) mpf_context_factory_process(mpf_context_factory_t *facto
/**
* Create MPF context.
* @param factory the factory context belongs to
+ * @param name the informative name of the context
* @param obj the external object associated with context
* @param max_termination_count the max number of terminations in context
* @param pool the pool to allocate memory from
*/
MPF_DECLARE(mpf_context_t*) mpf_context_create(
mpf_context_factory_t *factory,
+ const char *name,
void *obj,
apr_size_t max_termination_count,
apr_pool_t *pool);
@@ -67,7 +71,7 @@ MPF_DECLARE(apt_bool_t) mpf_context_destroy(mpf_context_t *context);
* Get external object associated with MPF context.
* @param context the context to get object from
*/
-MPF_DECLARE(void*) mpf_context_object_get(mpf_context_t *context);
+MPF_DECLARE(void*) mpf_context_object_get(const mpf_context_t *context);
/**
* Add termination to context.
@@ -126,4 +130,4 @@ MPF_DECLARE(apt_bool_t) mpf_context_process(mpf_context_t *context);
APT_END_EXTERN_C
-#endif /*__MPF_CONTEXT_H__*/
+#endif /* MPF_CONTEXT_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_decoder.h b/libs/unimrcp/libs/mpf/include/mpf_decoder.h
index ea99db8ad1..25402de6db 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_decoder.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_decoder.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_decoder.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_DECODER_H__
-#define __MPF_DECODER_H__
+#ifndef MPF_DECODER_H
+#define MPF_DECODER_H
/**
* @file mpf_decoder.h
@@ -37,4 +39,4 @@ MPF_DECLARE(mpf_audio_stream_t*) mpf_decoder_create(mpf_audio_stream_t *source,
APT_END_EXTERN_C
-#endif /*__MPF_ENCODER_H__*/
+#endif /* MPF_ENCODER_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_dtmf_detector.h b/libs/unimrcp/libs/mpf/include/mpf_dtmf_detector.h
index 6c6d95768d..4108e3bd9b 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_dtmf_detector.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_dtmf_detector.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Tomas Valenta, Arsen Chaloyan
+ * Copyright 2009-2010 Tomas Valenta, Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,12 +12,14 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_dtmf_detector.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_DTMF_DETECTOR_H__
-#define __MPF_DTMF_DETECTOR_H__
+#ifndef MPF_DTMF_DETECTOR_H
+#define MPF_DTMF_DETECTOR_H
-/*
+/**
* @file mpf_dtmf_detector.h
* @brief DTMF detector
*
@@ -118,4 +120,4 @@ MPF_DECLARE(void) mpf_dtmf_detector_destroy(struct mpf_dtmf_detector_t *detector
APT_END_EXTERN_C
-#endif /*__MPF_DTMF_DETECTOR_H__*/
+#endif /* MPF_DTMF_DETECTOR_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_dtmf_generator.h b/libs/unimrcp/libs/mpf/include/mpf_dtmf_generator.h
index 21953c2b5a..ea28bba432 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_dtmf_generator.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_dtmf_generator.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Tomas Valenta, Arsen Chaloyan
+ * Copyright 2009-2010 Tomas Valenta, Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-#ifndef __MPF_DTMF_GENERATOR_H__
-#define __MPF_DTMF_GENERATOR_H__
+#ifndef MPF_DTMF_GENERATOR_H
+#define MPF_DTMF_GENERATOR_H
-/*
- * @file mpf_named_event.h
+/**
+ * @file mpf_dtmf_generator.h
* @brief DTMF generator
*
* Generator used to send DTMF tones. Capable to send digits
@@ -128,4 +128,4 @@ MPF_DECLARE(void) mpf_dtmf_generator_destroy(struct mpf_dtmf_generator_t *genera
APT_END_EXTERN_C
-#endif /*__MPF_DTMF_GENERATOR_H__*/
+#endif /* MPF_DTMF_GENERATOR_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_encoder.h b/libs/unimrcp/libs/mpf/include/mpf_encoder.h
index 529f9a0b7e..5ef8366393 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_encoder.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_encoder.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_encoder.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_ENCODER_H__
-#define __MPF_ENCODER_H__
+#ifndef MPF_ENCODER_H
+#define MPF_ENCODER_H
/**
* @file mpf_encoder.h
@@ -37,4 +39,4 @@ MPF_DECLARE(mpf_audio_stream_t*) mpf_encoder_create(mpf_audio_stream_t *sink, mp
APT_END_EXTERN_C
-#endif /*__MPF_ENCODER_H__*/
+#endif /* MPF_ENCODER_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_engine.h b/libs/unimrcp/libs/mpf/include/mpf_engine.h
index 149de69ce4..0810c70700 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_engine.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_engine.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_engine.h 1709 2010-05-24 17:12:11Z achaloyan $
*/
-#ifndef __MPF_ENGINE_H__
-#define __MPF_ENGINE_H__
+#ifndef MPF_ENGINE_H
+#define MPF_ENGINE_H
/**
* @file mpf_engine.h
@@ -32,9 +34,10 @@ typedef apt_task_msg_t mpf_task_msg_t;
/**
* Create MPF engine.
+ * @param id the identifier of the engine
* @param pool the pool to allocate memory from
*/
-MPF_DECLARE(mpf_engine_t*) mpf_engine_create(apr_pool_t *pool);
+MPF_DECLARE(mpf_engine_t*) mpf_engine_create(const char *id, apr_pool_t *pool);
/**
* Create MPF codec manager.
@@ -52,12 +55,14 @@ MPF_DECLARE(apt_bool_t) mpf_engine_codec_manager_register(mpf_engine_t *engine,
/**
* Create MPF context.
* @param engine the engine to create context for
+ * @param name the informative name of the context
* @param obj the external object associated with context
* @param max_termination_count the max number of terminations in context
* @param pool the pool to allocate memory from
*/
MPF_DECLARE(mpf_context_t*) mpf_engine_context_create(
- mpf_engine_t *engine,
+ mpf_engine_t *engine,
+ const char *name,
void *obj,
apr_size_t max_termination_count,
apr_pool_t *pool);
@@ -72,13 +77,13 @@ MPF_DECLARE(apt_bool_t) mpf_engine_context_destroy(mpf_context_t *context);
* Get external object associated with MPF context.
* @param context the context to get object from
*/
-MPF_DECLARE(void*) mpf_engine_context_object_get(mpf_context_t *context);
+MPF_DECLARE(void*) mpf_engine_context_object_get(const mpf_context_t *context);
/**
* Get task.
* @param engine the engine to get task from
*/
-MPF_DECLARE(apt_task_t*) mpf_task_get(mpf_engine_t *engine);
+MPF_DECLARE(apt_task_t*) mpf_task_get(const mpf_engine_t *engine);
/**
* Set task msg type to send responses and events with.
@@ -148,7 +153,13 @@ MPF_DECLARE(apt_bool_t) mpf_engine_message_send(mpf_engine_t *engine, mpf_task_m
*/
MPF_DECLARE(apt_bool_t) mpf_engine_scheduler_rate_set(mpf_engine_t *engine, unsigned long rate);
+/**
+ * Get the identifier of the engine .
+ * @param engine the engine to get name of
+ */
+MPF_DECLARE(const char*) mpf_engine_id_get(const mpf_engine_t *engine);
+
APT_END_EXTERN_C
-#endif /*__MPF_ENGINE_H__*/
+#endif /* MPF_ENGINE_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_file_termination_factory.h b/libs/unimrcp/libs/mpf/include/mpf_file_termination_factory.h
index df8a05abd7..de5bc30686 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_file_termination_factory.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_file_termination_factory.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_file_termination_factory.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_FILE_TERMINATION_FACTORY_H__
-#define __MPF_FILE_TERMINATION_FACTORY_H__
+#ifndef MPF_FILE_TERMINATION_FACTORY_H
+#define MPF_FILE_TERMINATION_FACTORY_H
/**
* @file mpf_file_termination_factory.h
@@ -34,4 +36,4 @@ MPF_DECLARE(mpf_termination_factory_t*) mpf_file_termination_factory_create(apr_
APT_END_EXTERN_C
-#endif /*__MPF_RTP_TERMINATION_FACTORY_H__*/
+#endif /* MPF_RTP_TERMINATION_FACTORY_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_frame.h b/libs/unimrcp/libs/mpf/include/mpf_frame.h
index c5b45a6e61..f490f8b9ba 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_frame.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_frame.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_frame.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_FRAME_H__
-#define __MPF_FRAME_H__
+#ifndef MPF_FRAME_H
+#define MPF_FRAME_H
/**
* @file mpf_frame.h
@@ -61,4 +63,4 @@ struct mpf_frame_t {
APT_END_EXTERN_C
-#endif /*__MPF_FRAME_H__*/
+#endif /* MPF_FRAME_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_frame_buffer.h b/libs/unimrcp/libs/mpf/include/mpf_frame_buffer.h
index 8573963c6f..97d48d3dcb 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_frame_buffer.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_frame_buffer.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_frame_buffer.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_FRAME_BUFFER_H__
-#define __MPF_FRAME_BUFFER_H__
+#ifndef MPF_FRAME_BUFFER_H
+#define MPF_FRAME_BUFFER_H
/**
* @file mpf_frame_buffer.h
@@ -47,4 +49,4 @@ apt_bool_t mpf_frame_buffer_read(mpf_frame_buffer_t *buffer, mpf_frame_t *frame)
APT_END_EXTERN_C
-#endif /*__MPF_FRAME_BUFFER_H__*/
+#endif /* MPF_FRAME_BUFFER_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_jitter_buffer.h b/libs/unimrcp/libs/mpf/include/mpf_jitter_buffer.h
index a4cb4c8ba2..5bf142df43 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_jitter_buffer.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_jitter_buffer.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_jitter_buffer.h 1802 2011-05-13 02:43:12Z achaloyan $
*/
-#ifndef __MPF_JITTER_BUFFER_H__
-#define __MPF_JITTER_BUFFER_H__
+#ifndef MPF_JITTER_BUFFER_H
+#define MPF_JITTER_BUFFER_H
/**
* @file mpf_jitter_buffer.h
@@ -50,7 +52,7 @@ void mpf_jitter_buffer_destroy(mpf_jitter_buffer_t *jb);
apt_bool_t mpf_jitter_buffer_restart(mpf_jitter_buffer_t *jb);
/** Write audio data to jitter buffer */
-jb_result_t mpf_jitter_buffer_write(mpf_jitter_buffer_t *jb, void *buffer, apr_size_t size, apr_uint32_t ts);
+jb_result_t mpf_jitter_buffer_write(mpf_jitter_buffer_t *jb, void *buffer, apr_size_t size, apr_uint32_t ts, apr_byte_t marker);
/** Write named event to jitter buffer */
jb_result_t mpf_jitter_buffer_event_write(mpf_jitter_buffer_t *jb, const mpf_named_event_frame_t *named_event, apr_uint32_t ts, apr_byte_t marker);
@@ -60,4 +62,4 @@ apt_bool_t mpf_jitter_buffer_read(mpf_jitter_buffer_t *jb, mpf_frame_t *media_fr
APT_END_EXTERN_C
-#endif /*__MPF_JITTER_BUFFER_H__*/
+#endif /* MPF_JITTER_BUFFER_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_message.h b/libs/unimrcp/libs/mpf/include/mpf_message.h
index 601b306a9e..95f4092df7 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_message.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_message.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_message.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_MESSAGE_H__
-#define __MPF_MESSAGE_H__
+#ifndef MPF_MESSAGE_H
+#define MPF_MESSAGE_H
/**
* @file mpf_message.h
@@ -89,4 +91,4 @@ struct mpf_message_container_t {
APT_END_EXTERN_C
-#endif /*__MPF_MESSAGE_H__*/
+#endif /* MPF_MESSAGE_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_mixer.h b/libs/unimrcp/libs/mpf/include/mpf_mixer.h
index fa48f5b9a9..a552634aa8 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_mixer.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_mixer.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_mixer.h 1693 2010-05-16 18:33:07Z achaloyan $
*/
-#ifndef __MPF_MIXER_H__
-#define __MPF_MIXER_H__
+#ifndef MPF_MIXER_H
+#define MPF_MIXER_H
/**
* @file mpf_mixer.h
@@ -32,6 +34,7 @@ APT_BEGIN_EXTERN_C
* @param source_count the number of audio sources
* @param sink the audio sink
* @param codec_manager the codec manager
+ * @param name the informative name used for debugging
* @param pool the pool to allocate memory from
*/
MPF_DECLARE(mpf_object_t*) mpf_mixer_create(
@@ -39,9 +42,10 @@ MPF_DECLARE(mpf_object_t*) mpf_mixer_create(
apr_size_t source_count,
mpf_audio_stream_t *sink,
const mpf_codec_manager_t *codec_manager,
+ const char *name,
apr_pool_t *pool);
APT_END_EXTERN_C
-#endif /*__MPF_MIXER_H__*/
+#endif /* MPF_MIXER_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_multiplier.h b/libs/unimrcp/libs/mpf/include/mpf_multiplier.h
index 380d5b5f16..6e27e8b037 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_multiplier.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_multiplier.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_multiplier.h 1693 2010-05-16 18:33:07Z achaloyan $
*/
-#ifndef __MPF_MULTIPLIER_H__
-#define __MPF_MULTIPLIER_H__
+#ifndef MPF_MULTIPLIER_H
+#define MPF_MULTIPLIER_H
/**
* @file mpf_multiplier.h
@@ -32,6 +34,7 @@ APT_BEGIN_EXTERN_C
* @param sink_arr the array of audio sinks
* @param sink_count the number of audio sinks
* @param codec_manager the codec manager
+ * @param name the informative name used for debugging
* @param pool the pool to allocate memory from
*/
MPF_DECLARE(mpf_object_t*) mpf_multiplier_create(
@@ -39,9 +42,10 @@ MPF_DECLARE(mpf_object_t*) mpf_multiplier_create(
mpf_audio_stream_t **sink_arr,
apr_size_t sink_count,
const mpf_codec_manager_t *codec_manager,
+ const char *name,
apr_pool_t *pool);
APT_END_EXTERN_C
-#endif /*__MPF_MULTIPLIER_H__*/
+#endif /* MPF_MULTIPLIER_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_named_event.h b/libs/unimrcp/libs/mpf/include/mpf_named_event.h
index d8d4dc6750..1e4f04fdab 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_named_event.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_named_event.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_named_event.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_NAMED_EVENT_H__
-#define __MPF_NAMED_EVENT_H__
+#ifndef MPF_NAMED_EVENT_H
+#define MPF_NAMED_EVENT_H
/**
* @file mpf_named_event.h
@@ -68,4 +70,4 @@ MPF_DECLARE(char) mpf_event_id_to_dtmf_char(const apr_uint32_t event_id);
APT_END_EXTERN_C
-#endif /*__MPF_NAMED_EVENT_H__*/
+#endif /* MPF_NAMED_EVENT_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_object.h b/libs/unimrcp/libs/mpf/include/mpf_object.h
index 8e3e4eee95..cc48f4f879 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_object.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_object.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_object.h 1693 2010-05-16 18:33:07Z achaloyan $
*/
-#ifndef __MPF_OBJECT_H__
-#define __MPF_OBJECT_H__
+#ifndef MPF_OBJECT_H
+#define MPF_OBJECT_H
/**
* @file mpf_object.h
@@ -31,6 +33,8 @@ typedef struct mpf_object_t mpf_object_t;
/** Media processing objects base */
struct mpf_object_t {
+ /** Informative name used for debugging */
+ const char *name;
/** Virtual destroy */
apt_bool_t (*destroy)(mpf_object_t *object);
/** Virtual process */
@@ -40,8 +44,9 @@ struct mpf_object_t {
};
/** Initialize object */
-static APR_INLINE void mpf_object_init(mpf_object_t *object)
+static APR_INLINE void mpf_object_init(mpf_object_t *object, const char *name)
{
+ object->name = name;
object->destroy = NULL;
object->process = NULL;
object->trace = NULL;
@@ -71,4 +76,4 @@ static APR_INLINE void mpf_object_trace(mpf_object_t *object)
APT_END_EXTERN_C
-#endif /*__MPF_OBJECT_H__*/
+#endif /* MPF_OBJECT_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_resampler.h b/libs/unimrcp/libs/mpf/include/mpf_resampler.h
index d674336139..eeac10aaee 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_resampler.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_resampler.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_resampler.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_RESAMPLER_H__
-#define __MPF_RESAMPLER_H__
+#ifndef MPF_RESAMPLER_H
+#define MPF_RESAMPLER_H
/**
* @file mpf_resampler.h
@@ -37,4 +39,4 @@ MPF_DECLARE(mpf_audio_stream_t*) mpf_resampler_create(mpf_audio_stream_t *source
APT_END_EXTERN_C
-#endif /*__MPF_RESAMPLER_H__*/
+#endif /* MPF_RESAMPLER_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_rtcp_packet.h b/libs/unimrcp/libs/mpf/include/mpf_rtcp_packet.h
index 6773807fcd..ba65d3f695 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_rtcp_packet.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_rtcp_packet.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_rtcp_packet.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_RTCP_PACKET_H__
-#define __MPF_RTCP_PACKET_H__
+#ifndef MPF_RTCP_PACKET_H
+#define MPF_RTCP_PACKET_H
/**
* @file mpf_rtcp_packet.h
@@ -198,4 +200,4 @@ static APR_INLINE void rtcp_rr_ntoh(rtcp_rr_stat_t *rr_stat)
APT_END_EXTERN_C
-#endif /*__MPF_RTCP_PACKET_H__*/
+#endif /* MPF_RTCP_PACKET_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_rtp_attribs.h b/libs/unimrcp/libs/mpf/include/mpf_rtp_attribs.h
index dbce6b706f..c5212d78e8 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_rtp_attribs.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_rtp_attribs.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_rtp_attribs.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_RTP_ATTRIBS_H__
-#define __MPF_RTP_ATTRIBS_H__
+#ifndef MPF_RTP_ATTRIBS_H
+#define MPF_RTP_ATTRIBS_H
/**
* @file mpf_rtp_attribs.h
@@ -51,4 +53,4 @@ MPF_DECLARE(const apt_str_t*) mpf_rtp_direction_str_get(mpf_stream_direction_e d
APT_END_EXTERN_C
-#endif /*__MPF_RTP_ATTRIBS_H__*/
+#endif /* MPF_RTP_ATTRIBS_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_rtp_defs.h b/libs/unimrcp/libs/mpf/include/mpf_rtp_defs.h
index 883a1f5896..7d488db3ee 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_rtp_defs.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_rtp_defs.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_rtp_defs.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_RTP_DEFS_H__
-#define __MPF_RTP_DEFS_H__
+#ifndef MPF_RTP_DEFS_H
+#define MPF_RTP_DEFS_H
/**
* @file mpf_rtp_defs.h
@@ -178,4 +180,4 @@ static APR_INLINE void rtp_transmitter_init(rtp_transmitter_t *transmitter)
APT_END_EXTERN_C
-#endif /*__MPF_RTP_DEFS_H__*/
+#endif /* MPF_RTP_DEFS_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_rtp_descriptor.h b/libs/unimrcp/libs/mpf/include/mpf_rtp_descriptor.h
index 906a3c339c..8412c8fc2a 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_rtp_descriptor.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_rtp_descriptor.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_rtp_descriptor.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_RTP_DESCRIPTOR_H__
-#define __MPF_RTP_DESCRIPTOR_H__
+#ifndef MPF_RTP_DESCRIPTOR_H
+#define MPF_RTP_DESCRIPTOR_H
/**
* @file mpf_rtp_descriptor.h
@@ -36,6 +38,8 @@ typedef struct mpf_rtp_stream_descriptor_t mpf_rtp_stream_descriptor_t;
typedef struct mpf_rtp_termination_descriptor_t mpf_rtp_termination_descriptor_t;
/** RTP configuration declaration */
typedef struct mpf_rtp_config_t mpf_rtp_config_t;
+/** RTP settings declaration */
+typedef struct mpf_rtp_settings_t mpf_rtp_settings_t;
/** Jitter buffer configuration declaration */
typedef struct mpf_jb_config_t mpf_jb_config_t;
@@ -75,6 +79,8 @@ struct mpf_rtp_stream_descriptor_t {
mpf_rtp_media_descriptor_t *local;
/** Remote media descriptor */
mpf_rtp_media_descriptor_t *remote;
+ /** Settings loaded from config */
+ mpf_rtp_settings_t *settings;
};
/** RTP termination descriptor */
@@ -104,7 +110,7 @@ typedef enum {
RTCP_BYE_PER_TALKSPURT /**< transmit RTCP BYE at the end of each talkspurt (input) */
} rtcp_bye_policy_e;
-/** RTP config */
+/** RTP factory config */
struct mpf_rtp_config_t {
/** Local IP address to bind to */
apt_str_t ip;
@@ -116,6 +122,10 @@ struct mpf_rtp_config_t {
apr_port_t rtp_port_max;
/** Current RTP port */
apr_port_t rtp_port_cur;
+};
+
+/** RTP settings */
+struct mpf_rtp_settings_t {
/** Packetization time */
apr_uint16_t ptime;
/** Codec list */
@@ -172,8 +182,8 @@ static APR_INLINE void mpf_jb_config_init(mpf_jb_config_t *jb_config)
jb_config->max_playout_delay = 0;
}
-/** Create/allocate RTP config */
-static APR_INLINE mpf_rtp_config_t* mpf_rtp_config_create(apr_pool_t *pool)
+/** Allocate RTP config */
+static APR_INLINE mpf_rtp_config_t* mpf_rtp_config_alloc(apr_pool_t *pool)
{
mpf_rtp_config_t *rtp_config = (mpf_rtp_config_t*)apr_palloc(pool,sizeof(mpf_rtp_config_t));
apt_string_reset(&rtp_config->ip);
@@ -181,18 +191,25 @@ static APR_INLINE mpf_rtp_config_t* mpf_rtp_config_create(apr_pool_t *pool)
rtp_config->rtp_port_cur = 0;
rtp_config->rtp_port_min = 0;
rtp_config->rtp_port_max = 0;
- rtp_config->ptime = 0;
- mpf_codec_list_init(&rtp_config->codec_list,0,pool);
- rtp_config->own_preferrence = FALSE;
- rtp_config->rtcp = FALSE;
- rtp_config->rtcp_bye_policy = RTCP_BYE_DISABLE;
- rtp_config->rtcp_tx_interval = 0;
- rtp_config->rtcp_rx_resolution = 0;
- mpf_jb_config_init(&rtp_config->jb_config);
-
return rtp_config;
}
+/** Allocate RTP settings */
+static APR_INLINE mpf_rtp_settings_t* mpf_rtp_settings_alloc(apr_pool_t *pool)
+{
+ mpf_rtp_settings_t *rtp_settings = (mpf_rtp_settings_t*)apr_palloc(pool,sizeof(mpf_rtp_settings_t));
+ rtp_settings->ptime = 0;
+ mpf_codec_list_init(&rtp_settings->codec_list,0,pool);
+ rtp_settings->own_preferrence = FALSE;
+ rtp_settings->rtcp = FALSE;
+ rtp_settings->rtcp_bye_policy = RTCP_BYE_DISABLE;
+ rtp_settings->rtcp_tx_interval = 0;
+ rtp_settings->rtcp_rx_resolution = 0;
+ mpf_jb_config_init(&rtp_settings->jb_config);
+ return rtp_settings;
+}
+
+
APT_END_EXTERN_C
-#endif /*__MPF_RTP_DESCRIPTOR_H__*/
+#endif /* MPF_RTP_DESCRIPTOR_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_rtp_header.h b/libs/unimrcp/libs/mpf/include/mpf_rtp_header.h
index 398d844dce..a122cb6cc7 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_rtp_header.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_rtp_header.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_rtp_header.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_RTP_HEADER_H__
-#define __MPF_RTP_HEADER_H__
+#ifndef MPF_RTP_HEADER_H
+#define MPF_RTP_HEADER_H
/**
* @file mpf_rtp_header.h
@@ -83,4 +85,4 @@ struct rtp_extension_header_t {
APT_END_EXTERN_C
-#endif /*__MPF_RTP_HEADER_H__*/
+#endif /* MPF_RTP_HEADER_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_rtp_pt.h b/libs/unimrcp/libs/mpf/include/mpf_rtp_pt.h
index 27114c5e6e..27f88f1c7c 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_rtp_pt.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_rtp_pt.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_rtp_pt.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_RTP_PT_H__
-#define __MPF_RTP_PT_H__
+#ifndef MPF_RTP_PT_H
+#define MPF_RTP_PT_H
/**
* @file mpf_rtp_pt.h
@@ -41,4 +43,4 @@ typedef enum {
APT_END_EXTERN_C
-#endif /*__MPF_RTP_PT_H__*/
+#endif /* MPF_RTP_PT_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_rtp_stat.h b/libs/unimrcp/libs/mpf/include/mpf_rtp_stat.h
index 2d492ebf4f..e97b58c826 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_rtp_stat.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_rtp_stat.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_rtp_stat.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_RTP_STAT_H__
-#define __MPF_RTP_STAT_H__
+#ifndef MPF_RTP_STAT_H
+#define MPF_RTP_STAT_H
/**
* @file mpf_rtp_stat.h
@@ -110,4 +112,4 @@ static APR_INLINE void mpf_rtp_rx_stat_reset(rtp_rx_stat_t *rx_stat)
APT_END_EXTERN_C
-#endif /*__MPF_RTP_STAT_H__*/
+#endif /* MPF_RTP_STAT_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_rtp_stream.h b/libs/unimrcp/libs/mpf/include/mpf_rtp_stream.h
index 803ab34577..76ef8963a5 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_rtp_stream.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_rtp_stream.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_rtp_stream.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_RTP_STREAM_H__
-#define __MPF_RTP_STREAM_H__
+#ifndef MPF_RTP_STREAM_H
+#define MPF_RTP_STREAM_H
/**
* @file mpf_rtp_stream.h
@@ -30,10 +32,11 @@ APT_BEGIN_EXTERN_C
/**
* Create RTP stream.
* @param termination the back pointer to hold
- * @param config the configuration to use
+ * @param config the configuration of RTP factory
+ * @param settings the settings to use
* @param pool the pool to allocate memory from
*/
-MPF_DECLARE(mpf_audio_stream_t*) mpf_rtp_stream_create(mpf_termination_t *termination, mpf_rtp_config_t *config, apr_pool_t *pool);
+MPF_DECLARE(mpf_audio_stream_t*) mpf_rtp_stream_create(mpf_termination_t *termination, mpf_rtp_config_t *config, mpf_rtp_settings_t *settings, apr_pool_t *pool);
/**
* Add/enable RTP stream.
@@ -56,4 +59,4 @@ MPF_DECLARE(apt_bool_t) mpf_rtp_stream_modify(mpf_audio_stream_t *stream, mpf_rt
APT_END_EXTERN_C
-#endif /*__MPF_RTP_STREAM_H__*/
+#endif /* MPF_RTP_STREAM_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_rtp_termination_factory.h b/libs/unimrcp/libs/mpf/include/mpf_rtp_termination_factory.h
index f881c445af..d34ffcbc3d 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_rtp_termination_factory.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_rtp_termination_factory.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_rtp_termination_factory.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_RTP_TERMINATION_FACTORY_H__
-#define __MPF_RTP_TERMINATION_FACTORY_H__
+#ifndef MPF_RTP_TERMINATION_FACTORY_H
+#define MPF_RTP_TERMINATION_FACTORY_H
/**
* @file mpf_rtp_termination_factory.h
@@ -37,4 +39,4 @@ MPF_DECLARE(mpf_termination_factory_t*) mpf_rtp_termination_factory_create(
APT_END_EXTERN_C
-#endif /*__MPF_RTP_TERMINATION_FACTORY_H__*/
+#endif /* MPF_RTP_TERMINATION_FACTORY_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_scheduler.h b/libs/unimrcp/libs/mpf/include/mpf_scheduler.h
index 6617511fe7..1e83091b8e 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_scheduler.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_scheduler.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_scheduler.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_SCHEDULER_H__
-#define __MPF_SCHEDULER_H__
+#ifndef MPF_SCHEDULER_H
+#define MPF_SCHEDULER_H
/**
* @file mpf_scheduler.h
@@ -63,4 +65,4 @@ MPF_DECLARE(apt_bool_t) mpf_scheduler_stop(mpf_scheduler_t *scheduler);
APT_END_EXTERN_C
-#endif /*__MPF_SCHEDULER_H__*/
+#endif /* MPF_SCHEDULER_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_stream.h b/libs/unimrcp/libs/mpf/include/mpf_stream.h
index 4decae5235..93676b7eb0 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_stream.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_stream.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_stream.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_STREAM_H__
-#define __MPF_STREAM_H__
+#ifndef MPF_STREAM_H
+#define MPF_STREAM_H
/**
* @file mpf_stream.h
@@ -166,4 +168,4 @@ MPF_DECLARE(void) mpf_audio_stream_trace(mpf_audio_stream_t *stream, mpf_stream_
APT_END_EXTERN_C
-#endif /*__MPF_STREAM_H__*/
+#endif /* MPF_STREAM_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_stream_descriptor.h b/libs/unimrcp/libs/mpf/include/mpf_stream_descriptor.h
index 86b56b1b73..fbdeb5b068 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_stream_descriptor.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_stream_descriptor.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_stream_descriptor.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MPF_STREAM_DESCRIPTOR_H__
-#define __MPF_STREAM_DESCRIPTOR_H__
+#ifndef MPF_STREAM_DESCRIPTOR_H
+#define MPF_STREAM_DESCRIPTOR_H
/**
* @file mpf_stream_descriptor.h
@@ -85,4 +87,4 @@ static APR_INLINE mpf_stream_direction_e mpf_stream_reverse_direction_get(mpf_st
APT_END_EXTERN_C
-#endif /*__MPF_STREAM_DESCRIPTOR_H__*/
+#endif /* MPF_STREAM_DESCRIPTOR_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_termination.h b/libs/unimrcp/libs/mpf/include/mpf_termination.h
index 06ede3bfd8..8444f2edff 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_termination.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_termination.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_termination.h 1693 2010-05-16 18:33:07Z achaloyan $
*/
-#ifndef __MPF_TERMINATION_H__
-#define __MPF_TERMINATION_H__
+#ifndef MPF_TERMINATION_H
+#define MPF_TERMINATION_H
/**
* @file mpf_termination.h
@@ -23,6 +25,7 @@
*/
#include "mpf_types.h"
+#include "apt_timer_queue.h"
APT_BEGIN_EXTERN_C
@@ -50,6 +53,8 @@ struct mpf_termination_vtable_t {
struct mpf_termination_t {
/** Pool to allocate memory from */
apr_pool_t *pool;
+ /** Informative name used for debugging */
+ const char *name;
/** External object */
void *obj;
/** Object to send events to */
@@ -58,8 +63,8 @@ struct mpf_termination_t {
mpf_termination_event_handler_f event_handler;
/** Codec manager */
const mpf_codec_manager_t *codec_manager;
- /** Timer manager */
- mpf_timer_manager_t *timer_manager;
+ /** Timer queue */
+ apt_timer_queue_t *timer_queue;
/** Termination factory entire termination created by */
mpf_termination_factory_t *termination_factory;
/** Table of virtual methods */
@@ -113,4 +118,4 @@ MPF_DECLARE(apt_bool_t) mpf_termination_subtract(mpf_termination_t *termination)
APT_END_EXTERN_C
-#endif /*__MPF_TERMINATION_H__*/
+#endif /* MPF_TERMINATION_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_termination_factory.h b/libs/unimrcp/libs/mpf/include/mpf_termination_factory.h
index 564518657a..973044b888 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_termination_factory.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_termination_factory.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_termination_factory.h 1693 2010-05-16 18:33:07Z achaloyan $
*/
-#ifndef __MPF_TERMINATION_FACTORY_H__
-#define __MPF_TERMINATION_FACTORY_H__
+#ifndef MPF_TERMINATION_FACTORY_H
+#define MPF_TERMINATION_FACTORY_H
/**
* @file mpf_termination_factory.h
@@ -64,25 +66,31 @@ MPF_DECLARE(mpf_termination_t*) mpf_raw_termination_create(
*/
MPF_DECLARE(apt_bool_t) mpf_termination_destroy(mpf_termination_t *termination);
+/**
+ * Get termination name.
+ * @param termination the termination to get name of
+ */
+MPF_DECLARE(const char*) mpf_termination_name_get(const mpf_termination_t *termination);
+
/**
* Get associated object.
* @param termination the termination to get object from
*/
-MPF_DECLARE(void*) mpf_termination_object_get(mpf_termination_t *termination);
+MPF_DECLARE(void*) mpf_termination_object_get(const mpf_termination_t *termination);
/**
* Get audio stream.
* @param termination the termination to get audio stream from
*/
-MPF_DECLARE(mpf_audio_stream_t*) mpf_termination_audio_stream_get(mpf_termination_t *termination);
+MPF_DECLARE(mpf_audio_stream_t*) mpf_termination_audio_stream_get(const mpf_termination_t *termination);
/**
* Get video stream.
* @param termination the termination to get video stream from
*/
-MPF_DECLARE(mpf_video_stream_t*) mpf_termination_video_stream_get(mpf_termination_t *termination);
+MPF_DECLARE(mpf_video_stream_t*) mpf_termination_video_stream_get(const mpf_termination_t *termination);
APT_END_EXTERN_C
-#endif /*__MPF_TERMINATION_FACTORY_H__*/
+#endif /* MPF_TERMINATION_FACTORY_H */
diff --git a/libs/unimrcp/libs/mpf/include/mpf_timer_manager.h b/libs/unimrcp/libs/mpf/include/mpf_timer_manager.h
deleted file mode 100644
index 4de738c4f6..0000000000
--- a/libs/unimrcp/libs/mpf/include/mpf_timer_manager.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2008 Arsen Chaloyan
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __MPF_TIMER_MANAGER_H__
-#define __MPF_TIMER_MANAGER_H__
-
-/**
- * @file mpf_timer_manager.h
- * @brief MPF Timer Management
- */
-
-#include "mpf_types.h"
-
-APT_BEGIN_EXTERN_C
-
-
-/** Prototype of timer callback */
-typedef void (*mpf_timer_proc_f)(mpf_timer_t *timer, void *obj);
-
-
-/** Create timer manager */
-MPF_DECLARE(mpf_timer_manager_t*) mpf_timer_manager_create(mpf_scheduler_t *scheduler, apr_pool_t *pool);
-
-/** Destroy timer manager */
-MPF_DECLARE(void) mpf_timer_manager_destroy(mpf_timer_manager_t *timer_manager);
-
-
-/** Create timer */
-MPF_DECLARE(mpf_timer_t*) mpf_timer_create(mpf_timer_manager_t *timer_manager, mpf_timer_proc_f proc, void *obj, apr_pool_t *pool);
-
-/** Set one-shot timer */
-MPF_DECLARE(apt_bool_t) mpf_timer_set(mpf_timer_t *timer, apr_uint32_t timeout);
-
-/** Kill timer */
-MPF_DECLARE(apt_bool_t) mpf_timer_kill(mpf_timer_t *timer);
-
-
-APT_END_EXTERN_C
-
-#endif /*__MPF_TIMER_MANAGER_H__*/
diff --git a/libs/unimrcp/libs/mpf/include/mpf_types.h b/libs/unimrcp/libs/mpf/include/mpf_types.h
index 0b9814edb5..f3017489f6 100644
--- a/libs/unimrcp/libs/mpf/include/mpf_types.h
+++ b/libs/unimrcp/libs/mpf/include/mpf_types.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_types.h 1543 2010-02-24 21:46:24Z achaloyan $
*/
-#ifndef __MPF_TYPES_H__
-#define __MPF_TYPES_H__
+#ifndef MPF_TYPES_H
+#define MPF_TYPES_H
/**
* @file mpf_types.h
@@ -35,12 +37,6 @@ typedef struct mpf_scheduler_t mpf_scheduler_t;
/** Opaque codec manager declaration */
typedef struct mpf_codec_manager_t mpf_codec_manager_t;
-/** Opaque MPF timer manager declaration */
-typedef struct mpf_timer_manager_t mpf_timer_manager_t;
-
-/** Opaque MPF timer declaration */
-typedef struct mpf_timer_t mpf_timer_t;
-
/** Opaque MPF context declaration */
typedef struct mpf_context_t mpf_context_t;
@@ -59,4 +55,4 @@ typedef struct mpf_video_stream_t mpf_video_stream_t;
APT_END_EXTERN_C
-#endif /*__MPF_TYPES_H__*/
+#endif /* MPF_TYPES_H */
diff --git a/libs/unimrcp/libs/mpf/mpf.2008.vcproj b/libs/unimrcp/libs/mpf/mpf.2008.vcproj
deleted file mode 100644
index 2f02670890..0000000000
--- a/libs/unimrcp/libs/mpf/mpf.2008.vcproj
+++ /dev/null
@@ -1,567 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/libs/mpf/mpf.2010.vcxproj b/libs/unimrcp/libs/mpf/mpf.2010.vcxproj
deleted file mode 100644
index 1b48acef80..0000000000
--- a/libs/unimrcp/libs/mpf/mpf.2010.vcxproj
+++ /dev/null
@@ -1,193 +0,0 @@
-
-
-
-
- Debug
- Win32
-
-
- Debug
- x64
-
-
- Release
- Win32
-
-
- Release
- x64
-
-
-
- mpf
- {B5A00BFA-6083-4FAE-A097-71642D6473B5}
- mpf
- Win32Proj
-
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
-
-
-
- codecs;%(AdditionalIncludeDirectories)
- APT_STATIC_LIB;MPF_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- codecs;%(AdditionalIncludeDirectories)
- APT_STATIC_LIB;MPF_STATIC_LIB;%(PreprocessorDefinitions)
- false
- ProgramDatabase
-
-
-
-
- codecs;%(AdditionalIncludeDirectories)
- APT_STATIC_LIB;MPF_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- codecs;%(AdditionalIncludeDirectories)
- APT_STATIC_LIB;MPF_STATIC_LIB;%(PreprocessorDefinitions)
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/libs/mpf/mpf.2010.vcxproj.filters b/libs/unimrcp/libs/mpf/mpf.2010.vcxproj.filters
deleted file mode 100644
index 0e4bc84d13..0000000000
--- a/libs/unimrcp/libs/mpf/mpf.2010.vcxproj.filters
+++ /dev/null
@@ -1,239 +0,0 @@
-
-
-
-
- {3d69fc35-a195-4376-9508-ef77d7b27e71}
-
-
- {81e2eace-c57a-4135-92cd-cc3575dfb088}
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hpp;hxx;hm;inl;inc;xsd
-
-
- {6fc3533a-b688-477d-914d-e0ffb15aa9a9}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
-
-
- codecs\g711
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
-
-
- codecs\g711
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/libs/mpf/mpf.vcproj b/libs/unimrcp/libs/mpf/mpf.vcproj
index bf380d1e31..b3fde36677 100644
--- a/libs/unimrcp/libs/mpf/mpf.vcproj
+++ b/libs/unimrcp/libs/mpf/mpf.vcproj
@@ -416,10 +416,6 @@
RelativePath=".\include\mpf_termination_factory.h"
>
-
-
@@ -541,10 +537,6 @@
RelativePath=".\src\mpf_termination_factory.c"
>
-
-
diff --git a/libs/unimrcp/libs/mpf/src/mpf_activity_detector.c b/libs/unimrcp/libs/mpf/src/mpf_activity_detector.c
index 6ef66674eb..bf3cd76fc6 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_activity_detector.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_activity_detector.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_activity_detector.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "mpf_activity_detector.h"
diff --git a/libs/unimrcp/libs/mpf/src/mpf_audio_file_stream.c b/libs/unimrcp/libs/mpf/src/mpf_audio_file_stream.c
index 54010b69b4..c235da38de 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_audio_file_stream.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_audio_file_stream.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_audio_file_stream.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "mpf_audio_file_stream.h"
diff --git a/libs/unimrcp/libs/mpf/src/mpf_bridge.c b/libs/unimrcp/libs/mpf/src/mpf_bridge.c
index f4028063d3..25c12de2ff 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_bridge.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_bridge.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_bridge.c 1693 2010-05-16 18:33:07Z achaloyan $
*/
#include "mpf_bridge.h"
@@ -31,7 +33,8 @@ struct mpf_bridge_t {
mpf_audio_stream_t *source;
/** Audio stream sink */
mpf_audio_stream_t *sink;
-
+ /** Codec used in case of null bridge */
+ mpf_codec_t *codec;
/** Media frame used to read data from source and write it to sink */
mpf_frame_t frame;
};
@@ -57,7 +60,14 @@ static apt_bool_t mpf_null_bridge_process(mpf_object_t *object)
{
mpf_bridge_t *bridge = (mpf_bridge_t*) object;
bridge->frame.type = MEDIA_FRAME_TYPE_NONE;
+ bridge->frame.marker = MPF_MARKER_NONE;
bridge->source->vtable->read_frame(bridge->source,&bridge->frame);
+
+ if((bridge->frame.type & MEDIA_FRAME_TYPE_AUDIO) == 0) {
+ /* generate silence frame */
+ mpf_codec_initialize(bridge->codec,&bridge->frame.codec_frame);
+ }
+
bridge->sink->vtable->write_frame(bridge->sink,&bridge->frame);
return TRUE;
}
@@ -80,20 +90,20 @@ static void mpf_bridge_trace(mpf_object_t *object)
mpf_audio_stream_trace(bridge->sink,STREAM_DIRECTION_SEND,&output);
*output.pos = '\0';
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,output.text.buf);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Media Path %s %s",object->name,output.text.buf);
}
static apt_bool_t mpf_bridge_destroy(mpf_object_t *object)
{
mpf_bridge_t *bridge = (mpf_bridge_t*) object;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Destroy Audio Bridge");
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Destroy Audio Bridge %s",object->name);
mpf_audio_stream_rx_close(bridge->source);
mpf_audio_stream_tx_close(bridge->sink);
return TRUE;
}
-static mpf_bridge_t* mpf_bridge_base_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, apr_pool_t *pool)
+static mpf_bridge_t* mpf_bridge_base_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, const char *name, apr_pool_t *pool)
{
mpf_bridge_t *bridge;
if(!source || !sink) {
@@ -103,20 +113,21 @@ static mpf_bridge_t* mpf_bridge_base_create(mpf_audio_stream_t *source, mpf_audi
bridge = apr_palloc(pool,sizeof(mpf_bridge_t));
bridge->source = source;
bridge->sink = sink;
- mpf_object_init(&bridge->base);
+ bridge->codec = NULL;
+ mpf_object_init(&bridge->base,name);
bridge->base.destroy = mpf_bridge_destroy;
bridge->base.process = mpf_bridge_process;
bridge->base.trace = mpf_bridge_trace;
return bridge;
}
-static mpf_object_t* mpf_linear_bridge_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, const mpf_codec_manager_t *codec_manager, apr_pool_t *pool)
+static mpf_object_t* mpf_linear_bridge_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, const mpf_codec_manager_t *codec_manager, const char *name, apr_pool_t *pool)
{
mpf_codec_descriptor_t *descriptor;
apr_size_t frame_size;
mpf_bridge_t *bridge;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Create Linear Audio Bridge");
- bridge = mpf_bridge_base_create(source,sink,pool);
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Create Linear Audio Bridge %s",name);
+ bridge = mpf_bridge_base_create(source,sink,name,pool);
if(!bridge) {
return NULL;
}
@@ -136,13 +147,13 @@ static mpf_object_t* mpf_linear_bridge_create(mpf_audio_stream_t *source, mpf_au
return &bridge->base;
}
-static mpf_object_t* mpf_null_bridge_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, const mpf_codec_manager_t *codec_manager, apr_pool_t *pool)
+static mpf_object_t* mpf_null_bridge_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, const mpf_codec_manager_t *codec_manager, const char *name, apr_pool_t *pool)
{
mpf_codec_t *codec;
apr_size_t frame_size;
mpf_bridge_t *bridge;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Create Null Audio Bridge");
- bridge = mpf_bridge_base_create(source,sink,pool);
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Create Null Audio Bridge %s",name);
+ bridge = mpf_bridge_base_create(source,sink,name,pool);
if(!bridge) {
return NULL;
}
@@ -154,6 +165,7 @@ static mpf_object_t* mpf_null_bridge_create(mpf_audio_stream_t *source, mpf_audi
}
frame_size = mpf_codec_frame_size_calculate(source->rx_descriptor,codec->attribs);
+ bridge->codec = codec;
bridge->frame.codec_frame.size = frame_size;
bridge->frame.codec_frame.buffer = apr_palloc(pool,frame_size);
@@ -167,7 +179,12 @@ static mpf_object_t* mpf_null_bridge_create(mpf_audio_stream_t *source, mpf_audi
return &bridge->base;
}
-MPF_DECLARE(mpf_object_t*) mpf_bridge_create(mpf_audio_stream_t *source, mpf_audio_stream_t *sink, const mpf_codec_manager_t *codec_manager, apr_pool_t *pool)
+MPF_DECLARE(mpf_object_t*) mpf_bridge_create(
+ mpf_audio_stream_t *source,
+ mpf_audio_stream_t *sink,
+ const mpf_codec_manager_t *codec_manager,
+ const char *name,
+ apr_pool_t *pool)
{
if(!source || !sink) {
return NULL;
@@ -179,7 +196,7 @@ MPF_DECLARE(mpf_object_t*) mpf_bridge_create(mpf_audio_stream_t *source, mpf_aud
}
if(mpf_codec_descriptors_match(source->rx_descriptor,sink->tx_descriptor) == TRUE) {
- return mpf_null_bridge_create(source,sink,codec_manager,pool);
+ return mpf_null_bridge_create(source,sink,codec_manager,name,pool);
}
if(mpf_codec_lpcm_descriptor_match(source->rx_descriptor) == FALSE) {
@@ -209,5 +226,5 @@ MPF_DECLARE(mpf_object_t*) mpf_bridge_create(mpf_audio_stream_t *source, mpf_aud
source = resampler;
}
- return mpf_linear_bridge_create(source,sink,codec_manager,pool);
+ return mpf_linear_bridge_create(source,sink,codec_manager,name,pool);
}
diff --git a/libs/unimrcp/libs/mpf/src/mpf_buffer.c b/libs/unimrcp/libs/mpf/src/mpf_buffer.c
index f128760277..b253d6ae02 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_buffer.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_buffer.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_buffer.c 1709 2010-05-24 17:12:11Z achaloyan $
*/
#ifdef WIN32
@@ -165,7 +167,7 @@ apt_bool_t mpf_buffer_frame_read(mpf_buffer_t *buffer, mpf_frame_t *media_frame)
return TRUE;
}
-apr_size_t mpf_buffer_get_size(mpf_buffer_t *buffer)
+apr_size_t mpf_buffer_get_size(const mpf_buffer_t *buffer)
{
return buffer->size;
}
diff --git a/libs/unimrcp/libs/mpf/src/mpf_codec_descriptor.c b/libs/unimrcp/libs/mpf/src/mpf_codec_descriptor.c
index 2995cf94a5..b493f4959b 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_codec_descriptor.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_codec_descriptor.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_codec_descriptor.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "mpf_codec_descriptor.h"
diff --git a/libs/unimrcp/libs/mpf/src/mpf_codec_g711.c b/libs/unimrcp/libs/mpf/src/mpf_codec_g711.c
index ab20a278f9..5a4a66de2e 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_codec_g711.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_codec_g711.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_codec_g711.c 1686 2010-05-08 18:46:08Z achaloyan $
*/
#include "mpf_codec.h"
@@ -70,6 +72,17 @@ static apt_bool_t g711u_decode(mpf_codec_t *codec, const mpf_codec_frame_t *fram
return TRUE;
}
+static apt_bool_t g711u_init(mpf_codec_t *codec, mpf_codec_frame_t *frame_out)
+{
+ apr_size_t i;
+ unsigned char *encode_buf = frame_out->buffer;
+ for(i=0; isize; i++) {
+ encode_buf[i] = linear_to_ulaw(0);
+ }
+
+ return TRUE;
+}
+
static apt_bool_t g711a_encode(mpf_codec_t *codec, const mpf_codec_frame_t *frame_in, mpf_codec_frame_t *frame_out)
{
const apr_int16_t *decode_buf;
@@ -106,12 +119,24 @@ static apt_bool_t g711a_decode(mpf_codec_t *codec, const mpf_codec_frame_t *fram
return TRUE;
}
+static apt_bool_t g711a_init(mpf_codec_t *codec, mpf_codec_frame_t *frame_out)
+{
+ apr_size_t i;
+ unsigned char *encode_buf = frame_out->buffer;
+ for(i=0; isize; i++) {
+ encode_buf[i] = linear_to_alaw(0);
+ }
+
+ return TRUE;
+}
+
static const mpf_codec_vtable_t g711u_vtable = {
g711_open,
g711_close,
g711u_encode,
g711u_decode,
- NULL
+ NULL,
+ g711u_init
};
static const mpf_codec_vtable_t g711a_vtable = {
@@ -119,7 +144,8 @@ static const mpf_codec_vtable_t g711a_vtable = {
g711_close,
g711a_encode,
g711a_decode,
- NULL
+ NULL,
+ g711a_init
};
static const mpf_codec_descriptor_t g711u_descriptor = {
diff --git a/libs/unimrcp/libs/mpf/src/mpf_codec_linear.c b/libs/unimrcp/libs/mpf/src/mpf_codec_linear.c
index 7f342b0a31..7e6b091100 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_codec_linear.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_codec_linear.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_codec_linear.c 1686 2010-05-08 18:46:08Z achaloyan $
*/
#define APR_WANT_BYTEFUNC
@@ -71,6 +73,7 @@ static const mpf_codec_vtable_t l16_vtable = {
l16_close,
l16_encode,
l16_decode,
+ NULL,
NULL
};
diff --git a/libs/unimrcp/libs/mpf/src/mpf_codec_manager.c b/libs/unimrcp/libs/mpf/src/mpf_codec_manager.c
index b83581a25a..fa0482a610 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_codec_manager.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_codec_manager.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_codec_manager.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include
diff --git a/libs/unimrcp/libs/mpf/src/mpf_context.c b/libs/unimrcp/libs/mpf/src/mpf_context.c
index c6978d8e37..bdd0034ecb 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_context.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_context.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_context.c 1709 2010-05-24 17:12:11Z achaloyan $
*/
#ifdef WIN32
@@ -46,6 +48,8 @@ struct mpf_context_t {
mpf_context_factory_t *factory;
/** Pool to allocate memory from */
apr_pool_t *pool;
+ /** Informative name of the context used for debugging */
+ const char *name;
/** External object */
void *obj;
@@ -109,6 +113,7 @@ MPF_DECLARE(apt_bool_t) mpf_context_factory_process(mpf_context_factory_t *facto
MPF_DECLARE(mpf_context_t*) mpf_context_create(
mpf_context_factory_t *factory,
+ const char *name,
void *obj,
apr_size_t max_termination_count,
apr_pool_t *pool)
@@ -120,6 +125,10 @@ MPF_DECLARE(mpf_context_t*) mpf_context_create(
context->factory = factory;
context->obj = obj;
context->pool = pool;
+ context->name = name;
+ if(!context->name) {
+ context->name = apr_psprintf(pool,"0x%pp",context);
+ }
context->capacity = max_termination_count;
context->count = 0;
context->mpf_objects = apr_array_make(pool,1,sizeof(mpf_object_t*));
@@ -154,7 +163,7 @@ MPF_DECLARE(apt_bool_t) mpf_context_destroy(mpf_context_t *context)
return TRUE;
}
-MPF_DECLARE(void*) mpf_context_object_get(mpf_context_t *context)
+MPF_DECLARE(void*) mpf_context_object_get(const mpf_context_t *context)
{
return context->obj;
}
@@ -169,11 +178,10 @@ MPF_DECLARE(apt_bool_t) mpf_context_termination_add(mpf_context_t *context, mpf_
continue;
}
if(!context->count) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Add Context");
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Add Media Context %s",context->name);
APR_RING_INSERT_TAIL(&context->factory->head,context,mpf_context_t,link);
}
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Add Termination");
header_item->termination = termination;
header_item->tx_count = 0;
header_item->rx_count = 0;
@@ -200,7 +208,6 @@ MPF_DECLARE(apt_bool_t) mpf_context_termination_subtract(mpf_context_t *context,
return FALSE;
}
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Subtract Termination");
for(j=0,k=0; jcapacity && kcount; j++) {
header_item2 = &context->header[j];
if(!header_item2->termination) {
@@ -227,7 +234,7 @@ MPF_DECLARE(apt_bool_t) mpf_context_termination_subtract(mpf_context_t *context,
termination->slot = (apr_size_t)-1;
context->count--;
if(!context->count) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Remove Context");
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Remove Media Context %s",context->name);
APR_RING_REMOVE(context,link);
}
return TRUE;
@@ -463,6 +470,7 @@ static mpf_object_t* mpf_context_bridge_create(mpf_context_t *context, apr_size_
header_item1->termination->audio_stream,
header_item2->termination->audio_stream,
header_item1->termination->codec_manager,
+ context->name,
context->pool);
}
}
@@ -494,6 +502,7 @@ static mpf_object_t* mpf_context_multiplier_create(mpf_context_t *context, apr_s
sink_arr,
header_item1->tx_count,
header_item1->termination->codec_manager,
+ context->name,
context->pool);
}
@@ -522,6 +531,7 @@ static mpf_object_t* mpf_context_mixer_create(mpf_context_t *context, apr_size_t
header_item1->rx_count,
header_item1->termination->audio_stream,
header_item1->termination->codec_manager,
+ context->name,
context->pool);
}
diff --git a/libs/unimrcp/libs/mpf/src/mpf_decoder.c b/libs/unimrcp/libs/mpf/src/mpf_decoder.c
index 878dbbf459..e01d438803 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_decoder.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_decoder.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_decoder.c 1530 2010-02-19 18:40:08Z achaloyan $
*/
#include "mpf_decoder.h"
@@ -36,12 +38,14 @@ static apt_bool_t mpf_decoder_destroy(mpf_audio_stream_t *stream)
static apt_bool_t mpf_decoder_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
{
mpf_decoder_t *decoder = stream->obj;
+ mpf_codec_open(decoder->codec);
return mpf_audio_stream_rx_open(decoder->source,decoder->codec);
}
static apt_bool_t mpf_decoder_close(mpf_audio_stream_t *stream)
{
mpf_decoder_t *decoder = stream->obj;
+ mpf_codec_close(decoder->codec);
return mpf_audio_stream_rx_close(decoder->source);
}
diff --git a/libs/unimrcp/libs/mpf/src/mpf_dtmf_detector.c b/libs/unimrcp/libs/mpf/src/mpf_dtmf_detector.c
index e40096a2ed..f22da57a8d 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_dtmf_detector.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_dtmf_detector.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Tomas Valenta, Arsen Chaloyan
+ * Copyright 2009-2010 Tomas Valenta, Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_dtmf_detector.c 1788 2010-11-22 19:45:38Z tomas.valenta@speechtech.cz $
*/
#include "mpf_dtmf_detector.h"
@@ -217,8 +219,8 @@ static void goertzel_energies_digit(struct mpf_dtmf_detector_t *detector)
}
}
- if ((reng < 8.0e8 * detector->wsamples / GOERTZEL_SAMPLES_8K) ||
- (ceng < 8.0e8 * detector->wsamples / GOERTZEL_SAMPLES_8K))
+ if ((reng < 8.0e10 * detector->wsamples / GOERTZEL_SAMPLES_8K) ||
+ (ceng < 8.0e10 * detector->wsamples / GOERTZEL_SAMPLES_8K))
{
/* energy not high enough */
} else if ((ceng > reng) && (reng < ceng * 0.398)) { /* twist > 4dB, error */
@@ -233,7 +235,7 @@ static void goertzel_energies_digit(struct mpf_dtmf_detector_t *detector)
*/
} else if ((ceng < reng) && (ceng < reng * 0.158)) { /* twist > 8db, error */
/* Reverse twist check failed */
- } else if (0.025 * detector->totenergy > (reng + ceng)) { /* 16db */
+ } else if (0.25 * detector->totenergy > (reng + ceng)) { /* 16db */
/* Signal energy to total energy ratio test failed */
} else {
digit = freq2digits[rmax][cmax - DTMF_FREQUENCIES/2];
diff --git a/libs/unimrcp/libs/mpf/src/mpf_dtmf_generator.c b/libs/unimrcp/libs/mpf/src/mpf_dtmf_generator.c
index 836561db01..a31240be4a 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_dtmf_generator.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_dtmf_generator.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Tomas Valenta, Arsen Chaloyan
+ * Copyright 2009-2010 Tomas Valenta, Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_dtmf_generator.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "mpf_dtmf_generator.h"
diff --git a/libs/unimrcp/libs/mpf/src/mpf_encoder.c b/libs/unimrcp/libs/mpf/src/mpf_encoder.c
index 797600192f..c80d98fb45 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_encoder.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_encoder.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_encoder.c 1530 2010-02-19 18:40:08Z achaloyan $
*/
#include "mpf_encoder.h"
@@ -36,12 +38,14 @@ static apt_bool_t mpf_encoder_destroy(mpf_audio_stream_t *stream)
static apt_bool_t mpf_encoder_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
{
mpf_encoder_t *encoder = stream->obj;
+ mpf_codec_open(encoder->codec);
return mpf_audio_stream_tx_open(encoder->sink,encoder->codec);
}
static apt_bool_t mpf_encoder_close(mpf_audio_stream_t *stream)
{
mpf_encoder_t *encoder = stream->obj;
+ mpf_codec_close(encoder->codec);
return mpf_audio_stream_tx_close(encoder->sink);
}
diff --git a/libs/unimrcp/libs/mpf/src/mpf_engine.c b/libs/unimrcp/libs/mpf/src/mpf_engine.c
index 087b248884..06ef5db33f 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_engine.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_engine.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_engine.c 1709 2010-05-24 17:12:11Z achaloyan $
*/
#include "mpf_engine.h"
@@ -21,12 +23,11 @@
#include "mpf_scheduler.h"
#include "mpf_codec_descriptor.h"
#include "mpf_codec_manager.h"
-#include "mpf_timer_manager.h"
#include "apt_obj_list.h"
#include "apt_cyclic_queue.h"
#include "apt_log.h"
-#define MPF_TASK_NAME "Media Processing Engine"
+#define MPF_TIMER_RESOLUTION 100 /* 100 ms */
struct mpf_engine_t {
apr_pool_t *pool;
@@ -36,11 +37,12 @@ struct mpf_engine_t {
apt_cyclic_queue_t *request_queue;
mpf_context_factory_t *context_factory;
mpf_scheduler_t *scheduler;
- mpf_timer_manager_t *timer_manager;
+ apt_timer_queue_t *timer_queue;
const mpf_codec_manager_t *codec_manager;
};
-static void mpf_engine_main(mpf_scheduler_t *scheduler, void *data);
+static void mpf_engine_main(mpf_scheduler_t *scheduler, void *obj);
+static void mpf_engine_timer_proc(mpf_scheduler_t *scheduler, void *obj);
static apt_bool_t mpf_engine_destroy(apt_task_t *task);
static apt_bool_t mpf_engine_start(apt_task_t *task);
static apt_bool_t mpf_engine_terminate(apt_task_t *task);
@@ -52,7 +54,7 @@ mpf_codec_t* mpf_codec_l16_create(apr_pool_t *pool);
mpf_codec_t* mpf_codec_g711u_create(apr_pool_t *pool);
mpf_codec_t* mpf_codec_g711a_create(apr_pool_t *pool);
-MPF_DECLARE(mpf_engine_t*) mpf_engine_create(apr_pool_t *pool)
+MPF_DECLARE(mpf_engine_t*) mpf_engine_create(const char *id, apr_pool_t *pool)
{
apt_task_vtable_t *vtable;
apt_task_msg_pool_t *msg_pool;
@@ -64,13 +66,13 @@ MPF_DECLARE(mpf_engine_t*) mpf_engine_create(apr_pool_t *pool)
msg_pool = apt_task_msg_pool_create_dynamic(sizeof(mpf_message_container_t),pool);
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create "MPF_TASK_NAME);
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create Media Engine [%s]",id);
engine->task = apt_task_create(engine,msg_pool,pool);
if(!engine->task) {
return NULL;
}
- apt_task_name_set(engine->task,MPF_TASK_NAME);
+ apt_task_name_set(engine->task,id);
vtable = apt_task_vtable_get(engine->task);
if(vtable) {
@@ -90,17 +92,19 @@ MPF_DECLARE(mpf_engine_t*) mpf_engine_create(apr_pool_t *pool)
engine->scheduler = mpf_scheduler_create(engine->pool);
mpf_scheduler_media_clock_set(engine->scheduler,CODEC_FRAME_TIME_BASE,mpf_engine_main,engine);
- engine->timer_manager = mpf_timer_manager_create(engine->scheduler,engine->pool);
+ engine->timer_queue = apt_timer_queue_create(engine->pool);
+ mpf_scheduler_timer_clock_set(engine->scheduler,MPF_TIMER_RESOLUTION,mpf_engine_timer_proc,engine);
return engine;
}
MPF_DECLARE(mpf_context_t*) mpf_engine_context_create(
- mpf_engine_t *engine,
- void *obj,
- apr_size_t max_termination_count,
+ mpf_engine_t *engine,
+ const char *name,
+ void *obj,
+ apr_size_t max_termination_count,
apr_pool_t *pool)
{
- return mpf_context_create(engine->context_factory,obj,max_termination_count,pool);
+ return mpf_context_create(engine->context_factory,name,obj,max_termination_count,pool);
}
MPF_DECLARE(apt_bool_t) mpf_engine_context_destroy(mpf_context_t *context)
@@ -108,12 +112,12 @@ MPF_DECLARE(apt_bool_t) mpf_engine_context_destroy(mpf_context_t *context)
return mpf_context_destroy(context);
}
-MPF_DECLARE(void*) mpf_engine_context_object_get(mpf_context_t *context)
+MPF_DECLARE(void*) mpf_engine_context_object_get(const mpf_context_t *context)
{
return mpf_context_object_get(context);
}
-MPF_DECLARE(apt_task_t*) mpf_task_get(mpf_engine_t *engine)
+MPF_DECLARE(apt_task_t*) mpf_task_get(const mpf_engine_t *engine)
{
return engine->task;
}
@@ -223,7 +227,7 @@ static apt_bool_t mpf_engine_destroy(apt_task_t *task)
{
mpf_engine_t *engine = apt_task_object_get(task);
- mpf_timer_manager_destroy(engine->timer_manager);
+ apt_timer_queue_destroy(engine->timer_queue);
mpf_scheduler_destroy(engine->scheduler);
mpf_context_factory_destroy(engine->context_factory);
apt_cyclic_queue_destroy(engine->request_queue);
@@ -282,7 +286,7 @@ static apt_bool_t mpf_engine_msg_signal(apt_task_t *task, apt_task_msg_t *msg)
apr_thread_mutex_lock(engine->request_queue_guard);
if(apt_cyclic_queue_push(engine->request_queue,msg) == FALSE) {
- apt_log(APT_LOG_MARK,APT_PRIO_ERROR,"MPF Request Queue is Full");
+ apt_log(APT_LOG_MARK,APT_PRIO_ERROR,"MPF Request Queue is Full [%s]",apt_task_name_get(task));
}
apr_thread_mutex_unlock(engine->request_queue_guard);
return TRUE;
@@ -299,7 +303,6 @@ static apt_bool_t mpf_engine_msg_process(apt_task_t *task, apt_task_msg_t *msg)
mpf_termination_t *termination;
const mpf_message_t *mpf_request;
const mpf_message_container_t *request = (const mpf_message_container_t*) msg->data;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Process MPF Message");
response_msg = apt_task_msg_get(engine->task);
response_msg->type = engine->task_msg_type;
@@ -324,7 +327,7 @@ static apt_bool_t mpf_engine_msg_process(apt_task_t *task, apt_task_msg_t *msg)
termination->event_handler_obj = engine;
termination->event_handler = mpf_engine_event_raise;
termination->codec_manager = engine->codec_manager;
- termination->timer_manager = engine->timer_manager;
+ termination->timer_queue = engine->timer_queue;
mpf_termination_add(termination,mpf_request->descriptor);
if(mpf_context_termination_add(context,termination) == FALSE) {
@@ -383,9 +386,9 @@ static apt_bool_t mpf_engine_msg_process(apt_task_t *task, apt_task_msg_t *msg)
return apt_task_msg_parent_signal(engine->task,response_msg);
}
-static void mpf_engine_main(mpf_scheduler_t *scheduler, void *data)
+static void mpf_engine_main(mpf_scheduler_t *scheduler, void *obj)
{
- mpf_engine_t *engine = data;
+ mpf_engine_t *engine = obj;
apt_task_msg_t *msg;
/* process request queue */
@@ -403,6 +406,12 @@ static void mpf_engine_main(mpf_scheduler_t *scheduler, void *data)
mpf_context_factory_process(engine->context_factory);
}
+static void mpf_engine_timer_proc(mpf_scheduler_t *scheduler, void *obj)
+{
+ mpf_engine_t *engine = obj;
+ apt_timer_queue_advance(engine->timer_queue,MPF_TIMER_RESOLUTION);
+}
+
MPF_DECLARE(mpf_codec_manager_t*) mpf_engine_codec_manager_create(apr_pool_t *pool)
{
mpf_codec_manager_t *codec_manager = mpf_codec_manager_create(4,pool);
@@ -431,3 +440,8 @@ MPF_DECLARE(apt_bool_t) mpf_engine_scheduler_rate_set(mpf_engine_t *engine, unsi
{
return mpf_scheduler_rate_set(engine->scheduler,rate);
}
+
+MPF_DECLARE(const char*) mpf_engine_id_get(const mpf_engine_t *engine)
+{
+ return apt_task_name_get(engine->task);
+}
diff --git a/libs/unimrcp/libs/mpf/src/mpf_file_termination_factory.c b/libs/unimrcp/libs/mpf/src/mpf_file_termination_factory.c
index dd1bc6e280..5da0815fe3 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_file_termination_factory.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_file_termination_factory.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_file_termination_factory.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "mpf_termination.h"
diff --git a/libs/unimrcp/libs/mpf/src/mpf_frame_buffer.c b/libs/unimrcp/libs/mpf/src/mpf_frame_buffer.c
index d93e5c56aa..6f1d568377 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_frame_buffer.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_frame_buffer.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_frame_buffer.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "mpf_frame_buffer.h"
diff --git a/libs/unimrcp/libs/mpf/src/mpf_jitter_buffer.c b/libs/unimrcp/libs/mpf/src/mpf_jitter_buffer.c
index 0235e762c4..5ddfb2e7be 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_jitter_buffer.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_jitter_buffer.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_jitter_buffer.c 1802 2011-05-13 02:43:12Z achaloyan $
*/
#include "mpf_jitter_buffer.h"
@@ -102,6 +104,10 @@ mpf_jitter_buffer_t* mpf_jitter_buffer_create(mpf_jb_config_t *jb_config, mpf_co
frame->codec_frame.buffer = jb->raw_data + i*jb->frame_size;
}
+ if(jb->config->initial_playout_delay % CODEC_FRAME_TIME_BASE != 0) {
+ jb->config->initial_playout_delay += CODEC_FRAME_TIME_BASE - jb->config->initial_playout_delay % CODEC_FRAME_TIME_BASE;
+ }
+
jb->playout_delay_ts = (apr_uint32_t)(jb->config->initial_playout_delay *
descriptor->channel_count * descriptor->sampling_rate / 1000);
@@ -149,17 +155,28 @@ static APR_INLINE jb_result_t mpf_jitter_buffer_write_prepare(mpf_jitter_buffer_
*write_ts = ts - jb->write_ts_offset + jb->playout_delay_ts;
if(*write_ts % jb->frame_ts != 0) {
/* not frame alligned */
+ JB_TRACE("JB write ts=%"APR_SIZE_T_FMT" not alligned -> discard\n",write_ts);
return JB_DISCARD_NOT_ALLIGNED;
}
return JB_OK;
}
-jb_result_t mpf_jitter_buffer_write(mpf_jitter_buffer_t *jb, void *buffer, apr_size_t size, apr_uint32_t ts)
+jb_result_t mpf_jitter_buffer_write(mpf_jitter_buffer_t *jb, void *buffer, apr_size_t size, apr_uint32_t ts, apr_byte_t marker)
{
mpf_frame_t *media_frame;
apr_uint32_t write_ts;
apr_size_t available_frame_count;
- jb_result_t result = mpf_jitter_buffer_write_prepare(jb,ts,&write_ts);
+ jb_result_t result;
+
+ if(marker) {
+ /* new talkspurt */
+ if(jb->write_ts <= jb->read_ts) {
+ /* buffer is empty => it's safe to restart */
+ mpf_jitter_buffer_restart(jb);
+ }
+ }
+
+ result = mpf_jitter_buffer_write_prepare(jb,ts,&write_ts);
if(result != JB_OK) {
return result;
}
diff --git a/libs/unimrcp/libs/mpf/src/mpf_mixer.c b/libs/unimrcp/libs/mpf/src/mpf_mixer.c
index 9d46990c30..3c36dd449d 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_mixer.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_mixer.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_mixer.c 1693 2010-05-16 18:33:07Z achaloyan $
*/
#include "mpf_mixer.h"
@@ -90,6 +92,7 @@ static apt_bool_t mpf_mixer_destroy(mpf_object_t *object)
mpf_audio_stream_t *source;
mpf_mixer_t *mixer = (mpf_mixer_t*) object;
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Destroy Mixer %s",object->name);
for(i=0; isource_count; i++) {
source = mixer->source_arr[i];
if(source) {
@@ -126,7 +129,9 @@ static void mpf_mixer_trace(mpf_object_t *object)
mpf_audio_stream_trace(mixer->sink,STREAM_DIRECTION_SEND,&output);
*output.pos = '\0';
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,output.text.buf);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Media Path %s %s",
+ object->name,
+ output.text.buf);
}
MPF_DECLARE(mpf_object_t*) mpf_mixer_create(
@@ -134,6 +139,7 @@ MPF_DECLARE(mpf_object_t*) mpf_mixer_create(
apr_size_t source_count,
mpf_audio_stream_t *sink,
const mpf_codec_manager_t *codec_manager,
+ const char *name,
apr_pool_t *pool)
{
apr_size_t i;
@@ -145,11 +151,12 @@ MPF_DECLARE(mpf_object_t*) mpf_mixer_create(
return NULL;
}
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Create Mixer %s",name);
mixer = apr_palloc(pool,sizeof(mpf_mixer_t));
mixer->source_arr = NULL;
mixer->source_count = 0;
mixer->sink = NULL;
- mpf_object_init(&mixer->base);
+ mpf_object_init(&mixer->base,name);
mixer->base.process = mpf_mixer_process;
mixer->base.destroy = mpf_mixer_destroy;
mixer->base.trace = mpf_mixer_trace;
diff --git a/libs/unimrcp/libs/mpf/src/mpf_multiplier.c b/libs/unimrcp/libs/mpf/src/mpf_multiplier.c
index 7ea9b88690..2014932841 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_multiplier.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_multiplier.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_multiplier.c 1693 2010-05-16 18:33:07Z achaloyan $
*/
#include "mpf_multiplier.h"
@@ -69,6 +71,7 @@ static apt_bool_t mpf_multiplier_destroy(mpf_object_t *object)
mpf_audio_stream_t *sink;
mpf_multiplier_t *multiplier = (mpf_multiplier_t*) object;
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Destroy Multiplier %s",object->name);
mpf_audio_stream_rx_close(multiplier->source);
for(i=0; isink_count; i++) {
sink = multiplier->sink_arr[i];
@@ -105,7 +108,9 @@ static void mpf_multiplier_trace(mpf_object_t *object)
}
*output.pos = '\0';
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,output.text.buf);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Media Path %s %s",
+ object->name,
+ output.text.buf);
}
MPF_DECLARE(mpf_object_t*) mpf_multiplier_create(
@@ -113,6 +118,7 @@ MPF_DECLARE(mpf_object_t*) mpf_multiplier_create(
mpf_audio_stream_t **sink_arr,
apr_size_t sink_count,
const mpf_codec_manager_t *codec_manager,
+ const char *name,
apr_pool_t *pool)
{
apr_size_t i;
@@ -124,11 +130,12 @@ MPF_DECLARE(mpf_object_t*) mpf_multiplier_create(
return NULL;
}
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Create Multiplier %s",name);
multiplier = apr_palloc(pool,sizeof(mpf_multiplier_t));
multiplier->source = NULL;
multiplier->sink_arr = NULL;
multiplier->sink_count = 0;
- mpf_object_init(&multiplier->base);
+ mpf_object_init(&multiplier->base,name);
multiplier->base.process = mpf_multiplier_process;
multiplier->base.destroy = mpf_multiplier_destroy;
multiplier->base.trace = mpf_multiplier_trace;
diff --git a/libs/unimrcp/libs/mpf/src/mpf_named_event.c b/libs/unimrcp/libs/mpf/src/mpf_named_event.c
index f8bc75363f..22c319dae4 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_named_event.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_named_event.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_named_event.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "mpf_named_event.h"
diff --git a/libs/unimrcp/libs/mpf/src/mpf_resampler.c b/libs/unimrcp/libs/mpf/src/mpf_resampler.c
index 113ffac8fb..fe4a45c9fc 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_resampler.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_resampler.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_resampler.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "mpf_resampler.h"
diff --git a/libs/unimrcp/libs/mpf/src/mpf_rtp_attribs.c b/libs/unimrcp/libs/mpf/src/mpf_rtp_attribs.c
index a34f05fc93..5e9e184f0f 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_rtp_attribs.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_rtp_attribs.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_rtp_attribs.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "apt_string_table.h"
diff --git a/libs/unimrcp/libs/mpf/src/mpf_rtp_stream.c b/libs/unimrcp/libs/mpf/src/mpf_rtp_stream.c
index 0e8ac028a9..f94b3295c2 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_rtp_stream.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_rtp_stream.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,14 +12,16 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_rtp_stream.c 1802 2011-05-13 02:43:12Z achaloyan $
*/
#include
#include "apt_net.h"
+#include "apt_timer_queue.h"
#include "mpf_rtp_stream.h"
#include "mpf_termination.h"
#include "mpf_codec_manager.h"
-#include "mpf_timer_manager.h"
#include "mpf_rtp_header.h"
#include "mpf_rtcp_packet.h"
#include "mpf_rtp_defs.h"
@@ -55,6 +57,7 @@ struct mpf_rtp_stream_t {
rtp_receiver_t receiver;
mpf_rtp_config_t *config;
+ mpf_rtp_settings_t *settings;
apr_socket_t *rtp_socket;
apr_socket_t *rtcp_socket;
@@ -63,8 +66,8 @@ struct mpf_rtp_stream_t {
apr_sockaddr_t *rtcp_l_sockaddr;
apr_sockaddr_t *rtcp_r_sockaddr;
- mpf_timer_t *rtcp_tx_timer;
- mpf_timer_t *rtcp_rx_timer;
+ apt_timer_t *rtcp_tx_timer;
+ apt_timer_t *rtcp_rx_timer;
apr_pool_t *pool;
};
@@ -92,11 +95,11 @@ static void mpf_rtp_socket_pair_close(mpf_rtp_stream_t *stream);
static apt_bool_t mpf_rtcp_report_send(mpf_rtp_stream_t *stream);
static apt_bool_t mpf_rtcp_bye_send(mpf_rtp_stream_t *stream, apt_str_t *reason);
-static void mpf_rtcp_tx_timer_proc(mpf_timer_t *timer, void *obj);
-static void mpf_rtcp_rx_timer_proc(mpf_timer_t *timer, void *obj);
+static void mpf_rtcp_tx_timer_proc(apt_timer_t *timer, void *obj);
+static void mpf_rtcp_rx_timer_proc(apt_timer_t *timer, void *obj);
-MPF_DECLARE(mpf_audio_stream_t*) mpf_rtp_stream_create(mpf_termination_t *termination, mpf_rtp_config_t *config, apr_pool_t *pool)
+MPF_DECLARE(mpf_audio_stream_t*) mpf_rtp_stream_create(mpf_termination_t *termination, mpf_rtp_config_t *config, mpf_rtp_settings_t *settings, apr_pool_t *pool)
{
mpf_rtp_stream_t *rtp_stream = apr_palloc(pool,sizeof(mpf_rtp_stream_t));
mpf_stream_capabilities_t *capabilities = mpf_stream_capabilities_create(STREAM_DIRECTION_DUPLEX,pool);
@@ -111,6 +114,7 @@ MPF_DECLARE(mpf_audio_stream_t*) mpf_rtp_stream_create(mpf_termination_t *termin
rtp_stream->base = audio_stream;
rtp_stream->pool = pool;
rtp_stream->config = config;
+ rtp_stream->settings = settings;
rtp_stream->local_media = NULL;
rtp_stream->remote_media = NULL;
rtp_stream->rtp_socket = NULL;
@@ -126,16 +130,16 @@ MPF_DECLARE(mpf_audio_stream_t*) mpf_rtp_stream_create(mpf_termination_t *termin
rtp_transmitter_init(&rtp_stream->transmitter);
rtp_stream->transmitter.sr_stat.ssrc = (apr_uint32_t)apr_time_now();
- if(config->rtcp == TRUE) {
- if(config->rtcp_tx_interval) {
- rtp_stream->rtcp_tx_timer = mpf_timer_create(
- termination->timer_manager,
+ if(settings->rtcp == TRUE) {
+ if(settings->rtcp_tx_interval) {
+ rtp_stream->rtcp_tx_timer = apt_timer_create(
+ termination->timer_queue,
mpf_rtcp_tx_timer_proc,
rtp_stream, pool);
}
- if(config->rtcp_rx_resolution) {
- rtp_stream->rtcp_rx_timer = mpf_timer_create(
- termination->timer_manager,
+ if(settings->rtcp_rx_resolution) {
+ rtp_stream->rtcp_rx_timer = apt_timer_create(
+ termination->timer_queue,
mpf_rtcp_rx_timer_proc,
rtp_stream, pool);
}
@@ -163,21 +167,25 @@ static apt_bool_t mpf_rtp_stream_local_media_create(mpf_rtp_stream_t *rtp_stream
}
if(local_media->port == 0) {
/* RTP port management */
- apr_port_t first_port_in_search = rtp_stream->config->rtp_port_cur;
+ mpf_rtp_config_t *rtp_config = rtp_stream->config;
+ apr_port_t first_port_in_search = rtp_config->rtp_port_cur;
apt_bool_t is_port_ok = FALSE;
do {
- local_media->port = rtp_stream->config->rtp_port_cur;
- rtp_stream->config->rtp_port_cur += 2;
- if(rtp_stream->config->rtp_port_cur == rtp_stream->config->rtp_port_max) {
- rtp_stream->config->rtp_port_cur = rtp_stream->config->rtp_port_min;
+ local_media->port = rtp_config->rtp_port_cur;
+ rtp_config->rtp_port_cur += 2;
+ if(rtp_config->rtp_port_cur == rtp_config->rtp_port_max) {
+ rtp_config->rtp_port_cur = rtp_config->rtp_port_min;
}
if(mpf_rtp_socket_pair_create(rtp_stream,local_media) == TRUE) {
is_port_ok = TRUE;
}
- } while((is_port_ok == FALSE) && (first_port_in_search != rtp_stream->config->rtp_port_cur));
+ } while((is_port_ok == FALSE) && (first_port_in_search != rtp_config->rtp_port_cur));
if(is_port_ok == FALSE) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Find Free RTP Port");
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Find Free RTP Port %s:[%hu,%hu]",
+ rtp_config->ip.buf,
+ rtp_config->rtp_port_min,
+ rtp_config->rtp_port_max);
local_media->state = MPF_MEDIA_DISABLED;
status = FALSE;
}
@@ -187,12 +195,12 @@ static apt_bool_t mpf_rtp_stream_local_media_create(mpf_rtp_stream_t *rtp_stream
status = FALSE;
}
- if(rtp_stream->config->ptime) {
- local_media->ptime = rtp_stream->config->ptime;
+ if(rtp_stream->settings->ptime) {
+ local_media->ptime = rtp_stream->settings->ptime;
}
if(mpf_codec_list_is_empty(&local_media->codec_list) == TRUE) {
- if(mpf_codec_list_is_empty(&rtp_stream->config->codec_list) == TRUE) {
+ if(mpf_codec_list_is_empty(&rtp_stream->settings->codec_list) == TRUE) {
mpf_codec_manager_codec_list_get(
rtp_stream->base->termination->codec_manager,
&local_media->codec_list,
@@ -200,7 +208,7 @@ static apt_bool_t mpf_rtp_stream_local_media_create(mpf_rtp_stream_t *rtp_stream
}
else {
mpf_codec_list_copy(&local_media->codec_list,
- &rtp_stream->config->codec_list,
+ &rtp_stream->settings->codec_list,
rtp_stream->pool);
}
@@ -297,10 +305,10 @@ static apt_bool_t mpf_rtp_stream_media_negotiate(mpf_rtp_stream_t *rtp_stream)
}
if(rtp_stream->rtcp_tx_timer) {
- mpf_timer_set(rtp_stream->rtcp_tx_timer,rtp_stream->config->rtcp_tx_interval);
+ apt_timer_set(rtp_stream->rtcp_tx_timer,rtp_stream->settings->rtcp_tx_interval);
}
if(rtp_stream->rtcp_rx_timer) {
- mpf_timer_set(rtp_stream->rtcp_rx_timer,rtp_stream->config->rtcp_rx_resolution);
+ apt_timer_set(rtp_stream->rtcp_rx_timer,rtp_stream->settings->rtcp_rx_resolution);
}
}
else if(rtp_stream->state == MPF_MEDIA_ENABLED && remote_media->state == MPF_MEDIA_DISABLED) {
@@ -313,12 +321,12 @@ static apt_bool_t mpf_rtp_stream_media_negotiate(mpf_rtp_stream_t *rtp_stream)
}
if(rtp_stream->rtcp_tx_timer) {
- mpf_timer_kill(rtp_stream->rtcp_tx_timer);
+ apt_timer_kill(rtp_stream->rtcp_tx_timer);
}
if(rtp_stream->rtcp_rx_timer) {
- mpf_timer_kill(rtp_stream->rtcp_rx_timer);
+ apt_timer_kill(rtp_stream->rtcp_rx_timer);
}
- if(rtp_stream->config->rtcp == TRUE && rtp_stream->config->rtcp_bye_policy != RTCP_BYE_DISABLE) {
+ if(rtp_stream->settings->rtcp == TRUE && rtp_stream->settings->rtcp_bye_policy != RTCP_BYE_DISABLE) {
apt_str_t reason = {RTCP_BYE_SESSION_ENDED, sizeof(RTCP_BYE_SESSION_ENDED)-1};
mpf_rtcp_bye_send(rtp_stream,&reason);
}
@@ -337,7 +345,7 @@ static apt_bool_t mpf_rtp_stream_media_negotiate(mpf_rtp_stream_t *rtp_stream)
}
/* intersect local and remote codecs */
- if(rtp_stream->config->own_preferrence == TRUE) {
+ if(rtp_stream->settings->own_preferrence == TRUE) {
mpf_codec_lists_intersect(
&local_media->codec_list,
&remote_media->codec_list);
@@ -371,12 +379,12 @@ MPF_DECLARE(apt_bool_t) mpf_rtp_stream_remove(mpf_audio_stream_t *stream)
}
if(rtp_stream->rtcp_tx_timer) {
- mpf_timer_kill(rtp_stream->rtcp_tx_timer);
+ apt_timer_kill(rtp_stream->rtcp_tx_timer);
}
if(rtp_stream->rtcp_rx_timer) {
- mpf_timer_kill(rtp_stream->rtcp_rx_timer);
+ apt_timer_kill(rtp_stream->rtcp_rx_timer);
}
- if(rtp_stream->config->rtcp == TRUE && rtp_stream->config->rtcp_bye_policy != RTCP_BYE_DISABLE) {
+ if(rtp_stream->settings->rtcp == TRUE && rtp_stream->settings->rtcp_bye_policy != RTCP_BYE_DISABLE) {
apt_str_t reason = {RTCP_BYE_SESSION_ENDED, sizeof(RTCP_BYE_SESSION_ENDED)-1};
mpf_rtcp_bye_send(rtp_stream,&reason);
}
@@ -451,7 +459,7 @@ static apt_bool_t mpf_rtp_rx_stream_open(mpf_audio_stream_t *stream, mpf_codec_t
}
receiver->jb = mpf_jitter_buffer_create(
- &rtp_stream->config->jb_config,
+ &rtp_stream->settings->jb_config,
stream->rx_descriptor,
codec,
rtp_stream->pool);
@@ -461,7 +469,7 @@ static apt_bool_t mpf_rtp_rx_stream_open(mpf_audio_stream_t *stream, mpf_codec_t
rtp_stream->rtp_l_sockaddr->port,
rtp_stream->rtp_r_sockaddr->hostname,
rtp_stream->rtp_r_sockaddr->port,
- rtp_stream->config->jb_config.initial_playout_delay);
+ rtp_stream->settings->jb_config.initial_playout_delay);
return TRUE;
}
@@ -484,14 +492,16 @@ static apt_bool_t mpf_rtp_rx_stream_close(mpf_audio_stream_t *stream)
}
mpf_jitter_buffer_destroy(receiver->jb);
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Close RTP Receiver %s:%hu <- %s:%hu [r:%lu l:%lu j:%lu]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Close RTP Receiver %s:%hu <- %s:%hu [r:%u l:%u j:%u d:%u i:%u]",
rtp_stream->rtp_l_sockaddr->hostname,
rtp_stream->rtp_l_sockaddr->port,
rtp_stream->rtp_r_sockaddr->hostname,
rtp_stream->rtp_r_sockaddr->port,
receiver->stat.received_packets,
receiver->stat.lost_packets,
- receiver->rr_stat.jitter);
+ receiver->rr_stat.jitter,
+ receiver->stat.discarded_packets,
+ receiver->stat.ignored_packets);
return TRUE;
}
@@ -557,8 +567,13 @@ static APR_INLINE void rtp_periodic_history_update(rtp_receiver_t *receiver)
apr_uint32_t lost_interval;
/* calculate expected packets */
- expected_packets = receiver->history.seq_cycles +
- receiver->history.seq_num_max - receiver->history.seq_num_base + 1;
+ if(receiver->stat.received_packets) {
+ expected_packets = receiver->history.seq_cycles +
+ receiver->history.seq_num_max - receiver->history.seq_num_base + 1;
+ }
+ else {
+ expected_packets = 0;
+ }
/* calculate expected interval */
expected_interval = expected_packets - receiver->periodic_history.expected_prior;
@@ -709,7 +724,7 @@ static APR_INLINE void rtp_rx_failure_threshold_check(rtp_receiver_t *receiver)
discarded = receiver->stat.discarded_packets - receiver->periodic_history.discarded_prior;
if(discarded * 100 > received * DISCARDED_TO_RECEIVED_RATIO_THRESHOLD) {
- /* failure threshold hired, restart */
+ /* failure threshold reached -> restart */
rtp_rx_restart(receiver);
}
}
@@ -733,7 +748,7 @@ static apt_bool_t rtp_rx_packet_receive(mpf_rtp_stream_t *rtp_stream, void *buff
time = apr_time_now();
- RTP_TRACE("RTP time=%6lu ssrc=%8lx pt=%3u %cts=%9lu seq=%5u size=%lu\n",
+ RTP_TRACE("RTP time=%6u ssrc=%8x pt=%3u %cts=%9u seq=%5u size=%"APR_SIZE_T_FMT"\n",
(apr_uint32_t)apr_time_usec(time),
header->ssrc, header->type, (header->marker == 1) ? '*' : ' ',
header->timestamp, header->sequence, size);
@@ -761,7 +776,7 @@ static apt_bool_t rtp_rx_packet_receive(mpf_rtp_stream_t *rtp_stream, void *buff
return FALSE;
}
- if(mpf_jitter_buffer_write(receiver->jb,buffer,size,header->timestamp) != JB_OK) {
+ if(mpf_jitter_buffer_write(receiver->jb,buffer,size,header->timestamp,(apr_byte_t)header->marker) != JB_OK) {
receiver->stat.discarded_packets++;
rtp_rx_failure_threshold_check(receiver);
}
@@ -825,8 +840,8 @@ static apt_bool_t mpf_rtp_tx_stream_open(mpf_audio_stream_t *stream, mpf_codec_t
}
if(!transmitter->ptime) {
- if(rtp_stream->config && rtp_stream->config->ptime) {
- transmitter->ptime = rtp_stream->config->ptime;
+ if(rtp_stream->settings && rtp_stream->settings->ptime) {
+ transmitter->ptime = rtp_stream->settings->ptime;
}
else {
transmitter->ptime = 20;
@@ -857,10 +872,10 @@ static apt_bool_t mpf_rtp_tx_stream_close(mpf_audio_stream_t *stream)
if(!rtp_stream->rtp_l_sockaddr || !rtp_stream->rtp_r_sockaddr) {
return FALSE;
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Close RTP Transmitter %s:%hu -> %s:%hu [s:%lu o:%lu]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Close RTP Transmitter %s:%hu -> %s:%hu [s:%u o:%u]",
rtp_stream->rtp_l_sockaddr->hostname,
rtp_stream->rtp_l_sockaddr->port,
- rtp_stream->rtp_l_sockaddr->hostname,
+ rtp_stream->rtp_r_sockaddr->hostname,
rtp_stream->rtp_r_sockaddr->port,
rtp_stream->transmitter.sr_stat.sent_packets,
rtp_stream->transmitter.sr_stat.sent_octets);
@@ -973,7 +988,7 @@ static apt_bool_t mpf_rtp_stream_transmit(mpf_audio_stream_t *stream, const mpf_
if(transmitter->current_frames == 0) {
/* set inactivity (ptime alligned) */
transmitter->inactivity = 1;
- if(rtp_stream->config->rtcp == TRUE && rtp_stream->config->rtcp_bye_policy == RTCP_BYE_PER_TALKSPURT) {
+ if(rtp_stream->settings->rtcp == TRUE && rtp_stream->settings->rtcp_bye_policy == RTCP_BYE_PER_TALKSPURT) {
apt_str_t reason = {RTCP_BYE_TALKSPURT_ENDED, sizeof(RTCP_BYE_TALKSPURT_ENDED)-1};
mpf_rtcp_bye_send(rtp_stream,&reason);
}
@@ -1089,7 +1104,7 @@ static APR_INLINE void rtcp_sr_generate(mpf_rtp_stream_t *rtp_stream, rtcp_sr_st
apt_ntp_time_get(&sr_stat->ntp_sec, &sr_stat->ntp_frac);
sr_stat->rtp_ts = rtp_stream->transmitter.timestamp;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Generate RTCP SR [ssrc:%lu s:%lu o:%lu ts:%lu]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Generate RTCP SR [ssrc:%u s:%u o:%u ts:%u]",
sr_stat->ssrc,
sr_stat->sent_packets,
sr_stat->sent_octets,
@@ -1102,7 +1117,7 @@ static APR_INLINE void rtcp_rr_generate(mpf_rtp_stream_t *rtp_stream, rtcp_rr_st
*rr_stat = rtp_stream->receiver.rr_stat;
rr_stat->last_seq = rtp_stream->receiver.history.seq_num_max;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Generate RTCP RR [ssrc:%lu last_seq:%lu j:%lu lost:%lu frac:%d]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Generate RTCP RR [ssrc:%u last_seq:%u j:%u lost:%u frac:%d]",
rr_stat->ssrc,
rr_stat->last_seq,
rr_stat->jitter,
@@ -1302,7 +1317,7 @@ static apt_bool_t mpf_rtcp_bye_send(mpf_rtp_stream_t *rtp_stream, apt_str_t *rea
static APR_INLINE void rtcp_sr_get(mpf_rtp_stream_t *rtp_stream, rtcp_sr_stat_t *sr_stat)
{
rtcp_sr_ntoh(sr_stat);
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Get RTCP SR [ssrc:%lu s:%lu o:%lu ts:%lu]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Get RTCP SR [ssrc:%u s:%u o:%u ts:%u]",
sr_stat->ssrc,
sr_stat->sent_packets,
sr_stat->sent_octets,
@@ -1312,7 +1327,7 @@ static APR_INLINE void rtcp_sr_get(mpf_rtp_stream_t *rtp_stream, rtcp_sr_stat_t
static APR_INLINE void rtcp_rr_get(mpf_rtp_stream_t *rtp_stream, rtcp_rr_stat_t *rr_stat)
{
rtcp_rr_ntoh(rr_stat);
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Get RTCP RR [ssrc:%lu last_seq:%lu j:%lu lost:%lu frac:%d]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Get RTCP RR [ssrc:%u last_seq:%u j:%u lost:%u frac:%d]",
rr_stat->ssrc,
rr_stat->last_seq,
rr_stat->jitter,
@@ -1366,7 +1381,7 @@ static apt_bool_t mpf_rtcp_compound_packet_receive(mpf_rtp_stream_t *rtp_stream,
return TRUE;
}
-static void mpf_rtcp_tx_timer_proc(mpf_timer_t *timer, void *obj)
+static void mpf_rtcp_tx_timer_proc(apt_timer_t *timer, void *obj)
{
mpf_rtp_stream_t *rtp_stream = obj;
@@ -1374,10 +1389,10 @@ static void mpf_rtcp_tx_timer_proc(mpf_timer_t *timer, void *obj)
mpf_rtcp_report_send(rtp_stream);
/* re-schedule timer */
- mpf_timer_set(timer,rtp_stream->config->rtcp_tx_interval);
+ apt_timer_set(timer,rtp_stream->settings->rtcp_tx_interval);
}
-static void mpf_rtcp_rx_timer_proc(mpf_timer_t *timer, void *obj)
+static void mpf_rtcp_rx_timer_proc(apt_timer_t *timer, void *obj)
{
mpf_rtp_stream_t *rtp_stream = obj;
if(rtp_stream->rtcp_socket && rtp_stream->rtcp_l_sockaddr && rtp_stream->rtcp_r_sockaddr) {
@@ -1396,5 +1411,5 @@ static void mpf_rtcp_rx_timer_proc(mpf_timer_t *timer, void *obj)
}
/* re-schedule timer */
- mpf_timer_set(timer,rtp_stream->config->rtcp_rx_resolution);
+ apt_timer_set(timer,rtp_stream->settings->rtcp_rx_resolution);
}
diff --git a/libs/unimrcp/libs/mpf/src/mpf_rtp_termination_factory.c b/libs/unimrcp/libs/mpf/src/mpf_rtp_termination_factory.c
index 0202e2e498..7b3cfa144f 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_rtp_termination_factory.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_rtp_termination_factory.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_rtp_termination_factory.c 1693 2010-05-16 18:33:07Z achaloyan $
*/
#include "mpf_termination.h"
@@ -37,7 +39,11 @@ static apt_bool_t mpf_rtp_termination_add(mpf_termination_t *termination, void *
mpf_audio_stream_t *audio_stream = termination->audio_stream;
if(!audio_stream) {
rtp_termination_factory_t *termination_factory = (rtp_termination_factory_t*)termination->termination_factory;
- audio_stream = mpf_rtp_stream_create(termination,termination_factory->config,termination->pool);
+ audio_stream = mpf_rtp_stream_create(
+ termination,
+ termination_factory->config,
+ rtp_descriptor->audio.settings,
+ termination->pool);
if(!audio_stream) {
return FALSE;
}
@@ -85,7 +91,11 @@ static const mpf_termination_vtable_t rtp_vtable = {
static mpf_termination_t* mpf_rtp_termination_create(mpf_termination_factory_t *termination_factory, void *obj, apr_pool_t *pool)
{
- return mpf_termination_base_create(termination_factory,obj,&rtp_vtable,NULL,NULL,pool);
+ mpf_termination_t *termination = mpf_termination_base_create(termination_factory,obj,&rtp_vtable,NULL,NULL,pool);
+ if(termination) {
+ termination->name = "rtp-tm";
+ }
+ return termination;
}
MPF_DECLARE(mpf_termination_factory_t*) mpf_rtp_termination_factory_create(
diff --git a/libs/unimrcp/libs/mpf/src/mpf_scheduler.c b/libs/unimrcp/libs/mpf/src/mpf_scheduler.c
index 24a4c8adf2..452799cbf9 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_scheduler.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_scheduler.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_scheduler.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "mpf_scheduler.h"
diff --git a/libs/unimrcp/libs/mpf/src/mpf_stream.c b/libs/unimrcp/libs/mpf/src/mpf_stream.c
index 1135e46e01..fa474c39c4 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_stream.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_stream.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_stream.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "mpf_stream.h"
diff --git a/libs/unimrcp/libs/mpf/src/mpf_termination.c b/libs/unimrcp/libs/mpf/src/mpf_termination.c
index 05eff5c419..e32589eed5 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_termination.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_termination.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_termination.c 1693 2010-05-16 18:33:07Z achaloyan $
*/
#include "mpf_termination.h"
@@ -28,11 +30,12 @@ MPF_DECLARE(mpf_termination_t*) mpf_termination_base_create(
{
mpf_termination_t *termination = apr_palloc(pool,sizeof(mpf_termination_t));
termination->pool = pool;
+ termination->name = "media-tm";
termination->obj = obj;
termination->event_handler_obj = NULL;
termination->event_handler = NULL;
termination->codec_manager = NULL;
- termination->timer_manager = NULL;
+ termination->timer_queue = NULL;
termination->termination_factory = termination_factory;
termination->vtable = vtable;
termination->slot = 0;
diff --git a/libs/unimrcp/libs/mpf/src/mpf_termination_factory.c b/libs/unimrcp/libs/mpf/src/mpf_termination_factory.c
index ba89f51064..1823fd826a 100644
--- a/libs/unimrcp/libs/mpf/src/mpf_termination_factory.c
+++ b/libs/unimrcp/libs/mpf/src/mpf_termination_factory.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mpf_termination_factory.c 1693 2010-05-16 18:33:07Z achaloyan $
*/
#include "mpf_termination_factory.h"
@@ -47,20 +49,26 @@ MPF_DECLARE(apt_bool_t) mpf_termination_destroy(mpf_termination_t *termination)
return TRUE;
}
+/** Get termination name */
+MPF_DECLARE(const char*) mpf_termination_name_get(const mpf_termination_t *termination)
+{
+ return termination->name;
+}
+
/** Get associated object. */
-MPF_DECLARE(void*) mpf_termination_object_get(mpf_termination_t *termination)
+MPF_DECLARE(void*) mpf_termination_object_get(const mpf_termination_t *termination)
{
return termination->obj;
}
/** Get audio stream. */
-MPF_DECLARE(mpf_audio_stream_t*) mpf_termination_audio_stream_get(mpf_termination_t *termination)
+MPF_DECLARE(mpf_audio_stream_t*) mpf_termination_audio_stream_get(const mpf_termination_t *termination)
{
return termination->audio_stream;
}
/** Get video stream. */
-MPF_DECLARE(mpf_video_stream_t*) mpf_termination_video_stream_get(mpf_termination_t *termination)
+MPF_DECLARE(mpf_video_stream_t*) mpf_termination_video_stream_get(const mpf_termination_t *termination)
{
return termination->video_stream;
}
diff --git a/libs/unimrcp/libs/mpf/src/mpf_timer_manager.c b/libs/unimrcp/libs/mpf/src/mpf_timer_manager.c
deleted file mode 100644
index a3c8735869..0000000000
--- a/libs/unimrcp/libs/mpf/src/mpf_timer_manager.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright 2008 Arsen Chaloyan
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifdef WIN32
-#pragma warning(disable: 4127)
-#endif
-#include
-#include "mpf_timer_manager.h"
-#include "mpf_scheduler.h"
-#include "apt_log.h"
-
-/** MPF timer manager */
-struct mpf_timer_manager_t {
- /** Ring head */
- APR_RING_HEAD(mpf_timer_head_t, mpf_timer_t) head;
-
- /** Clock resolution */
- apr_uint32_t resolution;
- /** Elapsed time */
- apr_uint32_t elapsed_time;
-};
-
-/** MPF timer */
-struct mpf_timer_t {
- /** Ring entry */
- APR_RING_ENTRY(mpf_timer_t) link;
-
- /** Back pointer to manager */
- mpf_timer_manager_t *manager;
- /** Time next report is scheduled at */
- apr_uint32_t scheduled_time;
-
- /** Timer proc */
- mpf_timer_proc_f proc;
- /** Timer object */
- void *obj;
-};
-
-static void mpf_scheduler_proc(mpf_scheduler_t *scheduler, void *obj);
-
-/** Create timer manager */
-MPF_DECLARE(mpf_timer_manager_t*) mpf_timer_manager_create(mpf_scheduler_t *scheduler, apr_pool_t *pool)
-{
- mpf_timer_manager_t *timer_manager = apr_palloc(pool,sizeof(mpf_timer_manager_t));
- APR_RING_INIT(&timer_manager->head, mpf_timer_t, link);
- timer_manager->elapsed_time = 0;
- timer_manager->resolution = 100; /* 100 ms */
-
- mpf_scheduler_timer_clock_set(scheduler,timer_manager->resolution,mpf_scheduler_proc,timer_manager);
- return timer_manager;
-}
-
-/** Destroy timer manager */
-MPF_DECLARE(void) mpf_timer_manager_destroy(mpf_timer_manager_t *timer_manager)
-{
-}
-
-
-/** Create timer */
-MPF_DECLARE(mpf_timer_t*) mpf_timer_create(mpf_timer_manager_t *timer_manager, mpf_timer_proc_f proc, void *obj, apr_pool_t *pool)
-{
- mpf_timer_t *timer = apr_palloc(pool,sizeof(mpf_timer_t));
- timer->manager = timer_manager;
- timer->scheduled_time = 0;
- timer->proc = proc;
- timer->obj = obj;
- return timer;
-}
-
-static APR_INLINE apt_bool_t mpf_timer_insert(mpf_timer_manager_t *manager, mpf_timer_t *timer)
-{
- mpf_timer_t *it;
- for(it = APR_RING_LAST(&manager->head);
- it != APR_RING_SENTINEL(&manager->head, mpf_timer_t, link);
- it = APR_RING_PREV(it, link)) {
-
- if(it->scheduled_time <= timer->scheduled_time) {
- APR_RING_INSERT_AFTER(it,timer,link);
- return TRUE;
- }
- }
- APR_RING_INSERT_HEAD(&manager->head,timer,mpf_timer_t,link);
- return TRUE;
-}
-
-/** Set one-shot timer */
-MPF_DECLARE(apt_bool_t) mpf_timer_set(mpf_timer_t *timer, apr_uint32_t timeout)
-
-{
- mpf_timer_manager_t *manager = timer->manager;
-
- if(timeout <= 0 || !timer->proc) {
- return FALSE;
- }
-
- /* calculate time to elapse */
- timer->scheduled_time = manager->elapsed_time + timeout;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Set Timer 0x%x [%lu]",timer,timer->scheduled_time);
-
- if(APR_RING_EMPTY(&timer->manager->head, mpf_timer_t, link)) {
- APR_RING_INSERT_TAIL(&manager->head,timer,mpf_timer_t,link);
- return TRUE;
- }
-
- /* insert new node (timer) to sorted by scheduled time list */
- return mpf_timer_insert(manager,timer);
-}
-
-/** Kill timer */
-MPF_DECLARE(apt_bool_t) mpf_timer_kill(mpf_timer_t *timer)
-{
- if(!timer->scheduled_time) {
- return FALSE;
- }
-
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Kill Timer 0x%x [%lu]",timer,timer->scheduled_time);
- /* remove node (timer) from the list */
- APR_RING_REMOVE(timer,link);
- timer->scheduled_time = 0;
-
- if(APR_RING_EMPTY(&timer->manager->head, mpf_timer_t, link)) {
- /* reset elapsed time if no timers set */
- timer->manager->elapsed_time = 0;
- }
- return TRUE;
-}
-
-static void mpf_timers_reschedule(mpf_timer_manager_t *manager)
-{
- mpf_timer_t *it;
- for(it = APR_RING_LAST(&manager->head);
- it != APR_RING_SENTINEL(&manager->head, mpf_timer_t, link);
- it = APR_RING_PREV(it, link)) {
-
- it->scheduled_time -= manager->elapsed_time;
- }
- manager->elapsed_time = 0;
-}
-
-static void mpf_scheduler_proc(mpf_scheduler_t *scheduler, void *obj)
-{
- mpf_timer_manager_t *manager = obj;
- mpf_timer_t *timer;
-
- if(APR_RING_EMPTY(&manager->head, mpf_timer_t, link)) {
- /* just return, nothing to do */
- return;
- }
-
- /* increment elapsed time */
- manager->elapsed_time += manager->resolution;
- if(manager->elapsed_time >= 0xFFFF) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Reschedule Timers [%lu]",manager->elapsed_time);
- mpf_timers_reschedule(manager);
- }
-
- /* process timers */
- do {
- /* get first node (timer) */
- timer = APR_RING_FIRST(&manager->head);
-
- if(timer->scheduled_time > manager->elapsed_time) {
- /* scheduled time is not elapsed yet */
- break;
- }
-
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Timer Elapsed 0x%x [%lu]",timer,timer->scheduled_time);
- /* remove the elapsed timer from the list */
- APR_RING_REMOVE(timer, link);
- timer->scheduled_time = 0;
- /* process the elapsed timer */
- timer->proc(timer,timer->obj);
- }
- while(!APR_RING_EMPTY(&manager->head, mpf_timer_t, link));
-}
diff --git a/libs/unimrcp/libs/mrcp-client/Makefile.am b/libs/unimrcp/libs/mrcp-client/Makefile.am
index ec749369be..f2d306fb96 100644
--- a/libs/unimrcp/libs/mrcp-client/Makefile.am
+++ b/libs/unimrcp/libs/mrcp-client/Makefile.am
@@ -19,4 +19,5 @@ include_HEADERS = include/mrcp_client_types.h \
include/mrcp_application.h
libmrcpclient_la_SOURCES = src/mrcp_client.c \
- src/mrcp_client_session.c
+ src/mrcp_client_session.c \
+ src/mrcp_application.c
diff --git a/libs/unimrcp/libs/mrcp-client/include/mrcp_application.h b/libs/unimrcp/libs/mrcp-client/include/mrcp_application.h
index 629c445526..66b097b962 100644
--- a/libs/unimrcp/libs/mrcp-client/include/mrcp_application.h
+++ b/libs/unimrcp/libs/mrcp-client/include/mrcp_application.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_application.h 1779 2010-09-01 05:54:34Z achaloyan $
*/
-#ifndef __MRCP_APPLICATION_H__
-#define __MRCP_APPLICATION_H__
+#ifndef MRCP_APPLICATION_H
+#define MRCP_APPLICATION_H
/**
* @file mrcp_application.h
@@ -152,13 +154,13 @@ MRCP_DECLARE(apt_bool_t) mrcp_application_destroy(mrcp_application_t *applicatio
* Get external object associated with the application.
* @param application the application to get object from
*/
-MRCP_DECLARE(void*) mrcp_application_object_get(mrcp_application_t *application);
+MRCP_DECLARE(void*) mrcp_application_object_get(const mrcp_application_t *application);
/**
* Get dir layout structure.
* @param application the application to get dir layout from
*/
-MRCP_DECLARE(const apt_dir_layout_t*) mrcp_application_dir_layout_get(mrcp_application_t *application);
+MRCP_DECLARE(const apt_dir_layout_t*) mrcp_application_dir_layout_get(const mrcp_application_t *application);
/**
* Create session.
@@ -173,19 +175,19 @@ MRCP_DECLARE(mrcp_session_t*) mrcp_application_session_create(mrcp_application_t
* Get memory pool the session object is created out of.
* @param session the session to get pool from
*/
-MRCP_DECLARE(apr_pool_t*) mrcp_application_session_pool_get(mrcp_session_t *session);
+MRCP_DECLARE(apr_pool_t*) mrcp_application_session_pool_get(const mrcp_session_t *session);
/**
* Get session identifier.
* @param session the session to get identifier of
*/
-MRCP_DECLARE(const apt_str_t*) mrcp_application_session_id_get(mrcp_session_t *session);
+MRCP_DECLARE(const apt_str_t*) mrcp_application_session_id_get(const mrcp_session_t *session);
/**
* Get external object associated with the session.
* @param session the session to get object from
*/
-MRCP_DECLARE(void*) mrcp_application_session_object_get(mrcp_session_t *session);
+MRCP_DECLARE(void*) mrcp_application_session_object_get(const mrcp_session_t *session);
/**
* Set (associate) external object to the session.
@@ -194,6 +196,13 @@ MRCP_DECLARE(void*) mrcp_application_session_object_get(mrcp_session_t *session)
*/
MRCP_DECLARE(void) mrcp_application_session_object_set(mrcp_session_t *session, void *obj);
+/**
+ * Set name of the session (informative only used for debugging).
+ * @param session the session to set name for
+ * @param name the name to set
+ */
+MRCP_DECLARE(void) mrcp_application_session_name_set(mrcp_session_t *session, const char *name);
+
/**
* Send session update request.
* @param session the session to update
@@ -232,25 +241,31 @@ MRCP_DECLARE(mrcp_channel_t*) mrcp_application_channel_create(
* Get external object associated with the channel.
* @param channel the channel to get object from
*/
-MRCP_DECLARE(void*) mrcp_application_channel_object_get(mrcp_channel_t *channel);
+MRCP_DECLARE(void*) mrcp_application_channel_object_get(const mrcp_channel_t *channel);
/**
* Get RTP termination descriptor.
* @param channel the channel to get descriptor from
*/
-MRCP_DECLARE(mpf_rtp_termination_descriptor_t*) mrcp_application_rtp_descriptor_get(mrcp_channel_t *channel);
+MRCP_DECLARE(mpf_rtp_termination_descriptor_t*) mrcp_application_rtp_descriptor_get(const mrcp_channel_t *channel);
/**
* Get codec descriptor of source stream.
* @param channel the channel to get descriptor from
*/
-MRCP_DECLARE(const mpf_codec_descriptor_t*) mrcp_application_source_descriptor_get(mrcp_channel_t *channel);
+MRCP_DECLARE(const mpf_codec_descriptor_t*) mrcp_application_source_descriptor_get(const mrcp_channel_t *channel);
/**
* Get codec descriptor of sink stream.
* @param channel the channel to get descriptor from
*/
-MRCP_DECLARE(const mpf_codec_descriptor_t*) mrcp_application_sink_descriptor_get(mrcp_channel_t *channel);
+MRCP_DECLARE(const mpf_codec_descriptor_t*) mrcp_application_sink_descriptor_get(const mrcp_channel_t *channel);
+
+/**
+ * Get associated audio stream.
+ * @param channel the channel to get associated stream from
+ */
+MRCP_DECLARE(const mpf_audio_stream_t*) mrcp_application_audio_stream_get(const mrcp_channel_t *channel);
/**
* Send channel add request.
@@ -336,4 +351,4 @@ MRCP_DECLARE(mpf_termination_t*) mrcp_application_sink_termination_create(
APT_END_EXTERN_C
-#endif /*__MRCP_APPLICATION_H__*/
+#endif /* MRCP_APPLICATION_H */
diff --git a/libs/unimrcp/libs/mrcp-client/include/mrcp_client.h b/libs/unimrcp/libs/mrcp-client/include/mrcp_client.h
index c62f0e8baf..9ddd5643bf 100644
--- a/libs/unimrcp/libs/mrcp-client/include/mrcp_client.h
+++ b/libs/unimrcp/libs/mrcp-client/include/mrcp_client.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_client.h 1733 2010-06-07 17:26:49Z achaloyan $
*/
-#ifndef __MRCP_CLIENT_H__
-#define __MRCP_CLIENT_H__
+#ifndef MRCP_CLIENT_H
+#define MRCP_CLIENT_H
/**
* @file mrcp_client.h
@@ -23,6 +25,7 @@
*/
#include "mrcp_client_types.h"
+#include "mpf_rtp_descriptor.h"
#include "apt_task.h"
APT_BEGIN_EXTERN_C
@@ -82,15 +85,14 @@ MRCP_DECLARE(apt_bool_t) mrcp_client_codec_manager_register(mrcp_client_t *clien
* Get registered codec manager.
* @param client the MRCP client to get codec manager from
*/
-MRCP_DECLARE(const mpf_codec_manager_t*) mrcp_client_codec_manager_get(mrcp_client_t *client);
+MRCP_DECLARE(const mpf_codec_manager_t*) mrcp_client_codec_manager_get(const mrcp_client_t *client);
/**
* Register media engine.
* @param client the MRCP client to set media engine for
* @param media_engine the media engine to set
- * @param name the name of the media engine
*/
-MRCP_DECLARE(apt_bool_t) mrcp_client_media_engine_register(mrcp_client_t *client, mpf_engine_t *media_engine, const char *name);
+MRCP_DECLARE(apt_bool_t) mrcp_client_media_engine_register(mrcp_client_t *client, mpf_engine_t *media_engine);
/**
* Register RTP termination factory.
@@ -100,21 +102,35 @@ MRCP_DECLARE(apt_bool_t) mrcp_client_media_engine_register(mrcp_client_t *client
*/
MRCP_DECLARE(apt_bool_t) mrcp_client_rtp_factory_register(mrcp_client_t *client, mpf_termination_factory_t *rtp_termination_factory, const char *name);
+/**
+ * Register RTP settings.
+ * @param client the MRCP client to set RTP settings for
+ * @param rtp_settings the settings to set
+ * @param name the name of the settings
+ */
+MRCP_DECLARE(apt_bool_t) mrcp_client_rtp_settings_register(mrcp_client_t *client, mpf_rtp_settings_t *rtp_settings, const char *name);
+
/**
* Register MRCP signaling agent.
* @param client the MRCP client to set signaling agent for
* @param signaling_agent the signaling agent to set
+ */
+MRCP_DECLARE(apt_bool_t) mrcp_client_signaling_agent_register(mrcp_client_t *client, mrcp_sig_agent_t *signaling_agent);
+
+/**
+ * Register MRCP signaling settings.
+ * @param client the MRCP client to set signaling settings for
+ * @param signaling_settings the signaling settings to set
* @param name the name of the agent
*/
-MRCP_DECLARE(apt_bool_t) mrcp_client_signaling_agent_register(mrcp_client_t *client, mrcp_sig_agent_t *signaling_agent, const char *name);
+MRCP_DECLARE(apt_bool_t) mrcp_client_signaling_settings_register(mrcp_client_t *client, mrcp_sig_settings_t *signaling_settings, const char *name);
/**
* Register MRCP connection agent (MRCPv2 only).
* @param client the MRCP client to set connection agent for
* @param connection_agent the connection agent to set
- * @param name the name of the agent
*/
-MRCP_DECLARE(apt_bool_t) mrcp_client_connection_agent_register(mrcp_client_t *client, mrcp_connection_agent_t *connection_agent, const char *name);
+MRCP_DECLARE(apt_bool_t) mrcp_client_connection_agent_register(mrcp_client_t *client, mrcp_connection_agent_t *connection_agent);
/** Create MRCP profile */
MRCP_DECLARE(mrcp_profile_t*) mrcp_client_profile_create(
@@ -123,6 +139,8 @@ MRCP_DECLARE(mrcp_profile_t*) mrcp_client_profile_create(
mrcp_connection_agent_t *connection_agent,
mpf_engine_t *media_engine,
mpf_termination_factory_t *rtp_factory,
+ mpf_rtp_settings_t *rtp_settings,
+ mrcp_sig_settings_t *signaling_settings,
apr_pool_t *pool);
/**
@@ -145,43 +163,63 @@ MRCP_DECLARE(apt_bool_t) mrcp_client_application_register(mrcp_client_t *client,
* Get memory pool.
* @param client the MRCP client to get memory pool from
*/
-MRCP_DECLARE(apr_pool_t*) mrcp_client_memory_pool_get(mrcp_client_t *client);
+MRCP_DECLARE(apr_pool_t*) mrcp_client_memory_pool_get(const mrcp_client_t *client);
/**
* Get media engine by name.
* @param client the MRCP client to get media engine from
* @param name the name of the media engine to lookup
*/
-MRCP_DECLARE(mpf_engine_t*) mrcp_client_media_engine_get(mrcp_client_t *client, const char *name);
+MRCP_DECLARE(mpf_engine_t*) mrcp_client_media_engine_get(const mrcp_client_t *client, const char *name);
/**
* Get RTP termination factory by name.
* @param client the MRCP client to get from
* @param name the name to lookup
*/
-MRCP_DECLARE(mpf_termination_factory_t*) mrcp_client_rtp_factory_get(mrcp_client_t *client, const char *name);
+MRCP_DECLARE(mpf_termination_factory_t*) mrcp_client_rtp_factory_get(const mrcp_client_t *client, const char *name);
+
+/**
+ * Get RTP settings by name
+ * @param client the MRCP client to get from
+ * @param name the name to lookup
+ */
+MRCP_DECLARE(mpf_rtp_settings_t*) mrcp_client_rtp_settings_get(const mrcp_client_t *client, const char *name);
/**
* Get signaling agent by name.
* @param client the MRCP client to get from
* @param name the name to lookup
*/
-MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_client_signaling_agent_get(mrcp_client_t *client, const char *name);
+MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_client_signaling_agent_get(const mrcp_client_t *client, const char *name);
+
+/**
+ * Get signaling settings by name.
+ * @param client the MRCP client to get from
+ * @param name the name to lookup
+ */
+MRCP_DECLARE(mrcp_sig_settings_t*) mrcp_client_signaling_settings_get(const mrcp_client_t *client, const char *name);
/**
* Get connection agent by name.
* @param client the MRCP client to get from
* @param name the name to lookup
*/
-MRCP_DECLARE(mrcp_connection_agent_t*) mrcp_client_connection_agent_get(mrcp_client_t *client, const char *name);
+MRCP_DECLARE(mrcp_connection_agent_t*) mrcp_client_connection_agent_get(const mrcp_client_t *client, const char *name);
/**
* Get profile by name.
* @param client the MRCP client to get from
* @param name the name to lookup
*/
-MRCP_DECLARE(mrcp_profile_t*) mrcp_client_profile_get(mrcp_client_t *client, const char *name);
+MRCP_DECLARE(mrcp_profile_t*) mrcp_client_profile_get(const mrcp_client_t *client, const char *name);
+
+/**
+ * Get directory layout.
+ * @param client the MRCP client to get from
+ */
+MRCP_DECLARE(apt_dir_layout_t*) mrcp_client_dir_layout_get(const mrcp_client_t *client);
APT_END_EXTERN_C
-#endif /*__MRCP_CLIENT_H__*/
+#endif /* MRCP_CLIENT_H */
diff --git a/libs/unimrcp/libs/mrcp-client/include/mrcp_client_session.h b/libs/unimrcp/libs/mrcp-client/include/mrcp_client_session.h
index 40a444a825..8944e122a9 100644
--- a/libs/unimrcp/libs/mrcp-client/include/mrcp_client_session.h
+++ b/libs/unimrcp/libs/mrcp-client/include/mrcp_client_session.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_client_session.h 1733 2010-06-07 17:26:49Z achaloyan $
*/
-#ifndef __MRCP_CLIENT_SESSION_H__
-#define __MRCP_CLIENT_SESSION_H__
+#ifndef MRCP_CLIENT_SESSION_H
+#define MRCP_CLIENT_SESSION_H
/**
* @file mrcp_client_session.h
@@ -142,6 +144,11 @@ struct mrcp_profile_t {
mrcp_sig_agent_t *signaling_agent;
/** Connection agent */
mrcp_connection_agent_t *connection_agent;
+
+ /** Signaling settings */
+ mrcp_sig_settings_t *signaling_settings;
+ /** RTP settings */
+ mpf_rtp_settings_t *rtp_settings;
};
/** MRCP application */
@@ -156,14 +163,12 @@ struct mrcp_application_t {
apt_task_msg_pool_t *msg_pool;
};
-/** Create client session */
-mrcp_client_session_t* mrcp_client_session_create(mrcp_application_t *application, void *obj);
/** Create channel */
mrcp_channel_t* mrcp_client_channel_create(
- mrcp_session_t *session,
- mrcp_resource_t *resource,
- mpf_termination_t *termination,
- mpf_rtp_termination_descriptor_t *rtp_descriptor,
+ mrcp_client_session_t *session,
+ mrcp_resource_t *resource,
+ mpf_termination_t *termination,
+ mpf_rtp_termination_descriptor_t *rtp_descriptor,
void *obj);
/** Create signaling app_message_t request */
@@ -202,4 +207,4 @@ apt_bool_t mrcp_client_on_disconnect(mrcp_channel_t *channel);
APT_END_EXTERN_C
-#endif /*__MRCP_CLIENT_SESSION_H__*/
+#endif /* MRCP_CLIENT_SESSION_H */
diff --git a/libs/unimrcp/libs/mrcp-client/include/mrcp_client_types.h b/libs/unimrcp/libs/mrcp-client/include/mrcp_client_types.h
index 4da19f0081..4e3b783f06 100644
--- a/libs/unimrcp/libs/mrcp-client/include/mrcp_client_types.h
+++ b/libs/unimrcp/libs/mrcp-client/include/mrcp_client_types.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_client_types.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_CLIENT_TYPES_H__
-#define __MRCP_CLIENT_TYPES_H__
+#ifndef MRCP_CLIENT_TYPES_H
+#define MRCP_CLIENT_TYPES_H
/**
* @file mrcp_client_types.h
@@ -43,4 +45,4 @@ typedef struct mrcp_channel_t mrcp_channel_t;
APT_END_EXTERN_C
-#endif /*__MRCP_CLIENT_TYPES_H__*/
+#endif /* MRCP_CLIENT_TYPES_H */
diff --git a/libs/unimrcp/libs/mrcp-client/mrcpclient.2008.vcproj b/libs/unimrcp/libs/mrcp-client/mrcpclient.2008.vcproj
deleted file mode 100644
index ee8c9b4375..0000000000
--- a/libs/unimrcp/libs/mrcp-client/mrcpclient.2008.vcproj
+++ /dev/null
@@ -1,289 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/libs/mrcp-client/mrcpclient.2010.vcxproj b/libs/unimrcp/libs/mrcp-client/mrcpclient.2010.vcxproj
deleted file mode 100644
index 1c861d58b5..0000000000
--- a/libs/unimrcp/libs/mrcp-client/mrcpclient.2010.vcxproj
+++ /dev/null
@@ -1,121 +0,0 @@
-
-
-
-
- Debug
- Win32
-
-
- Debug
- x64
-
-
- Release
- Win32
-
-
- Release
- x64
-
-
-
- mrcpclient
- {72782932-37CC-46AE-8C7F-9A7B1A6EE108}
- mrcpclient
- Win32Proj
-
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
-
-
-
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;%(PreprocessorDefinitions)
- ProgramDatabase
-
-
-
-
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/libs/mrcp-client/mrcpclient.2010.vcxproj.filters b/libs/unimrcp/libs/mrcp-client/mrcpclient.2010.vcxproj.filters
deleted file mode 100644
index 4054110771..0000000000
--- a/libs/unimrcp/libs/mrcp-client/mrcpclient.2010.vcxproj.filters
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hpp;hxx;hm;inl;inc;xsd
-
-
- {890ddc88-1a65-4b89-996c-625f8ef76b90}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
-
-
- src
-
-
- src
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/libs/mrcp-client/mrcpclient.vcproj b/libs/unimrcp/libs/mrcp-client/mrcpclient.vcproj
index 1b156212e2..046c3e4695 100644
--- a/libs/unimrcp/libs/mrcp-client/mrcpclient.vcproj
+++ b/libs/unimrcp/libs/mrcp-client/mrcpclient.vcproj
@@ -261,6 +261,10 @@
Name="src"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
>
+
+
diff --git a/libs/unimrcp/libs/mrcp-client/src/mrcp_application.c b/libs/unimrcp/libs/mrcp-client/src/mrcp_application.c
new file mode 100644
index 0000000000..f3b73af544
--- /dev/null
+++ b/libs/unimrcp/libs/mrcp-client/src/mrcp_application.c
@@ -0,0 +1,538 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: mrcp_application.c 1792 2011-01-10 21:08:52Z achaloyan $
+ */
+
+#include "mrcp_application.h"
+#include "mrcp_client.h"
+#include "mrcp_client_session.h"
+#include "mrcp_message.h"
+#include "mrcp_sig_agent.h"
+#include "mrcp_resource_factory.h"
+#include "mpf_termination_factory.h"
+#include "apt_dir_layout.h"
+#include "apt_log.h"
+
+mrcp_client_session_t* mrcp_client_session_create(mrcp_client_t *client);
+
+apt_bool_t mrcp_app_signaling_task_msg_signal(mrcp_sig_command_e command_id, mrcp_session_t *session, mrcp_channel_t *channel);
+apt_bool_t mrcp_app_control_task_msg_signal(mrcp_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message);
+
+
+/** Create application instance */
+MRCP_DECLARE(mrcp_application_t*) mrcp_application_create(const mrcp_app_message_handler_f handler, void *obj, apr_pool_t *pool)
+{
+ mrcp_application_t *application;
+ if(!handler) {
+ return FALSE;
+ }
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create Application");
+ application = apr_palloc(pool,sizeof(mrcp_application_t));
+ application->obj = obj;
+ application->handler = handler;
+ application->client = NULL;
+ return application;
+}
+
+/** Destroy application instance */
+MRCP_DECLARE(apt_bool_t) mrcp_application_destroy(mrcp_application_t *application)
+{
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Destroy Application");
+ return TRUE;
+}
+
+/** Get external object associated with the application */
+MRCP_DECLARE(void*) mrcp_application_object_get(const mrcp_application_t *application)
+{
+ return application->obj;
+}
+
+/** Get dir layout structure */
+MRCP_DECLARE(const apt_dir_layout_t*) mrcp_application_dir_layout_get(const mrcp_application_t *application)
+{
+ return mrcp_client_dir_layout_get(application->client);
+}
+
+
+
+/** Create client session */
+MRCP_DECLARE(mrcp_session_t*) mrcp_application_session_create(mrcp_application_t *application, const char *profile_name, void *obj)
+{
+ mrcp_profile_t *profile;
+ mrcp_client_session_t *session;
+ if(!application || !application->client || !profile_name) {
+ return NULL;
+ }
+
+ profile = mrcp_client_profile_get(application->client,profile_name);
+ if(!profile) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No Such Profile [%s]",profile_name);
+ return NULL;
+ }
+
+ session = mrcp_client_session_create(application->client);
+ if(!session) {
+ return NULL;
+ }
+ session->application = application;
+ session->app_obj = obj;
+ session->base.log_obj = obj;
+ session->profile = profile;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create MRCP Handle "APT_PTR_FMT" [%s]",
+ MRCP_SESSION_PTR(session),
+ profile_name);
+ return &session->base;
+}
+
+/** Get memory pool the session object is created out of */
+MRCP_DECLARE(apr_pool_t*) mrcp_application_session_pool_get(const mrcp_session_t *session)
+{
+ if(!session) {
+ return NULL;
+ }
+ return session->pool;
+}
+
+/** Get session identifier */
+MRCP_DECLARE(const apt_str_t*) mrcp_application_session_id_get(const mrcp_session_t *session)
+{
+ if(!session) {
+ return NULL;
+ }
+ return &session->id;
+}
+
+/** Get external object associated with the session */
+MRCP_DECLARE(void*) mrcp_application_session_object_get(const mrcp_session_t *session)
+{
+ mrcp_client_session_t *client_session = (mrcp_client_session_t*)session;
+ if(!client_session) {
+ return NULL;
+ }
+ return client_session->app_obj;
+}
+
+/** Set (associate) external object to the session */
+MRCP_DECLARE(void) mrcp_application_session_object_set(mrcp_session_t *session, void *obj)
+{
+ mrcp_client_session_t *client_session = (mrcp_client_session_t*)session;
+ if(client_session) {
+ client_session->app_obj = obj;
+ }
+}
+
+/** Set name of the session (informative only used for debugging) */
+MRCP_DECLARE(void) mrcp_application_session_name_set(mrcp_session_t *session, const char *name)
+{
+ if(session && name) {
+ session->name = apr_pstrdup(session->pool,name);
+ }
+}
+
+
+/** Send session update request */
+MRCP_DECLARE(apt_bool_t) mrcp_application_session_update(mrcp_session_t *session)
+{
+ if(!session) {
+ return FALSE;
+ }
+ return mrcp_app_signaling_task_msg_signal(MRCP_SIG_COMMAND_SESSION_UPDATE,session,NULL);
+}
+
+/** Send session termination request */
+MRCP_DECLARE(apt_bool_t) mrcp_application_session_terminate(mrcp_session_t *session)
+{
+ if(!session) {
+ return FALSE;
+ }
+ return mrcp_app_signaling_task_msg_signal(MRCP_SIG_COMMAND_SESSION_TERMINATE,session,NULL);
+}
+
+/** Destroy client session (session must be terminated prior to destroy) */
+MRCP_DECLARE(apt_bool_t) mrcp_application_session_destroy(mrcp_session_t *session)
+{
+ if(!session) {
+ return FALSE;
+ }
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Destroy MRCP Handle %s",session->name);
+ mrcp_session_destroy(session);
+ return TRUE;
+}
+
+
+/** Create control channel */
+MRCP_DECLARE(mrcp_channel_t*) mrcp_application_channel_create(
+ mrcp_session_t *session,
+ mrcp_resource_id resource_id,
+ mpf_termination_t *termination,
+ mpf_rtp_termination_descriptor_t *rtp_descriptor,
+ void *obj)
+{
+ mrcp_resource_t *resource;
+ mrcp_profile_t *profile;
+ mrcp_client_session_t *client_session = (mrcp_client_session_t*)session;
+ if(!client_session || !client_session->profile) {
+ /* Invalid params */
+ return FALSE;
+ }
+ profile = client_session->profile;
+
+ if(!profile->resource_factory) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Channel: invalid profile");
+ return FALSE;
+ }
+ resource = mrcp_resource_get(profile->resource_factory,resource_id);
+ if(!resource) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Channel: no such resource");
+ return FALSE;
+ }
+
+ if(termination) {
+ /* Media engine and RTP factory must be specified in this case */
+ if(!profile->media_engine || !profile->rtp_termination_factory) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Channel: invalid profile");
+ return FALSE;
+ }
+ }
+ else {
+ /* Either termination or rtp_descriptor must be specified */
+ if(!rtp_descriptor) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Channel: missing both termination and RTP descriptor");
+ return FALSE;
+ }
+ }
+
+ return mrcp_client_channel_create(client_session,resource,termination,rtp_descriptor,obj);
+}
+
+/** Get external object associated with the channel */
+MRCP_DECLARE(void*) mrcp_application_channel_object_get(const mrcp_channel_t *channel)
+{
+ if(!channel) {
+ return FALSE;
+ }
+ return channel->obj;
+}
+
+/** Get RTP termination descriptor */
+MRCP_DECLARE(mpf_rtp_termination_descriptor_t*) mrcp_application_rtp_descriptor_get(const mrcp_channel_t *channel)
+{
+ if(!channel || !channel->rtp_termination_slot) {
+ return NULL;
+ }
+ return channel->rtp_termination_slot->descriptor;
+}
+
+/** Get codec descriptor of source stream */
+MRCP_DECLARE(const mpf_codec_descriptor_t*) mrcp_application_source_descriptor_get(const mrcp_channel_t *channel)
+{
+ mpf_audio_stream_t *audio_stream;
+ if(!channel || !channel->termination) {
+ return NULL;
+ }
+ audio_stream = mpf_termination_audio_stream_get(channel->termination);
+ if(!audio_stream) {
+ return NULL;
+ }
+ return audio_stream->rx_descriptor;
+}
+
+/** Get codec descriptor of sink stream */
+MRCP_DECLARE(const mpf_codec_descriptor_t*) mrcp_application_sink_descriptor_get(const mrcp_channel_t *channel)
+{
+ mpf_audio_stream_t *audio_stream;
+ if(!channel || !channel->termination) {
+ return NULL;
+ }
+ audio_stream = mpf_termination_audio_stream_get(channel->termination);
+ if(!audio_stream) {
+ return NULL;
+ }
+ return audio_stream->tx_descriptor;
+}
+
+/** Get associated audio stream */
+MRCP_DECLARE(const mpf_audio_stream_t*) mrcp_application_audio_stream_get(const mrcp_channel_t *channel)
+{
+ if(!channel || !channel->termination) {
+ return NULL;
+ }
+
+ return mpf_termination_audio_stream_get(channel->termination);
+}
+
+/** Send channel add request */
+MRCP_DECLARE(apt_bool_t) mrcp_application_channel_add(mrcp_session_t *session, mrcp_channel_t *channel)
+{
+ if(!session || !channel) {
+ return FALSE;
+ }
+ return mrcp_app_signaling_task_msg_signal(MRCP_SIG_COMMAND_CHANNEL_ADD,session,channel);
+}
+
+/** Send channel removal request */
+MRCP_DECLARE(apt_bool_t) mrcp_application_channel_remove(mrcp_session_t *session, mrcp_channel_t *channel)
+{
+ if(!session || !channel) {
+ return FALSE;
+ }
+ return mrcp_app_signaling_task_msg_signal(MRCP_SIG_COMMAND_CHANNEL_REMOVE,session,channel);
+}
+
+/** Send resource discovery request */
+MRCP_DECLARE(apt_bool_t) mrcp_application_resource_discover(mrcp_session_t *session)
+{
+ if(!session) {
+ return FALSE;
+ }
+ return mrcp_app_signaling_task_msg_signal(MRCP_SIG_COMMAND_RESOURCE_DISCOVER,session,NULL);
+}
+
+/** Create MRCP message */
+MRCP_DECLARE(mrcp_message_t*) mrcp_application_message_create(mrcp_session_t *session, mrcp_channel_t *channel, mrcp_method_id method_id)
+{
+ mrcp_message_t *mrcp_message;
+ mrcp_profile_t *profile;
+ mrcp_client_session_t *client_session = (mrcp_client_session_t*)session;
+ if(!client_session || !channel || !channel->resource) {
+ return NULL;
+ }
+ profile = client_session->profile;
+ if(!profile || !profile->resource_factory) {
+ return NULL;
+ }
+ mrcp_message = mrcp_request_create(
+ channel->resource,
+ profile->signaling_agent->mrcp_version,
+ method_id,
+ session->pool);
+ return mrcp_message;
+}
+
+/** Send MRCP message */
+MRCP_DECLARE(apt_bool_t) mrcp_application_message_send(mrcp_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message)
+{
+ if(!session || !channel || !message) {
+ return FALSE;
+ }
+ return mrcp_app_control_task_msg_signal(session,channel,message);
+}
+
+/** Create audio termination */
+MRCP_DECLARE(mpf_termination_t*) mrcp_application_audio_termination_create(
+ mrcp_session_t *session,
+ const mpf_audio_stream_vtable_t *stream_vtable,
+ mpf_stream_capabilities_t *capabilities,
+ void *obj)
+{
+ mpf_audio_stream_t *audio_stream;
+
+ if(!capabilities) {
+ return NULL;
+ }
+
+ if(mpf_codec_capabilities_validate(&capabilities->codecs) == FALSE) {
+ return NULL;
+ }
+
+ /* create audio stream */
+ audio_stream = mpf_audio_stream_create(
+ obj, /* object to associate */
+ stream_vtable, /* virtual methods table of audio stream */
+ capabilities, /* stream capabilities */
+ session->pool); /* memory pool to allocate memory from */
+ if(!audio_stream) {
+ return NULL;
+ }
+
+ /* create raw termination */
+ return mpf_raw_termination_create(
+ NULL, /* no object to associate */
+ audio_stream, /* audio stream */
+ NULL, /* no video stream */
+ session->pool); /* memory pool to allocate memory from */
+}
+
+/** Create source media termination */
+MRCP_DECLARE(mpf_termination_t*) mrcp_application_source_termination_create(
+ mrcp_session_t *session,
+ const mpf_audio_stream_vtable_t *stream_vtable,
+ mpf_codec_descriptor_t *codec_descriptor,
+ void *obj)
+{
+ mpf_stream_capabilities_t *capabilities;
+ mpf_audio_stream_t *audio_stream;
+
+ capabilities = mpf_source_stream_capabilities_create(session->pool);
+ if(codec_descriptor) {
+ mpf_codec_capabilities_add(
+ &capabilities->codecs,
+ mpf_sample_rate_mask_get(codec_descriptor->sampling_rate),
+ codec_descriptor->name.buf);
+ }
+ else {
+ mpf_codec_default_capabilities_add(&capabilities->codecs);
+ }
+
+ /* create audio stream */
+ audio_stream = mpf_audio_stream_create(
+ obj, /* object to associate */
+ stream_vtable, /* virtual methods table of audio stream */
+ capabilities, /* stream capabilities */
+ session->pool); /* memory pool to allocate memory from */
+
+ if(!audio_stream) {
+ return NULL;
+ }
+
+ audio_stream->rx_descriptor = codec_descriptor;
+
+ /* create raw termination */
+ return mpf_raw_termination_create(
+ NULL, /* no object to associate */
+ audio_stream, /* audio stream */
+ NULL, /* no video stream */
+ session->pool); /* memory pool to allocate memory from */
+}
+
+/** Create sink media termination */
+MRCP_DECLARE(mpf_termination_t*) mrcp_application_sink_termination_create(
+ mrcp_session_t *session,
+ const mpf_audio_stream_vtable_t *stream_vtable,
+ mpf_codec_descriptor_t *codec_descriptor,
+ void *obj)
+{
+ mpf_stream_capabilities_t *capabilities;
+ mpf_audio_stream_t *audio_stream;
+
+ capabilities = mpf_sink_stream_capabilities_create(session->pool);
+ if(codec_descriptor) {
+ mpf_codec_capabilities_add(
+ &capabilities->codecs,
+ mpf_sample_rate_mask_get(codec_descriptor->sampling_rate),
+ codec_descriptor->name.buf);
+ }
+ else {
+ mpf_codec_default_capabilities_add(&capabilities->codecs);
+ }
+
+ /* create audio stream */
+ audio_stream = mpf_audio_stream_create(
+ obj, /* object to associate */
+ stream_vtable, /* virtual methods table of audio stream */
+ capabilities, /* stream capabilities */
+ session->pool); /* memory pool to allocate memory from */
+ if(!audio_stream) {
+ return NULL;
+ }
+
+ audio_stream->tx_descriptor = codec_descriptor;
+
+ /* create raw termination */
+ return mpf_raw_termination_create(
+ NULL, /* no object to associate */
+ audio_stream, /* audio stream */
+ NULL, /* no video stream */
+ session->pool); /* memory pool to allocate memory from */
+}
+
+/** Dispatch application message */
+MRCP_DECLARE(apt_bool_t) mrcp_application_message_dispatch(const mrcp_app_message_dispatcher_t *dispatcher, const mrcp_app_message_t *app_message)
+{
+ apt_bool_t status = FALSE;
+ switch(app_message->message_type) {
+ case MRCP_APP_MESSAGE_TYPE_SIGNALING:
+ {
+ if(app_message->sig_message.message_type == MRCP_SIG_MESSAGE_TYPE_RESPONSE) {
+ switch(app_message->sig_message.command_id) {
+ case MRCP_SIG_COMMAND_SESSION_UPDATE:
+ if(dispatcher->on_session_update) {
+ status = dispatcher->on_session_update(
+ app_message->application,
+ app_message->session,
+ app_message->sig_message.status);
+ }
+ break;
+ case MRCP_SIG_COMMAND_SESSION_TERMINATE:
+ if(dispatcher->on_session_terminate) {
+ status = dispatcher->on_session_terminate(
+ app_message->application,
+ app_message->session,
+ app_message->sig_message.status);
+ }
+ break;
+ case MRCP_SIG_COMMAND_CHANNEL_ADD:
+ if(dispatcher->on_channel_add) {
+ status = dispatcher->on_channel_add(
+ app_message->application,
+ app_message->session,
+ app_message->channel,
+ app_message->sig_message.status);
+ }
+ break;
+ case MRCP_SIG_COMMAND_CHANNEL_REMOVE:
+ if(dispatcher->on_channel_remove) {
+ status = dispatcher->on_channel_remove(
+ app_message->application,
+ app_message->session,
+ app_message->channel,
+ app_message->sig_message.status);
+ }
+ break;
+ case MRCP_SIG_COMMAND_RESOURCE_DISCOVER:
+ if(dispatcher->on_resource_discover) {
+ status = dispatcher->on_resource_discover(
+ app_message->application,
+ app_message->session,
+ app_message->descriptor,
+ app_message->sig_message.status);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else if(app_message->sig_message.message_type == MRCP_SIG_MESSAGE_TYPE_EVENT) {
+ switch(app_message->sig_message.event_id) {
+ case MRCP_SIG_EVENT_TERMINATE:
+ if(dispatcher->on_terminate_event) {
+ status = dispatcher->on_terminate_event(
+ app_message->application,
+ app_message->session,
+ app_message->channel);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ }
+ case MRCP_APP_MESSAGE_TYPE_CONTROL:
+ {
+ if(dispatcher->on_message_receive) {
+ status = dispatcher->on_message_receive(
+ app_message->application,
+ app_message->session,
+ app_message->channel,
+ app_message->control_message);
+ }
+ break;
+ }
+ }
+ return status;
+}
diff --git a/libs/unimrcp/libs/mrcp-client/src/mrcp_client.c b/libs/unimrcp/libs/mrcp-client/src/mrcp_client.c
index 6fee8c09d7..7689cf37ef 100644
--- a/libs/unimrcp/libs/mrcp-client/src/mrcp_client.c
+++ b/libs/unimrcp/libs/mrcp-client/src/mrcp_client.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,22 +12,18 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_client.c 1733 2010-06-07 17:26:49Z achaloyan $
*/
#include
#include
#include "mrcp_client.h"
-#include "mrcp_resource_factory.h"
-#include "mrcp_resource.h"
#include "mrcp_sig_agent.h"
#include "mrcp_client_session.h"
#include "mrcp_client_connection.h"
-#include "mrcp_message.h"
-#include "mpf_engine.h"
-#include "mpf_termination_factory.h"
-#include "mpf_codec_manager.h"
-#include "apt_pool.h"
#include "apt_consumer_task.h"
+#include "apt_pool.h"
#include "apt_log.h"
#define CLIENT_TASK_NAME "MRCP Client"
@@ -47,8 +43,12 @@ struct mrcp_client_t {
apr_hash_t *rtp_factory_table;
/** Table of signaling agents (mrcp_sig_agent_t*) */
apr_hash_t *sig_agent_table;
+ /** Table of signaling settings (mrcp_sig_settings_t*) */
+ apr_hash_t *sig_settings_table;
/** Table of connection agents (mrcp_connection_agent_t*) */
apr_hash_t *cnt_agent_table;
+ /** Table of RTP settings (mpf_rtp_settings_t*) */
+ apr_hash_t *rtp_settings_table;
/** Table of profiles (mrcp_profile_t*) */
apr_hash_t *profile_table;
@@ -151,8 +151,6 @@ static const mrcp_connection_event_vtable_t connection_method_vtable = {
static void mrcp_client_on_start_complete(apt_task_t *task);
static void mrcp_client_on_terminate_complete(apt_task_t *task);
static apt_bool_t mrcp_client_msg_process(apt_task_t *task, apt_task_msg_t *msg);
-static apt_bool_t mrcp_app_signaling_task_msg_signal(mrcp_sig_command_e command_id, mrcp_session_t *session, mrcp_channel_t *channel);
-static apt_bool_t mrcp_app_control_task_msg_signal(mrcp_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message);
/** Create MRCP client instance */
@@ -177,7 +175,9 @@ MRCP_DECLARE(mrcp_client_t*) mrcp_client_create(apt_dir_layout_t *dir_layout)
client->media_engine_table = NULL;
client->rtp_factory_table = NULL;
client->sig_agent_table = NULL;
+ client->sig_settings_table = NULL;
client->cnt_agent_table = NULL;
+ client->rtp_settings_table = NULL;
client->profile_table = NULL;
client->app_table = NULL;
client->session_table = NULL;
@@ -201,7 +201,9 @@ MRCP_DECLARE(mrcp_client_t*) mrcp_client_create(apt_dir_layout_t *dir_layout)
client->media_engine_table = apr_hash_make(client->pool);
client->rtp_factory_table = apr_hash_make(client->pool);
client->sig_agent_table = apr_hash_make(client->pool);
+ client->sig_settings_table = apr_hash_make(client->pool);
client->cnt_agent_table = apr_hash_make(client->pool);
+ client->rtp_settings_table = apr_hash_make(client->pool);
client->profile_table = apr_hash_make(client->pool);
client->app_table = apr_hash_make(client->pool);
@@ -326,20 +328,25 @@ MRCP_DECLARE(apt_bool_t) mrcp_client_codec_manager_register(mrcp_client_t *clien
}
/** Get registered codec manager */
-MRCP_DECLARE(const mpf_codec_manager_t*) mrcp_client_codec_manager_get(mrcp_client_t *client)
+MRCP_DECLARE(const mpf_codec_manager_t*) mrcp_client_codec_manager_get(const mrcp_client_t *client)
{
return client->codec_manager;
}
/** Register media engine */
-MRCP_DECLARE(apt_bool_t) mrcp_client_media_engine_register(mrcp_client_t *client, mpf_engine_t *media_engine, const char *name)
+MRCP_DECLARE(apt_bool_t) mrcp_client_media_engine_register(mrcp_client_t *client, mpf_engine_t *media_engine)
{
- if(!media_engine || !name) {
+ const char *id;
+ if(!media_engine) {
return FALSE;
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Media Engine [%s]",name);
+ id = mpf_engine_id_get(media_engine);
+ if(!id) {
+ return FALSE;
+ }
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Media Engine [%s]",id);
mpf_engine_codec_manager_register(media_engine,client->codec_manager);
- apr_hash_set(client->media_engine_table,name,APR_HASH_KEY_STRING,media_engine);
+ apr_hash_set(client->media_engine_table,id,APR_HASH_KEY_STRING,media_engine);
mpf_engine_task_msg_type_set(media_engine,MRCP_CLIENT_MEDIA_TASK_MSG);
if(client->task) {
apt_task_t *media_task = mpf_task_get(media_engine);
@@ -350,7 +357,7 @@ MRCP_DECLARE(apt_bool_t) mrcp_client_media_engine_register(mrcp_client_t *client
}
/** Get media engine by name */
-MRCP_DECLARE(mpf_engine_t*) mrcp_client_media_engine_get(mrcp_client_t *client, const char *name)
+MRCP_DECLARE(mpf_engine_t*) mrcp_client_media_engine_get(const mrcp_client_t *client, const char *name)
{
return apr_hash_get(client->media_engine_table,name,APR_HASH_KEY_STRING);
}
@@ -367,22 +374,39 @@ MRCP_DECLARE(apt_bool_t) mrcp_client_rtp_factory_register(mrcp_client_t *client,
}
/** Get RTP termination factory by name */
-MRCP_DECLARE(mpf_termination_factory_t*) mrcp_client_rtp_factory_get(mrcp_client_t *client, const char *name)
+MRCP_DECLARE(mpf_termination_factory_t*) mrcp_client_rtp_factory_get(const mrcp_client_t *client, const char *name)
{
return apr_hash_get(client->rtp_factory_table,name,APR_HASH_KEY_STRING);
}
-/** Register MRCP signaling agent */
-MRCP_DECLARE(apt_bool_t) mrcp_client_signaling_agent_register(mrcp_client_t *client, mrcp_sig_agent_t *signaling_agent, const char *name)
+/** Register RTP settings */
+MRCP_DECLARE(apt_bool_t) mrcp_client_rtp_settings_register(mrcp_client_t *client, mpf_rtp_settings_t *rtp_settings, const char *name)
{
- if(!signaling_agent || !name) {
+ if(!rtp_settings || !name) {
return FALSE;
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Signaling Agent [%s]",name);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register RTP Settings [%s]",name);
+ apr_hash_set(client->rtp_settings_table,name,APR_HASH_KEY_STRING,rtp_settings);
+ return TRUE;
+}
+
+/** Get RTP settings by name */
+MRCP_DECLARE(mpf_rtp_settings_t*) mrcp_client_rtp_settings_get(const mrcp_client_t *client, const char *name)
+{
+ return apr_hash_get(client->rtp_settings_table,name,APR_HASH_KEY_STRING);
+}
+
+/** Register MRCP signaling agent */
+MRCP_DECLARE(apt_bool_t) mrcp_client_signaling_agent_register(mrcp_client_t *client, mrcp_sig_agent_t *signaling_agent)
+{
+ if(!signaling_agent || !signaling_agent->id) {
+ return FALSE;
+ }
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Signaling Agent [%s]",signaling_agent->id);
signaling_agent->msg_pool = apt_task_msg_pool_create_dynamic(sizeof(sig_agent_task_msg_data_t),client->pool);
signaling_agent->parent = client;
signaling_agent->resource_factory = client->resource_factory;
- apr_hash_set(client->sig_agent_table,name,APR_HASH_KEY_STRING,signaling_agent);
+ apr_hash_set(client->sig_agent_table,signaling_agent->id,APR_HASH_KEY_STRING,signaling_agent);
if(client->task) {
apt_task_t *task = apt_consumer_task_base_get(client->task);
apt_task_add(task,signaling_agent->task);
@@ -391,22 +415,45 @@ MRCP_DECLARE(apt_bool_t) mrcp_client_signaling_agent_register(mrcp_client_t *cli
}
/** Get signaling agent by name */
-MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_client_signaling_agent_get(mrcp_client_t *client, const char *name)
+MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_client_signaling_agent_get(const mrcp_client_t *client, const char *name)
{
return apr_hash_get(client->sig_agent_table,name,APR_HASH_KEY_STRING);
}
-/** Register MRCP connection agent (MRCPv2 only) */
-MRCP_DECLARE(apt_bool_t) mrcp_client_connection_agent_register(mrcp_client_t *client, mrcp_connection_agent_t *connection_agent, const char *name)
+/** Register MRCP signaling settings */
+MRCP_DECLARE(apt_bool_t) mrcp_client_signaling_settings_register(mrcp_client_t *client, mrcp_sig_settings_t *signaling_settings, const char *name)
{
- if(!connection_agent || !name) {
+ if(!signaling_settings || !name) {
return FALSE;
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Connection Agent [%s]",name);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Signaling Settings [%s]",name);
+ apr_hash_set(client->sig_settings_table,name,APR_HASH_KEY_STRING,signaling_settings);
+ return TRUE;
+}
+
+/** Get signaling settings by name */
+MRCP_DECLARE(mrcp_sig_settings_t*) mrcp_client_signaling_settings_get(const mrcp_client_t *client, const char *name)
+{
+ return apr_hash_get(client->sig_settings_table,name,APR_HASH_KEY_STRING);
+}
+
+
+/** Register MRCP connection agent (MRCPv2 only) */
+MRCP_DECLARE(apt_bool_t) mrcp_client_connection_agent_register(mrcp_client_t *client, mrcp_connection_agent_t *connection_agent)
+{
+ const char *id;
+ if(!connection_agent) {
+ return FALSE;
+ }
+ id = mrcp_client_connection_agent_id_get(connection_agent);
+ if(!id) {
+ return FALSE;
+ }
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Connection Agent [%s]",id);
mrcp_client_connection_resource_factory_set(connection_agent,client->resource_factory);
mrcp_client_connection_agent_handler_set(connection_agent,client,&connection_method_vtable);
client->cnt_msg_pool = apt_task_msg_pool_create_dynamic(sizeof(connection_agent_task_msg_data_t),client->pool);
- apr_hash_set(client->cnt_agent_table,name,APR_HASH_KEY_STRING,connection_agent);
+ apr_hash_set(client->cnt_agent_table,id,APR_HASH_KEY_STRING,connection_agent);
if(client->task) {
apt_task_t *task = apt_consumer_task_base_get(client->task);
apt_task_t *connection_task = mrcp_client_connection_agent_task_get(connection_agent);
@@ -416,7 +463,7 @@ MRCP_DECLARE(apt_bool_t) mrcp_client_connection_agent_register(mrcp_client_t *cl
}
/** Get connection agent by name */
-MRCP_DECLARE(mrcp_connection_agent_t*) mrcp_client_connection_agent_get(mrcp_client_t *client, const char *name)
+MRCP_DECLARE(mrcp_connection_agent_t*) mrcp_client_connection_agent_get(const mrcp_client_t *client, const char *name)
{
return apr_hash_get(client->cnt_agent_table,name,APR_HASH_KEY_STRING);
}
@@ -428,14 +475,18 @@ MRCP_DECLARE(mrcp_profile_t*) mrcp_client_profile_create(
mrcp_connection_agent_t *connection_agent,
mpf_engine_t *media_engine,
mpf_termination_factory_t *rtp_factory,
+ mpf_rtp_settings_t *rtp_settings,
+ mrcp_sig_settings_t *signaling_settings,
apr_pool_t *pool)
{
mrcp_profile_t *profile = apr_palloc(pool,sizeof(mrcp_profile_t));
profile->resource_factory = resource_factory;
profile->media_engine = media_engine;
profile->rtp_termination_factory = rtp_factory;
+ profile->rtp_settings = rtp_settings;
profile->signaling_agent = signaling_agent;
profile->connection_agent = connection_agent;
+ profile->signaling_settings = signaling_settings;
return profile;
}
@@ -459,13 +510,18 @@ MRCP_DECLARE(apt_bool_t) mrcp_client_profile_register(mrcp_client_t *client, mrc
return FALSE;
}
+ if(!profile->signaling_settings) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile [%s]: missing signaling settings",name);
+ return FALSE;
+ }
+
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Profile [%s]",name);
apr_hash_set(client->profile_table,name,APR_HASH_KEY_STRING,profile);
return TRUE;
}
/** Get profile by name */
-MRCP_DECLARE(mrcp_profile_t*) mrcp_client_profile_get(mrcp_client_t *client, const char *name)
+MRCP_DECLARE(mrcp_profile_t*) mrcp_client_profile_get(const mrcp_client_t *client, const char *name)
{
return apr_hash_get(client->profile_table,name,APR_HASH_KEY_STRING);
}
@@ -484,421 +540,52 @@ MRCP_DECLARE(apt_bool_t) mrcp_client_application_register(mrcp_client_t *client,
}
/** Get memory pool */
-MRCP_DECLARE(apr_pool_t*) mrcp_client_memory_pool_get(mrcp_client_t *client)
+MRCP_DECLARE(apr_pool_t*) mrcp_client_memory_pool_get(const mrcp_client_t *client)
{
return client->pool;
}
-
-/** Create application instance */
-MRCP_DECLARE(mrcp_application_t*) mrcp_application_create(const mrcp_app_message_handler_f handler, void *obj, apr_pool_t *pool)
+/** Get directory layout */
+MRCP_DECLARE(apt_dir_layout_t*) mrcp_client_dir_layout_get(const mrcp_client_t *client)
{
- mrcp_application_t *application;
- if(!handler) {
- return FALSE;
- }
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create Application");
- application = apr_palloc(pool,sizeof(mrcp_application_t));
- application->obj = obj;
- application->handler = handler;
- application->client = NULL;
- return application;
+ return client->dir_layout;
}
-/** Destroy application instance */
-MRCP_DECLARE(apt_bool_t) mrcp_application_destroy(mrcp_application_t *application)
+mrcp_client_session_t* mrcp_client_session_create(mrcp_client_t *client)
{
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Destroy Application");
- return TRUE;
-}
-
-/** Get external object associated with the application */
-MRCP_DECLARE(void*) mrcp_application_object_get(mrcp_application_t *application)
-{
- return application->obj;
-}
-
-/** Get dir layout structure */
-MRCP_DECLARE(const apt_dir_layout_t*) mrcp_application_dir_layout_get(mrcp_application_t *application)
-{
- return application->client->dir_layout;
-}
-
-
-
-/** Create client session */
-MRCP_DECLARE(mrcp_session_t*) mrcp_application_session_create(mrcp_application_t *application, const char *profile_name, void *obj)
-{
- mrcp_profile_t *profile;
- mrcp_client_session_t *session;
- if(!application || !application->client) {
- return NULL;
- }
-
- profile = mrcp_client_profile_get(application->client,profile_name);
- if(!profile) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No Such Profile [%s]",profile_name);
- return NULL;
- }
-
- session = mrcp_client_session_create(application,obj);
- if(!session) {
- return NULL;
- }
+ apr_pool_t *pool;
+ mrcp_client_session_t *session = (mrcp_client_session_t*) mrcp_session_create(sizeof(mrcp_client_session_t)-sizeof(mrcp_session_t));
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create MRCP Handle "APT_PTR_FMT" [%s]",
- MRCP_SESSION_PTR(session),
- profile_name);
- session->profile = profile;
- session->codec_manager = application->client->codec_manager;
+ pool = session->base.pool;
+ session->base.name = apr_psprintf(pool,"0x%pp",session);
session->base.response_vtable = &session_response_vtable;
session->base.event_vtable = &session_event_vtable;
- return &session->base;
-}
-/** Get memory pool the session object is created out of */
-MRCP_DECLARE(apr_pool_t*) mrcp_application_session_pool_get(mrcp_session_t *session)
-{
- if(!session) {
- return NULL;
- }
- return session->pool;
-}
-
-/** Get session identifier */
-MRCP_DECLARE(const apt_str_t*) mrcp_application_session_id_get(mrcp_session_t *session)
-{
- if(!session) {
- return NULL;
- }
- return &session->id;
-}
-
-/** Get external object associated with the session */
-MRCP_DECLARE(void*) mrcp_application_session_object_get(mrcp_session_t *session)
-{
- mrcp_client_session_t *client_session = (mrcp_client_session_t*)session;
- if(!client_session) {
- return NULL;
- }
- return client_session->app_obj;
-}
-
-/** Set (associate) external object to the session */
-MRCP_DECLARE(void) mrcp_application_session_object_set(mrcp_session_t *session, void *obj)
-{
- mrcp_client_session_t *client_session = (mrcp_client_session_t*)session;
- if(client_session) {
- client_session->app_obj = obj;
- }
-}
-
-/** Send session update request */
-MRCP_DECLARE(apt_bool_t) mrcp_application_session_update(mrcp_session_t *session)
-{
- if(!session) {
- return FALSE;
- }
- return mrcp_app_signaling_task_msg_signal(MRCP_SIG_COMMAND_SESSION_UPDATE,session,NULL);
-}
-
-/** Send session termination request */
-MRCP_DECLARE(apt_bool_t) mrcp_application_session_terminate(mrcp_session_t *session)
-{
- if(!session) {
- return FALSE;
- }
- return mrcp_app_signaling_task_msg_signal(MRCP_SIG_COMMAND_SESSION_TERMINATE,session,NULL);
-}
-
-/** Destroy client session (session must be terminated prior to destroy) */
-MRCP_DECLARE(apt_bool_t) mrcp_application_session_destroy(mrcp_session_t *session)
-{
- if(!session) {
- return FALSE;
- }
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Destroy MRCP Handle "APT_PTR_FMT,MRCP_SESSION_PTR(session));
- mrcp_session_destroy(session);
- return TRUE;
-}
-
-
-/** Create control channel */
-MRCP_DECLARE(mrcp_channel_t*) mrcp_application_channel_create(
- mrcp_session_t *session,
- mrcp_resource_id resource_id,
- mpf_termination_t *termination,
- mpf_rtp_termination_descriptor_t *rtp_descriptor,
- void *obj)
-{
- mrcp_resource_t *resource;
- mrcp_profile_t *profile;
- mrcp_client_session_t *client_session = (mrcp_client_session_t*)session;
- if(!client_session || !client_session->profile) {
- /* Invalid params */
- return FALSE;
- }
- profile = client_session->profile;
-
- if(!profile->resource_factory) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Channel: invalid profile");
- return FALSE;
- }
- resource = mrcp_resource_get(profile->resource_factory,resource_id);
- if(!resource) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Channel: no such resource");
- return FALSE;
- }
-
- if(termination) {
- /* Media engine and RTP factory must be specified in this case */
- if(!profile->media_engine || !profile->rtp_termination_factory) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Channel: invalid profile");
- return FALSE;
- }
- }
- else {
- /* Either termination or rtp_descriptor must be specified */
- if(!rtp_descriptor) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Channel: missing both termination and RTP descriptor");
- return FALSE;
- }
- }
-
- return mrcp_client_channel_create(session,resource,termination,rtp_descriptor,obj);
-}
-
-/** Get external object associated with the channel */
-MRCP_DECLARE(void*) mrcp_application_channel_object_get(mrcp_channel_t *channel)
-{
- if(!channel) {
- return FALSE;
- }
- return channel->obj;
-}
-
-/** Get RTP termination descriptor */
-MRCP_DECLARE(mpf_rtp_termination_descriptor_t*) mrcp_application_rtp_descriptor_get(mrcp_channel_t *channel)
-{
- if(!channel || !channel->rtp_termination_slot) {
- return NULL;
- }
- return channel->rtp_termination_slot->descriptor;
-}
-
-/** Get codec descriptor of source stream */
-MRCP_DECLARE(const mpf_codec_descriptor_t*) mrcp_application_source_descriptor_get(mrcp_channel_t *channel)
-{
- mpf_audio_stream_t *audio_stream;
- if(!channel || !channel->termination) {
- return NULL;
- }
- audio_stream = mpf_termination_audio_stream_get(channel->termination);
- if(!audio_stream) {
- return NULL;
- }
- return audio_stream->rx_descriptor;
-}
-
-/** Get codec descriptor of sink stream */
-MRCP_DECLARE(const mpf_codec_descriptor_t*) mrcp_application_sink_descriptor_get(mrcp_channel_t *channel)
-{
- mpf_audio_stream_t *audio_stream;
- if(!channel || !channel->termination) {
- return NULL;
- }
- audio_stream = mpf_termination_audio_stream_get(channel->termination);
- if(!audio_stream) {
- return NULL;
- }
- return audio_stream->tx_descriptor;
-}
-
-
-/** Send channel add request */
-MRCP_DECLARE(apt_bool_t) mrcp_application_channel_add(mrcp_session_t *session, mrcp_channel_t *channel)
-{
- if(!session || !channel) {
- return FALSE;
- }
- return mrcp_app_signaling_task_msg_signal(MRCP_SIG_COMMAND_CHANNEL_ADD,session,channel);
-}
-
-/** Send channel removal request */
-MRCP_DECLARE(apt_bool_t) mrcp_application_channel_remove(mrcp_session_t *session, mrcp_channel_t *channel)
-{
- if(!session || !channel) {
- return FALSE;
- }
- return mrcp_app_signaling_task_msg_signal(MRCP_SIG_COMMAND_CHANNEL_REMOVE,session,channel);
-}
-
-/** Send resource discovery request */
-MRCP_DECLARE(apt_bool_t) mrcp_application_resource_discover(mrcp_session_t *session)
-{
- if(!session) {
- return FALSE;
- }
- return mrcp_app_signaling_task_msg_signal(MRCP_SIG_COMMAND_RESOURCE_DISCOVER,session,NULL);
-}
-
-/** Create MRCP message */
-MRCP_DECLARE(mrcp_message_t*) mrcp_application_message_create(mrcp_session_t *session, mrcp_channel_t *channel, mrcp_method_id method_id)
-{
- mrcp_message_t *mrcp_message;
- mrcp_profile_t *profile;
- mrcp_client_session_t *client_session = (mrcp_client_session_t*)session;
- if(!client_session || !channel || !channel->resource) {
- return NULL;
- }
- profile = client_session->profile;
- if(!profile || !profile->resource_factory) {
- return NULL;
- }
- mrcp_message = mrcp_request_create(
- channel->resource,
- profile->signaling_agent->mrcp_version,
- method_id,
- session->pool);
- return mrcp_message;
-}
-
-/** Send MRCP message */
-MRCP_DECLARE(apt_bool_t) mrcp_application_message_send(mrcp_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message)
-{
- if(!session || !channel || !message) {
- return FALSE;
- }
- return mrcp_app_control_task_msg_signal(session,channel,message);
-}
-
-/**
- * Create audio termination
- * @param session the session to create termination for
- * @param stream_vtable the virtual table of audio stream
- * @param capabilities the capabilities of the stream
- * @param obj the external object
- */
-MRCP_DECLARE(mpf_termination_t*) mrcp_application_audio_termination_create(
- mrcp_session_t *session,
- const mpf_audio_stream_vtable_t *stream_vtable,
- mpf_stream_capabilities_t *capabilities,
- void *obj)
-{
- mpf_audio_stream_t *audio_stream;
-
- if(!capabilities) {
- return NULL;
- }
-
- if(mpf_codec_capabilities_validate(&capabilities->codecs) == FALSE) {
- return NULL;
- }
-
- /* create audio stream */
- audio_stream = mpf_audio_stream_create(
- obj, /* object to associate */
- stream_vtable, /* virtual methods table of audio stream */
- capabilities, /* stream capabilities */
- session->pool); /* memory pool to allocate memory from */
- if(!audio_stream) {
- return NULL;
- }
-
- /* create raw termination */
- return mpf_raw_termination_create(
- NULL, /* no object to associate */
- audio_stream, /* audio stream */
- NULL, /* no video stream */
- session->pool); /* memory pool to allocate memory from */
-}
-
-/** Create source media termination */
-MRCP_DECLARE(mpf_termination_t*) mrcp_application_source_termination_create(
- mrcp_session_t *session,
- const mpf_audio_stream_vtable_t *stream_vtable,
- mpf_codec_descriptor_t *codec_descriptor,
- void *obj)
-{
- mpf_stream_capabilities_t *capabilities;
- mpf_audio_stream_t *audio_stream;
-
- capabilities = mpf_source_stream_capabilities_create(session->pool);
- if(codec_descriptor) {
- mpf_codec_capabilities_add(
- &capabilities->codecs,
- mpf_sample_rate_mask_get(codec_descriptor->sampling_rate),
- codec_descriptor->name.buf);
- }
- else {
- mpf_codec_default_capabilities_add(&capabilities->codecs);
- }
-
- /* create audio stream */
- audio_stream = mpf_audio_stream_create(
- obj, /* object to associate */
- stream_vtable, /* virtual methods table of audio stream */
- capabilities, /* stream capabilities */
- session->pool); /* memory pool to allocate memory from */
-
- if(!audio_stream) {
- return NULL;
- }
-
- audio_stream->rx_descriptor = codec_descriptor;
-
- /* create raw termination */
- return mpf_raw_termination_create(
- NULL, /* no object to associate */
- audio_stream, /* audio stream */
- NULL, /* no video stream */
- session->pool); /* memory pool to allocate memory from */
-}
-
-MRCP_DECLARE(mpf_termination_t*) mrcp_application_sink_termination_create(
- mrcp_session_t *session,
- const mpf_audio_stream_vtable_t *stream_vtable,
- mpf_codec_descriptor_t *codec_descriptor,
- void *obj)
-{
- mpf_stream_capabilities_t *capabilities;
- mpf_audio_stream_t *audio_stream;
-
- capabilities = mpf_sink_stream_capabilities_create(session->pool);
- if(codec_descriptor) {
- mpf_codec_capabilities_add(
- &capabilities->codecs,
- mpf_sample_rate_mask_get(codec_descriptor->sampling_rate),
- codec_descriptor->name.buf);
- }
- else {
- mpf_codec_default_capabilities_add(&capabilities->codecs);
- }
-
- /* create audio stream */
- audio_stream = mpf_audio_stream_create(
- obj, /* object to associate */
- stream_vtable, /* virtual methods table of audio stream */
- capabilities, /* stream capabilities */
- session->pool); /* memory pool to allocate memory from */
- if(!audio_stream) {
- return NULL;
- }
-
- audio_stream->tx_descriptor = codec_descriptor;
-
- /* create raw termination */
- return mpf_raw_termination_create(
- NULL, /* no object to associate */
- audio_stream, /* audio stream */
- NULL, /* no video stream */
- session->pool); /* memory pool to allocate memory from */
+ session->application = NULL;
+ session->app_obj = NULL;
+ session->profile = NULL;
+ session->context = NULL;
+ session->codec_manager = client->codec_manager;
+ session->terminations = apr_array_make(pool,2,sizeof(rtp_termination_slot_t));
+ session->channels = apr_array_make(pool,2,sizeof(mrcp_channel_t*));
+ session->registered = FALSE;
+ session->offer = NULL;
+ session->answer = NULL;
+ session->active_request = NULL;
+ session->request_queue = apt_list_create(pool);
+ session->mpf_task_msg = NULL;
+ session->subrequest_count = 0;
+ session->state = SESSION_STATE_NONE;
+ session->status = MRCP_SIG_STATUS_CODE_SUCCESS;
+ return session;
}
void mrcp_client_session_add(mrcp_client_t *client, mrcp_client_session_t *session)
{
if(session) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Add MRCP Handle "APT_PTR_FMT,MRCP_SESSION_PTR(session));
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Add MRCP Handle "APT_NAMESID_FMT,
+ session->base.name,
+ MRCP_SESSION_SID(&session->base));
apr_hash_set(client->session_table,session,sizeof(session),session);
}
}
@@ -906,7 +593,9 @@ void mrcp_client_session_add(mrcp_client_t *client, mrcp_client_session_t *sessi
void mrcp_client_session_remove(mrcp_client_t *client, mrcp_client_session_t *session)
{
if(session) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Remove MRCP Handle "APT_PTR_FMT,MRCP_SESSION_PTR(session));
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Remove MRCP Handle "APT_NAMESID_FMT,
+ session->base.name,
+ MRCP_SESSION_SID(&session->base));
apr_hash_set(client->session_table,session,sizeof(session),NULL);
}
}
@@ -946,7 +635,6 @@ static apt_bool_t mrcp_client_msg_process(apt_task_t *task, apt_task_msg_t *msg)
case MRCP_CLIENT_SIGNALING_TASK_MSG:
{
const sig_agent_task_msg_data_t *sig_message = (const sig_agent_task_msg_data_t*)msg->data;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Receive Signaling Task Message [%d]", msg->sub_type);
switch(msg->sub_type) {
case SIG_AGENT_TASK_MSG_ANSWER:
mrcp_client_session_answer_process(sig_message->session,sig_message->descriptor);
@@ -971,7 +659,6 @@ static apt_bool_t mrcp_client_msg_process(apt_task_t *task, apt_task_msg_t *msg)
case MRCP_CLIENT_CONNECTION_TASK_MSG:
{
const connection_agent_task_msg_data_t *data = (const connection_agent_task_msg_data_t*)msg->data;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Receive Connection Task Message [%d]", msg->sub_type);
switch(msg->sub_type) {
case CONNECTION_AGENT_TASK_MSG_ADD_CHANNEL:
mrcp_client_on_channel_add(data->channel,data->descriptor,data->status);
@@ -996,27 +683,25 @@ static apt_bool_t mrcp_client_msg_process(apt_task_t *task, apt_task_msg_t *msg)
case MRCP_CLIENT_MEDIA_TASK_MSG:
{
mpf_message_container_t *container = (mpf_message_container_t*) msg->data;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Receive Media Task Message");
mrcp_client_mpf_message_process(container);
break;
}
case MRCP_CLIENT_APPLICATION_TASK_MSG:
{
mrcp_app_message_t **app_message = (mrcp_app_message_t**) msg->data;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Receive Application Task Message [%d]", (*app_message)->message_type);
mrcp_client_app_message_process(*app_message);
break;
}
default:
{
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Receive Unknown Task Message [%d]", msg->type);
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Task Message Received [%d;%d]", msg->type,msg->sub_type);
break;
}
}
return TRUE;
}
-static apt_bool_t mrcp_app_signaling_task_msg_signal(mrcp_sig_command_e command_id, mrcp_session_t *session, mrcp_channel_t *channel)
+apt_bool_t mrcp_app_signaling_task_msg_signal(mrcp_sig_command_e command_id, mrcp_session_t *session, mrcp_channel_t *channel)
{
mrcp_client_session_t *client_session = (mrcp_client_session_t*)session;
mrcp_application_t *application = client_session->application;
@@ -1035,11 +720,10 @@ static apt_bool_t mrcp_app_signaling_task_msg_signal(mrcp_sig_command_e command_
app_message->descriptor = NULL;
*slot = app_message;
}
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Signal Application Task Message");
return apt_task_msg_signal(task,task_msg);
}
-static apt_bool_t mrcp_app_control_task_msg_signal(mrcp_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message)
+apt_bool_t mrcp_app_control_task_msg_signal(mrcp_session_t *session, mrcp_channel_t *channel, mrcp_message_t *message)
{
mrcp_client_session_t *client_session = (mrcp_client_session_t*)session;
mrcp_application_t *application = client_session->application;
@@ -1057,7 +741,6 @@ static apt_bool_t mrcp_app_control_task_msg_signal(mrcp_session_t *session, mrcp
app_message->control_message = message;
*slot = app_message;
}
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Signal Application Task Message");
return apt_task_msg_signal(task,task_msg);
}
@@ -1072,7 +755,6 @@ static apt_bool_t mrcp_client_signaling_task_msg_signal(sig_agent_task_msg_type_
data->descriptor = descriptor;
data->message = message;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Signal Signaling Task Message");
return apt_task_msg_parent_signal(session->signaling_agent->task,task_msg);
}
@@ -1101,12 +783,10 @@ static apt_bool_t mrcp_client_connection_task_msg_signal(
data->message = message;
data->status = status;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Signal Connection Task Message");
return apt_task_msg_signal(task,task_msg);
}
-
static apt_bool_t mrcp_client_answer_signal(mrcp_session_t *session, mrcp_session_descriptor_t *descriptor)
{
return mrcp_client_signaling_task_msg_signal(SIG_AGENT_TASK_MSG_ANSWER,session,descriptor,NULL);
diff --git a/libs/unimrcp/libs/mrcp-client/src/mrcp_client_session.c b/libs/unimrcp/libs/mrcp-client/src/mrcp_client_session.c
index a2659e0f3c..b7c8db3bb7 100644
--- a/libs/unimrcp/libs/mrcp-client/src/mrcp_client_session.c
+++ b/libs/unimrcp/libs/mrcp-client/src/mrcp_client_session.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_client_session.c 1799 2011-05-12 02:32:32Z achaloyan $
*/
#include "mrcp_client_session.h"
@@ -29,6 +31,10 @@
#include "apt_obj_list.h"
#include "apt_log.h"
+/** Macro to log session name and identifier */
+#define MRCP_SESSION_NAMESID(session) \
+ session->base.name, MRCP_SESSION_SID(&session->base)
+
void mrcp_client_session_add(mrcp_client_t *client, mrcp_client_session_t *session);
void mrcp_client_session_remove(mrcp_client_t *client, mrcp_client_session_t *session);
@@ -88,41 +94,17 @@ static mrcp_app_message_t* mrcp_client_app_response_create(const mrcp_app_messag
}
-mrcp_client_session_t* mrcp_client_session_create(mrcp_application_t *application, void *obj)
-{
- apr_pool_t *pool;
- mrcp_client_session_t *session = (mrcp_client_session_t*) mrcp_session_create(sizeof(mrcp_client_session_t)-sizeof(mrcp_session_t));
- pool = session->base.pool;
- session->application = application;
- session->codec_manager = NULL;
- session->app_obj = obj;
- session->profile = NULL;
- session->context = NULL;
- session->terminations = apr_array_make(pool,2,sizeof(rtp_termination_slot_t));
- session->channels = apr_array_make(pool,2,sizeof(mrcp_channel_t*));
- session->registered = FALSE;
- session->offer = NULL;
- session->answer = NULL;
- session->active_request = NULL;
- session->request_queue = apt_list_create(pool);
- session->mpf_task_msg = NULL;
- session->subrequest_count = 0;
- session->state = SESSION_STATE_NONE;
- session->status = MRCP_SIG_STATUS_CODE_SUCCESS;
- return session;
-}
-
mrcp_channel_t* mrcp_client_channel_create(
- mrcp_session_t *session,
+ mrcp_client_session_t *session,
mrcp_resource_t *resource,
mpf_termination_t *termination,
mpf_rtp_termination_descriptor_t *rtp_descriptor,
void *obj)
{
- mrcp_channel_t *channel = apr_palloc(session->pool,sizeof(mrcp_channel_t));
- channel->pool = session->pool;
+ mrcp_channel_t *channel = apr_palloc(session->base.pool,sizeof(mrcp_channel_t));
+ channel->pool = session->base.pool;
channel->obj = obj;
- channel->session = session;
+ channel->session = &session->base;
channel->control_channel = NULL;
channel->termination = termination;
channel->rtp_termination_slot = NULL;
@@ -131,7 +113,7 @@ mrcp_channel_t* mrcp_client_channel_create(
channel->waiting_for_termination = FALSE;
if(rtp_descriptor) {
- rtp_termination_slot_t *termination_slot = apr_palloc(session->pool,sizeof(rtp_termination_slot_t));
+ rtp_termination_slot_t *termination_slot = apr_palloc(channel->pool,sizeof(rtp_termination_slot_t));
termination_slot->descriptor = rtp_descriptor;
termination_slot->termination = NULL;
termination_slot->waiting = FALSE;
@@ -139,7 +121,8 @@ mrcp_channel_t* mrcp_client_channel_create(
termination_slot->id = 0;
channel->rtp_termination_slot = termination_slot;
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Create Channel "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(session));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->base.log_obj,"Create Channel "APT_NAMESID_FMT,
+ MRCP_SESSION_NAMESID(session));
return channel;
}
@@ -149,14 +132,15 @@ apt_bool_t mrcp_client_session_answer_process(mrcp_client_session_t *session, mr
return FALSE;
}
if(!descriptor) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive Answer "APT_PTRSID_FMT" [null descriptor]", MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->base.log_obj,"Receive Answer "APT_NAMESID_FMT" [null descriptor]",
+ MRCP_SESSION_NAMESID(session));
session->status = MRCP_SIG_STATUS_CODE_FAILURE;
/* raise app response */
return mrcp_app_sig_response_raise(session,TRUE);
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive Answer "APT_PTRSID_FMT" [c:%d a:%d v:%d]",
- MRCP_SESSION_PTRSID(&session->base),
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->base.log_obj,"Receive Answer "APT_NAMESID_FMT" [c:%d a:%d v:%d]",
+ MRCP_SESSION_NAMESID(session),
descriptor->control_media_arr->nelts,
descriptor->audio_media_arr->nelts,
descriptor->video_media_arr->nelts);
@@ -207,7 +191,7 @@ apt_bool_t mrcp_client_session_answer_process(mrcp_client_session_t *session, mr
apt_bool_t mrcp_client_session_terminate_response_process(mrcp_client_session_t *session)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive Terminate Response "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->base.log_obj,"Session Terminated "APT_NAMESID_FMT, MRCP_SESSION_NAMESID(session));
if(mrcp_client_session_subrequest_remove(session) == TRUE) {
mrcp_app_session_terminate_raise(session,MRCP_SIG_STATUS_CODE_SUCCESS);
@@ -220,7 +204,8 @@ apt_bool_t mrcp_client_session_terminate_event_process(mrcp_client_session_t *se
if(session->state == SESSION_STATE_TERMINATING) {
/* session termination request has been sent, still waiting for the response,
all the events must be ignored at this stage */
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unexpected Event! "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_WARNING,session->base.log_obj,"Unexpected Event! "APT_NAMESID_FMT,
+ MRCP_SESSION_NAMESID(session));
return FALSE;
}
@@ -266,7 +251,7 @@ apt_bool_t mrcp_client_session_control_response_process(mrcp_client_session_t *s
apt_bool_t mrcp_client_session_discover_response_process(mrcp_client_session_t *session, mrcp_session_descriptor_t *descriptor)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive Resource Discovery Response "APT_PTR_FMT, MRCP_SESSION_PTR(&session->base));
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Resources Discovered %s", session->base.name);
if(!session->active_request) {
return FALSE;
}
@@ -288,13 +273,16 @@ apt_bool_t mrcp_client_session_discover_response_process(mrcp_client_session_t *
control_media->resource_name = descriptor->resource_name;
}
}
+ else {
+ session->answer = descriptor;
+ }
if(mrcp_client_session_subrequest_remove(session) == TRUE) {
mrcp_app_message_t *response;
response = mrcp_client_app_response_create(session->active_request,MRCP_SIG_STATUS_CODE_SUCCESS,session->base.pool);
response->descriptor = session->answer;
session->answer = NULL;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Raise App Resource Discovery Response "APT_PTR_FMT, MRCP_SESSION_PTR(&session->base));
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Raise App Resource Discovery Response %s", session->base.name);
session->application->handler(response);
session->active_request = apt_list_pop_front(session->request_queue);
@@ -308,7 +296,9 @@ apt_bool_t mrcp_client_session_discover_response_process(mrcp_client_session_t *
apt_bool_t mrcp_client_on_channel_add(mrcp_channel_t *channel, mrcp_control_descriptor_t *descriptor, apt_bool_t status)
{
mrcp_client_session_t *session = (mrcp_client_session_t*)channel->session;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"On Control Channel Add "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_DEBUG,session->base.log_obj,"Control Channel Added "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ channel->resource->name.buf);
if(!channel->waiting_for_channel) {
return FALSE;
}
@@ -323,7 +313,9 @@ apt_bool_t mrcp_client_on_channel_add(mrcp_channel_t *channel, mrcp_control_desc
apt_bool_t mrcp_client_on_channel_modify(mrcp_channel_t *channel, mrcp_control_descriptor_t *descriptor, apt_bool_t status)
{
mrcp_client_session_t *session = (mrcp_client_session_t*)channel->session;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"On Control Channel Modify "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_DEBUG,session->base.log_obj,"Control Channel Modified "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ channel->resource->name.buf);
if(!channel->waiting_for_channel) {
return FALSE;
}
@@ -341,7 +333,9 @@ apt_bool_t mrcp_client_on_channel_modify(mrcp_channel_t *channel, mrcp_control_d
apt_bool_t mrcp_client_on_channel_remove(mrcp_channel_t *channel, apt_bool_t status)
{
mrcp_client_session_t *session = (mrcp_client_session_t*)channel->session;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"On Control Channel Remove "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_DEBUG,session->base.log_obj,"Control Channel Removed "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ channel->resource->name.buf);
if(!channel->waiting_for_channel) {
return FALSE;
}
@@ -395,16 +389,18 @@ apt_bool_t mrcp_client_app_message_process(mrcp_app_message_t *app_message)
{
mrcp_client_session_t *session = (mrcp_client_session_t*)app_message->session;
if(app_message->message_type == MRCP_APP_MESSAGE_TYPE_SIGNALING) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive App Request "APT_PTRSID_FMT" [%d]",
- MRCP_SESSION_PTRSID(&session->base),
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->base.log_obj,"Receive App Request "APT_NAMESID_FMT" [%d]",
+ MRCP_SESSION_NAMESID(session),
app_message->sig_message.command_id);
}
else {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive App MRCP Request "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->base.log_obj,"Receive App MRCP Request "APT_NAMESID_FMT,
+ MRCP_SESSION_NAMESID(session));
}
if(session->active_request) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Push Request to Queue "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_DEBUG,session->base.log_obj,"Push Request to Queue "APT_NAMESID_FMT,
+ MRCP_SESSION_NAMESID(session));
apt_list_push_back(session->request_queue,app_message,session->base.pool);
return TRUE;
}
@@ -417,11 +413,13 @@ apt_bool_t mrcp_client_app_message_process(mrcp_app_message_t *app_message)
static apt_bool_t mrcp_client_session_offer_send(mrcp_client_session_t *session)
{
mrcp_session_descriptor_t *descriptor = session->offer;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Send Offer "APT_PTRSID_FMT" [c:%d a:%d v:%d]",
- MRCP_SESSION_PTRSID(&session->base),
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->base.log_obj,"Send Offer "APT_NAMESID_FMT" [c:%d a:%d v:%d] to %s:%hu",
+ MRCP_SESSION_NAMESID(session),
descriptor->control_media_arr->nelts,
descriptor->audio_media_arr->nelts,
- descriptor->video_media_arr->nelts);
+ descriptor->video_media_arr->nelts,
+ session->profile->signaling_settings->server_ip,
+ session->profile->signaling_settings->server_port);
return mrcp_session_offer(&session->base,descriptor);
}
@@ -456,8 +454,8 @@ static apt_bool_t mrcp_app_sig_response_raise(mrcp_client_session_t *session, ap
}
session->active_request = NULL;
response = mrcp_client_app_response_create(request,session->status,session->base.pool);
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Raise App Response "APT_PTRSID_FMT" [%d] %s [%d]",
- MRCP_SESSION_PTRSID(&session->base),
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->base.log_obj,"Raise App Response "APT_NAMESID_FMT" [%d] %s [%d]",
+ MRCP_SESSION_NAMESID(session),
response->sig_message.command_id,
session->status == MRCP_SIG_STATUS_CODE_SUCCESS ? "SUCCESS" : "FAILURE",
session->status);
@@ -482,8 +480,8 @@ static apt_bool_t mrcp_app_sig_event_raise(mrcp_client_session_t *session, mrcp_
app_event->application = session->application;
app_event->session = &session->base;
app_event->channel = channel;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Raise App Event "APT_PTRSID_FMT" [%d]",
- MRCP_SESSION_PTRSID(&session->base),
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->base.log_obj,"Raise App Event "APT_NAMESID_FMT" [%d]",
+ MRCP_SESSION_NAMESID(session),
app_event->sig_message.event_id);
return session->application->handler(app_event);
}
@@ -501,7 +499,8 @@ static apt_bool_t mrcp_app_control_message_raise(mrcp_client_session_t *session,
mrcp_message->start_line.method_id = mrcp_request->start_line.method_id;
mrcp_message->start_line.method_name = mrcp_request->start_line.method_name;
response->control_message = mrcp_message;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Raise App MRCP Response "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->base.log_obj,"Raise App MRCP Response "APT_NAMESID_FMT,
+ MRCP_SESSION_NAMESID(session));
session->application->handler(response);
session->active_request = apt_list_pop_front(session->request_queue);
@@ -516,7 +515,8 @@ static apt_bool_t mrcp_app_control_message_raise(mrcp_client_session_t *session,
app_message->application = session->application;
app_message->session = &session->base;
app_message->channel = channel;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Raise App MRCP Event "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->base.log_obj,"Raise App MRCP Event "APT_NAMESID_FMT,
+ MRCP_SESSION_NAMESID(session));
session->application->handler(app_message);
}
return TRUE;
@@ -532,8 +532,8 @@ static apt_bool_t mrcp_app_failure_message_raise(mrcp_client_session_t *session)
session->active_request = NULL;
response = mrcp_client_app_response_create(request,session->status,session->base.pool);
if(response->message_type == MRCP_APP_MESSAGE_TYPE_SIGNALING) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Raise App Response "APT_PTRSID_FMT" [%d] %s [%d]",
- MRCP_SESSION_PTRSID(&session->base),
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->base.log_obj,"Raise App Response "APT_NAMESID_FMT" [%d] %s [%d]",
+ MRCP_SESSION_NAMESID(session),
response->sig_message.command_id,
session->status == MRCP_SIG_STATUS_CODE_SUCCESS ? "SUCCESS" : "FAILURE",
session->status);
@@ -542,7 +542,8 @@ static apt_bool_t mrcp_app_failure_message_raise(mrcp_client_session_t *session)
mrcp_message_t *mrcp_response = mrcp_response_create(response->control_message,response->control_message->pool);
mrcp_response->start_line.status_code = MRCP_STATUS_CODE_METHOD_FAILED;
response->control_message = mrcp_response;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Raise App MRCP Response "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->base.log_obj,"Raise App MRCP Response "APT_NAMESID_FMT,
+ MRCP_SESSION_NAMESID(session));
}
session->application->handler(response);
return TRUE;
@@ -612,15 +613,16 @@ static apt_bool_t mrcp_client_message_send(mrcp_client_session_t *session, mrcp_
if(!session->base.id.length) {
mrcp_message_t *response = mrcp_response_create(message,message->pool);
response->start_line.status_code = MRCP_STATUS_CODE_METHOD_FAILED;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Raise App Failure MRCP Response "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_DEBUG,session->base.log_obj,"Raise App Failure MRCP Response "APT_NAMESID_FMT,
+ MRCP_SESSION_NAMESID(session));
mrcp_app_control_message_raise(session,channel,response);
return TRUE;
}
message->channel_id.session_id = session->base.id;
message->start_line.request_id = ++session->base.last_request_id;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Send MRCP Request "APT_PTRSIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
- MRCP_SESSION_PTRSID(&session->base),
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->base.log_obj,"Send MRCP Request "APT_NAMESIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_SESSION_NAMESID(session),
channel->resource->name.buf,
message->start_line.request_id);
@@ -646,8 +648,8 @@ static apt_bool_t mrcp_client_channel_modify(mrcp_client_session_t *session, mrc
return FALSE;
}
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Modify Control Channel "APT_PTRSIDRES_FMT" [%d]",
- MRCP_SESSION_PTRSID(&session->base),
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_NOTICE,session->base.log_obj,"Modify Control Channel "APT_NAMESIDRES_FMT" [%d]",
+ MRCP_SESSION_NAMESID(session),
channel->resource->name.buf,
enable);
if(mrcp_client_channel_find(session,channel,&index) == TRUE) {
@@ -704,6 +706,7 @@ static apt_bool_t mrcp_client_channel_add(mrcp_client_session_t *session, mrcp_c
mrcp_control_descriptor_t *control_media;
if(!channel->control_channel) {
channel->control_channel = mrcp_client_control_channel_create(profile->connection_agent,channel,pool);
+ mrcp_client_control_channel_log_obj_set(channel->control_channel,session->base.log_obj);
}
control_media = mrcp_control_offer_create(pool);
control_media->id = mrcp_session_control_media_add(session->offer,control_media);
@@ -715,8 +718,8 @@ static apt_bool_t mrcp_client_channel_add(mrcp_client_session_t *session, mrcp_c
}
}
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Add Control Channel "APT_PTRSIDRES_FMT,
- MRCP_SESSION_PTRSID(&session->base),
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_NOTICE,session->base.log_obj,"Add Control Channel "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
channel->resource->name.buf);
/* add control channel */
APR_ARRAY_PUSH(session->channels,mrcp_channel_t*) = channel;
@@ -736,8 +739,14 @@ static apt_bool_t mrcp_client_channel_add(mrcp_client_session_t *session, mrcp_c
if(!session->context) {
/* create media context first */
- session->context = mpf_engine_context_create(profile->media_engine,session,5,pool);
+ session->context = mpf_engine_context_create(
+ profile->media_engine,
+ session->base.name,
+ session,5,pool);
}
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_DEBUG,session->base.log_obj,"Add Media Termination "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ mpf_termination_name_get(channel->termination));
if(mpf_engine_termination_message_add(
profile->media_engine,
MPF_ADD_TERMINATION,session->context,channel->termination,NULL,
@@ -749,6 +758,7 @@ static apt_bool_t mrcp_client_channel_add(mrcp_client_session_t *session, mrcp_c
/* initialize rtp descriptor */
rtp_descriptor = apr_palloc(pool,sizeof(mpf_rtp_termination_descriptor_t));
mpf_rtp_termination_descriptor_init(rtp_descriptor);
+ rtp_descriptor->audio.settings = profile->rtp_settings;
audio_stream = mpf_termination_audio_stream_get(channel->termination);
if(audio_stream) {
mpf_rtp_media_descriptor_t *media;
@@ -759,10 +769,12 @@ static apt_bool_t mrcp_client_channel_add(mrcp_client_session_t *session, mrcp_c
rtp_descriptor->audio.local = media;
}
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Add RTP Termination "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
/* create rtp termination */
termination = mpf_termination_create(profile->rtp_termination_factory,session,pool);
slot->termination = termination;
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_DEBUG,session->base.log_obj,"Add Media Termination "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ mpf_termination_name_get(termination));
/* send add termination request (add to media context) */
if(mpf_engine_termination_message_add(
@@ -805,7 +817,8 @@ static apt_bool_t mrcp_client_session_update(mrcp_client_session_t *session)
if(!session->offer) {
return FALSE;
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Update Session "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->base.log_obj,"Update Session "APT_NAMESID_FMT,
+ MRCP_SESSION_NAMESID(session));
return mrcp_client_session_offer_send(session);
}
@@ -816,7 +829,8 @@ static apt_bool_t mrcp_client_session_terminate(mrcp_client_session_t *session)
rtp_termination_slot_t *slot;
int i;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Terminate Session "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->base.log_obj,"Terminate Session "APT_NAMESID_FMT,
+ MRCP_SESSION_NAMESID(session));
profile = session->profile;
mrcp_client_session_state_set(session,SESSION_STATE_TERMINATING);
@@ -837,7 +851,8 @@ static apt_bool_t mrcp_client_session_terminate(mrcp_client_session_t *session)
if(channel->control_channel) {
/* remove channel */
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Remove Control Channel "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_DEBUG,session->base.log_obj,"Remove Control Channel "APT_NAMESID_FMT,
+ MRCP_SESSION_NAMESID(session));
if(mrcp_client_control_channel_remove(channel->control_channel) == TRUE) {
channel->waiting_for_channel = TRUE;
mrcp_client_session_subrequest_add(session);
@@ -846,7 +861,9 @@ static apt_bool_t mrcp_client_session_terminate(mrcp_client_session_t *session)
/* send subtract termination request */
if(channel->termination) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Subtract Channel Termination "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_DEBUG,session->base.log_obj,"Subtract Media Termination "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ mpf_termination_name_get(channel->termination));
if(mpf_engine_termination_message_add(
profile->media_engine,
MPF_SUBTRACT_TERMINATION,session->context,channel->termination,NULL,
@@ -865,7 +882,9 @@ static apt_bool_t mrcp_client_session_terminate(mrcp_client_session_t *session)
if(!slot || !slot->termination) continue;
/* send subtract termination request */
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Subtract Termination "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_DEBUG,session->base.log_obj,"Subtract Media Termination "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ mpf_termination_name_get(slot->termination));
if(mpf_engine_termination_message_add(
profile->media_engine,
MPF_SUBTRACT_TERMINATION,session->context,slot->termination,NULL,
@@ -887,7 +906,7 @@ static apt_bool_t mrcp_client_resource_discover(mrcp_client_session_t *session)
{
mrcp_session_descriptor_t *descriptor = NULL;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Send Resource Discovery Request "APT_PTR_FMT, MRCP_SESSION_PTR(&session->base));
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Discover Resources "APT_PTR_FMT, MRCP_SESSION_PTR(&session->base));
session->answer = NULL;
mrcp_client_session_state_set(session,SESSION_STATE_DISCOVERING);
@@ -925,6 +944,9 @@ static apt_bool_t mrcp_client_on_termination_add(mrcp_client_session_t *session,
if(!session) {
return FALSE;
}
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_DEBUG,session->base.log_obj,"Media Termination Added "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ mpf_termination_name_get(mpf_message->termination));
termination_slot = mrcp_client_rtp_termination_find(session,mpf_message->termination);
if(termination_slot) {
/* rtp termination */
@@ -966,6 +988,9 @@ static apt_bool_t mrcp_client_on_termination_modify(mrcp_client_session_t *sessi
if(!session) {
return FALSE;
}
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_DEBUG,session->base.log_obj,"Media Termination Modified "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ mpf_termination_name_get(mpf_message->termination));
termination_slot = mrcp_client_rtp_termination_find(session,mpf_message->termination);
if(termination_slot) {
/* rtp termination */
@@ -995,6 +1020,9 @@ static apt_bool_t mrcp_client_on_termination_subtract(mrcp_client_session_t *ses
if(!session) {
return FALSE;
}
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_DEBUG,session->base.log_obj,"Media Termination Subtracted "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ mpf_termination_name_get(mpf_message->termination));
termination_slot = mrcp_client_rtp_termination_find(session,mpf_message->termination);
if(termination_slot) {
/* rtp termination */
@@ -1036,15 +1064,12 @@ apt_bool_t mrcp_client_mpf_message_process(mpf_message_container_t *mpf_message_
if(mpf_message->message_type == MPF_MESSAGE_TYPE_RESPONSE) {
switch(mpf_message->command_id) {
case MPF_ADD_TERMINATION:
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"On Termination Add "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
mrcp_client_on_termination_add(session,mpf_message);
break;
case MPF_MODIFY_TERMINATION:
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"On Termination Modify "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
mrcp_client_on_termination_modify(session,mpf_message);
break;
case MPF_SUBTRACT_TERMINATION:
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"On Termination Subtract "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
mrcp_client_on_termination_subtract(session,mpf_message);
break;
case MPF_ADD_ASSOCIATION:
@@ -1068,7 +1093,8 @@ apt_bool_t mrcp_client_mpf_message_process(mpf_message_container_t *mpf_message_
}
}
else if(mpf_message->message_type == MPF_MESSAGE_TYPE_EVENT) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Process MPF Event "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_DEBUG,session->base.log_obj,"Process MPF Event "APT_NAMESID_FMT,
+ MRCP_SESSION_NAMESID(session));
}
}
return TRUE;
@@ -1117,7 +1143,8 @@ static apt_bool_t mrcp_client_control_media_answer_process(mrcp_client_session_t
/* get control descriptor */
control_descriptor = mrcp_session_control_media_get(descriptor,i);
/* modify channel */
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Modify Control Channel "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_DEBUG,session->base.log_obj,"Modify Control Channel "APT_NAMESID_FMT,
+ MRCP_SESSION_NAMESID(session));
if(mrcp_client_control_channel_modify(channel->control_channel,control_descriptor) == TRUE) {
channel->waiting_for_channel = TRUE;
mrcp_client_session_subrequest_add(session);
@@ -1157,7 +1184,9 @@ static apt_bool_t mrcp_client_av_media_answer_process(mrcp_client_session_t *ses
rtp_descriptor->audio.remote = remote_media;
/* send modify termination request */
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Modify Termination "APT_PTRSID_FMT, MRCP_SESSION_PTRSID(&session->base));
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_DEBUG,session->base.log_obj,"Modify Media Termination "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ mpf_termination_name_get(slot->termination));
if(mpf_engine_termination_message_add(
session->profile->media_engine,
MPF_MODIFY_TERMINATION,session->context,slot->termination,rtp_descriptor,
@@ -1183,15 +1212,15 @@ static apt_bool_t mrcp_app_request_dispatch(mrcp_client_session_t *session, cons
if(session->state == SESSION_STATE_TERMINATING) {
/* no more requests are allowed, as session is being terminated!
just return, it is horribly wrong and can crash anytime here */
- apt_log(APT_LOG_MARK,APT_PRIO_ERROR,"Inappropriate Application Request "APT_PTRSID_FMT" [%d]",
- MRCP_SESSION_PTRSID(&session->base),
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_ERROR,session->base.log_obj,"Inappropriate Application Request "APT_NAMESID_FMT" [%d]",
+ MRCP_SESSION_NAMESID(session),
app_message->sig_message.command_id);
return FALSE;
}
if(session->registered == FALSE) {
session->base.signaling_agent = session->profile->signaling_agent;
- session->base.signaling_agent->create_client_session(&session->base);
+ session->base.signaling_agent->create_client_session(&session->base,session->profile->signaling_settings);
mrcp_client_session_add(session->application->client,session);
session->registered = TRUE;
@@ -1200,8 +1229,8 @@ static apt_bool_t mrcp_app_request_dispatch(mrcp_client_session_t *session, cons
switch(app_message->message_type) {
case MRCP_APP_MESSAGE_TYPE_SIGNALING:
{
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Dispatch Application Request "APT_PTRSID_FMT" [%d]",
- MRCP_SESSION_PTRSID(&session->base),
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_DEBUG,session->base.log_obj,"Dispatch App Request "APT_NAMESID_FMT" [%d]",
+ MRCP_SESSION_NAMESID(session),
app_message->sig_message.command_id);
switch(app_message->sig_message.command_id) {
case MRCP_SIG_COMMAND_SESSION_UPDATE:
@@ -1232,90 +1261,3 @@ static apt_bool_t mrcp_app_request_dispatch(mrcp_client_session_t *session, cons
}
return TRUE;
}
-
-/** Dispatch application message */
-MRCP_DECLARE(apt_bool_t) mrcp_application_message_dispatch(const mrcp_app_message_dispatcher_t *dispatcher, const mrcp_app_message_t *app_message)
-{
- apt_bool_t status = FALSE;
- switch(app_message->message_type) {
- case MRCP_APP_MESSAGE_TYPE_SIGNALING:
- {
- if(app_message->sig_message.message_type == MRCP_SIG_MESSAGE_TYPE_RESPONSE) {
- switch(app_message->sig_message.command_id) {
- case MRCP_SIG_COMMAND_SESSION_UPDATE:
- if(dispatcher->on_session_update) {
- status = dispatcher->on_session_update(
- app_message->application,
- app_message->session,
- app_message->sig_message.status);
- }
- break;
- case MRCP_SIG_COMMAND_SESSION_TERMINATE:
- if(dispatcher->on_session_terminate) {
- status = dispatcher->on_session_terminate(
- app_message->application,
- app_message->session,
- app_message->sig_message.status);
- }
- break;
- case MRCP_SIG_COMMAND_CHANNEL_ADD:
- if(dispatcher->on_channel_add) {
- status = dispatcher->on_channel_add(
- app_message->application,
- app_message->session,
- app_message->channel,
- app_message->sig_message.status);
- }
- break;
- case MRCP_SIG_COMMAND_CHANNEL_REMOVE:
- if(dispatcher->on_channel_remove) {
- status = dispatcher->on_channel_remove(
- app_message->application,
- app_message->session,
- app_message->channel,
- app_message->sig_message.status);
- }
- break;
- case MRCP_SIG_COMMAND_RESOURCE_DISCOVER:
- if(dispatcher->on_resource_discover) {
- status = dispatcher->on_resource_discover(
- app_message->application,
- app_message->session,
- app_message->descriptor,
- app_message->sig_message.status);
- }
- break;
- default:
- break;
- }
- }
- else if(app_message->sig_message.message_type == MRCP_SIG_MESSAGE_TYPE_EVENT) {
- switch(app_message->sig_message.event_id) {
- case MRCP_SIG_EVENT_TERMINATE:
- if(dispatcher->on_terminate_event) {
- status = dispatcher->on_terminate_event(
- app_message->application,
- app_message->session,
- app_message->channel);
- }
- break;
- default:
- break;
- }
- }
- break;
- }
- case MRCP_APP_MESSAGE_TYPE_CONTROL:
- {
- if(dispatcher->on_message_receive) {
- status = dispatcher->on_message_receive(
- app_message->application,
- app_message->session,
- app_message->channel,
- app_message->control_message);
- }
- break;
- }
- }
- return status;
-}
diff --git a/libs/unimrcp/libs/mrcp-engine/Makefile.am b/libs/unimrcp/libs/mrcp-engine/Makefile.am
index 74bac2d06b..f30e21a2bd 100644
--- a/libs/unimrcp/libs/mrcp-engine/Makefile.am
+++ b/libs/unimrcp/libs/mrcp-engine/Makefile.am
@@ -18,13 +18,15 @@ include_HEADERS = include/mrcp_engine_types.h \
include/mrcp_synth_engine.h \
include/mrcp_recog_engine.h \
include/mrcp_recorder_engine.h \
+ include/mrcp_verifier_engine.h \
include/mrcp_resource_engine.h \
include/mrcp_engine_factory.h \
include/mrcp_engine_loader.h \
include/mrcp_state_machine.h \
include/mrcp_synth_state_machine.h \
include/mrcp_recog_state_machine.h \
- include/mrcp_recorder_state_machine.h
+ include/mrcp_recorder_state_machine.h \
+ include/mrcp_verifier_state_machine.h
libmrcpengine_la_SOURCES = src/mrcp_engine_iface.c \
src/mrcp_engine_impl.c \
@@ -32,4 +34,5 @@ libmrcpengine_la_SOURCES = src/mrcp_engine_iface.c \
src/mrcp_engine_loader.c \
src/mrcp_synth_state_machine.c \
src/mrcp_recog_state_machine.c \
- src/mrcp_recorder_state_machine.c
+ src/mrcp_recorder_state_machine.c \
+ src/mrcp_verifier_state_machine.c
diff --git a/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_factory.h b/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_factory.h
index ac8ccd78da..b86192eff6 100644
--- a/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_factory.h
+++ b/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_factory.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_engine_factory.h 1710 2010-05-24 17:36:19Z achaloyan $
*/
-#ifndef __MRCP_ENGINE_FACTORY_H__
-#define __MRCP_ENGINE_FACTORY_H__
+#ifndef MRCP_ENGINE_FACTORY_H
+#define MRCP_ENGINE_FACTORY_H
/**
* @file mrcp_engine_factory.h
@@ -43,15 +45,18 @@ MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_close(mrcp_engine_factory_t *factor
/** Register engine */
-MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_engine_register(mrcp_engine_factory_t *factory, mrcp_engine_t *engine, const char *name);
+MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_engine_register(mrcp_engine_factory_t *factory, mrcp_engine_t *engine);
/** Get engine by name */
-MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_factory_engine_get(mrcp_engine_factory_t *factory, const char *name);
+MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_factory_engine_get(const mrcp_engine_factory_t *factory, const char *name);
/** Find engine by resource identifier */
-MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_factory_engine_find(mrcp_engine_factory_t *factory, mrcp_resource_id resource_id);
+MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_factory_engine_find(const mrcp_engine_factory_t *factory, mrcp_resource_id resource_id);
+
+/** Start iterating over the engines in a factory */
+MRCP_DECLARE(apr_hash_index_t*) mrcp_engine_factory_engine_first(const mrcp_engine_factory_t *factory);
APT_END_EXTERN_C
-#endif /*__MRCP_ENGINE_FACTORY_H__*/
+#endif /* MRCP_ENGINE_FACTORY_H */
diff --git a/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_iface.h b/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_iface.h
index ee123fee0f..e602b7d836 100644
--- a/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_iface.h
+++ b/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_iface.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_engine_iface.h 1677 2010-05-01 18:45:50Z achaloyan $
*/
-#ifndef __MRCP_ENGINE_IFACE_H__
-#define __MRCP_ENGINE_IFACE_H__
+#ifndef MRCP_ENGINE_IFACE_H
+#define MRCP_ENGINE_IFACE_H
/**
* @file mrcp_engine_iface.h
@@ -27,30 +29,20 @@
APT_BEGIN_EXTERN_C
/** Destroy engine */
-static APR_INLINE apt_bool_t mrcp_engine_virtual_destroy(mrcp_engine_t *engine)
-{
- return engine->method_vtable->destroy(engine);
-}
+apt_bool_t mrcp_engine_virtual_destroy(mrcp_engine_t *engine);
/** Open engine */
-static APR_INLINE apt_bool_t mrcp_engine_virtual_open(mrcp_engine_t *engine)
-{
- if(engine->is_open == FALSE) {
- engine->is_open = engine->method_vtable->open(engine);
- return engine->is_open;
- }
- return FALSE;
-}
+apt_bool_t mrcp_engine_virtual_open(mrcp_engine_t *engine);
+
+/** Response to open engine request */
+void mrcp_engine_on_open(mrcp_engine_t *engine, apt_bool_t status);
/** Close engine */
-static APR_INLINE apt_bool_t mrcp_engine_virtual_close(mrcp_engine_t *engine)
-{
- if(engine->is_open == TRUE) {
- engine->is_open = FALSE;
- return engine->method_vtable->close(engine);
- }
- return FALSE;
-}
+apt_bool_t mrcp_engine_virtual_close(mrcp_engine_t *engine);
+
+/** Response to close engine request */
+void mrcp_engine_on_close(mrcp_engine_t *engine);
+
/** Create engine channel */
mrcp_engine_channel_t* mrcp_engine_channel_virtual_create(mrcp_engine_t *engine, mrcp_version_e mrcp_version, apr_pool_t *pool);
@@ -90,4 +82,4 @@ mrcp_engine_config_t* mrcp_engine_config_alloc(apr_pool_t *pool);
APT_END_EXTERN_C
-#endif /*__MRCP_ENGINE_IFACE_H__*/
+#endif /* MRCP_ENGINE_IFACE_H */
diff --git a/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_impl.h b/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_impl.h
index 32de2ad6b2..915d1e53f5 100644
--- a/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_impl.h
+++ b/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_impl.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_engine_impl.h 1710 2010-05-24 17:36:19Z achaloyan $
*/
-#ifndef __MRCP_ENGINE_IMPL_H__
-#define __MRCP_ENGINE_IMPL_H__
+#ifndef MRCP_ENGINE_IMPL_H
+#define MRCP_ENGINE_IMPL_H
/**
* @file mrcp_engine_impl.h
@@ -34,6 +36,18 @@ mrcp_engine_t* mrcp_engine_create(
const mrcp_engine_method_vtable_t *vtable,
apr_pool_t *pool);
+/** Send engine open response */
+static APR_INLINE apt_bool_t mrcp_engine_open_respond(mrcp_engine_t *engine, apt_bool_t status)
+{
+ return engine->event_vtable->on_open(engine,status);
+}
+
+/** Send engine close response */
+static APR_INLINE apt_bool_t mrcp_engine_close_respond(mrcp_engine_t *engine)
+{
+ return engine->event_vtable->on_close(engine);
+}
+
/** Get engine config */
const mrcp_engine_config_t* mrcp_engine_config_get(const mrcp_engine_t *engine);
@@ -104,18 +118,18 @@ static APR_INLINE const char* mrcp_engine_channel_id_get(mrcp_engine_channel_t *
}
/** Get MRCP version channel is created in the scope of */
-static APR_INLINE mrcp_version_e mrcp_engine_channel_version_get(mrcp_engine_channel_t *channel)
+static APR_INLINE mrcp_version_e mrcp_engine_channel_version_get(const mrcp_engine_channel_t *channel)
{
return channel->mrcp_version;
}
/** Get codec descriptor of the audio source stream */
-const mpf_codec_descriptor_t* mrcp_engine_source_stream_codec_get(mrcp_engine_channel_t *channel);
+const mpf_codec_descriptor_t* mrcp_engine_source_stream_codec_get(const mrcp_engine_channel_t *channel);
/** Get codec descriptor of the audio sink stream */
-const mpf_codec_descriptor_t* mrcp_engine_sink_stream_codec_get(mrcp_engine_channel_t *channel);
+const mpf_codec_descriptor_t* mrcp_engine_sink_stream_codec_get(const mrcp_engine_channel_t *channel);
APT_END_EXTERN_C
-#endif /*__MRCP_ENGINE_IMPL_H__*/
+#endif /* MRCP_ENGINE_IMPL_H */
diff --git a/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_loader.h b/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_loader.h
index a4fc9d2e39..f6a47b8fa2 100644
--- a/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_loader.h
+++ b/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_loader.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_engine_loader.h 1700 2010-05-21 18:56:06Z achaloyan $
*/
-#ifndef __MRCP_ENGINE_LOADER_H__
-#define __MRCP_ENGINE_LOADER_H__
+#ifndef MRCP_ENGINE_LOADER_H
+#define MRCP_ENGINE_LOADER_H
/**
* @file mrcp_engine_loader.h
@@ -40,9 +42,13 @@ MRCP_DECLARE(apt_bool_t) mrcp_engine_loader_plugins_unload(mrcp_engine_loader_t
/** Load engine plugin */
-MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_loader_plugin_load(mrcp_engine_loader_t *loader, const char *path, const char *name);
+MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_loader_plugin_load(
+ mrcp_engine_loader_t *loader,
+ const char *id,
+ const char *path,
+ mrcp_engine_config_t *config);
APT_END_EXTERN_C
-#endif /*__MRCP_ENGINE_LOADER_H__*/
+#endif /* MRCP_ENGINE_LOADER_H */
diff --git a/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_plugin.h b/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_plugin.h
index afa5e334c3..50a5391ef3 100644
--- a/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_plugin.h
+++ b/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_plugin.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_engine_plugin.h 1724 2010-06-02 18:42:20Z achaloyan $
*/
-#ifndef __MRCP_ENGINE_PLUGIN_H__
-#define __MRCP_ENGINE_PLUGIN_H__
+#ifndef MRCP_ENGINE_PLUGIN_H
+#define MRCP_ENGINE_PLUGIN_H
/**
* @file mrcp_engine_plugin.h
@@ -64,13 +66,13 @@ typedef apt_bool_t (*mrcp_plugin_log_accessor_f)(apt_logger_t *logger);
* plugins such as structure size changes. No binary compatibility is
* possible across a change in the major version.
*/
-#define PLUGIN_MAJOR_VERSION 0
+#define PLUGIN_MAJOR_VERSION 1
/** minor version
* Minor API changes that do not cause binary compatibility problems.
* Reset to 0 when upgrading PLUGIN_MAJOR_VERSION
*/
-#define PLUGIN_MINOR_VERSION 6
+#define PLUGIN_MINOR_VERSION 0
/** patch level
* The Patch Level never includes API changes, simply bug fixes.
@@ -113,4 +115,4 @@ static APR_INLINE int mrcp_plugin_version_check(mrcp_plugin_version_t *version)
APT_END_EXTERN_C
-#endif /*__MRCP_ENGINE_PLUGIN_H__*/
+#endif /* MRCP_ENGINE_PLUGIN_H */
diff --git a/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_types.h b/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_types.h
index eec9ec89a5..2187d19829 100644
--- a/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_types.h
+++ b/libs/unimrcp/libs/mrcp-engine/include/mrcp_engine_types.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_engine_types.h 1700 2010-05-21 18:56:06Z achaloyan $
*/
-#ifndef __MRCP_ENGINE_TYPES_H__
-#define __MRCP_ENGINE_TYPES_H__
+#ifndef MRCP_ENGINE_TYPES_H
+#define MRCP_ENGINE_TYPES_H
/**
* @file mrcp_engine_types.h
@@ -35,6 +37,8 @@ typedef struct mrcp_engine_t mrcp_engine_t;
typedef struct mrcp_engine_config_t mrcp_engine_config_t;
/** MRCP engine vtable declaration */
typedef struct mrcp_engine_method_vtable_t mrcp_engine_method_vtable_t;
+/** MRCP engine event vtable declaration */
+typedef struct mrcp_engine_event_vtable_t mrcp_engine_event_vtable_t;
/** MRCP engine channel declaration */
typedef struct mrcp_engine_channel_t mrcp_engine_channel_t;
/** MRCP engine channel virtual method table declaration */
@@ -100,14 +104,28 @@ struct mrcp_engine_method_vtable_t {
mrcp_engine_channel_t* (*create_channel)(mrcp_engine_t *engine, apr_pool_t *pool);
};
+/** Table of MRCP engine virtual event handlers */
+struct mrcp_engine_event_vtable_t {
+ /** Open event handler */
+ apt_bool_t (*on_open)(mrcp_engine_t *channel, apt_bool_t status);
+ /** Close event handler */
+ apt_bool_t (*on_close)(mrcp_engine_t *channel);
+};
+
/** MRCP engine */
struct mrcp_engine_t {
+ /** Identifier of the engine */
+ const char *id;
/** Resource identifier */
mrcp_resource_id resource_id;
/** External object associated with engine */
void *obj;
/** Table of virtual methods */
const mrcp_engine_method_vtable_t *method_vtable;
+ /** Table of virtual event handlers */
+ const mrcp_engine_event_vtable_t *event_vtable;
+ /** External object used with event handlers */
+ void *event_obj;
/** Codec manager */
const mpf_codec_manager_t *codec_manager;
/** Dir layout structure */
@@ -121,15 +139,12 @@ struct mrcp_engine_t {
/** Pool to allocate memory from */
apr_pool_t *pool;
-
/** Create state machine */
mrcp_state_machine_t* (*create_state_machine)(void *obj, mrcp_version_e version, apr_pool_t *pool);
};
/** MRCP engine config */
struct mrcp_engine_config_t {
- /** Name of the engine */
- const char *name;
/** Max number of simultaneous channels */
apr_size_t max_channel_count;
/** Table of name/value string params */
@@ -138,4 +153,4 @@ struct mrcp_engine_config_t {
APT_END_EXTERN_C
-#endif /*__MRCP_ENGINE_TYPES_H__*/
+#endif /* MRCP_ENGINE_TYPES_H */
diff --git a/libs/unimrcp/libs/mrcp-engine/include/mrcp_recog_engine.h b/libs/unimrcp/libs/mrcp-engine/include/mrcp_recog_engine.h
index 2e58c0663c..7a79f7e536 100644
--- a/libs/unimrcp/libs/mrcp-engine/include/mrcp_recog_engine.h
+++ b/libs/unimrcp/libs/mrcp-engine/include/mrcp_recog_engine.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_recog_engine.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_RECOG_ENGINE_H__
-#define __MRCP_RECOG_ENGINE_H__
+#ifndef MRCP_RECOG_ENGINE_H
+#define MRCP_RECOG_ENGINE_H
/**
* @file mrcp_recog_engine.h
@@ -30,4 +32,4 @@
#include "mrcp_generic_header.h"
#include "mrcp_message.h"
-#endif /*__MRCP_RECOG_ENGINE_H__*/
+#endif /* MRCP_RECOG_ENGINE_H */
diff --git a/libs/unimrcp/libs/mrcp-engine/include/mrcp_recog_state_machine.h b/libs/unimrcp/libs/mrcp-engine/include/mrcp_recog_state_machine.h
index 32d5482593..f03ebf13de 100644
--- a/libs/unimrcp/libs/mrcp-engine/include/mrcp_recog_state_machine.h
+++ b/libs/unimrcp/libs/mrcp-engine/include/mrcp_recog_state_machine.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_recog_state_machine.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_RECOG_STATE_MACHINE_H__
-#define __MRCP_RECOG_STATE_MACHINE_H__
+#ifndef MRCP_RECOG_STATE_MACHINE_H
+#define MRCP_RECOG_STATE_MACHINE_H
/**
* @file mrcp_recog_state_machine.h
@@ -31,4 +33,4 @@ mrcp_state_machine_t* mrcp_recog_state_machine_create(void *obj, mrcp_version_e
APT_END_EXTERN_C
-#endif /*__MRCP_RECOG_STATE_MACHINE_H__*/
+#endif /* MRCP_RECOG_STATE_MACHINE_H */
diff --git a/libs/unimrcp/libs/mrcp-engine/include/mrcp_recorder_engine.h b/libs/unimrcp/libs/mrcp-engine/include/mrcp_recorder_engine.h
index 3e4e818d4d..9c2c239145 100644
--- a/libs/unimrcp/libs/mrcp-engine/include/mrcp_recorder_engine.h
+++ b/libs/unimrcp/libs/mrcp-engine/include/mrcp_recorder_engine.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_recorder_engine.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_RECORDER_ENGINE_H__
-#define __MRCP_RECORDER_ENGINE_H__
+#ifndef MRCP_RECORDER_ENGINE_H
+#define MRCP_RECORDER_ENGINE_H
/**
* @file mrcp_recorder_engine.h
@@ -30,4 +32,4 @@
#include "mrcp_generic_header.h"
#include "mrcp_message.h"
-#endif /*__MRCP_RECORDER_ENGINE_H__*/
+#endif /* MRCP_RECORDER_ENGINE_H */
diff --git a/libs/unimrcp/libs/mrcp-engine/include/mrcp_recorder_state_machine.h b/libs/unimrcp/libs/mrcp-engine/include/mrcp_recorder_state_machine.h
index ccd6096d95..2c2f19bb58 100644
--- a/libs/unimrcp/libs/mrcp-engine/include/mrcp_recorder_state_machine.h
+++ b/libs/unimrcp/libs/mrcp-engine/include/mrcp_recorder_state_machine.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_recorder_state_machine.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_RECORDER_STATE_MACHINE_H__
-#define __MRCP_RECORDER_STATE_MACHINE_H__
+#ifndef MRCP_RECORDER_STATE_MACHINE_H
+#define MRCP_RECORDER_STATE_MACHINE_H
/**
* @file mrcp_recorder_state_machine.h
@@ -31,4 +33,4 @@ mrcp_state_machine_t* mrcp_recorder_state_machine_create(void *obj, mrcp_version
APT_END_EXTERN_C
-#endif /*__MRCP_RECORDER_STATE_MACHINE_H__*/
+#endif /* MRCP_RECORDER_STATE_MACHINE_H */
diff --git a/libs/unimrcp/libs/mrcp-engine/include/mrcp_resource_engine.h b/libs/unimrcp/libs/mrcp-engine/include/mrcp_resource_engine.h
index c69e5d0b93..650e47a9e1 100644
--- a/libs/unimrcp/libs/mrcp-engine/include/mrcp_resource_engine.h
+++ b/libs/unimrcp/libs/mrcp-engine/include/mrcp_resource_engine.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_resource_engine.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_RESOURCE_ENGINE_H__
-#define __MRCP_RESOURCE_ENGINE_H__
+#ifndef MRCP_RESOURCE_ENGINE_H
+#define MRCP_RESOURCE_ENGINE_H
/**
* @file mrcp_resource_engine.h
@@ -46,4 +48,4 @@ static APR_INLINE mrcp_engine_t* mrcp_resource_engine_create(
APT_END_EXTERN_C
-#endif /*__MRCP_RESOURCE_ENGINE_H__*/
+#endif /* MRCP_RESOURCE_ENGINE_H */
diff --git a/libs/unimrcp/libs/mrcp-engine/include/mrcp_state_machine.h b/libs/unimrcp/libs/mrcp-engine/include/mrcp_state_machine.h
index 4089a8bd07..a34a280443 100644
--- a/libs/unimrcp/libs/mrcp-engine/include/mrcp_state_machine.h
+++ b/libs/unimrcp/libs/mrcp-engine/include/mrcp_state_machine.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_state_machine.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_STATE_MACHINE_H__
-#define __MRCP_STATE_MACHINE_H__
+#ifndef MRCP_STATE_MACHINE_H
+#define MRCP_STATE_MACHINE_H
/**
* @file mrcp_state_machine.h
@@ -81,4 +83,4 @@ static APR_INLINE apt_bool_t mrcp_state_machine_deactivate(mrcp_state_machine_t
APT_END_EXTERN_C
-#endif /*__MRCP_STATE_MACHINE_H__*/
+#endif /* MRCP_STATE_MACHINE_H */
diff --git a/libs/unimrcp/libs/mrcp-engine/include/mrcp_synth_engine.h b/libs/unimrcp/libs/mrcp-engine/include/mrcp_synth_engine.h
index 305f7eadaa..8cdc18dcef 100644
--- a/libs/unimrcp/libs/mrcp-engine/include/mrcp_synth_engine.h
+++ b/libs/unimrcp/libs/mrcp-engine/include/mrcp_synth_engine.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_synth_engine.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_SYNTH_ENGINE_H__
-#define __MRCP_SYNTH_ENGINE_H__
+#ifndef MRCP_SYNTH_ENGINE_H
+#define MRCP_SYNTH_ENGINE_H
/**
* @file mrcp_synth_engine.h
@@ -30,4 +32,4 @@
#include "mrcp_generic_header.h"
#include "mrcp_message.h"
-#endif /*__MRCP_SYNTH_ENGINE_H__*/
+#endif /* MRCP_SYNTH_ENGINE_H */
diff --git a/libs/unimrcp/libs/mrcp-engine/include/mrcp_synth_state_machine.h b/libs/unimrcp/libs/mrcp-engine/include/mrcp_synth_state_machine.h
index efe26dcc73..08ae5716c1 100644
--- a/libs/unimrcp/libs/mrcp-engine/include/mrcp_synth_state_machine.h
+++ b/libs/unimrcp/libs/mrcp-engine/include/mrcp_synth_state_machine.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_synth_state_machine.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_SYNTH_STATE_MACHINE_H__
-#define __MRCP_SYNTH_STATE_MACHINE_H__
+#ifndef MRCP_SYNTH_STATE_MACHINE_H
+#define MRCP_SYNTH_STATE_MACHINE_H
/**
* @file mrcp_synth_state_machine.h
@@ -31,4 +33,4 @@ mrcp_state_machine_t* mrcp_synth_state_machine_create(void *obj, mrcp_version_e
APT_END_EXTERN_C
-#endif /*__MRCP_SYNTH_STATE_MACHINE_H__*/
+#endif /* MRCP_SYNTH_STATE_MACHINE_H */
diff --git a/libs/unimrcp/libs/mrcp-engine/include/mrcp_verifier_engine.h b/libs/unimrcp/libs/mrcp-engine/include/mrcp_verifier_engine.h
new file mode 100644
index 0000000000..20e4de31f1
--- /dev/null
+++ b/libs/unimrcp/libs/mrcp-engine/include/mrcp_verifier_engine.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: mrcp_verifier_engine.h 1755 2010-08-18 19:35:08Z achaloyan $
+ */
+
+#ifndef MRCP_VERIFIER_ENGINE_H
+#define MRCP_VERIFIER_ENGINE_H
+
+/**
+ * @file mrcp_verifier_engine.h
+ * @brief Verifier Engine Includes
+ */
+
+#include "mrcp_engine_plugin.h"
+#include "mrcp_engine_impl.h"
+
+#include "mrcp_verifier_resource.h"
+#include "mrcp_verifier_header.h"
+#include "mrcp_generic_header.h"
+#include "mrcp_message.h"
+
+#endif /* MRCP_VERIFIER_ENGINE_H */
diff --git a/libs/unimrcp/libs/mrcp-engine/include/mrcp_verifier_state_machine.h b/libs/unimrcp/libs/mrcp-engine/include/mrcp_verifier_state_machine.h
new file mode 100644
index 0000000000..a3b5e8e2b4
--- /dev/null
+++ b/libs/unimrcp/libs/mrcp-engine/include/mrcp_verifier_state_machine.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: mrcp_verifier_state_machine.h 1755 2010-08-18 19:35:08Z achaloyan $
+ */
+
+#ifndef MRCP_VERIFIER_STATE_MACHINE_H
+#define MRCP_VERIFIER_STATE_MACHINE_H
+
+/**
+ * @file mrcp_verifier_state_machine.h
+ * @brief MRCP Verifier State Machine
+ */
+
+#include "mrcp_state_machine.h"
+
+APT_BEGIN_EXTERN_C
+
+/** Create MRCP verifier state machine */
+mrcp_state_machine_t* mrcp_verifier_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool);
+
+APT_END_EXTERN_C
+
+#endif /* MRCP_VERIFIER_STATE_MACHINE_H */
diff --git a/libs/unimrcp/libs/mrcp-engine/mrcpengine.2008.vcproj b/libs/unimrcp/libs/mrcp-engine/mrcpengine.2008.vcproj
deleted file mode 100644
index fbc62b016a..0000000000
--- a/libs/unimrcp/libs/mrcp-engine/mrcpengine.2008.vcproj
+++ /dev/null
@@ -1,154 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/libs/mrcp-engine/mrcpengine.vcproj b/libs/unimrcp/libs/mrcp-engine/mrcpengine.vcproj
index c5b163eae1..8966705a4e 100644
--- a/libs/unimrcp/libs/mrcp-engine/mrcpengine.vcproj
+++ b/libs/unimrcp/libs/mrcp-engine/mrcpengine.vcproj
@@ -296,6 +296,14 @@
RelativePath=".\include\mrcp_synth_state_machine.h"
>
+
+
+
+
+
+
diff --git a/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_factory.c b/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_factory.c
index 2faaabfd2c..8de989af0a 100644
--- a/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_factory.c
+++ b/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_factory.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_engine_factory.c 1761 2010-08-20 17:35:28Z achaloyan $
*/
#include
@@ -19,6 +21,7 @@
#include "mrcp_synth_state_machine.h"
#include "mrcp_recog_state_machine.h"
#include "mrcp_recorder_state_machine.h"
+#include "mrcp_verifier_state_machine.h"
#include "apt_log.h"
/** Engine factory declaration */
@@ -61,7 +64,6 @@ MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_open(mrcp_engine_factory_t *factory
mrcp_engine_t *engine;
apr_hash_index_t *it;
void *val;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Open MRCP Engines");
it = apr_hash_first(factory->pool,factory->engines);
for(; it; it = apr_hash_next(it)) {
apr_hash_this(it,NULL,NULL,&val);
@@ -79,7 +81,6 @@ MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_close(mrcp_engine_factory_t *factor
mrcp_engine_t *engine;
apr_hash_index_t *it;
void *val;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Close MRCP Engines");
it=apr_hash_first(factory->pool,factory->engines);
for(; it; it = apr_hash_next(it)) {
apr_hash_this(it,NULL,NULL,&val);
@@ -92,9 +93,9 @@ MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_close(mrcp_engine_factory_t *factor
}
/** Register new engine */
-MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_engine_register(mrcp_engine_factory_t *factory, mrcp_engine_t *engine, const char *name)
+MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_engine_register(mrcp_engine_factory_t *factory, mrcp_engine_t *engine)
{
- if(!engine || !name) {
+ if(!engine || !engine->id) {
return FALSE;
}
@@ -108,6 +109,9 @@ MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_engine_register(mrcp_engine_factory
case MRCP_RECORDER_RESOURCE:
engine->create_state_machine = mrcp_recorder_state_machine_create;
break;
+ case MRCP_VERIFIER_RESOURCE:
+ engine->create_state_machine = mrcp_verifier_state_machine_create;
+ break;
default:
break;
}
@@ -116,12 +120,12 @@ MRCP_DECLARE(apt_bool_t) mrcp_engine_factory_engine_register(mrcp_engine_factory
return FALSE;
}
- apr_hash_set(factory->engines,name,APR_HASH_KEY_STRING,engine);
+ apr_hash_set(factory->engines,engine->id,APR_HASH_KEY_STRING,engine);
return TRUE;
}
/** Get engine by name */
-MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_factory_engine_get(mrcp_engine_factory_t *factory, const char *name)
+MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_factory_engine_get(const mrcp_engine_factory_t *factory, const char *name)
{
if(!name) {
return NULL;
@@ -130,7 +134,7 @@ MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_factory_engine_get(mrcp_engine_factory_
}
/** Find engine by resource identifier */
-MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_factory_engine_find(mrcp_engine_factory_t *factory, mrcp_resource_id resource_id)
+MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_factory_engine_find(const mrcp_engine_factory_t *factory, mrcp_resource_id resource_id)
{
mrcp_engine_t *engine;
void *val;
@@ -145,3 +149,9 @@ MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_factory_engine_find(mrcp_engine_factory
}
return NULL;
}
+
+/** Start iterating over the engines in a factory */
+MRCP_DECLARE(apr_hash_index_t*) mrcp_engine_factory_engine_first(const mrcp_engine_factory_t *factory)
+{
+ return apr_hash_first(factory->pool,factory->engines);
+}
diff --git a/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_iface.c b/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_iface.c
index 137af17827..e8f45a4f98 100644
--- a/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_iface.c
+++ b/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_iface.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,9 +12,55 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_engine_iface.c 1700 2010-05-21 18:56:06Z achaloyan $
*/
#include "mrcp_engine_iface.h"
+#include "apt_log.h"
+
+/** Destroy engine */
+apt_bool_t mrcp_engine_virtual_destroy(mrcp_engine_t *engine)
+{
+ return engine->method_vtable->destroy(engine);
+}
+
+/** Open engine */
+apt_bool_t mrcp_engine_virtual_open(mrcp_engine_t *engine)
+{
+ if(engine->is_open == FALSE) {
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Open Engine [%s]",engine->id);
+ return engine->method_vtable->open(engine);
+ }
+ return FALSE;
+}
+
+/** Response to open engine request */
+void mrcp_engine_on_open(mrcp_engine_t *engine, apt_bool_t status)
+{
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Engine Opened [%s] status [%s]",
+ engine->id,
+ status == TRUE ? "success" : "failure");
+ engine->is_open = status;
+}
+
+/** Close engine */
+apt_bool_t mrcp_engine_virtual_close(mrcp_engine_t *engine)
+{
+ if(engine->is_open == TRUE) {
+ engine->is_open = FALSE;
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Close Engine [%s]",engine->id);
+ return engine->method_vtable->close(engine);
+ }
+ return FALSE;
+}
+
+/** Response to close engine request */
+void mrcp_engine_on_close(mrcp_engine_t *engine)
+{
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Engine Closed [%s]",engine->id);
+ engine->is_open = FALSE;
+}
/** Create engine channel */
mrcp_engine_channel_t* mrcp_engine_channel_virtual_create(mrcp_engine_t *engine, mrcp_version_e mrcp_version, apr_pool_t *pool)
@@ -48,7 +94,6 @@ apt_bool_t mrcp_engine_channel_virtual_destroy(mrcp_engine_channel_t *channel)
mrcp_engine_config_t* mrcp_engine_config_alloc(apr_pool_t *pool)
{
mrcp_engine_config_t *config = apr_palloc(pool,sizeof(mrcp_engine_config_t));
- config->name = NULL;
config->max_channel_count = 0;
config->params = NULL;
return config;
diff --git a/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_impl.c b/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_impl.c
index e2c7a24dae..969dee4675 100644
--- a/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_impl.c
+++ b/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_impl.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_engine_impl.c 1710 2010-05-24 17:36:19Z achaloyan $
*/
#include "mrcp_engine_impl.h"
@@ -25,9 +27,12 @@ mrcp_engine_t* mrcp_engine_create(
apr_pool_t *pool)
{
mrcp_engine_t *engine = apr_palloc(pool,sizeof(mrcp_engine_t));
+ engine->id = NULL;
engine->resource_id = resource_id;
engine->obj = obj;
engine->method_vtable =vtable;
+ engine->event_vtable = NULL;
+ engine->event_obj = NULL;
engine->config = NULL;
engine->codec_manager = NULL;
engine->dir_layout = NULL;
@@ -217,7 +222,7 @@ mrcp_engine_channel_t* mrcp_engine_sink_channel_create(
}
/** Get codec descriptor of the audio source stream */
-const mpf_codec_descriptor_t* mrcp_engine_source_stream_codec_get(mrcp_engine_channel_t *channel)
+const mpf_codec_descriptor_t* mrcp_engine_source_stream_codec_get(const mrcp_engine_channel_t *channel)
{
if(channel && channel->termination) {
mpf_audio_stream_t *audio_stream = mpf_termination_audio_stream_get(channel->termination);
@@ -229,7 +234,7 @@ const mpf_codec_descriptor_t* mrcp_engine_source_stream_codec_get(mrcp_engine_ch
}
/** Get codec descriptor of the audio sink stream */
-const mpf_codec_descriptor_t* mrcp_engine_sink_stream_codec_get(mrcp_engine_channel_t *channel)
+const mpf_codec_descriptor_t* mrcp_engine_sink_stream_codec_get(const mrcp_engine_channel_t *channel)
{
if(channel && channel->termination) {
mpf_audio_stream_t *audio_stream = mpf_termination_audio_stream_get(channel->termination);
diff --git a/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_loader.c b/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_loader.c
index dfa5bd617a..da29170d65 100644
--- a/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_loader.c
+++ b/libs/unimrcp/libs/mrcp-engine/src/mrcp_engine_loader.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_engine_loader.c 1700 2010-05-21 18:56:06Z achaloyan $
*/
#include
@@ -121,17 +123,17 @@ static apt_bool_t plugin_logger_load(apr_dso_handle_t *plugin)
/** Load engine plugin */
-MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_loader_plugin_load(mrcp_engine_loader_t *loader, const char *path, const char *name)
+MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_loader_plugin_load(mrcp_engine_loader_t *loader, const char *id, const char *path, mrcp_engine_config_t *config)
{
apr_dso_handle_t *plugin = NULL;
mrcp_plugin_creator_f plugin_creator = NULL;
mrcp_engine_t *engine = NULL;
- if(!path || !name) {
+ if(!path || !id) {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Load Plugin: invalid params");
return NULL;
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Load Plugin [%s] [%s]",path,name);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Load Plugin [%s] [%s]",id,path);
if(apr_dso_load(&plugin,path,loader->pool) != APR_SUCCESS) {
char derr[512] = "";
apr_dso_error(plugin,derr,sizeof(derr));
@@ -153,12 +155,14 @@ MRCP_DECLARE(mrcp_engine_t*) mrcp_engine_loader_plugin_load(mrcp_engine_loader_t
plugin_logger_load(plugin);
- apr_hash_set(loader->plugins,name,APR_HASH_KEY_STRING,plugin);
+ apr_hash_set(loader->plugins,id,APR_HASH_KEY_STRING,plugin);
engine = plugin_creator(loader->pool);
if(!engine) {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create MRCP Engine");
}
-
+
+ engine->id = id;
+ engine->config = config;
return engine;
}
diff --git a/libs/unimrcp/libs/mrcp-engine/src/mrcp_recog_state_machine.c b/libs/unimrcp/libs/mrcp-engine/src/mrcp_recog_state_machine.c
index 1965192d96..50ddb972cb 100644
--- a/libs/unimrcp/libs/mrcp-engine/src/mrcp_recog_state_machine.c
+++ b/libs/unimrcp/libs/mrcp-engine/src/mrcp_recog_state_machine.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_recog_state_machine.c 1782 2010-09-06 17:52:41Z achaloyan $
*/
#include "apt_obj_list.h"
@@ -41,19 +43,19 @@ static const char * state_names[RECOGNIZER_STATE_COUNT] = {
typedef struct mrcp_recog_state_machine_t mrcp_recog_state_machine_t;
struct mrcp_recog_state_machine_t {
/** state machine base */
- mrcp_state_machine_t base;
+ mrcp_state_machine_t base;
/** recognizer state */
- mrcp_recog_state_e state;
+ mrcp_recog_state_e state;
/** indicate whether active_request was processed from pending request queue */
- apt_bool_t is_pending;
+ apt_bool_t is_pending;
/** request sent to recognition engine and waiting for the response to be received */
- mrcp_message_t *active_request;
+ mrcp_message_t *active_request;
/** in-progress recognize request */
- mrcp_message_t *recog;
+ mrcp_message_t *recog;
/** queue of pending recognition requests */
- apt_obj_list_t *queue;
+ apt_obj_list_t *queue;
/** properties used in set/get params */
- mrcp_message_header_t properties;
+ mrcp_message_header_t *properties;
};
typedef apt_bool_t (*recog_method_f)(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message);
@@ -83,9 +85,12 @@ static APR_INLINE apt_bool_t recog_event_dispatch(mrcp_recog_state_machine_t *st
return state_machine->base.on_dispatch(&state_machine->base,message);
}
-static APR_INLINE void recog_state_change(mrcp_recog_state_machine_t *state_machine, mrcp_recog_state_e state)
+static APR_INLINE void recog_state_change(mrcp_recog_state_machine_t *state_machine, mrcp_recog_state_e state, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"State Transition %s -> %s",state_names[state_machine->state],state_names[state]);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"State Transition %s -> %s "APT_SIDRES_FMT,
+ state_names[state_machine->state],
+ state_names[state],
+ MRCP_MESSAGE_SIDRES(message));
state_machine->state = state;
if(state == RECOGNIZER_STATE_IDLE) {
state_machine->recog = NULL;
@@ -95,32 +100,24 @@ static APR_INLINE void recog_state_change(mrcp_recog_state_machine_t *state_mach
static apt_bool_t recog_request_set_params(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process SET-PARAMS Request [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
- mrcp_message_header_set(&state_machine->properties,&message->header,message->pool);
+ mrcp_header_fields_set(state_machine->properties,&message->header,message->pool);
return recog_request_dispatch(state_machine,message);
}
static apt_bool_t recog_response_set_params(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process SET-PARAMS Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return recog_response_dispatch(state_machine,message);
}
static apt_bool_t recog_request_get_params(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process GET-PARAMS Request [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return recog_request_dispatch(state_machine,message);
}
static apt_bool_t recog_response_get_params(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process GET-PARAMS Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
- mrcp_message_header_set(&message->header,&state_machine->active_request->header,message->pool);
- mrcp_message_header_get(&message->header,&state_machine->properties,message->pool);
+ mrcp_header_fields_set(&message->header,&state_machine->active_request->header,message->pool);
+ mrcp_header_fields_get(&message->header,state_machine->properties,message->pool);
return recog_response_dispatch(state_machine,message);
}
@@ -132,18 +129,14 @@ static apt_bool_t recog_request_define_grammar(mrcp_recog_state_machine_t *state
return recog_response_dispatch(state_machine,response_message);
}
else if(state_machine->state == RECOGNIZER_STATE_RECOGNIZED) {
- recog_state_change(state_machine,RECOGNIZER_STATE_IDLE);
+ recog_state_change(state_machine,RECOGNIZER_STATE_IDLE,message);
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process DEFINE-GRAMMAR Request [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return recog_request_dispatch(state_machine,message);
}
static apt_bool_t recog_response_define_grammar(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process DEFINE-GRAMMAR Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
if(mrcp_resource_header_property_check(message,RECOGNIZER_HEADER_COMPLETION_CAUSE) != TRUE) {
mrcp_recog_header_t *recog_header = mrcp_resource_header_prepare(message);
recog_header->completion_cause = RECOGNIZER_COMPLETION_CAUSE_SUCCESS;
@@ -154,10 +147,11 @@ static apt_bool_t recog_response_define_grammar(mrcp_recog_state_machine_t *stat
static apt_bool_t recog_request_recognize(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
{
- mrcp_message_header_inherit(&message->header,&state_machine->properties,message->pool);
+ mrcp_header_fields_inherit(&message->header,state_machine->properties,message->pool);
if(state_machine->state == RECOGNIZER_STATE_RECOGNIZING) {
mrcp_message_t *response;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Queue Up RECOGNIZE Request [%"MRCP_REQUEST_ID_FMT"]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Queue Up RECOGNIZE Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
message->start_line.request_id);
message->start_line.request_state = MRCP_REQUEST_STATE_PENDING;
apt_list_push_back(state_machine->queue,message,message->pool);
@@ -167,18 +161,14 @@ static apt_bool_t recog_request_recognize(mrcp_recog_state_machine_t *state_mach
return recog_response_dispatch(state_machine,response);
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process RECOGNIZE Request [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return recog_request_dispatch(state_machine,message);
}
static apt_bool_t recog_response_recognize(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process RECOGNIZE Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
if(message->start_line.request_state == MRCP_REQUEST_STATE_INPROGRESS) {
state_machine->recog = state_machine->active_request;
- recog_state_change(state_machine,RECOGNIZER_STATE_RECOGNIZING);
+ recog_state_change(state_machine,RECOGNIZER_STATE_RECOGNIZING,message);
}
if(state_machine->is_pending == TRUE) {
state_machine->is_pending = FALSE;
@@ -188,13 +178,22 @@ static apt_bool_t recog_response_recognize(mrcp_recog_state_machine_t *state_mac
return recog_response_dispatch(state_machine,message);
}
+static apt_bool_t recog_request_interpret(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ mrcp_header_fields_inherit(&message->header,state_machine->properties,message->pool);
+ return recog_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t recog_response_interpret(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ return recog_response_dispatch(state_machine,message);
+}
+
static apt_bool_t recog_request_get_result(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
{
mrcp_message_t *response_message;
if(state_machine->state == RECOGNIZER_STATE_RECOGNIZED) {
/* found recognized request */
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process GET-RESULT Request [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return recog_request_dispatch(state_machine,message);
}
@@ -206,8 +205,6 @@ static apt_bool_t recog_request_get_result(mrcp_recog_state_machine_t *state_mac
static apt_bool_t recog_response_get_result(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process GET-RESULT Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return recog_response_dispatch(state_machine,message);
}
@@ -216,8 +213,6 @@ static apt_bool_t recog_request_recognition_start_timers(mrcp_recog_state_machin
mrcp_message_t *response_message;
if(state_machine->state == RECOGNIZER_STATE_RECOGNIZING) {
/* found in-progress request */
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process START-INPUT-TIMERS Request [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return recog_request_dispatch(state_machine,message);
}
@@ -229,8 +224,6 @@ static apt_bool_t recog_request_recognition_start_timers(mrcp_recog_state_machin
static apt_bool_t recog_response_recognition_start_timers(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process START-INPUT-TIMERS Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return recog_response_dispatch(state_machine,message);
}
@@ -252,7 +245,9 @@ static apt_bool_t recog_pending_requests_remove(mrcp_recog_state_machine_t *stat
while(elem) {
pending_message = apt_list_elem_object_get(elem);
if(!request_id_list || active_request_id_list_find(generic_header,pending_message->start_line.request_id) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Remove Pending RECOGNIZE Request [%d]",pending_message->start_line.request_id);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Remove Pending RECOGNIZE Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(pending_message),
+ pending_message->start_line.request_id);
elem = apt_list_elem_remove(state_machine->queue,elem);
/* append active id list */
active_request_id_list_append(response_generic_header,pending_message->start_line.request_id);
@@ -283,13 +278,14 @@ static apt_bool_t recog_request_stop(mrcp_recog_state_machine_t *state_machine,
if(!request_id_list || active_request_id_list_find(generic_header,state_machine->recog->start_line.request_id) == TRUE) {
/* found in-progress RECOGNIZE request, stop it */
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process STOP Request [%"MRCP_REQUEST_ID_FMT"]",
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Found IN-PROGRESS RECOGNIZE Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
message->start_line.request_id);
return recog_request_dispatch(state_machine,message);
}
}
else if(state_machine->state == RECOGNIZER_STATE_RECOGNIZED) {
- recog_state_change(state_machine,RECOGNIZER_STATE_IDLE);
+ recog_state_change(state_machine,RECOGNIZER_STATE_IDLE,message);
}
/* found no in-progress RECOGNIZE request, sending immediate response */
@@ -302,19 +298,19 @@ static apt_bool_t recog_response_stop(mrcp_recog_state_machine_t *state_machine,
{
mrcp_message_t *pending_request;
mrcp_generic_header_t *generic_header = mrcp_generic_header_prepare(message);
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process STOP Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
/* append active id list */
active_request_id_list_append(generic_header,state_machine->recog->start_line.request_id);
mrcp_generic_header_property_add(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
recog_pending_requests_remove(state_machine,state_machine->active_request,message);
- recog_state_change(state_machine,RECOGNIZER_STATE_IDLE);
+ recog_state_change(state_machine,RECOGNIZER_STATE_IDLE,message);
pending_request = apt_list_pop_front(state_machine->queue);
recog_response_dispatch(state_machine,message);
/* process pending RECOGNIZE requests / if any */
if(pending_request) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process Pending RECOGNIZE Request [%d]",pending_request->start_line.request_id);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process Pending RECOGNIZE Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(pending_request),
+ pending_request->start_line.request_id);
state_machine->is_pending = TRUE;
recog_request_dispatch(state_machine,pending_request);
}
@@ -333,8 +329,6 @@ static apt_bool_t recog_event_start_of_input(mrcp_recog_state_machine_t *state_m
return FALSE;
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process START-OF-INPUT Event [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
message->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
return recog_event_dispatch(state_machine,message);
}
@@ -343,47 +337,62 @@ static apt_bool_t recog_event_recognition_complete(mrcp_recog_state_machine_t *s
{
mrcp_message_t *pending_request;
if(!state_machine->recog) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Unexpected RECOGNITION-COMPLETE Event [%"MRCP_REQUEST_ID_FMT"]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Unexpected RECOGNITION-COMPLETE Event "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
message->start_line.request_id);
return FALSE;
}
if(state_machine->recog->start_line.request_id != message->start_line.request_id) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Unexpected RECOGNITION-COMPLETE Event [%"MRCP_REQUEST_ID_FMT"]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Unexpected RECOGNITION-COMPLETE Event "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
message->start_line.request_id);
return FALSE;
}
if(state_machine->active_request && state_machine->active_request->start_line.method_id == RECOGNIZER_STOP) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Ignore RECOGNITION-COMPLETE Event [%d]: waiting for STOP response",message->start_line.request_id);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Ignore RECOGNITION-COMPLETE Event "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]: waiting for STOP response",
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
return FALSE;
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process RECOGNITION-COMPLETE Event [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
if(mrcp_resource_header_property_check(message,RECOGNIZER_HEADER_COMPLETION_CAUSE) != TRUE) {
mrcp_recog_header_t *recog_header = mrcp_resource_header_prepare(message);
recog_header->completion_cause = RECOGNIZER_COMPLETION_CAUSE_SUCCESS;
mrcp_resource_header_property_add(message,RECOGNIZER_HEADER_COMPLETION_CAUSE);
}
- recog_state_change(state_machine,RECOGNIZER_STATE_RECOGNIZED);
+ recog_state_change(state_machine,RECOGNIZER_STATE_RECOGNIZED,message);
recog_event_dispatch(state_machine,message);
/* process pending RECOGNIZE requests */
pending_request = apt_list_pop_front(state_machine->queue);
if(pending_request) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process Pending RECOGNIZE Request [%d]",pending_request->start_line.request_id);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process Pending RECOGNIZE Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(pending_request),
+ pending_request->start_line.request_id);
state_machine->is_pending = TRUE;
recog_request_dispatch(state_machine,pending_request);
}
return TRUE;
}
+static apt_bool_t recog_event_interpretation_complete(mrcp_recog_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ if(mrcp_resource_header_property_check(message,RECOGNIZER_HEADER_COMPLETION_CAUSE) != TRUE) {
+ mrcp_recog_header_t *recog_header = mrcp_resource_header_prepare(message);
+ recog_header->completion_cause = RECOGNIZER_COMPLETION_CAUSE_SUCCESS;
+ mrcp_resource_header_property_add(message,RECOGNIZER_HEADER_COMPLETION_CAUSE);
+ }
+ return recog_event_dispatch(state_machine,message);
+}
+
static recog_method_f recog_request_method_array[RECOGNIZER_METHOD_COUNT] = {
recog_request_set_params,
recog_request_get_params,
recog_request_define_grammar,
recog_request_recognize,
+ recog_request_interpret,
recog_request_get_result,
recog_request_recognition_start_timers,
recog_request_stop
@@ -394,6 +403,7 @@ static recog_method_f recog_response_method_array[RECOGNIZER_METHOD_COUNT] = {
recog_response_get_params,
recog_response_define_grammar,
recog_response_recognize,
+ recog_response_interpret,
recog_response_get_result,
recog_response_recognition_start_timers,
recog_response_stop
@@ -401,7 +411,8 @@ static recog_method_f recog_response_method_array[RECOGNIZER_METHOD_COUNT] = {
static recog_method_f recog_event_method_array[RECOGNIZER_EVENT_COUNT] = {
recog_event_start_of_input,
- recog_event_recognition_complete
+ recog_event_recognition_complete,
+ recog_event_interpretation_complete
};
/** Update state according to received incoming request from MRCP client */
@@ -412,6 +423,10 @@ static apt_bool_t recog_request_state_update(mrcp_recog_state_machine_t *state_m
return FALSE;
}
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process %s Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ message->start_line.method_name.buf,
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
method = recog_request_method_array[message->start_line.method_id];
if(method) {
return method(state_machine,message);
@@ -436,6 +451,10 @@ static apt_bool_t recog_response_state_update(mrcp_recog_state_machine_t *state_
return FALSE;
}
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process %s Response "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ message->start_line.method_name.buf,
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
method = recog_response_method_array[message->start_line.method_id];
if(method) {
return method(state_machine,message);
@@ -451,6 +470,10 @@ static apt_bool_t recog_event_state_update(mrcp_recog_state_machine_t *state_mac
return FALSE;
}
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process %s Event "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ message->start_line.method_name.buf,
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
method = recog_event_method_array[message->start_line.method_id];
if(method) {
return method(state_machine,message);
@@ -505,7 +528,8 @@ static apt_bool_t recog_state_deactivate(mrcp_state_machine_t *base)
message->start_line.request_id = source->start_line.request_id + 1;
apt_string_set(&message->start_line.method_name,"DEACTIVATE"); /* informative only */
message->header = source->header;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Create and Process STOP Request [%"MRCP_REQUEST_ID_FMT"]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Create and Process STOP Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
message->start_line.request_id);
return recog_request_dispatch(state_machine,message);
}
@@ -513,7 +537,6 @@ static apt_bool_t recog_state_deactivate(mrcp_state_machine_t *base)
/** Create MRCP recognizer state machine */
mrcp_state_machine_t* mrcp_recog_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool)
{
- mrcp_message_header_t *properties;
mrcp_recog_state_machine_t *state_machine = apr_palloc(pool,sizeof(mrcp_recog_state_machine_t));
mrcp_state_machine_init(&state_machine->base,obj);
state_machine->base.update = recog_state_update;
@@ -523,9 +546,9 @@ mrcp_state_machine_t* mrcp_recog_state_machine_create(void *obj, mrcp_version_e
state_machine->active_request = NULL;
state_machine->recog = NULL;
state_machine->queue = apt_list_create(pool);
- properties = &state_machine->properties;
- mrcp_message_header_init(properties);
- properties->generic_header_accessor.vtable = mrcp_generic_header_vtable_get(version);
- properties->resource_header_accessor.vtable = mrcp_recog_header_vtable_get(version);
+ state_machine->properties = mrcp_message_header_create(
+ mrcp_generic_header_vtable_get(version),
+ mrcp_recog_header_vtable_get(version),
+ pool);
return &state_machine->base;
}
diff --git a/libs/unimrcp/libs/mrcp-engine/src/mrcp_recorder_state_machine.c b/libs/unimrcp/libs/mrcp-engine/src/mrcp_recorder_state_machine.c
index 9692d33244..312b4d57c3 100644
--- a/libs/unimrcp/libs/mrcp-engine/src/mrcp_recorder_state_machine.c
+++ b/libs/unimrcp/libs/mrcp-engine/src/mrcp_recorder_state_machine.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_recorder_state_machine.c 1705 2010-05-23 14:04:20Z achaloyan $
*/
#include "apt_obj_list.h"
@@ -39,15 +41,15 @@ typedef struct mrcp_recorder_state_machine_t mrcp_recorder_state_machine_t;
struct mrcp_recorder_state_machine_t {
/** state machine base */
- mrcp_state_machine_t base;
+ mrcp_state_machine_t base;
/** recorder state */
- mrcp_recorder_state_e state;
+ mrcp_recorder_state_e state;
/** request sent to recorder engine and waiting for the response to be received */
- mrcp_message_t *active_request;
+ mrcp_message_t *active_request;
/** in-progress record request */
- mrcp_message_t *record;
+ mrcp_message_t *record;
/** properties used in set/get params */
- mrcp_message_header_t properties;
+ mrcp_message_header_t *properties;
};
typedef apt_bool_t (*recorder_method_f)(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message);
@@ -77,9 +79,12 @@ static APR_INLINE apt_bool_t recorder_event_dispatch(mrcp_recorder_state_machine
return state_machine->base.on_dispatch(&state_machine->base,message);
}
-static APR_INLINE void recorder_state_change(mrcp_recorder_state_machine_t *state_machine, mrcp_recorder_state_e state)
+static APR_INLINE void recorder_state_change(mrcp_recorder_state_machine_t *state_machine, mrcp_recorder_state_e state, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"State Transition %s -> %s",state_names[state_machine->state],state_names[state]);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"State Transition %s -> %s "APT_SIDRES_FMT,
+ state_names[state_machine->state],
+ state_names[state],
+ MRCP_MESSAGE_SIDRES(message));
state_machine->state = state;
if(state == RECORDER_STATE_IDLE) {
state_machine->record = NULL;
@@ -89,41 +94,34 @@ static APR_INLINE void recorder_state_change(mrcp_recorder_state_machine_t *stat
static apt_bool_t recorder_request_set_params(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process SET-PARAMS Request [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
- mrcp_message_header_set(&state_machine->properties,&message->header,message->pool);
+ mrcp_header_fields_set(state_machine->properties,&message->header,message->pool);
return recorder_request_dispatch(state_machine,message);
}
static apt_bool_t recorder_response_set_params(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process SET-PARAMS Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return recorder_response_dispatch(state_machine,message);
}
static apt_bool_t recorder_request_get_params(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process GET-PARAMS Request [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return recorder_request_dispatch(state_machine,message);
}
static apt_bool_t recorder_response_get_params(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process GET-PARAMS Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
- mrcp_message_header_set(&message->header,&state_machine->active_request->header,message->pool);
- mrcp_message_header_get(&message->header,&state_machine->properties,message->pool);
+ mrcp_header_fields_set(&message->header,&state_machine->active_request->header,message->pool);
+ mrcp_header_fields_get(&message->header,state_machine->properties,message->pool);
return recorder_response_dispatch(state_machine,message);
}
static apt_bool_t recorder_request_record(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
{
- mrcp_message_header_inherit(&message->header,&state_machine->properties,message->pool);
+ mrcp_header_fields_inherit(&message->header,state_machine->properties,message->pool);
if(state_machine->state == RECORDER_STATE_RECORDING) {
mrcp_message_t *response;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Reject RECORD Request [%"MRCP_REQUEST_ID_FMT"]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Reject RECORD Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
message->start_line.request_id);
/* there is in-progress request, reject this one */
@@ -132,18 +130,14 @@ static apt_bool_t recorder_request_record(mrcp_recorder_state_machine_t *state_m
return recorder_response_dispatch(state_machine,response);
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process RECORD Request [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return recorder_request_dispatch(state_machine,message);
}
static apt_bool_t recorder_response_record(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process RECORD Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
if(message->start_line.request_state == MRCP_REQUEST_STATE_INPROGRESS) {
state_machine->record = state_machine->active_request;
- recorder_state_change(state_machine,RECORDER_STATE_RECORDING);
+ recorder_state_change(state_machine,RECORDER_STATE_RECORDING,message);
}
return recorder_response_dispatch(state_machine,message);
}
@@ -153,8 +147,6 @@ static apt_bool_t recorder_request_stop(mrcp_recorder_state_machine_t *state_mac
mrcp_message_t *response;
if(state_machine->state == RECORDER_STATE_RECORDING) {
/* found in-progress RECORDER request, stop it */
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process STOP Request [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return recorder_request_dispatch(state_machine,message);
}
@@ -166,12 +158,10 @@ static apt_bool_t recorder_request_stop(mrcp_recorder_state_machine_t *state_mac
static apt_bool_t recorder_response_stop(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
{
mrcp_generic_header_t *generic_header = mrcp_generic_header_prepare(message);
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process STOP Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
/* append active id list */
active_request_id_list_append(generic_header,state_machine->record->start_line.request_id);
mrcp_generic_header_property_add(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
- recorder_state_change(state_machine,RECORDER_STATE_IDLE);
+ recorder_state_change(state_machine,RECORDER_STATE_IDLE,message);
return recorder_response_dispatch(state_machine,message);
}
@@ -180,8 +170,6 @@ static apt_bool_t recorder_request_start_timers(mrcp_recorder_state_machine_t *s
mrcp_message_t *response;
if(state_machine->state == RECORDER_STATE_RECORDING) {
/* found in-progress request */
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process START-INPUT-TIMERS Request [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return recorder_request_dispatch(state_machine,message);
}
@@ -193,8 +181,6 @@ static apt_bool_t recorder_request_start_timers(mrcp_recorder_state_machine_t *s
static apt_bool_t recorder_response_start_timers(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process START-INPUT-TIMERS Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return recorder_response_dispatch(state_machine,message);
}
@@ -210,8 +196,6 @@ static apt_bool_t recorder_event_start_of_input(mrcp_recorder_state_machine_t *s
return FALSE;
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process START-OF-INPUT Event [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
message->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
return recorder_event_dispatch(state_machine,message);
}
@@ -219,30 +203,32 @@ static apt_bool_t recorder_event_start_of_input(mrcp_recorder_state_machine_t *s
static apt_bool_t recorder_event_record_complete(mrcp_recorder_state_machine_t *state_machine, mrcp_message_t *message)
{
if(!state_machine->record) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Unexpected RECORD-COMPLETE Event [%"MRCP_REQUEST_ID_FMT"]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Unexpected RECORD-COMPLETE Event "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
message->start_line.request_id);
return FALSE;
}
if(state_machine->record->start_line.request_id != message->start_line.request_id) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Unexpected RECORD-COMPLETE Event [%"MRCP_REQUEST_ID_FMT"]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Unexpected RECORD-COMPLETE Event "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
message->start_line.request_id);
return FALSE;
}
if(state_machine->active_request && state_machine->active_request->start_line.method_id == RECORDER_STOP) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Ignore RECORD-COMPLETE Event [%d]: waiting for STOP response",message->start_line.request_id);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Ignore RECORD-COMPLETE Event "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]: waiting for STOP response",
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
return FALSE;
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process RECORD-COMPLETE Event [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
if(mrcp_resource_header_property_check(message,RECORDER_HEADER_COMPLETION_CAUSE) != TRUE) {
mrcp_recorder_header_t *recorder_header = mrcp_resource_header_prepare(message);
recorder_header->completion_cause = RECORDER_COMPLETION_CAUSE_SUCCESS_SILENCE;
mrcp_resource_header_property_add(message,RECORDER_HEADER_COMPLETION_CAUSE);
}
- recorder_state_change(state_machine,RECORDER_STATE_IDLE);
+ recorder_state_change(state_machine,RECORDER_STATE_IDLE,message);
return recorder_event_dispatch(state_machine,message);
}
@@ -275,6 +261,10 @@ static apt_bool_t recorder_request_state_update(mrcp_recorder_state_machine_t *s
return FALSE;
}
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process %s Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ message->start_line.method_name.buf,
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
method = recorder_request_method_array[message->start_line.method_id];
if(method) {
return method(state_machine,message);
@@ -299,6 +289,10 @@ static apt_bool_t recorder_response_state_update(mrcp_recorder_state_machine_t *
return FALSE;
}
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process %s Response "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ message->start_line.method_name.buf,
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
method = recorder_response_method_array[message->start_line.method_id];
if(method) {
return method(state_machine,message);
@@ -314,6 +308,10 @@ static apt_bool_t recorder_event_state_update(mrcp_recorder_state_machine_t *sta
return FALSE;
}
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process %s Event "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ message->start_line.method_name.buf,
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
method = recorder_event_method_array[message->start_line.method_id];
if(method) {
return method(state_machine,message);
@@ -368,7 +366,8 @@ static apt_bool_t recorder_state_deactivate(mrcp_state_machine_t *base)
message->start_line.request_id = source->start_line.request_id + 1;
apt_string_set(&message->start_line.method_name,"DEACTIVATE"); /* informative only */
message->header = source->header;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Create and Process STOP Request [%"MRCP_REQUEST_ID_FMT"]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Create and Process STOP Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
message->start_line.request_id);
return recorder_request_dispatch(state_machine,message);
}
@@ -376,7 +375,6 @@ static apt_bool_t recorder_state_deactivate(mrcp_state_machine_t *base)
/** Create MRCP recorder state machine */
mrcp_state_machine_t* mrcp_recorder_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool)
{
- mrcp_message_header_t *properties;
mrcp_recorder_state_machine_t *state_machine = apr_palloc(pool,sizeof(mrcp_recorder_state_machine_t));
mrcp_state_machine_init(&state_machine->base,obj);
state_machine->base.update = recorder_state_update;
@@ -384,9 +382,9 @@ mrcp_state_machine_t* mrcp_recorder_state_machine_create(void *obj, mrcp_version
state_machine->state = RECORDER_STATE_IDLE;
state_machine->active_request = NULL;
state_machine->record = NULL;
- properties = &state_machine->properties;
- mrcp_message_header_init(properties);
- properties->generic_header_accessor.vtable = mrcp_generic_header_vtable_get(version);
- properties->resource_header_accessor.vtable = mrcp_recorder_header_vtable_get(version);
+ state_machine->properties = mrcp_message_header_create(
+ mrcp_generic_header_vtable_get(version),
+ mrcp_recorder_header_vtable_get(version),
+ pool);
return &state_machine->base;
}
diff --git a/libs/unimrcp/libs/mrcp-engine/src/mrcp_synth_state_machine.c b/libs/unimrcp/libs/mrcp-engine/src/mrcp_synth_state_machine.c
index 01ff0af30f..523fbd3fbc 100644
--- a/libs/unimrcp/libs/mrcp-engine/src/mrcp_synth_state_machine.c
+++ b/libs/unimrcp/libs/mrcp-engine/src/mrcp_synth_state_machine.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_synth_state_machine.c 1705 2010-05-23 14:04:20Z achaloyan $
*/
#include "apt_obj_list.h"
@@ -41,19 +43,19 @@ static const char * state_names[SYNTHESIZER_STATE_COUNT] = {
typedef struct mrcp_synth_state_machine_t mrcp_synth_state_machine_t;
struct mrcp_synth_state_machine_t {
/** state machine base */
- mrcp_state_machine_t base;
+ mrcp_state_machine_t base;
/** synthesizer state */
- mrcp_synth_state_e state;
+ mrcp_synth_state_e state;
/** indicate whether active_request was processed from pending request queue */
- apt_bool_t is_pending;
+ apt_bool_t is_pending;
/** request sent to synthesizer engine and waiting for the response to be received */
- mrcp_message_t *active_request;
+ mrcp_message_t *active_request;
/** in-progress speak request */
- mrcp_message_t *speaker;
+ mrcp_message_t *speaker;
/** queue of pending speak requests */
- apt_obj_list_t *queue;
+ apt_obj_list_t *queue;
/** properties used in set/get params */
- mrcp_message_header_t properties;
+ mrcp_message_header_t *properties;
};
typedef apt_bool_t (*synth_method_f)(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message);
@@ -83,9 +85,12 @@ static APR_INLINE apt_bool_t synth_event_dispatch(mrcp_synth_state_machine_t *st
return state_machine->base.on_dispatch(&state_machine->base,message);
}
-static APR_INLINE void synth_state_change(mrcp_synth_state_machine_t *state_machine, mrcp_synth_state_e state)
+static APR_INLINE void synth_state_change(mrcp_synth_state_machine_t *state_machine, mrcp_synth_state_e state, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"State Transition %s -> %s",state_names[state_machine->state],state_names[state]);
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"State Transition %s -> %s "APT_SIDRES_FMT,
+ state_names[state_machine->state],
+ state_names[state],
+ MRCP_MESSAGE_SIDRES(message));
state_machine->state = state;
if(state == SYNTHESIZER_STATE_IDLE) {
state_machine->speaker = NULL;
@@ -95,41 +100,34 @@ static APR_INLINE void synth_state_change(mrcp_synth_state_machine_t *state_mach
static apt_bool_t synth_request_set_params(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process SET-PARAMS Request [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
- mrcp_message_header_set(&state_machine->properties,&message->header,message->pool);
+ mrcp_header_fields_set(state_machine->properties,&message->header,message->pool);
return synth_request_dispatch(state_machine,message);
}
static apt_bool_t synth_response_set_params(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process SET-PARAMS Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return synth_response_dispatch(state_machine,message);
}
static apt_bool_t synth_request_get_params(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process GET-PARAMS Request [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return synth_request_dispatch(state_machine,message);
}
static apt_bool_t synth_response_get_params(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process GET-PARAMS Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
- mrcp_message_header_set(&message->header,&state_machine->active_request->header,message->pool);
- mrcp_message_header_get(&message->header,&state_machine->properties,message->pool);
+ mrcp_header_fields_set(&message->header,&state_machine->active_request->header,message->pool);
+ mrcp_header_fields_get(&message->header,state_machine->properties,message->pool);
return synth_response_dispatch(state_machine,message);
}
static apt_bool_t synth_request_speak(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
{
- mrcp_message_header_inherit(&message->header,&state_machine->properties,message->pool);
+ mrcp_header_fields_inherit(&message->header,state_machine->properties,message->pool);
if(state_machine->speaker) {
mrcp_message_t *response;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Queue Up SPEAK Request [%"MRCP_REQUEST_ID_FMT"]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Queue Up SPEAK Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
message->start_line.request_id);
message->start_line.request_state = MRCP_REQUEST_STATE_PENDING;
apt_list_push_back(state_machine->queue,message,message->pool);
@@ -139,18 +137,14 @@ static apt_bool_t synth_request_speak(mrcp_synth_state_machine_t *state_machine,
return synth_response_dispatch(state_machine,response);
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process SPEAK Request [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return synth_request_dispatch(state_machine,message);
}
static apt_bool_t synth_response_speak(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process SPEAK Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
if(message->start_line.request_state == MRCP_REQUEST_STATE_INPROGRESS) {
state_machine->speaker = state_machine->active_request;
- synth_state_change(state_machine,SYNTHESIZER_STATE_SPEAKING);
+ synth_state_change(state_machine,SYNTHESIZER_STATE_SPEAKING,message);
}
if(state_machine->is_pending == TRUE) {
mrcp_message_t *event_message = mrcp_event_create(
@@ -183,7 +177,9 @@ static apt_bool_t synth_pending_requests_remove(mrcp_synth_state_machine_t *stat
while(elem) {
pending_message = apt_list_elem_object_get(elem);
if(!request_id_list || active_request_id_list_find(generic_header,pending_message->start_line.request_id) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Remove Pending SPEAK Request [%d]",pending_message->start_line.request_id);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Remove Pending SPEAK Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(pending_message),
+ pending_message->start_line.request_id);
elem = apt_list_elem_remove(state_machine->queue,elem);
/* append active id list */
active_request_id_list_append(response_generic_header,pending_message->start_line.request_id);
@@ -214,7 +210,8 @@ static apt_bool_t synth_request_stop(mrcp_synth_state_machine_t *state_machine,
if(!request_id_list || active_request_id_list_find(generic_header,state_machine->speaker->start_line.request_id) == TRUE) {
/* found in-progress SPEAK request, stop it */
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process STOP Request [%"MRCP_REQUEST_ID_FMT"]",
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Found IN-PROGRESS SPEAK Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
message->start_line.request_id);
return synth_request_dispatch(state_machine,message);
}
@@ -230,19 +227,19 @@ static apt_bool_t synth_response_stop(mrcp_synth_state_machine_t *state_machine,
{
mrcp_message_t *pending_request;
mrcp_generic_header_t *generic_header = mrcp_generic_header_prepare(message);
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process STOP Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
/* append active id list */
active_request_id_list_append(generic_header,state_machine->speaker->start_line.request_id);
mrcp_generic_header_property_add(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
synth_pending_requests_remove(state_machine,state_machine->active_request,message);
- synth_state_change(state_machine,SYNTHESIZER_STATE_IDLE);
+ synth_state_change(state_machine,SYNTHESIZER_STATE_IDLE,message);
pending_request = apt_list_pop_front(state_machine->queue);
synth_response_dispatch(state_machine,message);
/* process pending SPEAK requests / if any */
if(pending_request) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process Pending SPEAK Request [%d]",pending_request->start_line.request_id);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process Pending SPEAK Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
+ pending_request->start_line.request_id);
state_machine->is_pending = TRUE;
synth_request_dispatch(state_machine,pending_request);
}
@@ -254,7 +251,6 @@ static apt_bool_t synth_request_pause(mrcp_synth_state_machine_t *state_machine,
if(state_machine->speaker) {
/* speaking or paused state */
if(state_machine->state == SYNTHESIZER_STATE_SPEAKING) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process PAUSE Request [%d]",state_machine->speaker->start_line.request_id);
synth_request_dispatch(state_machine,message);
}
else {
@@ -274,14 +270,12 @@ static apt_bool_t synth_request_pause(mrcp_synth_state_machine_t *state_machine,
static apt_bool_t synth_response_pause(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process PAUSE Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
if(message->start_line.status_code == MRCP_STATUS_CODE_SUCCESS) {
mrcp_generic_header_t *generic_header = mrcp_generic_header_prepare(message);
/* append active id list */
active_request_id_list_append(generic_header,state_machine->speaker->start_line.request_id);
mrcp_generic_header_property_add(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
- synth_state_change(state_machine,SYNTHESIZER_STATE_PAUSED);
+ synth_state_change(state_machine,SYNTHESIZER_STATE_PAUSED,message);
}
synth_response_dispatch(state_machine,message);
return TRUE;
@@ -292,7 +286,6 @@ static apt_bool_t synth_request_resume(mrcp_synth_state_machine_t *state_machine
if(state_machine->speaker) {
/* speaking or paused state */
if(state_machine->state == SYNTHESIZER_STATE_PAUSED) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process RESUME Request [%d]",state_machine->speaker->start_line.request_id);
synth_request_dispatch(state_machine,message);
}
else {
@@ -312,14 +305,12 @@ static apt_bool_t synth_request_resume(mrcp_synth_state_machine_t *state_machine
static apt_bool_t synth_response_resume(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process RESUME Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
if(message->start_line.status_code == MRCP_STATUS_CODE_SUCCESS) {
mrcp_generic_header_t *generic_header = mrcp_generic_header_prepare(message);
/* append active id list */
active_request_id_list_append(generic_header,state_machine->speaker->start_line.request_id);
mrcp_generic_header_property_add(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
- synth_state_change(state_machine,SYNTHESIZER_STATE_SPEAKING);
+ synth_state_change(state_machine,SYNTHESIZER_STATE_SPEAKING,message);
}
synth_response_dispatch(state_machine,message);
return TRUE;
@@ -338,8 +329,6 @@ static apt_bool_t synth_request_barge_in_occurred(mrcp_synth_state_machine_t *st
}
if(kill_on_barge_in == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process BARGE-IN Request [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return synth_request_dispatch(state_machine,message);
}
}
@@ -352,13 +341,11 @@ static apt_bool_t synth_request_barge_in_occurred(mrcp_synth_state_machine_t *st
static apt_bool_t synth_response_barge_in_occurred(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
{
mrcp_generic_header_t *generic_header = mrcp_generic_header_prepare(message);
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process BARGE-IN Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
/* append active id list */
active_request_id_list_append(generic_header,state_machine->speaker->start_line.request_id);
mrcp_generic_header_property_add(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
synth_pending_requests_remove(state_machine,state_machine->active_request,message);
- synth_state_change(state_machine,SYNTHESIZER_STATE_IDLE);
+ synth_state_change(state_machine,SYNTHESIZER_STATE_IDLE,message);
return synth_response_dispatch(state_machine,message);
}
@@ -366,8 +353,6 @@ static apt_bool_t synth_request_control(mrcp_synth_state_machine_t *state_machin
{
mrcp_message_t *response_message;
if(state_machine->state == SYNTHESIZER_STATE_SPEAKING) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process CONTROL Request [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return synth_request_dispatch(state_machine,message);
}
@@ -379,8 +364,6 @@ static apt_bool_t synth_request_control(mrcp_synth_state_machine_t *state_machin
static apt_bool_t synth_response_control(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
{
mrcp_generic_header_t *generic_header = mrcp_generic_header_prepare(message);
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process CONTROL Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
/* append active id list */
active_request_id_list_append(generic_header,state_machine->speaker->start_line.request_id);
mrcp_generic_header_property_add(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
@@ -391,8 +374,6 @@ static apt_bool_t synth_request_define_lexicon(mrcp_synth_state_machine_t *state
{
mrcp_message_t *response_message;
if(state_machine->state == SYNTHESIZER_STATE_IDLE) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process DEFINE-LEXICON Request [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return synth_request_dispatch(state_machine,message);
}
@@ -404,8 +385,6 @@ static apt_bool_t synth_request_define_lexicon(mrcp_synth_state_machine_t *state
static apt_bool_t synth_response_define_lexicon(mrcp_synth_state_machine_t *state_machine, mrcp_message_t *message)
{
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process DEFINE-LEXICON Response [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
return synth_response_dispatch(state_machine,message);
}
@@ -421,8 +400,6 @@ static apt_bool_t synth_event_speech_marker(mrcp_synth_state_machine_t *state_ma
return FALSE;
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process SPEECH-MARKER Event [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
message->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
return synth_event_dispatch(state_machine,message);
}
@@ -431,36 +408,40 @@ static apt_bool_t synth_event_speak_complete(mrcp_synth_state_machine_t *state_m
{
mrcp_message_t *pending_request;
if(!state_machine->speaker) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Unexpected SPEAK-COMPLETE Event [%"MRCP_REQUEST_ID_FMT"]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Unexpected SPEAK-COMPLETE Event "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
message->start_line.request_id);
return FALSE;
}
if(state_machine->speaker->start_line.request_id != message->start_line.request_id) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Unexpected SPEAK-COMPLETE Event [%"MRCP_REQUEST_ID_FMT"]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Unexpected SPEAK-COMPLETE Event "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
message->start_line.request_id);
return FALSE;
}
if(state_machine->active_request && state_machine->active_request->start_line.method_id == SYNTHESIZER_STOP) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Ignore SPEAK-COMPLETE Event [%d]: waiting for STOP response",message->start_line.request_id);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Ignore SPEAK-COMPLETE Event "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]: waiting for STOP response",
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
return FALSE;
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process SPEAK-COMPLETE Event [%"MRCP_REQUEST_ID_FMT"]",
- message->start_line.request_id);
if(mrcp_resource_header_property_check(message,SYNTHESIZER_HEADER_COMPLETION_CAUSE) != TRUE) {
mrcp_synth_header_t *synth_header = mrcp_resource_header_prepare(message);
synth_header->completion_cause = SYNTHESIZER_COMPLETION_CAUSE_NORMAL;
mrcp_resource_header_property_add(message,SYNTHESIZER_HEADER_COMPLETION_CAUSE);
}
- synth_state_change(state_machine,SYNTHESIZER_STATE_IDLE);
+ synth_state_change(state_machine,SYNTHESIZER_STATE_IDLE,message);
synth_event_dispatch(state_machine,message);
/* process pending SPEAK requests */
pending_request = apt_list_pop_front(state_machine->queue);
if(pending_request) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process Pending SPEAK Request [%d]",pending_request->start_line.request_id);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process Pending SPEAK Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(pending_request),
+ pending_request->start_line.request_id);
state_machine->is_pending = TRUE;
synth_request_dispatch(state_machine,pending_request);
}
@@ -504,6 +485,10 @@ static apt_bool_t synth_request_state_update(mrcp_synth_state_machine_t *state_m
return FALSE;
}
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process %s Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ message->start_line.method_name.buf,
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
method = synth_request_method_array[message->start_line.method_id];
if(method) {
return method(state_machine,message);
@@ -528,6 +513,10 @@ static apt_bool_t synth_response_state_update(mrcp_synth_state_machine_t *state_
return FALSE;
}
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process %s Response "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ message->start_line.method_name.buf,
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
method = synth_response_method_array[message->start_line.method_id];
if(method) {
return method(state_machine,message);
@@ -543,6 +532,10 @@ static apt_bool_t synth_event_state_update(mrcp_synth_state_machine_t *state_mac
return FALSE;
}
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process %s Event "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ message->start_line.method_name.buf,
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
method = synth_event_method_array[message->start_line.method_id];
if(method) {
return method(state_machine,message);
@@ -594,7 +587,8 @@ static apt_bool_t synth_state_deactivate(mrcp_state_machine_t *base)
message->start_line.request_id = source->start_line.request_id + 1;
apt_string_set(&message->start_line.method_name,"DEACTIVATE"); /* informative only */
message->header = source->header;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Create and Process STOP Request [%"MRCP_REQUEST_ID_FMT"]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Create and Process STOP Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
message->start_line.request_id);
return synth_request_dispatch(state_machine,message);
}
@@ -602,7 +596,6 @@ static apt_bool_t synth_state_deactivate(mrcp_state_machine_t *base)
/** Create MRCP synthesizer state machine */
mrcp_state_machine_t* mrcp_synth_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool)
{
- mrcp_message_header_t *properties;
mrcp_synth_state_machine_t *state_machine = apr_palloc(pool,sizeof(mrcp_synth_state_machine_t));
mrcp_state_machine_init(&state_machine->base,obj);
state_machine->base.update = synth_state_update;
@@ -612,9 +605,9 @@ mrcp_state_machine_t* mrcp_synth_state_machine_create(void *obj, mrcp_version_e
state_machine->active_request = NULL;
state_machine->speaker = NULL;
state_machine->queue = apt_list_create(pool);
- properties = &state_machine->properties;
- mrcp_message_header_init(properties);
- properties->generic_header_accessor.vtable = mrcp_generic_header_vtable_get(version);
- properties->resource_header_accessor.vtable = mrcp_synth_header_vtable_get(version);
+ state_machine->properties = mrcp_message_header_create(
+ mrcp_generic_header_vtable_get(version),
+ mrcp_synth_header_vtable_get(version),
+ pool);
return &state_machine->base;
}
diff --git a/libs/unimrcp/libs/mrcp-engine/src/mrcp_verifier_state_machine.c b/libs/unimrcp/libs/mrcp-engine/src/mrcp_verifier_state_machine.c
new file mode 100644
index 0000000000..335fdc9758
--- /dev/null
+++ b/libs/unimrcp/libs/mrcp-engine/src/mrcp_verifier_state_machine.c
@@ -0,0 +1,525 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: mrcp_verifier_state_machine.c 1756 2010-08-19 19:02:39Z achaloyan $
+ */
+
+#include "apt_obj_list.h"
+#include "apt_log.h"
+#include "mrcp_verifier_state_machine.h"
+#include "mrcp_generic_header.h"
+#include "mrcp_verifier_header.h"
+#include "mrcp_verifier_resource.h"
+#include "mrcp_message.h"
+
+/** MRCP verifier states */
+typedef enum {
+ VERIFIER_STATE_IDLE,
+ VERIFIER_STATE_OPENED,
+ VERIFIER_STATE_VERIFYING,
+
+ VERIFIER_STATE_COUNT
+} mrcp_verifier_state_e;
+
+static const char * state_names[VERIFIER_STATE_COUNT] = {
+ "IDLE",
+ "OPENED",
+ "VERIFYING"
+};
+
+typedef struct mrcp_verifier_state_machine_t mrcp_verifier_state_machine_t;
+
+struct mrcp_verifier_state_machine_t {
+ /** state machine base */
+ mrcp_state_machine_t base;
+ /** verifier state */
+ mrcp_verifier_state_e state;
+ /** request sent to verification engine and waiting for the response to be received */
+ mrcp_message_t *active_request;
+ /** in-progress verify request */
+ mrcp_message_t *verify;
+ /** properties used in set/get params */
+ mrcp_message_header_t *properties;
+};
+
+typedef apt_bool_t (*verifier_method_f)(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message);
+
+static APR_INLINE apt_bool_t verifier_request_dispatch(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ state_machine->active_request = message;
+ return state_machine->base.on_dispatch(&state_machine->base,message);
+}
+
+static APR_INLINE apt_bool_t verifier_response_dispatch(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ state_machine->active_request = NULL;
+ if(state_machine->base.active == FALSE) {
+ /* this is the response to deactivation (STOP) request */
+ return state_machine->base.on_deactivate(&state_machine->base);
+ }
+ return state_machine->base.on_dispatch(&state_machine->base,message);
+}
+
+static APR_INLINE apt_bool_t verifier_event_dispatch(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ if(state_machine->base.active == FALSE) {
+ /* do nothing, state machine has already been deactivated */
+ return FALSE;
+ }
+ return state_machine->base.on_dispatch(&state_machine->base,message);
+}
+
+static APR_INLINE void verifier_state_change(mrcp_verifier_state_machine_t *state_machine, mrcp_verifier_state_e state, mrcp_message_t *message)
+{
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"State Transition %s -> %s "APT_SIDRES_FMT,
+ state_names[state_machine->state],
+ state_names[state],
+ MRCP_MESSAGE_SIDRES(message));
+ state_machine->state = state;
+ if(state == VERIFIER_STATE_IDLE) {
+ state_machine->verify = NULL;
+ }
+}
+
+
+static apt_bool_t verifier_request_set_params(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ mrcp_header_fields_set(state_machine->properties,&message->header,message->pool);
+ return verifier_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_response_set_params(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ return verifier_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_request_get_params(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ return verifier_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_response_get_params(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ mrcp_header_fields_set(&message->header,&state_machine->active_request->header,message->pool);
+ mrcp_header_fields_get(&message->header,state_machine->properties,message->pool);
+ return verifier_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_request_start_session(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ if(state_machine->state == VERIFIER_STATE_VERIFYING) {
+ mrcp_message_t *response_message = mrcp_response_create(message,message->pool);
+ response_message->start_line.status_code = MRCP_STATUS_CODE_METHOD_NOT_VALID;
+ return verifier_response_dispatch(state_machine,response_message);
+ }
+
+ return verifier_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_response_start_session(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ verifier_state_change(state_machine,VERIFIER_STATE_OPENED,message);
+
+ return verifier_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_request_end_session(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ if(state_machine->state == VERIFIER_STATE_IDLE) {
+ mrcp_message_t *response_message = mrcp_response_create(message,message->pool);
+ response_message->start_line.status_code = MRCP_STATUS_CODE_METHOD_NOT_VALID;
+ return verifier_response_dispatch(state_machine,response_message);
+ }
+
+ return verifier_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_response_end_session(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ verifier_state_change(state_machine,VERIFIER_STATE_IDLE,message);
+
+ return verifier_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_request_query_voiceprint(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ if(state_machine->state == VERIFIER_STATE_IDLE) {
+ mrcp_message_t *response_message = mrcp_response_create(message,message->pool);
+ response_message->start_line.status_code = MRCP_STATUS_CODE_METHOD_NOT_VALID;
+ return verifier_response_dispatch(state_machine,response_message);
+ }
+
+ return verifier_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_response_query_voiceprint(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+
+ return verifier_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_request_delete_voiceprint(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ if(state_machine->state == VERIFIER_STATE_IDLE) {
+ mrcp_message_t *response_message = mrcp_response_create(message,message->pool);
+ response_message->start_line.status_code = MRCP_STATUS_CODE_METHOD_NOT_VALID;
+ return verifier_response_dispatch(state_machine,response_message);
+ }
+
+ return verifier_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_response_delete_voiceprint(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ return verifier_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_request_verify(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ if(state_machine->state == VERIFIER_STATE_IDLE || state_machine->state == VERIFIER_STATE_VERIFYING) {
+ mrcp_message_t *response_message = mrcp_response_create(message,message->pool);
+ response_message->start_line.status_code = MRCP_STATUS_CODE_METHOD_NOT_VALID;
+ return verifier_response_dispatch(state_machine,response_message);
+ }
+
+ state_machine->verify = message;
+ return verifier_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_response_verify(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ verifier_state_change(state_machine,VERIFIER_STATE_VERIFYING,message);
+
+ return verifier_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_request_verify_from_buffer(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ if(state_machine->state == VERIFIER_STATE_IDLE || state_machine->state == VERIFIER_STATE_VERIFYING) {
+ mrcp_message_t *response_message = mrcp_response_create(message,message->pool);
+ response_message->start_line.status_code = MRCP_STATUS_CODE_METHOD_NOT_VALID;
+ return verifier_response_dispatch(state_machine,response_message);
+ }
+
+ state_machine->verify = message;
+ return verifier_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_response_verify_from_buffer(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ verifier_state_change(state_machine,VERIFIER_STATE_VERIFYING,message);
+
+ return verifier_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_request_verify_rollback(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ return verifier_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_response_verify_rollback(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ return verifier_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_request_stop(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ if(state_machine->state == VERIFIER_STATE_IDLE) {
+ mrcp_message_t *response_message = mrcp_response_create(message,message->pool);
+ response_message->start_line.status_code = MRCP_STATUS_CODE_METHOD_NOT_VALID;
+ return verifier_response_dispatch(state_machine,response_message);
+ }
+
+ if(state_machine->state == VERIFIER_STATE_OPENED) {
+ /* no in-progress VERIFY request, sending immediate response */
+ mrcp_message_t *response_message = mrcp_response_create(message,message->pool);
+ return verifier_response_dispatch(state_machine,response_message);
+ }
+
+ return verifier_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_response_stop(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ mrcp_generic_header_t *generic_header = mrcp_generic_header_prepare(message);
+ /* append active id list */
+ active_request_id_list_append(generic_header,state_machine->verify->start_line.request_id);
+ mrcp_generic_header_property_add(message,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
+ verifier_state_change(state_machine,VERIFIER_STATE_OPENED,message);
+ return verifier_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_request_clear_buffer(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ return verifier_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_response_clear_buffer(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ return verifier_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_request_start_input_timers(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ if(state_machine->state == VERIFIER_STATE_IDLE || state_machine->state == VERIFIER_STATE_VERIFYING) {
+ mrcp_message_t *response_message = mrcp_response_create(message,message->pool);
+ response_message->start_line.status_code = MRCP_STATUS_CODE_METHOD_NOT_VALID;
+ return verifier_response_dispatch(state_machine,response_message);
+ }
+
+ return verifier_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_response_start_input_timers(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ return verifier_response_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_request_get_intermidiate_result(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ if(state_machine->state != VERIFIER_STATE_VERIFYING) {
+ mrcp_message_t *response_message = mrcp_response_create(message,message->pool);
+ response_message->start_line.status_code = MRCP_STATUS_CODE_METHOD_NOT_VALID;
+ return verifier_response_dispatch(state_machine,response_message);
+ }
+ return verifier_request_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_response_get_intermidiate_result(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ return verifier_response_dispatch(state_machine,message);
+}
+
+
+static apt_bool_t verifier_event_start_of_input(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ if(!state_machine->verify) {
+ /* unexpected event, no in-progress verify request */
+ return FALSE;
+ }
+
+ if(state_machine->verify->start_line.request_id != message->start_line.request_id) {
+ /* unexpected event */
+ return FALSE;
+ }
+
+ message->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
+ return verifier_event_dispatch(state_machine,message);
+}
+
+static apt_bool_t verifier_event_verification_complete(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ if(!state_machine->verify) {
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Unexpected VERIFICATION-COMPLETE Event "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
+ return FALSE;
+ }
+
+ if(state_machine->verify->start_line.request_id != message->start_line.request_id) {
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Unexpected VERIFICATION-COMPLETE Event "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
+ return FALSE;
+ }
+
+ if(state_machine->active_request && state_machine->active_request->start_line.method_id == VERIFIER_STOP) {
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Ignore VERIFICATION-COMPLETE Event "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]: waiting for STOP response",
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
+ return FALSE;
+ }
+
+ if(mrcp_resource_header_property_check(message,VERIFIER_HEADER_COMPLETION_CAUSE) != TRUE) {
+ mrcp_verifier_header_t *verifier_header = mrcp_resource_header_prepare(message);
+ verifier_header->completion_cause = VERIFIER_COMPLETION_CAUSE_SUCCESS;
+ mrcp_resource_header_property_add(message,VERIFIER_HEADER_COMPLETION_CAUSE);
+ }
+ verifier_state_change(state_machine,VERIFIER_STATE_OPENED,message);
+ return verifier_event_dispatch(state_machine,message);
+}
+
+static verifier_method_f verifier_request_method_array[VERIFIER_METHOD_COUNT] = {
+ verifier_request_set_params,
+ verifier_request_get_params,
+ verifier_request_start_session,
+ verifier_request_end_session,
+ verifier_request_query_voiceprint,
+ verifier_request_delete_voiceprint,
+ verifier_request_verify,
+ verifier_request_verify_from_buffer,
+ verifier_request_verify_rollback,
+ verifier_request_stop,
+ verifier_request_clear_buffer,
+ verifier_request_start_input_timers,
+ verifier_request_get_intermidiate_result
+};
+
+static verifier_method_f verifier_response_method_array[VERIFIER_METHOD_COUNT] = {
+ verifier_response_set_params,
+ verifier_response_get_params,
+ verifier_response_start_session,
+ verifier_response_end_session,
+ verifier_response_query_voiceprint,
+ verifier_response_delete_voiceprint,
+ verifier_response_verify,
+ verifier_response_verify_from_buffer,
+ verifier_response_verify_rollback,
+ verifier_response_stop,
+ verifier_response_clear_buffer,
+ verifier_response_start_input_timers,
+ verifier_response_get_intermidiate_result
+};
+
+static verifier_method_f verifier_event_method_array[VERIFIER_EVENT_COUNT] = {
+ verifier_event_start_of_input,
+ verifier_event_verification_complete
+};
+
+/** Update state according to received incoming request from MRCP client */
+static apt_bool_t verifier_request_state_update(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ verifier_method_f method;
+ if(message->start_line.method_id >= VERIFIER_METHOD_COUNT) {
+ return FALSE;
+ }
+
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process %s Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ message->start_line.method_name.buf,
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
+ method = verifier_request_method_array[message->start_line.method_id];
+ if(method) {
+ return method(state_machine,message);
+ }
+ return verifier_request_dispatch(state_machine,message);
+}
+
+/** Update state according to received outgoing response from verification engine */
+static apt_bool_t verifier_response_state_update(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ verifier_method_f method;
+ if(!state_machine->active_request) {
+ /* unexpected response, no active request waiting for response */
+ return FALSE;
+ }
+ if(state_machine->active_request->start_line.request_id != message->start_line.request_id) {
+ /* unexpected response, request id doesn't match */
+ return FALSE;
+ }
+
+ if(message->start_line.method_id >= VERIFIER_METHOD_COUNT) {
+ return FALSE;
+ }
+
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process %s Response "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ message->start_line.method_name.buf,
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
+ method = verifier_response_method_array[message->start_line.method_id];
+ if(method) {
+ return method(state_machine,message);
+ }
+ return verifier_response_dispatch(state_machine,message);
+}
+
+/** Update state according to received outgoing event from verification engine */
+static apt_bool_t verifier_event_state_update(mrcp_verifier_state_machine_t *state_machine, mrcp_message_t *message)
+{
+ verifier_method_f method;
+ if(message->start_line.method_id >= VERIFIER_EVENT_COUNT) {
+ return FALSE;
+ }
+
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Process %s Event "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ message->start_line.method_name.buf,
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
+ method = verifier_event_method_array[message->start_line.method_id];
+ if(method) {
+ return method(state_machine,message);
+ }
+ return verifier_event_dispatch(state_machine,message);
+}
+
+/** Update state according to request received from MRCP client or response/event received from verification engine */
+static apt_bool_t verifier_state_update(mrcp_state_machine_t *base, mrcp_message_t *message)
+{
+ mrcp_verifier_state_machine_t *state_machine = (mrcp_verifier_state_machine_t*)base;
+ apt_bool_t status = TRUE;
+ switch(message->start_line.message_type) {
+ case MRCP_MESSAGE_TYPE_REQUEST:
+ status = verifier_request_state_update(state_machine,message);
+ break;
+ case MRCP_MESSAGE_TYPE_RESPONSE:
+ status = verifier_response_state_update(state_machine,message);
+ break;
+ case MRCP_MESSAGE_TYPE_EVENT:
+ status = verifier_event_state_update(state_machine,message);
+ break;
+ default:
+ status = FALSE;
+ break;
+ }
+ return status;
+}
+
+/** Deactivate state machine */
+static apt_bool_t verifier_state_deactivate(mrcp_state_machine_t *base)
+{
+ mrcp_verifier_state_machine_t *state_machine = (mrcp_verifier_state_machine_t*)base;
+ mrcp_message_t *message;
+ mrcp_message_t *source;
+ if(state_machine->state != VERIFIER_STATE_VERIFYING) {
+ /* no in-progress VERIFY request to deactivate */
+ return FALSE;
+ }
+ source = state_machine->verify;
+ if(!source) {
+ return FALSE;
+ }
+
+ /* create internal STOP request */
+ message = mrcp_request_create(
+ source->resource,
+ source->start_line.version,
+ VERIFIER_STOP,
+ source->pool);
+ message->channel_id = source->channel_id;
+ message->start_line.request_id = source->start_line.request_id + 1;
+ apt_string_set(&message->start_line.method_name,"DEACTIVATE"); /* informative only */
+ message->header = source->header;
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Create and Process STOP Request "APT_SIDRES_FMT" [%"MRCP_REQUEST_ID_FMT"]",
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
+ return verifier_request_dispatch(state_machine,message);
+}
+
+/** Create MRCP verification state machine */
+mrcp_state_machine_t* mrcp_verifier_state_machine_create(void *obj, mrcp_version_e version, apr_pool_t *pool)
+{
+ mrcp_verifier_state_machine_t *state_machine = apr_palloc(pool,sizeof(mrcp_verifier_state_machine_t));
+ mrcp_state_machine_init(&state_machine->base,obj);
+ state_machine->base.update = verifier_state_update;
+ state_machine->base.deactivate = verifier_state_deactivate;
+ state_machine->state = VERIFIER_STATE_IDLE;
+ state_machine->active_request = NULL;
+ state_machine->verify = NULL;
+ state_machine->properties = mrcp_message_header_create(
+ mrcp_generic_header_vtable_get(version),
+ mrcp_verifier_header_vtable_get(version),
+ pool);
+ return &state_machine->base;
+}
diff --git a/libs/unimrcp/libs/mrcp-server/include/mrcp_server.h b/libs/unimrcp/libs/mrcp-server/include/mrcp_server.h
index 59a33db059..f2bf49fe37 100644
--- a/libs/unimrcp/libs/mrcp-server/include/mrcp_server.h
+++ b/libs/unimrcp/libs/mrcp-server/include/mrcp_server.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_server.h 1721 2010-06-01 05:45:46Z achaloyan $
*/
-#ifndef __MRCP_SERVER_H__
-#define __MRCP_SERVER_H__
+#ifndef MRCP_SERVER_H
+#define MRCP_SERVER_H
/**
* @file mrcp_server.h
@@ -24,6 +26,7 @@
#include "mrcp_server_types.h"
#include "mrcp_engine_iface.h"
+#include "mpf_rtp_descriptor.h"
#include "apt_task.h"
APT_BEGIN_EXTERN_C
@@ -59,15 +62,18 @@ MRCP_DECLARE(apt_bool_t) mrcp_server_destroy(mrcp_server_t *server);
* @param server the MRCP server to set resource factory for
* @param resource_factory the resource factory to set
*/
-MRCP_DECLARE(apt_bool_t) mrcp_server_resource_factory_register(mrcp_server_t *server, mrcp_resource_factory_t *resource_factory);
+MRCP_DECLARE(apt_bool_t) mrcp_server_resource_factory_register(
+ mrcp_server_t *server,
+ mrcp_resource_factory_t *resource_factory);
/**
* Register MRCP engine.
* @param server the MRCP server to set engine for
* @param engine the engine to set
- * @param config the config of the engine
*/
-MRCP_DECLARE(apt_bool_t) mrcp_server_engine_register(mrcp_server_t *server, mrcp_engine_t *engine, mrcp_engine_config_t *config);
+MRCP_DECLARE(apt_bool_t) mrcp_server_engine_register(
+ mrcp_server_t *server,
+ mrcp_engine_t *engine);
/**
* Register codec manager.
@@ -80,15 +86,16 @@ MRCP_DECLARE(apt_bool_t) mrcp_server_codec_manager_register(mrcp_server_t *serve
* Get registered codec manager.
* @param server the MRCP server to get codec manager from
*/
-MRCP_DECLARE(const mpf_codec_manager_t*) mrcp_server_codec_manager_get(mrcp_server_t *server);
+MRCP_DECLARE(const mpf_codec_manager_t*) mrcp_server_codec_manager_get(const mrcp_server_t *server);
/**
* Register media engine.
* @param server the MRCP server to set media engine for
* @param media_engine the media engine to set
- * @param name the name of the media engine
*/
-MRCP_DECLARE(apt_bool_t) mrcp_server_media_engine_register(mrcp_server_t *server, mpf_engine_t *media_engine, const char *name);
+MRCP_DECLARE(apt_bool_t) mrcp_server_media_engine_register(
+ mrcp_server_t *server,
+ mpf_engine_t *media_engine);
/**
* Register RTP termination factory.
@@ -96,95 +103,123 @@ MRCP_DECLARE(apt_bool_t) mrcp_server_media_engine_register(mrcp_server_t *server
* @param rtp_termination_factory the termination factory
* @param name the name of the factory
*/
-MRCP_DECLARE(apt_bool_t) mrcp_server_rtp_factory_register(mrcp_server_t *server, mpf_termination_factory_t *rtp_termination_factory, const char *name);
+MRCP_DECLARE(apt_bool_t) mrcp_server_rtp_factory_register(
+ mrcp_server_t *server,
+ mpf_termination_factory_t *rtp_termination_factory,
+ const char *name);
+
+/**
+ * Register RTP settings.
+ * @param server the MRCP server to set RTP settings for
+ * @param rtp_settings the settings to set
+ * @param name the name of the settings
+ */
+MRCP_DECLARE(apt_bool_t) mrcp_server_rtp_settings_register(
+ mrcp_server_t *server,
+ mpf_rtp_settings_t *rtp_settings,
+ const char *name);
/**
* Register MRCP signaling agent.
* @param server the MRCP server to set signaling agent for
* @param signaling_agent the signaling agent to set
- * @param name the name of the agent
*/
-MRCP_DECLARE(apt_bool_t) mrcp_server_signaling_agent_register(mrcp_server_t *server, mrcp_sig_agent_t *signaling_agent, const char *name);
+MRCP_DECLARE(apt_bool_t) mrcp_server_signaling_agent_register(
+ mrcp_server_t *server,
+ mrcp_sig_agent_t *signaling_agent);
/**
* Register MRCP connection agent (MRCPv2 only).
* @param server the MRCP server to set connection agent for
* @param connection_agent the connection agent to set
- * @param name the name of the agent
*/
-MRCP_DECLARE(apt_bool_t) mrcp_server_connection_agent_register(mrcp_server_t *server, mrcp_connection_agent_t *connection_agent, const char *name);
+MRCP_DECLARE(apt_bool_t) mrcp_server_connection_agent_register(
+ mrcp_server_t *server,
+ mrcp_connection_agent_t *connection_agent);
/** Create MRCP profile */
MRCP_DECLARE(mrcp_profile_t*) mrcp_server_profile_create(
- mrcp_resource_factory_t *resource_factory,
- mrcp_sig_agent_t *signaling_agent,
- mrcp_connection_agent_t *connection_agent,
- mpf_engine_t *media_engine,
- mpf_termination_factory_t *rtp_factory,
- apr_pool_t *pool);
+ const char *id,
+ mrcp_resource_factory_t *resource_factory,
+ mrcp_sig_agent_t *signaling_agent,
+ mrcp_connection_agent_t *connection_agent,
+ mpf_engine_t *media_engine,
+ mpf_termination_factory_t *rtp_factory,
+ mpf_rtp_settings_t *rtp_settings,
+ apr_pool_t *pool);
/**
* Register MRCP profile.
* @param server the MRCP server to set profile for
* @param profile the profile to set
* @param plugin_map the map of engines (plugins)
- * @param name the name of the profile
*/
MRCP_DECLARE(apt_bool_t) mrcp_server_profile_register(
mrcp_server_t *server,
mrcp_profile_t *profile,
- apr_table_t *plugin_map,
- const char *name);
+ apr_table_t *plugin_map);
/**
- * Register MRCP engine plugin.
- * @param server the MRCP server to set engine for
- * @param path the path to plugin
- * @param config the config of the plugin
+ * Load MRCP engine as a plugin.
+ * @param server the MRCP server to use
+ * @param id the identifier of the plugin
+ * @param path the path to the plugin to load
+ * @param config the config of the engine
*/
-MRCP_DECLARE(apt_bool_t) mrcp_server_plugin_register(mrcp_server_t *server, const char *path, mrcp_engine_config_t *config);
+MRCP_DECLARE(mrcp_engine_t*) mrcp_server_engine_load(
+ mrcp_server_t *server,
+ const char *id,
+ const char *path,
+ mrcp_engine_config_t *config);
/**
* Get memory pool.
* @param server the MRCP server to get memory pool from
*/
-MRCP_DECLARE(apr_pool_t*) mrcp_server_memory_pool_get(mrcp_server_t *server);
+MRCP_DECLARE(apr_pool_t*) mrcp_server_memory_pool_get(const mrcp_server_t *server);
/**
* Get media engine by name.
* @param server the MRCP server to get media engine from
* @param name the name of the media engine to lookup
*/
-MRCP_DECLARE(mpf_engine_t*) mrcp_server_media_engine_get(mrcp_server_t *server, const char *name);
+MRCP_DECLARE(mpf_engine_t*) mrcp_server_media_engine_get(const mrcp_server_t *server, const char *name);
/**
* Get RTP termination factory by name.
* @param server the MRCP server to get from
* @param name the name to lookup
*/
-MRCP_DECLARE(mpf_termination_factory_t*) mrcp_server_rtp_factory_get(mrcp_server_t *server, const char *name);
+MRCP_DECLARE(mpf_termination_factory_t*) mrcp_server_rtp_factory_get(const mrcp_server_t *server, const char *name);
+
+/**
+ * Get RTP settings by name
+ * @param server the MRCP server to get from
+ * @param name the name to lookup
+ */
+MRCP_DECLARE(mpf_rtp_settings_t*) mrcp_server_rtp_settings_get(const mrcp_server_t *server, const char *name);
/**
* Get signaling agent by name.
* @param server the MRCP server to get from
* @param name the name to lookup
*/
-MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_server_signaling_agent_get(mrcp_server_t *server, const char *name);
+MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_server_signaling_agent_get(const mrcp_server_t *server, const char *name);
/**
* Get connection agent by name.
* @param server the MRCP server to get from
* @param name the name to lookup
*/
-MRCP_DECLARE(mrcp_connection_agent_t*) mrcp_server_connection_agent_get(mrcp_server_t *server, const char *name);
+MRCP_DECLARE(mrcp_connection_agent_t*) mrcp_server_connection_agent_get(const mrcp_server_t *server, const char *name);
/**
* Get profile by name.
* @param server the MRCP client to get from
* @param name the name to lookup
*/
-MRCP_DECLARE(mrcp_profile_t*) mrcp_server_profile_get(mrcp_server_t *server, const char *name);
+MRCP_DECLARE(mrcp_profile_t*) mrcp_server_profile_get(const mrcp_server_t *server, const char *name);
APT_END_EXTERN_C
-#endif /*__MRCP_SERVER_H__*/
+#endif /* MRCP_SERVER_H */
diff --git a/libs/unimrcp/libs/mrcp-server/include/mrcp_server_session.h b/libs/unimrcp/libs/mrcp-server/include/mrcp_server_session.h
index 4cd88f6b3e..07258f0298 100644
--- a/libs/unimrcp/libs/mrcp-server/include/mrcp_server_session.h
+++ b/libs/unimrcp/libs/mrcp-server/include/mrcp_server_session.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_server_session.h 1700 2010-05-21 18:56:06Z achaloyan $
*/
-#ifndef __MRCP_SERVER_SESSION_H__
-#define __MRCP_SERVER_SESSION_H__
+#ifndef MRCP_SERVER_SESSION_H
+#define MRCP_SERVER_SESSION_H
/**
* @file mrcp_server_session.h
@@ -109,6 +111,8 @@ struct mrcp_server_session_t {
/** MRCP profile */
struct mrcp_profile_t {
+ /** Identifier of the profile */
+ const char *id;
/** Table of engines (mrcp_engine_t*) */
apr_hash_t *engine_table;
/** MRCP resource factory */
@@ -117,6 +121,8 @@ struct mrcp_profile_t {
mpf_engine_t *media_engine;
/** RTP termination factory */
mpf_termination_factory_t *rtp_termination_factory;
+ /** RTP settings */
+ mpf_rtp_settings_t *rtp_settings;
/** Signaling agent */
mrcp_sig_agent_t *signaling_agent;
/** Connection agent */
@@ -152,4 +158,4 @@ mrcp_session_t* mrcp_server_channel_session_get(mrcp_channel_t *channel);
APT_END_EXTERN_C
-#endif /*__MRCP_SERVER_SESSION_H__*/
+#endif /* MRCP_SERVER_SESSION_H */
diff --git a/libs/unimrcp/libs/mrcp-server/include/mrcp_server_types.h b/libs/unimrcp/libs/mrcp-server/include/mrcp_server_types.h
index ac640fc750..2c9f3f0be8 100644
--- a/libs/unimrcp/libs/mrcp-server/include/mrcp_server_types.h
+++ b/libs/unimrcp/libs/mrcp-server/include/mrcp_server_types.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_server_types.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_SERVER_TYPES_H__
-#define __MRCP_SERVER_TYPES_H__
+#ifndef MRCP_SERVER_TYPES_H
+#define MRCP_SERVER_TYPES_H
/**
* @file mrcp_server_types.h
@@ -37,4 +39,4 @@ typedef struct mrcp_profile_t mrcp_profile_t;
APT_END_EXTERN_C
-#endif /*__MRCP_SERVER_TYPES_H__*/
+#endif /* MRCP_SERVER_TYPES_H */
diff --git a/libs/unimrcp/libs/mrcp-server/mrcpserver.2008.vcproj b/libs/unimrcp/libs/mrcp-server/mrcpserver.2008.vcproj
deleted file mode 100644
index fe124d4a8a..0000000000
--- a/libs/unimrcp/libs/mrcp-server/mrcpserver.2008.vcproj
+++ /dev/null
@@ -1,162 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/libs/mrcp-server/src/mrcp_server.c b/libs/unimrcp/libs/mrcp-server/src/mrcp_server.c
index 0c8d2a8a07..bd1b6aa848 100644
--- a/libs/unimrcp/libs/mrcp-server/src/mrcp_server.c
+++ b/libs/unimrcp/libs/mrcp-server/src/mrcp_server.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_server.c 1721 2010-06-01 05:45:46Z achaloyan $
*/
#include "mrcp_server.h"
@@ -53,6 +55,8 @@ struct mrcp_server_t {
apr_hash_t *sig_agent_table;
/** Table of connection agents (mrcp_connection_agent_t*) */
apr_hash_t *cnt_agent_table;
+ /** Table of RTP settings (mpf_rtp_settings_t*) */
+ apr_hash_t *rtp_settings_table;
/** Table of profiles (mrcp_profile_t*) */
apr_hash_t *profile_table;
@@ -126,6 +130,8 @@ static const mrcp_connection_event_vtable_t connection_method_vtable = {
/* MRCP engine interface */
typedef enum {
+ ENGINE_TASK_MSG_OPEN_ENGINE,
+ ENGINE_TASK_MSG_CLOSE_ENGINE,
ENGINE_TASK_MSG_OPEN_CHANNEL,
ENGINE_TASK_MSG_CLOSE_CHANNEL,
ENGINE_TASK_MSG_MESSAGE
@@ -133,11 +139,20 @@ typedef enum {
typedef struct engine_task_msg_data_t engine_task_msg_data_t;
struct engine_task_msg_data_t {
+ mrcp_engine_t *engine;
mrcp_channel_t *channel;
apt_bool_t status;
mrcp_message_t *mrcp_message;
};
+static apt_bool_t mrcp_server_engine_open_signal(mrcp_engine_t *engine, apt_bool_t status);
+static apt_bool_t mrcp_server_engine_close_signal(mrcp_engine_t *engine);
+
+const mrcp_engine_event_vtable_t engine_vtable = {
+ mrcp_server_engine_open_signal,
+ mrcp_server_engine_close_signal,
+};
+
static apt_bool_t mrcp_server_channel_open_signal(mrcp_engine_channel_t *channel, apt_bool_t status);
static apt_bool_t mrcp_server_channel_close_signal(mrcp_engine_channel_t *channel);
static apt_bool_t mrcp_server_channel_message_signal(mrcp_engine_channel_t *channel, mrcp_message_t *message);
@@ -149,6 +164,8 @@ const mrcp_engine_channel_event_vtable_t engine_channel_vtable = {
};
/* Task interface */
+static void mrcp_server_on_start_request(apt_task_t *task);
+static void mrcp_server_on_terminate_request(apt_task_t *task);
static void mrcp_server_on_start_complete(apt_task_t *task);
static void mrcp_server_on_terminate_complete(apt_task_t *task);
static apt_bool_t mrcp_server_msg_process(apt_task_t *task, apt_task_msg_t *msg);
@@ -181,6 +198,7 @@ MRCP_DECLARE(mrcp_server_t*) mrcp_server_create(apt_dir_layout_t *dir_layout)
server->rtp_factory_table = NULL;
server->sig_agent_table = NULL;
server->cnt_agent_table = NULL;
+ server->rtp_settings_table = NULL;
server->profile_table = NULL;
server->session_table = NULL;
server->connection_msg_pool = NULL;
@@ -198,6 +216,8 @@ MRCP_DECLARE(mrcp_server_t*) mrcp_server_create(apt_dir_layout_t *dir_layout)
vtable = apt_task_vtable_get(task);
if(vtable) {
vtable->process_msg = mrcp_server_msg_process;
+ vtable->on_start_request = mrcp_server_on_start_request;
+ vtable->on_terminate_request = mrcp_server_on_terminate_request;
vtable->on_start_complete = mrcp_server_on_start_complete;
vtable->on_terminate_complete = mrcp_server_on_terminate_complete;
}
@@ -207,6 +227,7 @@ MRCP_DECLARE(mrcp_server_t*) mrcp_server_create(apt_dir_layout_t *dir_layout)
server->media_engine_table = apr_hash_make(server->pool);
server->rtp_factory_table = apr_hash_make(server->pool);
+ server->rtp_settings_table = apr_hash_make(server->pool);
server->sig_agent_table = apr_hash_make(server->pool);
server->cnt_agent_table = apr_hash_make(server->pool);
@@ -249,7 +270,7 @@ MRCP_DECLARE(apt_bool_t) mrcp_server_shutdown(mrcp_server_t *server)
}
server->session_table = NULL;
uptime = apr_time_now() - server->start_time;
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Server Uptime [%d sec]", apr_time_sec(uptime));
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Server Uptime [%"APR_TIME_T_FMT" sec]", apr_time_sec(uptime));
return TRUE;
}
@@ -284,19 +305,21 @@ MRCP_DECLARE(apt_bool_t) mrcp_server_resource_factory_register(mrcp_server_t *se
}
/** Register MRCP engine */
-MRCP_DECLARE(apt_bool_t) mrcp_server_engine_register(mrcp_server_t *server, mrcp_engine_t *engine, mrcp_engine_config_t *config)
+MRCP_DECLARE(apt_bool_t) mrcp_server_engine_register(mrcp_server_t *server, mrcp_engine_t *engine)
{
- if(!engine || !config || !config->name) {
+ if(!engine || !engine->id) {
return FALSE;
}
+
if(!server->engine_msg_pool) {
server->engine_msg_pool = apt_task_msg_pool_create_dynamic(sizeof(engine_task_msg_data_t),server->pool);
}
- engine->config = config;
engine->codec_manager = server->codec_manager;
engine->dir_layout = server->dir_layout;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register MRCP Engine [%s]",config->name);
- return mrcp_engine_factory_engine_register(server->engine_factory,engine,config->name);
+ engine->event_vtable = &engine_vtable;
+ engine->event_obj = server;
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register MRCP Engine [%s]",engine->id);
+ return mrcp_engine_factory_engine_register(server->engine_factory,engine);
}
/** Register codec manager */
@@ -310,20 +333,26 @@ MRCP_DECLARE(apt_bool_t) mrcp_server_codec_manager_register(mrcp_server_t *serve
}
/** Get registered codec manager */
-MRCP_DECLARE(const mpf_codec_manager_t*) mrcp_server_codec_manager_get(mrcp_server_t *server)
+MRCP_DECLARE(const mpf_codec_manager_t*) mrcp_server_codec_manager_get(const mrcp_server_t *server)
{
return server->codec_manager;
}
/** Register media engine */
-MRCP_DECLARE(apt_bool_t) mrcp_server_media_engine_register(mrcp_server_t *server, mpf_engine_t *media_engine, const char *name)
+MRCP_DECLARE(apt_bool_t) mrcp_server_media_engine_register(mrcp_server_t *server, mpf_engine_t *media_engine)
{
- if(!media_engine || !name) {
+ const char *id;
+ if(!media_engine) {
return FALSE;
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Media Engine [%s]",name);
+ id = mpf_engine_id_get(media_engine);
+ if(!id) {
+ return FALSE;
+ }
+
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Media Engine [%s]",id);
mpf_engine_codec_manager_register(media_engine,server->codec_manager);
- apr_hash_set(server->media_engine_table,name,APR_HASH_KEY_STRING,media_engine);
+ apr_hash_set(server->media_engine_table,id,APR_HASH_KEY_STRING,media_engine);
mpf_engine_task_msg_type_set(media_engine,MRCP_SERVER_MEDIA_TASK_MSG);
if(server->task) {
apt_task_t *media_task = mpf_task_get(media_engine);
@@ -334,7 +363,7 @@ MRCP_DECLARE(apt_bool_t) mrcp_server_media_engine_register(mrcp_server_t *server
}
/** Get media engine by name */
-MRCP_DECLARE(mpf_engine_t*) mrcp_server_media_engine_get(mrcp_server_t *server, const char *name)
+MRCP_DECLARE(mpf_engine_t*) mrcp_server_media_engine_get(const mrcp_server_t *server, const char *name)
{
return apr_hash_get(server->media_engine_table,name,APR_HASH_KEY_STRING);
}
@@ -351,23 +380,40 @@ MRCP_DECLARE(apt_bool_t) mrcp_server_rtp_factory_register(mrcp_server_t *server,
}
/** Get RTP termination factory by name */
-MRCP_DECLARE(mpf_termination_factory_t*) mrcp_server_rtp_factory_get(mrcp_server_t *server, const char *name)
+MRCP_DECLARE(mpf_termination_factory_t*) mrcp_server_rtp_factory_get(const mrcp_server_t *server, const char *name)
{
return apr_hash_get(server->rtp_factory_table,name,APR_HASH_KEY_STRING);
}
-/** Register MRCP signaling agent */
-MRCP_DECLARE(apt_bool_t) mrcp_server_signaling_agent_register(mrcp_server_t *server, mrcp_sig_agent_t *signaling_agent, const char *name)
+/** Register RTP settings */
+MRCP_DECLARE(apt_bool_t) mrcp_server_rtp_settings_register(mrcp_server_t *server, mpf_rtp_settings_t *rtp_settings, const char *name)
{
- if(!signaling_agent || !name) {
+ if(!rtp_settings || !name) {
return FALSE;
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Signaling Agent [%s]",name);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register RTP Settings [%s]",name);
+ apr_hash_set(server->rtp_settings_table,name,APR_HASH_KEY_STRING,rtp_settings);
+ return TRUE;
+}
+
+/** Get RTP settings by name */
+MRCP_DECLARE(mpf_rtp_settings_t*) mrcp_server_rtp_settings_get(const mrcp_server_t *server, const char *name)
+{
+ return apr_hash_get(server->rtp_settings_table,name,APR_HASH_KEY_STRING);
+}
+
+/** Register MRCP signaling agent */
+MRCP_DECLARE(apt_bool_t) mrcp_server_signaling_agent_register(mrcp_server_t *server, mrcp_sig_agent_t *signaling_agent)
+{
+ if(!signaling_agent || !signaling_agent->id) {
+ return FALSE;
+ }
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Signaling Agent [%s]",signaling_agent->id);
signaling_agent->parent = server;
signaling_agent->resource_factory = server->resource_factory;
signaling_agent->create_server_session = mrcp_server_sig_agent_session_create;
signaling_agent->msg_pool = apt_task_msg_pool_create_dynamic(sizeof(mrcp_signaling_message_t*),server->pool);
- apr_hash_set(server->sig_agent_table,name,APR_HASH_KEY_STRING,signaling_agent);
+ apr_hash_set(server->sig_agent_table,signaling_agent->id,APR_HASH_KEY_STRING,signaling_agent);
if(server->task) {
apt_task_t *task = apt_consumer_task_base_get(server->task);
apt_task_add(task,signaling_agent->task);
@@ -376,22 +422,27 @@ MRCP_DECLARE(apt_bool_t) mrcp_server_signaling_agent_register(mrcp_server_t *ser
}
/** Get signaling agent by name */
-MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_server_signaling_agent_get(mrcp_server_t *server, const char *name)
+MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_server_signaling_agent_get(const mrcp_server_t *server, const char *name)
{
return apr_hash_get(server->sig_agent_table,name,APR_HASH_KEY_STRING);
}
/** Register MRCP connection agent (MRCPv2 only) */
-MRCP_DECLARE(apt_bool_t) mrcp_server_connection_agent_register(mrcp_server_t *server, mrcp_connection_agent_t *connection_agent, const char *name)
+MRCP_DECLARE(apt_bool_t) mrcp_server_connection_agent_register(mrcp_server_t *server, mrcp_connection_agent_t *connection_agent)
{
- if(!connection_agent || !name) {
+ const char *id;
+ if(!connection_agent) {
return FALSE;
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Connection Agent [%s]",name);
+ id = mrcp_server_connection_agent_id_get(connection_agent);
+ if(!id) {
+ return FALSE;
+ }
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Connection Agent [%s]",id);
mrcp_server_connection_resource_factory_set(connection_agent,server->resource_factory);
mrcp_server_connection_agent_handler_set(connection_agent,server,&connection_method_vtable);
server->connection_msg_pool = apt_task_msg_pool_create_dynamic(sizeof(connection_agent_task_msg_data_t),server->pool);
- apr_hash_set(server->cnt_agent_table,name,APR_HASH_KEY_STRING,connection_agent);
+ apr_hash_set(server->cnt_agent_table,id,APR_HASH_KEY_STRING,connection_agent);
if(server->task) {
apt_task_t *task = apt_consumer_task_base_get(server->task);
apt_task_t *connection_task = mrcp_server_connection_agent_task_get(connection_agent);
@@ -401,25 +452,29 @@ MRCP_DECLARE(apt_bool_t) mrcp_server_connection_agent_register(mrcp_server_t *se
}
/** Get connection agent by name */
-MRCP_DECLARE(mrcp_connection_agent_t*) mrcp_server_connection_agent_get(mrcp_server_t *server, const char *name)
+MRCP_DECLARE(mrcp_connection_agent_t*) mrcp_server_connection_agent_get(const mrcp_server_t *server, const char *name)
{
return apr_hash_get(server->cnt_agent_table,name,APR_HASH_KEY_STRING);
}
/** Create MRCP profile */
MRCP_DECLARE(mrcp_profile_t*) mrcp_server_profile_create(
+ const char *id,
mrcp_resource_factory_t *resource_factory,
mrcp_sig_agent_t *signaling_agent,
mrcp_connection_agent_t *connection_agent,
mpf_engine_t *media_engine,
mpf_termination_factory_t *rtp_factory,
+ mpf_rtp_settings_t *rtp_settings,
apr_pool_t *pool)
{
mrcp_profile_t *profile = apr_palloc(pool,sizeof(mrcp_profile_t));
+ profile->id = id;
profile->resource_factory = resource_factory;
profile->engine_table = NULL;
profile->media_engine = media_engine;
profile->rtp_termination_factory = rtp_factory;
+ profile->rtp_settings = rtp_settings;
profile->signaling_agent = signaling_agent;
profile->connection_agent = connection_agent;
return profile;
@@ -452,8 +507,8 @@ static apt_bool_t mrcp_server_engine_table_make(mrcp_server_t *server, mrcp_prof
}
if(engine) {
- if(engine->config->name) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Assign MRCP Engine [%s] [%s]",resource->name.buf,engine->config->name);
+ if(engine->id) {
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Assign MRCP Engine [%s] [%s]",resource->name.buf,engine->id);
}
apr_hash_set(profile->engine_table,resource->name.buf,resource->name.length,engine);
}
@@ -467,18 +522,17 @@ static apt_bool_t mrcp_server_engine_table_make(mrcp_server_t *server, mrcp_prof
/** Register MRCP profile */
MRCP_DECLARE(apt_bool_t) mrcp_server_profile_register(
- mrcp_server_t *server,
- mrcp_profile_t *profile,
- apr_table_t *plugin_map,
- const char *name)
+ mrcp_server_t *server,
+ mrcp_profile_t *profile,
+ apr_table_t *plugin_map)
{
- if(!profile || !name) {
+ if(!profile || !profile->id) {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile: no name");
return FALSE;
}
if(!profile->resource_factory) {
if(!server->resource_factory) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile: no resources");
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile [%s]: missing resource factory",profile->id);
return FALSE;
}
profile->resource_factory = server->resource_factory;
@@ -486,58 +540,55 @@ MRCP_DECLARE(apt_bool_t) mrcp_server_profile_register(
mrcp_server_engine_table_make(server,profile,plugin_map);
if(!profile->signaling_agent) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile [%s]: missing signaling agent",name);
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile [%s]: missing signaling agent",profile->id);
return FALSE;
}
if(profile->signaling_agent->mrcp_version == MRCP_VERSION_2 &&
!profile->connection_agent) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile [%s]: missing connection agent",name);
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile [%s]: missing connection agent",profile->id);
return FALSE;
}
if(!profile->media_engine) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile [%s]: missing media engine",name);
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile [%s]: missing media engine",profile->id);
return FALSE;
}
if(!profile->rtp_termination_factory) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile [%s]: missing RTP factory",name);
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Register Profile [%s]: missing RTP factory",profile->id);
return FALSE;
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Profile [%s]",name);
- apr_hash_set(server->profile_table,name,APR_HASH_KEY_STRING,profile);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register Profile [%s]",profile->id);
+ apr_hash_set(server->profile_table,profile->id,APR_HASH_KEY_STRING,profile);
return TRUE;
}
/** Get profile by name */
-MRCP_DECLARE(mrcp_profile_t*) mrcp_server_profile_get(mrcp_server_t *server, const char *name)
+MRCP_DECLARE(mrcp_profile_t*) mrcp_server_profile_get(const mrcp_server_t *server, const char *name)
{
return apr_hash_get(server->profile_table,name,APR_HASH_KEY_STRING);
}
-/** Register MRCP engine plugin */
-MRCP_DECLARE(apt_bool_t) mrcp_server_plugin_register(mrcp_server_t *server, const char *path, mrcp_engine_config_t *config)
+/** Load MRCP engine */
+MRCP_DECLARE(mrcp_engine_t*) mrcp_server_engine_load(
+ mrcp_server_t *server,
+ const char *id,
+ const char *path,
+ mrcp_engine_config_t *config)
{
mrcp_engine_t *engine;
- if(!config) {
+ if(!id || !path || !config) {
return FALSE;
}
-
- engine = mrcp_engine_loader_plugin_load(server->engine_loader,path,config->name);
+
+ engine = mrcp_engine_loader_plugin_load(server->engine_loader,id,path,config);
if(!engine) {
return FALSE;
}
- if(!server->engine_msg_pool) {
- server->engine_msg_pool = apt_task_msg_pool_create_dynamic(sizeof(engine_task_msg_data_t),server->pool);
- }
- engine->config = config;
- engine->codec_manager = server->codec_manager;
- engine->dir_layout = server->dir_layout;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Register MRCP Engine [%s]",config->name);
- return mrcp_engine_factory_engine_register(server->engine_factory,engine,config->name);
+ return engine;
}
-MRCP_DECLARE(apr_pool_t*) mrcp_server_memory_pool_get(mrcp_server_t *server)
+MRCP_DECLARE(apr_pool_t*) mrcp_server_memory_pool_get(const mrcp_server_t *server)
{
return server->pool;
}
@@ -563,22 +614,53 @@ static APR_INLINE mrcp_server_session_t* mrcp_server_session_find(mrcp_server_t
return apr_hash_get(server->session_table,session_id->buf,session_id->length);
}
-
-static void mrcp_server_on_start_complete(apt_task_t *task)
+static void mrcp_server_on_start_request(apt_task_t *task)
{
apt_consumer_task_t *consumer_task = apt_task_object_get(task);
mrcp_server_t *server = apt_consumer_task_object_get(consumer_task);
- mrcp_engine_factory_open(server->engine_factory);
+ mrcp_engine_t *engine;
+ apr_hash_index_t *it;
+ void *val;
+ it = mrcp_engine_factory_engine_first(server->engine_factory);
+ for(; it; it = apr_hash_next(it)) {
+ apr_hash_this(it,NULL,NULL,&val);
+ engine = val;
+ if(engine) {
+ if(mrcp_engine_virtual_open(engine) == TRUE) {
+ apt_task_start_request_add(task);
+ }
+ }
+ }
+}
+
+static void mrcp_server_on_terminate_request(apt_task_t *task)
+{
+ apt_consumer_task_t *consumer_task = apt_task_object_get(task);
+ mrcp_server_t *server = apt_consumer_task_object_get(consumer_task);
+
+ mrcp_engine_t *engine;
+ apr_hash_index_t *it;
+ void *val;
+ it = mrcp_engine_factory_engine_first(server->engine_factory);
+ for(; it; it = apr_hash_next(it)) {
+ apr_hash_this(it,NULL,NULL,&val);
+ engine = val;
+ if(engine) {
+ if(mrcp_engine_virtual_close(engine) == TRUE) {
+ apt_task_terminate_request_add(task);
+ }
+ }
+ }
+}
+
+static void mrcp_server_on_start_complete(apt_task_t *task)
+{
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,SERVER_TASK_NAME" Started");
}
static void mrcp_server_on_terminate_complete(apt_task_t *task)
{
- apt_consumer_task_t *consumer_task = apt_task_object_get(task);
- mrcp_server_t *server = apt_consumer_task_object_get(consumer_task);
-
- mrcp_engine_factory_close(server->engine_factory);
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,SERVER_TASK_NAME" Terminated");
}
@@ -588,14 +670,12 @@ static apt_bool_t mrcp_server_msg_process(apt_task_t *task, apt_task_msg_t *msg)
case MRCP_SERVER_SIGNALING_TASK_MSG:
{
mrcp_signaling_message_t **signaling_message = (mrcp_signaling_message_t**) msg->data;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Receive Signaling Task Message [%d]", (*signaling_message)->type);
mrcp_server_signaling_message_process(*signaling_message);
break;
}
case MRCP_SERVER_CONNECTION_TASK_MSG:
{
const connection_agent_task_msg_data_t *connection_message = (const connection_agent_task_msg_data_t*)msg->data;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Receive Connection Task Message [%d]", msg->sub_type);
switch(msg->sub_type) {
case CONNECTION_AGENT_TASK_MSG_ADD_CHANNEL:
{
@@ -630,8 +710,15 @@ static apt_bool_t mrcp_server_msg_process(apt_task_t *task, apt_task_msg_t *msg)
case MRCP_SERVER_ENGINE_TASK_MSG:
{
engine_task_msg_data_t *data = (engine_task_msg_data_t*)msg->data;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Receive Engine Task Message [%d]", msg->sub_type);
switch(msg->sub_type) {
+ case ENGINE_TASK_MSG_OPEN_ENGINE:
+ mrcp_engine_on_open(data->engine,data->status);
+ apt_task_start_request_remove(task);
+ break;
+ case ENGINE_TASK_MSG_CLOSE_ENGINE:
+ mrcp_engine_on_close(data->engine);
+ apt_task_terminate_request_remove(task);
+ break;
case ENGINE_TASK_MSG_OPEN_CHANNEL:
mrcp_server_on_engine_channel_open(data->channel,data->status);
break;
@@ -649,13 +736,12 @@ static apt_bool_t mrcp_server_msg_process(apt_task_t *task, apt_task_msg_t *msg)
case MRCP_SERVER_MEDIA_TASK_MSG:
{
mpf_message_container_t *mpf_message_container = (mpf_message_container_t*) msg->data;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Receive Media Task Message");
mrcp_server_mpf_message_process(mpf_message_container);
break;
}
default:
{
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Receive Unknown Task Message [%d]", msg->type);
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Task Message Received [%d;%d]", msg->type,msg->sub_type);
break;
}
}
@@ -678,7 +764,6 @@ static apt_bool_t mrcp_server_signaling_task_msg_signal(mrcp_signaling_message_t
signaling_message->message = message;
*slot = signaling_message;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Signal Signaling Task Message");
return apt_task_msg_parent_signal(session->signaling_agent->task,task_msg);
}
@@ -702,15 +787,34 @@ static apt_bool_t mrcp_server_connection_task_msg_signal(
data->message = message;
data->status = status;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Signal Connection Task Message");
return apt_task_msg_signal(task,task_msg);
}
static apt_bool_t mrcp_server_engine_task_msg_signal(
engine_task_msg_type_e type,
- mrcp_engine_channel_t *engine_channel,
- apt_bool_t status,
- mrcp_message_t *message)
+ mrcp_engine_t *engine,
+ apt_bool_t status)
+{
+ mrcp_server_t *server = engine->event_obj;
+ apt_task_t *task = apt_consumer_task_base_get(server->task);
+ engine_task_msg_data_t *data;
+ apt_task_msg_t *task_msg = apt_task_msg_acquire(server->engine_msg_pool);
+ task_msg->type = MRCP_SERVER_ENGINE_TASK_MSG;
+ task_msg->sub_type = type;
+ data = (engine_task_msg_data_t*) task_msg->data;
+ data->engine = engine;
+ data->channel = NULL;
+ data->status = status;
+ data->mrcp_message = NULL;
+
+ return apt_task_msg_signal(task,task_msg);
+}
+
+static apt_bool_t mrcp_server_channel_task_msg_signal(
+ engine_task_msg_type_e type,
+ mrcp_engine_channel_t *engine_channel,
+ apt_bool_t status,
+ mrcp_message_t *message)
{
mrcp_channel_t *channel = engine_channel->event_obj;
mrcp_session_t *session = mrcp_server_channel_session_get(channel);
@@ -721,11 +825,11 @@ static apt_bool_t mrcp_server_engine_task_msg_signal(
task_msg->type = MRCP_SERVER_ENGINE_TASK_MSG;
task_msg->sub_type = type;
data = (engine_task_msg_data_t*) task_msg->data;
+ data->engine = engine_channel->engine;
data->channel = channel;
data->status = status;
data->mrcp_message = message;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Signal Engine Task Message");
return apt_task_msg_signal(task,task_msg);
}
@@ -734,19 +838,14 @@ static mrcp_profile_t* mrcp_server_profile_get_by_agent(mrcp_server_t *server, m
mrcp_profile_t *profile;
apr_hash_index_t *it;
void *val;
- const void *key;
- const char *name;
it = apr_hash_first(session->base.pool,server->profile_table);
for(; it; it = apr_hash_next(it)) {
- apr_hash_this(it,&key,NULL,&val);
+ apr_hash_this(it,NULL,NULL,&val);
profile = val;
- name = key;
- if(profile && name && profile->signaling_agent == signaling_agent) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Found Profile [%s]",name);
+ if(profile && profile->signaling_agent == signaling_agent) {
return profile;
}
}
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot Find Profile by Agent "APT_SID_FMT,MRCP_SESSION_SID(&session->base));
return NULL;
}
@@ -757,9 +856,16 @@ static mrcp_session_t* mrcp_server_sig_agent_session_create(mrcp_sig_agent_t *si
session->server = server;
session->profile = mrcp_server_profile_get_by_agent(server,session,signaling_agent);
if(!session->profile) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot Find Profile by Agent "APT_NAMESID_FMT,
+ session->base.name,
+ MRCP_SESSION_SID(&session->base));
mrcp_session_destroy(&session->base);
return NULL;
}
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Create Session "APT_NAMESID_FMT" [%s]",
+ session->base.name,
+ MRCP_SESSION_SID(&session->base),
+ session->profile->id);
session->base.signaling_agent = signaling_agent;
session->base.request_vtable = &session_request_vtable;
return &session->base;
@@ -840,9 +946,25 @@ static apt_bool_t mrcp_server_disconnect_signal(mrcp_control_channel_t *channel)
TRUE);
}
-static apt_bool_t mrcp_server_channel_open_signal(mrcp_engine_channel_t *channel, apt_bool_t status)
+static apt_bool_t mrcp_server_engine_open_signal(mrcp_engine_t *engine, apt_bool_t status)
{
return mrcp_server_engine_task_msg_signal(
+ ENGINE_TASK_MSG_OPEN_ENGINE,
+ engine,
+ status);
+}
+
+static apt_bool_t mrcp_server_engine_close_signal(mrcp_engine_t *engine)
+{
+ return mrcp_server_engine_task_msg_signal(
+ ENGINE_TASK_MSG_CLOSE_ENGINE,
+ engine,
+ TRUE);
+}
+
+static apt_bool_t mrcp_server_channel_open_signal(mrcp_engine_channel_t *channel, apt_bool_t status)
+{
+ return mrcp_server_channel_task_msg_signal(
ENGINE_TASK_MSG_OPEN_CHANNEL,
channel,
status,
@@ -851,7 +973,7 @@ static apt_bool_t mrcp_server_channel_open_signal(mrcp_engine_channel_t *channel
static apt_bool_t mrcp_server_channel_close_signal(mrcp_engine_channel_t *channel)
{
- return mrcp_server_engine_task_msg_signal(
+ return mrcp_server_channel_task_msg_signal(
ENGINE_TASK_MSG_CLOSE_CHANNEL,
channel,
TRUE,
@@ -860,7 +982,7 @@ static apt_bool_t mrcp_server_channel_close_signal(mrcp_engine_channel_t *channe
static apt_bool_t mrcp_server_channel_message_signal(mrcp_engine_channel_t *channel, mrcp_message_t *message)
{
- return mrcp_server_engine_task_msg_signal(
+ return mrcp_server_channel_task_msg_signal(
ENGINE_TASK_MSG_MESSAGE,
channel,
TRUE,
diff --git a/libs/unimrcp/libs/mrcp-server/src/mrcp_server_session.c b/libs/unimrcp/libs/mrcp-server/src/mrcp_server_session.c
index b254300921..9a18b9ae14 100644
--- a/libs/unimrcp/libs/mrcp-server/src/mrcp_server_session.c
+++ b/libs/unimrcp/libs/mrcp-server/src/mrcp_server_session.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_server_session.c 1794 2011-01-20 18:59:01Z achaloyan $
*/
#include "mrcp_server.h"
@@ -30,6 +32,10 @@
#include "apt_consumer_task.h"
#include "apt_log.h"
+/** Macro to log session name and identifier */
+#define MRCP_SESSION_NAMESID(session) \
+ session->base.name, MRCP_SESSION_SID(&session->base)
+
#define MRCP_SESSION_ID_HEX_STRING_LENGTH 16
struct mrcp_channel_t {
@@ -106,6 +112,7 @@ mrcp_server_session_t* mrcp_server_session_create()
session->mpf_task_msg = NULL;
session->subrequest_count = 0;
session->state = SESSION_STATE_NONE;
+ session->base.name = apr_psprintf(session->base.pool,"0x%pp",session);
return session;
}
@@ -124,7 +131,9 @@ static mrcp_engine_channel_t* mrcp_server_engine_channel_create(
resource_name->buf,
resource_name->length);
if(!engine) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Find MRCP Engine [%s]",resource_name->buf);
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Find MRCP Engine "APT_NAMESID_FMT" [%s]",
+ MRCP_SESSION_NAMESID(session),
+ resource_name->buf);
return NULL;
}
@@ -177,17 +186,22 @@ static mrcp_channel_t* mrcp_server_channel_create(mrcp_server_session_t *session
channel->engine_channel = engine_channel;
}
else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Engine Channel [%s]",resource_name->buf);
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Engine Channel "APT_NAMESID_FMT" [%s]",
+ MRCP_SESSION_NAMESID(session),
+ resource_name->buf);
session->answer->status = MRCP_SESSION_STATUS_UNACCEPTABLE_RESOURCE;
}
}
else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No Such Resource [%s]",resource_name->buf);
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No Such Resource "APT_NAMESID_FMT" [%s]",
+ MRCP_SESSION_NAMESID(session),
+ resource_name->buf);
session->answer->status = MRCP_SESSION_STATUS_NO_SUCH_RESOURCE;
}
}
else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Invalid Resource Identifier");
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Invalid Resource Identifier "APT_NAMESID_FMT,
+ MRCP_SESSION_NAMESID(session));
session->answer->status = MRCP_SESSION_STATUS_NO_SUCH_RESOURCE;
}
@@ -245,7 +259,8 @@ apt_bool_t mrcp_server_signaling_message_process(mrcp_signaling_message_t *signa
{
mrcp_server_session_t *session = signaling_message->session;
if(session->active_request) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Push Request to Queue");
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Push Request to Queue "APT_NAMESID_FMT,
+ MRCP_SESSION_NAMESID(session));
apt_list_push_back(session->request_queue,signaling_message,session->base.pool);
}
else {
@@ -258,7 +273,9 @@ apt_bool_t mrcp_server_signaling_message_process(mrcp_signaling_message_t *signa
apt_bool_t mrcp_server_on_channel_modify(mrcp_channel_t *channel, mrcp_control_descriptor_t *answer, apt_bool_t status)
{
mrcp_server_session_t *session = (mrcp_server_session_t*)channel->session;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"On Control Channel Modify");
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Control Channel Modified "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ channel->resource->name.buf);
if(!answer) {
return FALSE;
}
@@ -275,7 +292,9 @@ apt_bool_t mrcp_server_on_channel_modify(mrcp_channel_t *channel, mrcp_control_d
apt_bool_t mrcp_server_on_channel_remove(mrcp_channel_t *channel, apt_bool_t status)
{
mrcp_server_session_t *session = (mrcp_server_session_t*)channel->session;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"On Control Channel Remove");
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Control Channel Removed "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ channel->resource->name.buf);
if(!channel->waiting_for_channel) {
return FALSE;
}
@@ -306,7 +325,10 @@ apt_bool_t mrcp_server_on_disconnect(mrcp_channel_t *channel)
apt_bool_t mrcp_server_on_engine_channel_open(mrcp_channel_t *channel, apt_bool_t status)
{
mrcp_server_session_t *session = (mrcp_server_session_t*)channel->session;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"On Engine Channel Open [%s]", status == TRUE ? "OK" : "Failed");
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Engine Channel Opened "APT_NAMESIDRES_FMT" [%s]",
+ MRCP_SESSION_NAMESID(session),
+ channel->resource->name.buf,
+ status == TRUE ? "OK" : "Failed");
if(status == FALSE) {
session->answer->status = MRCP_SESSION_STATUS_UNAVAILABLE_RESOURCE;
}
@@ -317,7 +339,9 @@ apt_bool_t mrcp_server_on_engine_channel_open(mrcp_channel_t *channel, apt_bool_
apt_bool_t mrcp_server_on_engine_channel_close(mrcp_channel_t *channel)
{
mrcp_server_session_t *session = (mrcp_server_session_t*)channel->session;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"On Engine Channel Close");
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Engine Channel Closed "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ channel->resource->name.buf);
mrcp_server_session_subrequest_remove(session);
return TRUE;
}
@@ -366,10 +390,13 @@ static apt_bool_t mrcp_server_session_offer_process(mrcp_server_session_t *sessi
}
mrcp_server_session_add(session);
- session->context = mpf_engine_context_create(session->profile->media_engine,session,5,session->base.pool);
+ session->context = mpf_engine_context_create(
+ session->profile->media_engine,
+ session->base.name,
+ session,5,session->base.pool);
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive Offer "APT_SID_FMT" [c:%d a:%d v:%d]",
- MRCP_SESSION_SID(&session->base),
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive Offer "APT_NAMESID_FMT" [c:%d a:%d v:%d]",
+ MRCP_SESSION_NAMESID(session),
descriptor->control_media_arr->nelts,
descriptor->audio_media_arr->nelts,
descriptor->video_media_arr->nelts);
@@ -422,7 +449,7 @@ static apt_bool_t mrcp_server_session_terminate_process(mrcp_server_session_t *s
mrcp_channel_t *channel;
mrcp_termination_slot_t *slot;
int i;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive Terminate Request "APT_SID_FMT,MRCP_SESSION_SID(&session->base));
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Terminate Session "APT_NAMESID_FMT,MRCP_SESSION_NAMESID(session));
mrcp_server_session_state_set(session,SESSION_STATE_TERMINATING);
@@ -441,7 +468,10 @@ static apt_bool_t mrcp_server_session_terminate_process(mrcp_server_session_t *s
if(!channel) continue;
/* send remove channel request */
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Remove Control Channel [%d]",i);
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Remove Control Channel "APT_NAMESIDRES_FMT" [%d]",
+ MRCP_SESSION_NAMESID(session),
+ channel->resource->name.buf,
+ i);
if(channel->control_channel) {
if(mrcp_server_control_channel_remove(channel->control_channel) == TRUE) {
channel->waiting_for_channel = TRUE;
@@ -453,7 +483,9 @@ static apt_bool_t mrcp_server_session_terminate_process(mrcp_server_session_t *s
mpf_termination_t *termination = channel->engine_channel->termination;
/* send subtract termination request */
if(termination) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Subtract Channel Termination");
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Subtract Media Termination "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ mpf_termination_name_get(termination));
if(mpf_engine_termination_message_add(
session->profile->media_engine,
MPF_SUBTRACT_TERMINATION,session->context,termination,NULL,
@@ -475,7 +507,9 @@ static apt_bool_t mrcp_server_session_terminate_process(mrcp_server_session_t *s
if(!slot || !slot->termination) continue;
/* send subtract termination request */
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Subtract RTP Termination [%d]",i);
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Subtract Media Termination "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ mpf_termination_name_get(slot->termination));
if(mpf_engine_termination_message_add(
session->profile->media_engine,
MPF_SUBTRACT_TERMINATION,session->context,slot->termination,NULL,
@@ -502,7 +536,7 @@ static apt_bool_t mrcp_server_session_deactivate(mrcp_server_session_t *session)
{
mrcp_channel_t *channel;
int i;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Deactivate Session "APT_SID_FMT,MRCP_SESSION_SID(&session->base));
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Deactivate Session "APT_NAMESID_FMT,MRCP_SESSION_NAMESID(session));
mrcp_server_session_state_set(session,SESSION_STATE_DEACTIVATING);
for(i=0; ichannels->nelts; i++) {
channel = APR_ARRAY_IDX(session->channels,i,mrcp_channel_t*);
@@ -525,12 +559,16 @@ static apt_bool_t mrcp_server_on_message_receive(mrcp_server_session_t *session,
if(!channel) {
channel = mrcp_server_channel_find(session,&message->channel_id.resource_name);
if(!channel) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No Such Channel");
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No Such Channel "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ message->channel_id.resource_name.buf);
return FALSE;
}
}
if(!channel->resource || !channel->state_machine) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No Resource");
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Missing Resource "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ channel->resource->name.buf);
return FALSE;
}
@@ -626,7 +664,10 @@ static apt_bool_t mrcp_server_resource_offer_process(mrcp_server_session_t *sess
return FALSE;
}
/* add to channel array */
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Add Control Channel [%d]",count);
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Add Control Channel "APT_NAMESIDRES_FMT" [%d]",
+ MRCP_SESSION_NAMESID(session),
+ channel->resource->name.buf,
+ count);
APR_ARRAY_PUSH(session->channels,mrcp_channel_t*) = channel;
if(channel->engine_channel && channel->engine_channel->termination) {
mpf_termination_t *termination = channel->engine_channel->termination;
@@ -668,7 +709,10 @@ static apt_bool_t mrcp_server_control_media_offer_process(mrcp_server_session_t
control_descriptor = mrcp_session_control_media_get(descriptor,i);
if(!control_descriptor) continue;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Modify Control Channel [%d]",i);
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Modify Control Channel "APT_NAMESIDRES_FMT" [%d]",
+ MRCP_SESSION_NAMESID(session),
+ channel->resource->name.buf,
+ i);
if(channel->control_channel) {
/* send offer */
if(mrcp_server_control_channel_modify(channel->control_channel,control_descriptor) == TRUE) {
@@ -696,7 +740,10 @@ static apt_bool_t mrcp_server_control_media_offer_process(mrcp_server_session_t
if(!channel) continue;
control_descriptor->session_id = session->base.id;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Add Control Channel [%d]",i);
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Add Control Channel "APT_NAMESIDRES_FMT" [%d]",
+ MRCP_SESSION_NAMESID(session),
+ channel->resource->name.buf,
+ i);
APR_ARRAY_PUSH(session->channels,mrcp_channel_t*) = channel;
if(channel->control_channel) {
@@ -746,6 +793,7 @@ static mpf_rtp_termination_descriptor_t* mrcp_server_associations_build(mrcp_ser
mpf_rtp_termination_descriptor_init(rtp_descriptor);
rtp_descriptor->audio.local = NULL;
rtp_descriptor->audio.remote = media_descriptor;
+ rtp_descriptor->audio.settings = session->profile->rtp_settings;
slot->mid = media_descriptor->mid;
slot->channels = apr_array_make(session->base.pool,1,sizeof(mrcp_channel_t*));
@@ -753,7 +801,7 @@ static mpf_rtp_termination_descriptor_t* mrcp_server_associations_build(mrcp_ser
channel = APR_ARRAY_IDX(session->channels,i,mrcp_channel_t*);
if(!channel) continue;
- if(!channel->cmid_arr || mrcp_cmid_find(channel->cmid_arr,slot->mid) == TRUE) {
+ if(session->terminations->nelts == 1 || (!channel->cmid_arr || mrcp_cmid_find(channel->cmid_arr,slot->mid) == TRUE)) {
APR_ARRAY_PUSH(slot->channels, mrcp_channel_t*) = channel;
audio_stream = NULL;
@@ -840,7 +888,10 @@ static apt_bool_t mrcp_server_av_media_offer_process(mrcp_server_session_t *sess
if(!rtp_descriptor) continue;
/* send modify termination request */
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Modify RTP Termination [%d]",i);
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Modify Media Termination "APT_NAMESIDRES_FMT" [%d]",
+ MRCP_SESSION_NAMESID(session),
+ mpf_termination_name_get(slot->termination),
+ i);
if(mpf_engine_termination_message_add(
session->profile->media_engine,
MPF_MODIFY_TERMINATION,session->context,slot->termination,rtp_descriptor,
@@ -859,7 +910,10 @@ static apt_bool_t mrcp_server_av_media_offer_process(mrcp_server_session_t *sess
/* create new RTP termination instance */
termination = mpf_termination_create(session->profile->rtp_termination_factory,session,session->base.pool);
/* add to termination array */
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Add RTP Termination [%d]",i);
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Add Media Termination "APT_NAMESIDRES_FMT" [%d]",
+ MRCP_SESSION_NAMESID(session),
+ mpf_termination_name_get(termination),
+ i);
slot = apr_array_push(session->terminations);
slot->id = i;
slot->mid = 0;
@@ -890,8 +944,8 @@ static apt_bool_t mrcp_server_session_answer_send(mrcp_server_session_t *session
{
apt_bool_t status;
mrcp_session_descriptor_t *descriptor = session->answer;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Send Answer "APT_SID_FMT" [c:%d a:%d v:%d] Status %s",
- MRCP_SESSION_SID(&session->base),
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Send Answer "APT_NAMESID_FMT" [c:%d a:%d v:%d] Status %s",
+ MRCP_SESSION_NAMESID(session),
descriptor->control_media_arr->nelts,
descriptor->audio_media_arr->nelts,
descriptor->video_media_arr->nelts,
@@ -924,7 +978,7 @@ static apt_bool_t mrcp_server_session_terminate_send(mrcp_server_session_t *sess
channel->engine_channel = NULL;
}
}
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Send Terminate Response "APT_SID_FMT,MRCP_SESSION_SID(&session->base));
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Session Terminated "APT_NAMESID_FMT,MRCP_SESSION_NAMESID(session));
mrcp_session_terminate_response(&session->base);
return TRUE;
}
@@ -979,6 +1033,9 @@ static apt_bool_t mrcp_server_on_termination_modify(mrcp_server_session_t *sessi
if(!session) {
return FALSE;
}
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Media Termination Modified "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ mpf_termination_name_get(mpf_message->termination));
termination_slot = mrcp_server_rtp_termination_find(session,mpf_message->termination);
if(termination_slot) {
/* rtp termination */
@@ -1012,6 +1069,9 @@ static apt_bool_t mrcp_server_on_termination_subtract(mrcp_server_session_t *ses
if(!session) {
return FALSE;
}
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Media Termination Subtracted "APT_NAMESIDRES_FMT,
+ MRCP_SESSION_NAMESID(session),
+ mpf_termination_name_get(mpf_message->termination));
termination_slot = mrcp_server_rtp_termination_find(session,mpf_message->termination);
if(termination_slot) {
/* rtp termination */
@@ -1049,15 +1109,12 @@ apt_bool_t mrcp_server_mpf_message_process(mpf_message_container_t *mpf_message_
if(mpf_message->message_type == MPF_MESSAGE_TYPE_RESPONSE) {
switch(mpf_message->command_id) {
case MPF_ADD_TERMINATION:
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"On Termination Add");
mrcp_server_on_termination_modify(session,mpf_message);
break;
case MPF_MODIFY_TERMINATION:
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"On Termination Modify");
mrcp_server_on_termination_modify(session,mpf_message);
break;
case MPF_SUBTRACT_TERMINATION:
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"On Termination Subtract");
mrcp_server_on_termination_subtract(session,mpf_message);
break;
case MPF_ADD_ASSOCIATION:
diff --git a/libs/unimrcp/libs/mrcp-signaling/include/mrcp_session.h b/libs/unimrcp/libs/mrcp-signaling/include/mrcp_session.h
index 173d1c39b2..b1f2ead512 100644
--- a/libs/unimrcp/libs/mrcp-signaling/include/mrcp_session.h
+++ b/libs/unimrcp/libs/mrcp-signaling/include/mrcp_session.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_session.h 1792 2011-01-10 21:08:52Z achaloyan $
*/
-#ifndef __MRCP_SESSION_H__
-#define __MRCP_SESSION_H__
+#ifndef MRCP_SESSION_H
+#define MRCP_SESSION_H
/**
* @file mrcp_session.h
@@ -51,6 +53,10 @@ struct mrcp_session_t {
apr_pool_t *pool;
/** External object associated with session */
void *obj;
+ /** External logger object associated with session */
+ void *log_obj;
+ /** Informative name of the session used for debugging */
+ const char *name;
/** Back pointer to signaling agent */
mrcp_sig_agent_t *signaling_agent;
@@ -189,4 +195,4 @@ static APR_INLINE apt_bool_t mrcp_session_discover_response(mrcp_session_t *sess
APT_END_EXTERN_C
-#endif /*__MRCP_SESSION_H__*/
+#endif /* MRCP_SESSION_H */
diff --git a/libs/unimrcp/libs/mrcp-signaling/include/mrcp_session_descriptor.h b/libs/unimrcp/libs/mrcp-signaling/include/mrcp_session_descriptor.h
index 7a94a42496..9cdbbc9dfe 100644
--- a/libs/unimrcp/libs/mrcp-signaling/include/mrcp_session_descriptor.h
+++ b/libs/unimrcp/libs/mrcp-signaling/include/mrcp_session_descriptor.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_session_descriptor.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_SESSION_DESCRIPTOR_H__
-#define __MRCP_SESSION_DESCRIPTOR_H__
+#ifndef MRCP_SESSION_DESCRIPTOR_H
+#define MRCP_SESSION_DESCRIPTOR_H
/**
* @file mrcp_session_descriptor.h
@@ -143,4 +145,4 @@ MRCP_DECLARE(const char*) mrcp_session_status_phrase_get(mrcp_session_status_e s
APT_END_EXTERN_C
-#endif /*__MRCP_SESSION_DESCRIPTOR_H__*/
+#endif /* MRCP_SESSION_DESCRIPTOR_H */
diff --git a/libs/unimrcp/libs/mrcp-signaling/include/mrcp_sig_agent.h b/libs/unimrcp/libs/mrcp-signaling/include/mrcp_sig_agent.h
index d17986c445..a0ef308470 100644
--- a/libs/unimrcp/libs/mrcp-signaling/include/mrcp_sig_agent.h
+++ b/libs/unimrcp/libs/mrcp-signaling/include/mrcp_sig_agent.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,48 +12,78 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_sig_agent.h 1750 2010-07-23 19:33:34Z achaloyan $
*/
-#ifndef __MRCP_SIG_AGENT_H__
-#define __MRCP_SIG_AGENT_H__
+#ifndef MRCP_SIG_AGENT_H
+#define MRCP_SIG_AGENT_H
/**
* @file mrcp_sig_agent.h
* @brief Abstract MRCP Signaling Agent
*/
+#include
+#include
#include "mrcp_sig_types.h"
#include "apt_task.h"
APT_BEGIN_EXTERN_C
+/** Signaling settings */
+struct mrcp_sig_settings_t {
+ /** Server IP address */
+ char *server_ip;
+ /** Server port */
+ apr_port_t server_port;
+ /** Server SIP user name (v2 only) */
+ char *user_name;
+ /** Resource location (v1 only) */
+ char *resource_location;
+ /** Map of the MRCP resource names (v1 only) */
+ apr_table_t *resource_map;
+ /** Force destination ip address. Should be used only in case
+ SDP contains incorrect connection address (local IP address behind NAT) */
+ apt_bool_t force_destination;
+ /** Optional feature tags */
+ char *feature_tags;
+};
+
+
/** MRCP signaling agent */
struct mrcp_sig_agent_t {
+ /** Agent identifier */
+ const char *id;
/** Memory pool to allocate memory from */
- apr_pool_t *pool;
+ apr_pool_t *pool;
/** External object associated with agent */
- void *obj;
+ void *obj;
/** Parent object (client/server) */
- void *parent;
+ void *parent;
/** MRCP version */
- mrcp_version_e mrcp_version;
+ mrcp_version_e mrcp_version;
/** MRCP resource factory */
mrcp_resource_factory_t *resource_factory;
/** Task interface */
- apt_task_t *task;
+ apt_task_t *task;
/** Task message pool used to allocate signaling agent messages */
- apt_task_msg_pool_t *msg_pool;
+ apt_task_msg_pool_t *msg_pool;
/** Virtual create_server_session */
mrcp_session_t* (*create_server_session)(mrcp_sig_agent_t *signaling_agent);
/** Virtual create_client_session */
- apt_bool_t (*create_client_session)(mrcp_session_t *session);
+ apt_bool_t (*create_client_session)(mrcp_session_t *session, mrcp_sig_settings_t *settings);
};
/** Create signaling agent. */
-MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_signaling_agent_create(void *obj, mrcp_version_e mrcp_version, apr_pool_t *pool);
+MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_signaling_agent_create(const char *id, void *obj, mrcp_version_e mrcp_version, apr_pool_t *pool);
+
+/** Allocate MRCP signaling settings. */
+MRCP_DECLARE(mrcp_sig_settings_t*) mrcp_signaling_settings_alloc(apr_pool_t *pool);
+
APT_END_EXTERN_C
-#endif /*__MRCP_SIG_AGENT_H__*/
+#endif /* MRCP_SIG_AGENT_H */
diff --git a/libs/unimrcp/libs/mrcp-signaling/include/mrcp_sig_types.h b/libs/unimrcp/libs/mrcp-signaling/include/mrcp_sig_types.h
index 41de32b861..c45b4be6e6 100644
--- a/libs/unimrcp/libs/mrcp-signaling/include/mrcp_sig_types.h
+++ b/libs/unimrcp/libs/mrcp-signaling/include/mrcp_sig_types.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_sig_types.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_SIG_TYPES_H__
-#define __MRCP_SIG_TYPES_H__
+#ifndef MRCP_SIG_TYPES_H
+#define MRCP_SIG_TYPES_H
/**
* @file mrcp_sig_types.h
@@ -26,6 +28,9 @@
APT_BEGIN_EXTERN_C
+/** Opaque MRCP signaling settings declaration */
+typedef struct mrcp_sig_settings_t mrcp_sig_settings_t;
+
/** Opaque MRCP signaling agent declaration */
typedef struct mrcp_sig_agent_t mrcp_sig_agent_t;
@@ -37,4 +42,4 @@ typedef struct mrcp_session_descriptor_t mrcp_session_descriptor_t;
APT_END_EXTERN_C
-#endif /*__MRCP_SIG_TYPES_H__*/
+#endif /* MRCP_SIG_TYPES_H */
diff --git a/libs/unimrcp/libs/mrcp-signaling/mrcpsignaling.2008.vcproj b/libs/unimrcp/libs/mrcp-signaling/mrcpsignaling.2008.vcproj
deleted file mode 100644
index 25e0f23d9c..0000000000
--- a/libs/unimrcp/libs/mrcp-signaling/mrcpsignaling.2008.vcproj
+++ /dev/null
@@ -1,289 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/libs/mrcp-signaling/mrcpsignaling.2010.vcxproj b/libs/unimrcp/libs/mrcp-signaling/mrcpsignaling.2010.vcxproj
deleted file mode 100644
index f11e3bd765..0000000000
--- a/libs/unimrcp/libs/mrcp-signaling/mrcpsignaling.2010.vcxproj
+++ /dev/null
@@ -1,121 +0,0 @@
-
-
-
-
- Debug
- Win32
-
-
- Debug
- x64
-
-
- Release
- Win32
-
-
- Release
- x64
-
-
-
- mrcpsignaling
- {12A49562-BAB9-43A3-A21D-15B60BBB4C31}
- mrcpsignaling
- Win32Proj
-
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
-
-
-
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;%(PreprocessorDefinitions)
- ProgramDatabase
-
-
-
-
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/libs/mrcp-signaling/mrcpsignaling.2010.vcxproj.filters b/libs/unimrcp/libs/mrcp-signaling/mrcpsignaling.2010.vcxproj.filters
deleted file mode 100644
index 4e5d30c3da..0000000000
--- a/libs/unimrcp/libs/mrcp-signaling/mrcpsignaling.2010.vcxproj.filters
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hpp;hxx;hm;inl;inc;xsd
-
-
- {f3dc550f-1a0f-4b9e-b077-3b6940dc5531}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
-
-
- src
-
-
- src
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/libs/mrcp-signaling/src/mrcp_session_descriptor.c b/libs/unimrcp/libs/mrcp-signaling/src/mrcp_session_descriptor.c
index 5b0162725f..54d89ff258 100644
--- a/libs/unimrcp/libs/mrcp-signaling/src/mrcp_session_descriptor.c
+++ b/libs/unimrcp/libs/mrcp-signaling/src/mrcp_session_descriptor.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_session_descriptor.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "mrcp_session_descriptor.h"
diff --git a/libs/unimrcp/libs/mrcp-signaling/src/mrcp_sig_agent.c b/libs/unimrcp/libs/mrcp-signaling/src/mrcp_sig_agent.c
index 90773c345b..ba8570a606 100644
--- a/libs/unimrcp/libs/mrcp-signaling/src/mrcp_sig_agent.c
+++ b/libs/unimrcp/libs/mrcp-signaling/src/mrcp_sig_agent.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,15 +12,18 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_sig_agent.c 1792 2011-01-10 21:08:52Z achaloyan $
*/
#include "mrcp_sig_agent.h"
#include "mrcp_session.h"
#include "apt_pool.h"
-MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_signaling_agent_create(void *obj, mrcp_version_e mrcp_version, apr_pool_t *pool)
+MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_signaling_agent_create(const char *id, void *obj, mrcp_version_e mrcp_version, apr_pool_t *pool)
{
mrcp_sig_agent_t *sig_agent = apr_palloc(pool,sizeof(mrcp_sig_agent_t));
+ sig_agent->id = id;
sig_agent->pool = pool;
sig_agent->obj = obj;
sig_agent->mrcp_version = mrcp_version;
@@ -33,6 +36,21 @@ MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_signaling_agent_create(void *obj, mrcp_vers
return sig_agent;
}
+/** Allocate MRCP signaling settings */
+MRCP_DECLARE(mrcp_sig_settings_t*) mrcp_signaling_settings_alloc(apr_pool_t *pool)
+{
+ mrcp_sig_settings_t *settings = apr_palloc(pool,sizeof(mrcp_sig_settings_t));
+ settings->server_ip = NULL;
+ settings->server_port = 0;
+ settings->user_name = NULL;
+ settings->resource_location = NULL;
+ settings->resource_map = apr_table_make(pool,2);
+ settings->force_destination = FALSE;
+ settings->feature_tags = NULL;
+ return settings;
+}
+
+
MRCP_DECLARE(mrcp_session_t*) mrcp_session_create(apr_size_t padding)
{
mrcp_session_t *session;
@@ -43,6 +61,8 @@ MRCP_DECLARE(mrcp_session_t*) mrcp_session_create(apr_size_t padding)
session = apr_palloc(pool,sizeof(mrcp_session_t)+padding);
session->pool = pool;
session->obj = NULL;
+ session->log_obj = NULL;
+ session->name = NULL;
session->signaling_agent = NULL;
session->request_vtable = NULL;
session->response_vtable = NULL;
diff --git a/libs/unimrcp/libs/mrcp/Makefile.am b/libs/unimrcp/libs/mrcp/Makefile.am
index 014261f81d..7528d04928 100644
--- a/libs/unimrcp/libs/mrcp/Makefile.am
+++ b/libs/unimrcp/libs/mrcp/Makefile.am
@@ -14,6 +14,7 @@ include_HEADERS = include/mrcp.h \
message/include/mrcp_start_line.h \
message/include/mrcp_header_accessor.h \
message/include/mrcp_generic_header.h \
+ message/include/mrcp_header.h \
message/include/mrcp_message.h \
control/include/mrcp_resource.h \
control/include/mrcp_resource_factory.h \
@@ -24,11 +25,14 @@ include_HEADERS = include/mrcp.h \
resources/include/mrcp_recog_header.h \
resources/include/mrcp_recog_resource.h \
resources/include/mrcp_recorder_header.h \
- resources/include/mrcp_recorder_resource.h
+ resources/include/mrcp_recorder_resource.h \
+ resources/include/mrcp_verifier_header.h \
+ resources/include/mrcp_verifier_resource.h
-libmrcp_la_SOURCES = message/src/mrcp_header_accessor.c \
+libmrcp_la_SOURCES = message/src/mrcp_start_line.c \
+ message/src/mrcp_header_accessor.c \
message/src/mrcp_generic_header.c \
- message/src/mrcp_start_line.c \
+ message/src/mrcp_header.c \
message/src/mrcp_message.c \
control/src/mrcp_resource_factory.c \
control/src/mrcp_resource_loader.c \
@@ -38,4 +42,6 @@ libmrcp_la_SOURCES = message/src/mrcp_header_accessor.c \
resources/src/mrcp_recog_header.c \
resources/src/mrcp_recog_resource.c \
resources/src/mrcp_recorder_header.c \
- resources/src/mrcp_recorder_resource.c
+ resources/src/mrcp_recorder_resource.c \
+ resources/src/mrcp_verifier_header.c \
+ resources/src/mrcp_verifier_resource.c
diff --git a/libs/unimrcp/libs/mrcp/control/include/mrcp_resource.h b/libs/unimrcp/libs/mrcp/control/include/mrcp_resource.h
index dd7a7f8abd..0f45fe54cc 100644
--- a/libs/unimrcp/libs/mrcp/control/include/mrcp_resource.h
+++ b/libs/unimrcp/libs/mrcp/control/include/mrcp_resource.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_resource.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_RESOURCE_H__
-#define __MRCP_RESOURCE_H__
+#ifndef MRCP_RESOURCE_H
+#define MRCP_RESOURCE_H
/**
* @file mrcp_resource.h
@@ -77,4 +79,4 @@ static APR_INLINE apt_bool_t mrcp_resource_validate(mrcp_resource_t *resource)
APT_END_EXTERN_C
-#endif /*__MRCP_RESOURCE_H__*/
+#endif /* MRCP_RESOURCE_H */
diff --git a/libs/unimrcp/libs/mrcp/control/include/mrcp_resource_factory.h b/libs/unimrcp/libs/mrcp/control/include/mrcp_resource_factory.h
index f0349a7e2e..84631b13d7 100644
--- a/libs/unimrcp/libs/mrcp/control/include/mrcp_resource_factory.h
+++ b/libs/unimrcp/libs/mrcp/control/include/mrcp_resource_factory.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_resource_factory.h 1632 2010-03-30 20:46:25Z achaloyan $
*/
-#ifndef __MRCP_RESOURCE_FACTORY_H__
-#define __MRCP_RESOURCE_FACTORY_H__
+#ifndef MRCP_RESOURCE_FACTORY_H
+#define MRCP_RESOURCE_FACTORY_H
/**
* @file mrcp_resource_factory.h
@@ -37,12 +39,12 @@ MRCP_DECLARE(apt_bool_t) mrcp_resource_factory_destroy(mrcp_resource_factory_t *
MRCP_DECLARE(apt_bool_t) mrcp_resource_register(mrcp_resource_factory_t *resource_factory, mrcp_resource_t *resource);
/** Get MRCP resource by resource id */
-MRCP_DECLARE(mrcp_resource_t*) mrcp_resource_get(mrcp_resource_factory_t *resource_factory, mrcp_resource_id resource_id);
+MRCP_DECLARE(mrcp_resource_t*) mrcp_resource_get(const mrcp_resource_factory_t *resource_factory, mrcp_resource_id resource_id);
/** Find MRCP resource by resource name */
-MRCP_DECLARE(mrcp_resource_t*) mrcp_resource_find(mrcp_resource_factory_t *resource_factory, const apt_str_t *name);
+MRCP_DECLARE(mrcp_resource_t*) mrcp_resource_find(const mrcp_resource_factory_t *resource_factory, const apt_str_t *name);
APT_END_EXTERN_C
-#endif /*__MRCP_RESOURCE_FACTORY_H__*/
+#endif /* MRCP_RESOURCE_FACTORY_H */
diff --git a/libs/unimrcp/libs/mrcp/control/include/mrcp_resource_loader.h b/libs/unimrcp/libs/mrcp/control/include/mrcp_resource_loader.h
index e88cca4305..a6608aba3b 100644
--- a/libs/unimrcp/libs/mrcp/control/include/mrcp_resource_loader.h
+++ b/libs/unimrcp/libs/mrcp/control/include/mrcp_resource_loader.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_resource_loader.h 1710 2010-05-24 17:36:19Z achaloyan $
*/
-#ifndef __MRCP_RESOURCE_LOADER_H__
-#define __MRCP_RESOURCE_LOADER_H__
+#ifndef MRCP_RESOURCE_LOADER_H
+#define MRCP_RESOURCE_LOADER_H
/**
* @file mrcp_resource_loader.h
@@ -44,8 +46,8 @@ MRCP_DECLARE(apt_bool_t) mrcp_resource_load(mrcp_resource_loader_t *loader, cons
MRCP_DECLARE(apt_bool_t) mrcp_resource_load_by_id(mrcp_resource_loader_t *loader, mrcp_resource_id id);
/** Get MRCP resource factory */
-MRCP_DECLARE(mrcp_resource_factory_t*) mrcp_resource_factory_get(mrcp_resource_loader_t *loader);
+MRCP_DECLARE(mrcp_resource_factory_t*) mrcp_resource_factory_get(const mrcp_resource_loader_t *loader);
APT_END_EXTERN_C
-#endif /*__MRCP_RESOURCE_LOADER_H__*/
+#endif /* MRCP_RESOURCE_LOADER_H */
diff --git a/libs/unimrcp/libs/mrcp/control/include/mrcp_stream.h b/libs/unimrcp/libs/mrcp/control/include/mrcp_stream.h
index 3cc9d38511..ab5c4c6fa5 100644
--- a/libs/unimrcp/libs/mrcp/control/include/mrcp_stream.h
+++ b/libs/unimrcp/libs/mrcp/control/include/mrcp_stream.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,68 +12,58 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_stream.h 1660 2010-04-19 18:29:06Z achaloyan $
*/
-#ifndef __MRCP_STREAM_H__
-#define __MRCP_STREAM_H__
+#ifndef MRCP_STREAM_H
+#define MRCP_STREAM_H
/**
* @file mrcp_stream.h
* @brief MRCP Stream Parser and Generator
*/
-#include "apt_text_stream.h"
+#include "apt_text_message.h"
#include "mrcp_types.h"
APT_BEGIN_EXTERN_C
-/** Status of MRCP stream processing (parse/generate) */
-typedef enum {
- MRCP_STREAM_STATUS_COMPLETE,
- MRCP_STREAM_STATUS_INCOMPLETE,
- MRCP_STREAM_STATUS_INVALID
-} mrcp_stream_status_e;
/** Opaque MRCP parser declaration */
typedef struct mrcp_parser_t mrcp_parser_t;
/** Opaque MRCP generator declaration */
typedef struct mrcp_generator_t mrcp_generator_t;
-/** MRCP message handler */
-typedef apt_bool_t (*mrcp_message_handler_f)(void *obj, mrcp_message_t *message, mrcp_stream_status_e status);
-
-/** Parse MRCP message (excluding message body) */
-MRCP_DECLARE(apt_bool_t) mrcp_message_parse(mrcp_resource_factory_t *resource_factory, mrcp_message_t *message, apt_text_stream_t *stream);
-
-/** Generate MRCP message (excluding message body) */
-MRCP_DECLARE(apt_bool_t) mrcp_message_generate(mrcp_resource_factory_t *resource_factory, mrcp_message_t *message, apt_text_stream_t *stream);
-
/** Create MRCP stream parser */
-MRCP_DECLARE(mrcp_parser_t*) mrcp_parser_create(mrcp_resource_factory_t *resource_factory, apr_pool_t *pool);
+MRCP_DECLARE(mrcp_parser_t*) mrcp_parser_create(const mrcp_resource_factory_t *resource_factory, apr_pool_t *pool);
-/** Set resource name to be used while parsing (MRCPv1 only) */
-MRCP_DECLARE(void) mrcp_parser_resource_name_set(mrcp_parser_t *parser, const apt_str_t *resource_name);
+/** Set resource by name to be used for parsing of MRCPv1 messages */
+MRCP_DECLARE(void) mrcp_parser_resource_set(mrcp_parser_t *parser, const apt_str_t *resource_name);
+
+/** Set verbose mode for the parser */
+MRCP_DECLARE(void) mrcp_parser_verbose_set(mrcp_parser_t *parser, apt_bool_t verbose);
/** Parse MRCP stream */
-MRCP_DECLARE(mrcp_stream_status_e) mrcp_parser_run(mrcp_parser_t *parser, apt_text_stream_t *stream);
+MRCP_DECLARE(apt_message_status_e) mrcp_parser_run(mrcp_parser_t *parser, apt_text_stream_t *stream, mrcp_message_t **message);
-/** Get parsed MRCP message */
-MRCP_DECLARE(mrcp_message_t*) mrcp_parser_message_get(const mrcp_parser_t *parser);
/** Create MRCP stream generator */
-MRCP_DECLARE(mrcp_generator_t*) mrcp_generator_create(mrcp_resource_factory_t *resource_factory, apr_pool_t *pool);
+MRCP_DECLARE(mrcp_generator_t*) mrcp_generator_create(const mrcp_resource_factory_t *resource_factory, apr_pool_t *pool);
-/** Set MRCP message to generate */
-MRCP_DECLARE(apt_bool_t) mrcp_generator_message_set(mrcp_generator_t *generator, mrcp_message_t *message);
+/** Set verbose mode for the generator */
+MRCP_DECLARE(void) mrcp_generator_verbose_set(mrcp_generator_t *generator, apt_bool_t verbose);
/** Generate MRCP stream */
-MRCP_DECLARE(mrcp_stream_status_e) mrcp_generator_run(mrcp_generator_t *generator, apt_text_stream_t *stream);
+MRCP_DECLARE(apt_message_status_e) mrcp_generator_run(mrcp_generator_t *generator, mrcp_message_t *message, apt_text_stream_t *stream);
+
+
+/** Generate MRCP message (excluding message body) */
+MRCP_DECLARE(apt_bool_t) mrcp_message_generate(const mrcp_resource_factory_t *resource_factory, mrcp_message_t *message, apt_text_stream_t *stream);
-/** Walk through MRCP stream and call message handler for each parsed message */
-MRCP_DECLARE(apt_bool_t) mrcp_stream_walk(mrcp_parser_t *parser, apt_text_stream_t *stream, mrcp_message_handler_f handler, void *obj);
APT_END_EXTERN_C
-#endif /*__MRCP_STREAM_H__*/
+#endif /* MRCP_STREAM_H */
diff --git a/libs/unimrcp/libs/mrcp/control/src/mrcp_resource_factory.c b/libs/unimrcp/libs/mrcp/control/src/mrcp_resource_factory.c
index 894f89f158..21c6d341e6 100644
--- a/libs/unimrcp/libs/mrcp/control/src/mrcp_resource_factory.c
+++ b/libs/unimrcp/libs/mrcp/control/src/mrcp_resource_factory.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_resource_factory.c 1632 2010-03-30 20:46:25Z achaloyan $
*/
#include
@@ -80,7 +82,7 @@ MRCP_DECLARE(apt_bool_t) mrcp_resource_register(mrcp_resource_factory_t *resourc
}
/** Get MRCP resource by resource id */
-MRCP_DECLARE(mrcp_resource_t*) mrcp_resource_get(mrcp_resource_factory_t *resource_factory, mrcp_resource_id resource_id)
+MRCP_DECLARE(mrcp_resource_t*) mrcp_resource_get(const mrcp_resource_factory_t *resource_factory, mrcp_resource_id resource_id)
{
if(resource_id >= resource_factory->resource_count) {
return NULL;
@@ -89,7 +91,7 @@ MRCP_DECLARE(mrcp_resource_t*) mrcp_resource_get(mrcp_resource_factory_t *resour
}
/** Find MRCP resource by resource name */
-MRCP_DECLARE(mrcp_resource_t*) mrcp_resource_find(mrcp_resource_factory_t *resource_factory, const apt_str_t *name)
+MRCP_DECLARE(mrcp_resource_t*) mrcp_resource_find(const mrcp_resource_factory_t *resource_factory, const apt_str_t *name)
{
if(!name->buf || !name->length) {
return NULL;
diff --git a/libs/unimrcp/libs/mrcp/control/src/mrcp_resource_loader.c b/libs/unimrcp/libs/mrcp/control/src/mrcp_resource_loader.c
index c670b8ba79..2160b2a614 100644
--- a/libs/unimrcp/libs/mrcp/control/src/mrcp_resource_loader.c
+++ b/libs/unimrcp/libs/mrcp/control/src/mrcp_resource_loader.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_resource_loader.c 1764 2010-08-23 18:02:18Z achaloyan $
*/
#include "mrcp_resource_loader.h"
@@ -20,6 +22,7 @@
#include "mrcp_synth_resource.h"
#include "mrcp_recog_resource.h"
#include "mrcp_recorder_resource.h"
+#include "mrcp_verifier_resource.h"
#include "apt_log.h"
/** Resource loader */
@@ -28,11 +31,12 @@ struct mrcp_resource_loader_t {
apr_pool_t *pool;
};
-/** String table of MRCPv2 resources (mrcp_resource_types_e) */
+/** String table of MRCPv2 resources (mrcp_resource_type_e) */
static const apt_str_table_item_t mrcp_resource_string_table[] = {
{{"speechsynth",11},6},
{{"speechrecog",11},6},
- {{"recorder", 8},0}
+ {{"recorder", 8},0},
+ {{"speakverify",11},3}
};
static mrcp_resource_t* mrcp_resource_create_by_id(mrcp_resource_id id, apr_pool_t *pool);
@@ -106,7 +110,7 @@ MRCP_DECLARE(apt_bool_t) mrcp_resource_load_by_id(mrcp_resource_loader_t *loader
}
/** Get MRCP resource factory */
-MRCP_DECLARE(mrcp_resource_factory_t*) mrcp_resource_factory_get(mrcp_resource_loader_t *loader)
+MRCP_DECLARE(mrcp_resource_factory_t*) mrcp_resource_factory_get(const mrcp_resource_loader_t *loader)
{
return loader->factory;
}
@@ -124,6 +128,9 @@ static mrcp_resource_t* mrcp_resource_create_by_id(mrcp_resource_id id, apr_pool
case MRCP_RECORDER_RESOURCE:
resource = mrcp_recorder_resource_create(pool);
break;
+ case MRCP_VERIFIER_RESOURCE:
+ resource = mrcp_verifier_resource_create(pool);
+ break;
}
if(resource) {
diff --git a/libs/unimrcp/libs/mrcp/control/src/mrcp_stream.c b/libs/unimrcp/libs/mrcp/control/src/mrcp_stream.c
index daef44c219..94f067240c 100644
--- a/libs/unimrcp/libs/mrcp/control/src/mrcp_stream.c
+++ b/libs/unimrcp/libs/mrcp/control/src/mrcp_stream.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,124 +12,210 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_stream.c 1671 2010-04-28 19:50:29Z achaloyan $
*/
#include "mrcp_stream.h"
#include "mrcp_message.h"
-#include "mrcp_generic_header.h"
#include "mrcp_resource_factory.h"
+#include "mrcp_resource.h"
#include "apt_log.h"
-/** Stage of MRCP stream processing (parse/generate) */
-typedef enum {
- MRCP_STREAM_STAGE_NONE,
- MRCP_STREAM_STAGE_START_LINE,
- MRCP_STREAM_STAGE_RESOURCE,
- MRCP_STREAM_STAGE_HEADER,
- MRCP_STREAM_STAGE_BODY
-} mrcp_stream_stage_e;
/** MRCP parser */
struct mrcp_parser_t {
- mrcp_resource_factory_t *resource_factory;
- apt_str_t resource_name;
- mrcp_stream_stage_e stage;
- apt_bool_t skip_lf;
- mrcp_message_t *message;
- apr_pool_t *pool;
+ apt_message_parser_t *base;
+ const mrcp_resource_factory_t *resource_factory;
+ mrcp_resource_t *resource;
};
/** MRCP generator */
struct mrcp_generator_t {
- mrcp_resource_factory_t *resource_factory;
- mrcp_stream_stage_e stage;
- mrcp_message_t *message;
- apr_pool_t *pool;
+ apt_message_generator_t *base;
+ const mrcp_resource_factory_t *resource_factory;
+};
+
+/** Create message and read start line */
+static apt_bool_t mrcp_parser_on_start(apt_message_parser_t *parser, apt_message_context_t *context, apt_text_stream_t *stream, apr_pool_t *pool);
+/** Header section handler */
+static apt_bool_t mrcp_parser_on_header_complete(apt_message_parser_t *parser, apt_message_context_t *context);
+
+static const apt_message_parser_vtable_t parser_vtable = {
+ mrcp_parser_on_start,
+ mrcp_parser_on_header_complete,
+ NULL
+};
+
+/** Start message generation */
+apt_bool_t mrcp_generator_on_start(apt_message_generator_t *generator, apt_message_context_t *context, apt_text_stream_t *stream);
+/** Finalize by setting overall message length in start line */
+apt_bool_t mrcp_generator_on_header_complete(apt_message_generator_t *generator, apt_message_context_t *context, apt_text_stream_t *stream);
+
+static const apt_message_generator_vtable_t generator_vtable = {
+ mrcp_generator_on_start,
+ mrcp_generator_on_header_complete,
+ NULL
};
-/** Read MRCP message-body */
-static apt_bool_t mrcp_message_body_read(mrcp_message_t *message, apt_text_stream_t *stream)
+/** Create MRCP stream parser */
+MRCP_DECLARE(mrcp_parser_t*) mrcp_parser_create(const mrcp_resource_factory_t *resource_factory, apr_pool_t *pool)
{
- apt_bool_t status = TRUE;
- if(message->body.buf) {
- mrcp_generic_header_t *generic_header = mrcp_generic_header_get(message);
- /* stream length available to read */
- apr_size_t stream_length = stream->text.length - (stream->pos - stream->text.buf);
- /* required/remaining length to read */
- apr_size_t required_length = generic_header->content_length - message->body.length;
- if(required_length > stream_length) {
- required_length = stream_length;
- /* not complete */
- status = FALSE;
- }
- memcpy(message->body.buf+message->body.length,stream->pos,required_length);
- message->body.length += required_length;
- stream->pos += required_length;
- message->body.buf[message->body.length] = '\0';
- }
-
- return status;
+ mrcp_parser_t *parser = apr_palloc(pool,sizeof(mrcp_parser_t));
+ parser->base = apt_message_parser_create(parser,&parser_vtable,pool);
+ parser->resource_factory = resource_factory;
+ parser->resource = NULL;
+ return parser;
}
-/** Write MRCP message-body */
-static apt_bool_t mrcp_message_body_write(mrcp_message_t *message, apt_text_stream_t *stream)
+/** Set resource by name to be used for parsing of MRCPv1 messages */
+MRCP_DECLARE(void) mrcp_parser_resource_set(mrcp_parser_t *parser, const apt_str_t *resource_name)
{
- apt_bool_t status = TRUE;
- mrcp_generic_header_t *generic_header = mrcp_generic_header_get(message);
- if(generic_header && message->body.length < generic_header->content_length) {
- /* stream length available to write */
- apr_size_t stream_length = stream->text.length - (stream->pos - stream->text.buf);
- /* required/remaining length to write */
- apr_size_t required_length = generic_header->content_length - message->body.length;
- if(required_length > stream_length) {
- required_length = stream_length;
- /* not complete */
- status = FALSE;
- }
-
- memcpy(stream->pos,message->body.buf+message->body.length,required_length);
- message->body.length += required_length;
- stream->pos += required_length;
+ if(resource_name) {
+ parser->resource = mrcp_resource_find(parser->resource_factory,resource_name);
}
-
- return status;
}
-/** Parse MRCP message (excluding message body) */
-MRCP_DECLARE(apt_bool_t) mrcp_message_parse(mrcp_resource_factory_t *resource_factory, mrcp_message_t *message, apt_text_stream_t *stream)
+/** Set verbose mode for the parser */
+MRCP_DECLARE(void) mrcp_parser_verbose_set(mrcp_parser_t *parser, apt_bool_t verbose)
{
- mrcp_resource_t *resource;
+ apt_message_parser_verbose_set(parser->base,verbose);
+}
+/** Parse MRCP stream */
+MRCP_DECLARE(apt_message_status_e) mrcp_parser_run(mrcp_parser_t *parser, apt_text_stream_t *stream, mrcp_message_t **message)
+{
+ return apt_message_parser_run(parser->base,stream,(void**)message);
+}
+
+/** Create message and read start line */
+static apt_bool_t mrcp_parser_on_start(apt_message_parser_t *parser, apt_message_context_t *context, apt_text_stream_t *stream, apr_pool_t *pool)
+{
+ mrcp_message_t *mrcp_message;
+ apt_str_t start_line;
+ /* read start line */
+ if(apt_text_line_read(stream,&start_line) == FALSE) {
+ return FALSE;
+ }
+
+ /* create new MRCP message */
+ mrcp_message = mrcp_message_create(pool);
/* parse start-line */
- if(mrcp_start_line_parse(&message->start_line,stream,message->pool) == FALSE) {
+ if(mrcp_start_line_parse(&mrcp_message->start_line,&start_line,mrcp_message->pool) == FALSE) {
return FALSE;
}
- if(message->start_line.version == MRCP_VERSION_2) {
- mrcp_channel_id_parse(&message->channel_id,stream,message->pool);
- }
-
- /* find resource */
- resource = mrcp_resource_find(resource_factory,&message->channel_id.resource_name);
- if(!resource) {
- return FALSE;
- }
-
- if(mrcp_message_resource_set(message,resource) == FALSE) {
- return FALSE;
- }
-
- /* parse header */
- if(mrcp_message_header_parse(&message->header,stream,message->pool) == FALSE) {
- return FALSE;
+ if(mrcp_message->start_line.version == MRCP_VERSION_1) {
+ mrcp_parser_t *mrcp_parser = apt_message_parser_object_get(parser);
+ if(!mrcp_parser->resource) {
+ return FALSE;
+ }
+ apt_string_copy(
+ &mrcp_message->channel_id.resource_name,
+ &mrcp_parser->resource->name,
+ pool);
+
+ if(mrcp_message_resource_set(mrcp_message,mrcp_parser->resource) == FALSE) {
+ return FALSE;
+ }
}
+ context->message = mrcp_message;
+ context->header = &mrcp_message->header.header_section;
+ context->body = &mrcp_message->body;
return TRUE;
}
+/** Header section handler */
+static apt_bool_t mrcp_parser_on_header_complete(apt_message_parser_t *parser, apt_message_context_t *context)
+{
+ mrcp_message_t *mrcp_message = context->message;
+ if(mrcp_message->start_line.version == MRCP_VERSION_2) {
+ mrcp_resource_t *resource;
+ mrcp_parser_t *mrcp_parser;
+ if(mrcp_channel_id_parse(&mrcp_message->channel_id,&mrcp_message->header,mrcp_message->pool) == FALSE) {
+ return FALSE;
+ }
+ mrcp_parser = apt_message_parser_object_get(parser);
+ /* find resource */
+ resource = mrcp_resource_find(mrcp_parser->resource_factory,&mrcp_message->channel_id.resource_name);
+ if(!resource) {
+ return FALSE;
+ }
+
+ if(mrcp_message_resource_set(mrcp_message,resource) == FALSE) {
+ return FALSE;
+ }
+ }
+
+ if(mrcp_header_fields_parse(&mrcp_message->header,mrcp_message->pool) == FALSE) {
+ return FALSE;
+ }
+
+ if(context->body && mrcp_generic_header_property_check(mrcp_message,GENERIC_HEADER_CONTENT_LENGTH) == TRUE) {
+ mrcp_generic_header_t *generic_header = mrcp_generic_header_get(mrcp_message);
+ if(generic_header && generic_header->content_length) {
+ context->body->length = generic_header->content_length;
+ }
+ }
+ return TRUE;
+}
+
+
+/** Create MRCP stream generator */
+MRCP_DECLARE(mrcp_generator_t*) mrcp_generator_create(const mrcp_resource_factory_t *resource_factory, apr_pool_t *pool)
+{
+ mrcp_generator_t *generator = apr_palloc(pool,sizeof(mrcp_generator_t));
+ generator->base = apt_message_generator_create(generator,&generator_vtable,pool);
+ generator->resource_factory = resource_factory;
+ return generator;
+}
+
+/** Set verbose mode for the generator */
+MRCP_DECLARE(void) mrcp_generator_verbose_set(mrcp_generator_t *generator, apt_bool_t verbose)
+{
+ apt_message_generator_verbose_set(generator->base,verbose);
+}
+
+/** Generate MRCP stream */
+MRCP_DECLARE(apt_message_status_e) mrcp_generator_run(mrcp_generator_t *generator, mrcp_message_t *message, apt_text_stream_t *stream)
+{
+ return apt_message_generator_run(generator->base,message,stream);
+}
+
+/** Initialize by generating message start line and return header section and body */
+apt_bool_t mrcp_generator_on_start(apt_message_generator_t *generator, apt_message_context_t *context, apt_text_stream_t *stream)
+{
+ mrcp_message_t *mrcp_message = context->message;
+ /* validate message */
+ if(mrcp_message_validate(mrcp_message) == FALSE) {
+ return FALSE;
+ }
+ /* generate start-line */
+ if(mrcp_start_line_generate(&mrcp_message->start_line,stream) == FALSE) {
+ return FALSE;
+ }
+
+ if(mrcp_message->start_line.version == MRCP_VERSION_2) {
+ mrcp_channel_id_generate(&mrcp_message->channel_id,stream);
+ }
+
+ context->header = &mrcp_message->header.header_section;
+ context->body = &mrcp_message->body;
+ return TRUE;
+}
+
+/** Finalize by setting overall message length in start line */
+apt_bool_t mrcp_generator_on_header_complete(apt_message_generator_t *generator, apt_message_context_t *context, apt_text_stream_t *stream)
+{
+ mrcp_message_t *mrcp_message = context->message;
+ /* finalize start-line generation */
+ return mrcp_start_line_finalize(&mrcp_message->start_line,mrcp_message->body.length,stream);
+}
+
/** Generate MRCP message (excluding message body) */
-MRCP_DECLARE(apt_bool_t) mrcp_message_generate(mrcp_resource_factory_t *resource_factory, mrcp_message_t *message, apt_text_stream_t *stream)
+MRCP_DECLARE(apt_bool_t) mrcp_message_generate(const mrcp_resource_factory_t *resource_factory, mrcp_message_t *message, apt_text_stream_t *stream)
{
/* validate message */
if(mrcp_message_validate(message) == FALSE) {
@@ -145,8 +231,8 @@ MRCP_DECLARE(apt_bool_t) mrcp_message_generate(mrcp_resource_factory_t *resource
mrcp_channel_id_generate(&message->channel_id,stream);
}
- /* generate header */
- if(mrcp_message_header_generate(&message->header,stream) == FALSE) {
+ /* generate header section */
+ if(apt_header_section_generate(&message->header.header_section,stream) == FALSE) {
return FALSE;
}
@@ -157,254 +243,3 @@ MRCP_DECLARE(apt_bool_t) mrcp_message_generate(mrcp_resource_factory_t *resource
return TRUE;
}
-
-
-/** Create MRCP stream parser */
-MRCP_DECLARE(mrcp_parser_t*) mrcp_parser_create(mrcp_resource_factory_t *resource_factory, apr_pool_t *pool)
-{
- mrcp_parser_t *parser = apr_palloc(pool,sizeof(mrcp_parser_t));
- parser->resource_factory = resource_factory;
- apt_string_reset(&parser->resource_name);
- parser->stage = MRCP_STREAM_STAGE_NONE;
- parser->skip_lf = FALSE;
- parser->message = NULL;
- parser->pool = pool;
- return parser;
-}
-
-/** Set resource name to be used while parsing (MRCPv1 only) */
-MRCP_DECLARE(void) mrcp_parser_resource_name_set(mrcp_parser_t *parser, const apt_str_t *resource_name)
-{
- if(resource_name) {
- apt_string_copy(&parser->resource_name,resource_name,parser->pool);
- }
-}
-
-static mrcp_stream_status_e mrcp_parser_break(mrcp_parser_t *parser, apt_text_stream_t *stream)
-{
- /* failed to parse message */
- if(apt_text_is_eos(stream) == TRUE) {
- /* end of stream reached */
- return MRCP_STREAM_STATUS_INCOMPLETE;
- }
-
- /* error case */
- parser->stage = MRCP_STREAM_STAGE_NONE;
- return MRCP_STREAM_STATUS_INVALID;
-}
-
-/** Parse MRCP stream */
-MRCP_DECLARE(mrcp_stream_status_e) mrcp_parser_run(mrcp_parser_t *parser, apt_text_stream_t *stream)
-{
- mrcp_message_t *message = parser->message;
- if(parser->stage == MRCP_STREAM_STAGE_NONE || !message) {
- /* create new MRCP message */
- message = mrcp_message_create(parser->pool);
- message->channel_id.resource_name = parser->resource_name;
- parser->message = message;
- parser->stage = MRCP_STREAM_STAGE_START_LINE;
- }
-
- if(parser->stage == MRCP_STREAM_STAGE_START_LINE) {
- /* parse start-line */
- if(mrcp_start_line_parse(&message->start_line,stream,message->pool) == FALSE) {
- return mrcp_parser_break(parser,stream);
- }
- parser->stage = MRCP_STREAM_STAGE_RESOURCE;
- }
-
- if(parser->stage == MRCP_STREAM_STAGE_RESOURCE) {
- mrcp_resource_t *resource;
-
- if(message->start_line.version == MRCP_VERSION_2) {
- mrcp_channel_id_parse(&message->channel_id,stream,message->pool);
- }
-
- /* find resource */
- resource = mrcp_resource_find(parser->resource_factory,&message->channel_id.resource_name);
- if(!resource) {
- return mrcp_parser_break(parser,stream);
- }
-
- if(mrcp_message_resource_set(message,resource) == FALSE) {
- return mrcp_parser_break(parser,stream);
- }
- parser->stage = MRCP_STREAM_STAGE_HEADER;
- }
-
- if(parser->stage == MRCP_STREAM_STAGE_HEADER) {
- /* parse header */
- if(mrcp_message_header_parse(&message->header,stream,message->pool) == FALSE) {
- return mrcp_parser_break(parser,stream);
- }
-
- parser->stage = MRCP_STREAM_STAGE_NONE;
- if(mrcp_generic_header_property_check(message,GENERIC_HEADER_CONTENT_LENGTH) == TRUE) {
- mrcp_generic_header_t *generic_header = mrcp_generic_header_get(message);
- if(generic_header && generic_header->content_length) {
- apt_str_t *body = &message->body;
- body->buf = apr_palloc(message->pool,generic_header->content_length+1);
- body->length = 0;
- parser->stage = MRCP_STREAM_STAGE_BODY;
- }
- }
- }
-
- if(parser->stage == MRCP_STREAM_STAGE_BODY) {
- if(mrcp_message_body_read(message,stream) == FALSE) {
- return mrcp_parser_break(parser,stream);
- }
- parser->stage = MRCP_STREAM_STAGE_NONE;
- }
-
- /* in the worst case message segmentation may occur between and
- of the final empty header */
- if(!message->body.length && *(stream->pos-1)== APT_TOKEN_CR) {
- /* if this is the case be prepared to skip */
- parser->skip_lf = TRUE;
- }
- return MRCP_STREAM_STATUS_COMPLETE;
-}
-
-/** Get parsed MRCP message */
-MRCP_DECLARE(mrcp_message_t*) mrcp_parser_message_get(const mrcp_parser_t *parser)
-{
- return parser->message;
-}
-
-
-/** Create MRCP stream generator */
-MRCP_DECLARE(mrcp_generator_t*) mrcp_generator_create(mrcp_resource_factory_t *resource_factory, apr_pool_t *pool)
-{
- mrcp_generator_t *generator = apr_palloc(pool,sizeof(mrcp_generator_t));
- generator->resource_factory = resource_factory;
- generator->stage = MRCP_STREAM_STAGE_NONE;
- generator->message = NULL;
- generator->pool = pool;
- return generator;
-}
-
-/** Set MRCP message to generate */
-MRCP_DECLARE(apt_bool_t) mrcp_generator_message_set(mrcp_generator_t *generator, mrcp_message_t *message)
-{
- if(!message) {
- return FALSE;
- }
- generator->message = message;
- return TRUE;
-}
-
-static mrcp_stream_status_e mrcp_generator_break(mrcp_generator_t *generator, apt_text_stream_t *stream)
-{
- /* failed to generate message */
- if(apt_text_is_eos(stream) == TRUE) {
- /* end of stream reached */
- return MRCP_STREAM_STATUS_INCOMPLETE;
- }
-
- /* error case */
- generator->stage = MRCP_STREAM_STAGE_NONE;
- return MRCP_STREAM_STATUS_INVALID;
-}
-
-/** Generate MRCP stream */
-MRCP_DECLARE(mrcp_stream_status_e) mrcp_generator_run(mrcp_generator_t *generator, apt_text_stream_t *stream)
-{
- mrcp_message_t *message = generator->message;
- if(!message) {
- return MRCP_STREAM_STATUS_INVALID;
- }
-
- if(generator->stage == MRCP_STREAM_STAGE_NONE) {
- /* validate message */
- if(mrcp_message_validate(message) == FALSE) {
- return MRCP_STREAM_STATUS_INVALID;
- }
- generator->stage = MRCP_STREAM_STAGE_START_LINE;
- }
-
- if(generator->stage == MRCP_STREAM_STAGE_START_LINE) {
- /* generate start-line */
- if(mrcp_start_line_generate(&message->start_line,stream) == FALSE) {
- return mrcp_generator_break(generator,stream);
- }
-
- if(message->start_line.version == MRCP_VERSION_2) {
- mrcp_channel_id_generate(&message->channel_id,stream);
- }
-
- /* generate header */
- if(mrcp_message_header_generate(&message->header,stream) == FALSE) {
- return mrcp_generator_break(generator,stream);
- }
-
- /* finalize start-line generation */
- if(mrcp_start_line_finalize(&message->start_line,message->body.length,stream) == FALSE) {
- return mrcp_generator_break(generator,stream);
- }
-
- generator->stage = MRCP_STREAM_STAGE_NONE;
- if(mrcp_generic_header_property_check(message,GENERIC_HEADER_CONTENT_LENGTH) == TRUE) {
- mrcp_generic_header_t *generic_header = mrcp_generic_header_get(message);
- if(generic_header && generic_header->content_length) {
- apt_str_t *body = &message->body;
- body->length = 0;
- generator->stage = MRCP_STREAM_STAGE_BODY;
- }
- }
- }
-
- if(generator->stage == MRCP_STREAM_STAGE_BODY) {
- if(mrcp_message_body_write(message,stream) == FALSE) {
- return mrcp_generator_break(generator,stream);
- }
-
- generator->stage = MRCP_STREAM_STAGE_NONE;
- }
-
- return MRCP_STREAM_STATUS_COMPLETE;
-}
-
-
-/** Walk through MRCP stream and invoke message handler for each parsed message */
-MRCP_DECLARE(apt_bool_t) mrcp_stream_walk(mrcp_parser_t *parser, apt_text_stream_t *stream, mrcp_message_handler_f handler, void *obj)
-{
- mrcp_stream_status_e status;
- if(parser->skip_lf == TRUE) {
- /* skip occurred as a result of message segmentation between and */
- apt_text_char_skip(stream,APT_TOKEN_LF);
- parser->skip_lf = FALSE;
- }
- do {
- status = mrcp_parser_run(parser,stream);
- if(status == MRCP_STREAM_STATUS_COMPLETE) {
- /* message is completely parsed */
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Parsed MRCP Message [%lu]", stream->pos - stream->text.buf);
- /* invoke message handler */
- handler(obj,parser->message,status);
- }
- else if(status == MRCP_STREAM_STATUS_INCOMPLETE) {
- /* message is partially parsed, to be continued */
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Truncated MRCP Message [%lu]", stream->pos - stream->text.buf);
- /* prepare stream for further processing */
- if(apt_text_stream_scroll(stream) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Scroll MRCP Stream", stream->text.buf);
- }
- return TRUE;
- }
- else if(status == MRCP_STREAM_STATUS_INVALID){
- /* error case */
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Parse MRCP Message");
- /* invoke message handler */
- handler(obj,parser->message,status);
- /* reset stream pos */
- stream->pos = stream->text.buf;
- return FALSE;
- }
- }
- while(apt_text_is_eos(stream) == FALSE);
-
- /* reset stream pos */
- apt_text_stream_reset(stream);
- return TRUE;
-}
diff --git a/libs/unimrcp/libs/mrcp/include/mrcp.h b/libs/unimrcp/libs/mrcp/include/mrcp.h
index 0140a1bfe8..9425954a78 100644
--- a/libs/unimrcp/libs/mrcp/include/mrcp.h
+++ b/libs/unimrcp/libs/mrcp/include/mrcp.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_H__
-#define __MRCP_H__
+#ifndef MRCP_H
+#define MRCP_H
/**
* @file mrcp.h
@@ -40,4 +42,4 @@
#define MRCP_DECLARE(type) type
#endif
-#endif /*__MRCP_H__*/
+#endif /* MRCP_H */
diff --git a/libs/unimrcp/libs/mrcp/include/mrcp_types.h b/libs/unimrcp/libs/mrcp/include/mrcp_types.h
index 3177077b39..7509f01888 100644
--- a/libs/unimrcp/libs/mrcp/include/mrcp_types.h
+++ b/libs/unimrcp/libs/mrcp/include/mrcp_types.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_types.h 1753 2010-08-16 20:46:45Z achaloyan $
*/
-#ifndef __MRCP_TYPES_H__
-#define __MRCP_TYPES_H__
+#ifndef MRCP_TYPES_H
+#define MRCP_TYPES_H
/**
* @file mrcp_types.h
@@ -39,6 +41,7 @@ typedef enum {
MRCP_SYNTHESIZER_RESOURCE, /**< Synthesizer resource */
MRCP_RECOGNIZER_RESOURCE, /**< Recognizer resource */
MRCP_RECORDER_RESOURCE, /**< Recorder resource */
+ MRCP_VERIFIER_RESOURCE, /**< Verifier resource */
MRCP_RESOURCE_TYPE_COUNT /**< Number of resources */
} mrcp_resource_type_e;
@@ -77,4 +80,4 @@ typedef struct mrcp_resource_factory_t mrcp_resource_factory_t;
APT_END_EXTERN_C
-#endif /*__MRCP_TYPES_H__*/
+#endif /* MRCP_TYPES_H */
diff --git a/libs/unimrcp/libs/mrcp/message/include/mrcp_generic_header.h b/libs/unimrcp/libs/mrcp/message/include/mrcp_generic_header.h
index fb8ebf852f..10b3d98917 100644
--- a/libs/unimrcp/libs/mrcp/message/include/mrcp_generic_header.h
+++ b/libs/unimrcp/libs/mrcp/message/include/mrcp_generic_header.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_generic_header.h 1710 2010-05-24 17:36:19Z achaloyan $
*/
-#ifndef __MRCP_GENERIC_HEADER_H__
-#define __MRCP_GENERIC_HEADER_H__
+#ifndef MRCP_GENERIC_HEADER_H
+#define MRCP_GENERIC_HEADER_H
/**
* @file mrcp_generic_header.h
@@ -27,7 +29,7 @@
APT_BEGIN_EXTERN_C
-/** Enumeration of MRCP generic headers */
+/** Enumeration of MRCP generic header fields */
typedef enum {
GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST,
GENERIC_HEADER_PROXY_SYNC_ID,
@@ -42,7 +44,7 @@ typedef enum {
GENERIC_HEADER_LOGGING_TAG,
GENERIC_HEADER_VENDOR_SPECIFIC_PARAMS,
- /** Additional headers for MRCP v2 */
+ /** Additional header fields for MRCP v2 */
GENERIC_HEADER_ACCEPT,
GENERIC_HEADER_FETCH_TIMEOUT,
GENERIC_HEADER_SET_COOKIE,
@@ -65,7 +67,7 @@ struct mrcp_request_id_list_t {
/** Array of request identifiers */
mrcp_request_id ids[MAX_ACTIVE_REQUEST_ID_COUNT];
/** Number of request identifiers */
- size_t count;
+ apr_size_t count;
};
@@ -97,7 +99,7 @@ struct mrcp_generic_header_t {
/** Specifies the vendor specific parameters used by the media server */
apt_pair_arr_t *vendor_specific_params;
- /** Additional headers for MRCP v2 */
+ /** Additional header fields for MRCP v2 */
/** Specifies the acceptable media types set for entities returned in the response or events associated with this request */
apt_str_t accept;
/** Defines the timeout for content that the server may need to fetch over the network */
@@ -115,9 +117,9 @@ MRCP_DECLARE(const mrcp_header_vtable_t*) mrcp_generic_header_vtable_get(mrcp_ve
/** Append active request id list */
MRCP_DECLARE(apt_bool_t) active_request_id_list_append(mrcp_generic_header_t *generic_header, mrcp_request_id request_id);
/** Find request id in active request id list */
-MRCP_DECLARE(apt_bool_t) active_request_id_list_find(mrcp_generic_header_t *generic_header, mrcp_request_id request_id);
+MRCP_DECLARE(apt_bool_t) active_request_id_list_find(const mrcp_generic_header_t *generic_header, mrcp_request_id request_id);
APT_END_EXTERN_C
-#endif /*__MRCP_GENERIC_HEADER_H__*/
+#endif /* MRCP_GENERIC_HEADER_H */
diff --git a/libs/unimrcp/libs/mrcp/message/include/mrcp_header.h b/libs/unimrcp/libs/mrcp/message/include/mrcp_header.h
new file mode 100644
index 0000000000..91655864c9
--- /dev/null
+++ b/libs/unimrcp/libs/mrcp/message/include/mrcp_header.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: mrcp_header.h 1648 2010-04-12 20:03:59Z achaloyan $
+ */
+
+#ifndef MRCP_HEADER_H
+#define MRCP_HEADER_H
+
+/**
+ * @file mrcp_header.h
+ * @brief MRCP Message Header Definition
+ */
+
+#include "mrcp_header_accessor.h"
+
+APT_BEGIN_EXTERN_C
+
+/**
+ * Allows external applications to trigger whether
+ * transaprent header fields are supported or not
+ */
+#define TRANSPARENT_HEADER_FIELDS_SUPPORT
+
+/** MRCP message header declaration */
+typedef struct mrcp_message_header_t mrcp_message_header_t;
+/** MRCP channel-id declaration */
+typedef struct mrcp_channel_id mrcp_channel_id;
+
+
+/** MRCP message-header */
+struct mrcp_message_header_t {
+ /** MRCP generic-header */
+ mrcp_header_accessor_t generic_header_accessor;
+ /** MRCP resource specific header */
+ mrcp_header_accessor_t resource_header_accessor;
+
+ /** Header section (collection of header fields)*/
+ apt_header_section_t header_section;
+};
+
+/** MRCP channel-identifier */
+struct mrcp_channel_id {
+ /** Unambiguous string identifying the MRCP session */
+ apt_str_t session_id;
+ /** MRCP resource name */
+ apt_str_t resource_name;
+};
+
+
+/** Initialize MRCP message-header */
+static APR_INLINE void mrcp_message_header_init(mrcp_message_header_t *header)
+{
+ mrcp_header_accessor_init(&header->generic_header_accessor);
+ mrcp_header_accessor_init(&header->resource_header_accessor);
+ apt_header_section_init(&header->header_section);
+}
+
+/** Allocate MRCP message-header data */
+MRCP_DECLARE(apt_bool_t) mrcp_message_header_data_alloc(
+ mrcp_message_header_t *header,
+ const mrcp_header_vtable_t *generic_header_vtable,
+ const mrcp_header_vtable_t *resource_header_vtable,
+ apr_pool_t *pool);
+
+/** Create MRCP message-header */
+MRCP_DECLARE(mrcp_message_header_t*) mrcp_message_header_create(
+ const mrcp_header_vtable_t *generic_header_vtable,
+ const mrcp_header_vtable_t *resource_header_vtable,
+ apr_pool_t *pool);
+
+/** Destroy MRCP message-header */
+static APR_INLINE void mrcp_message_header_destroy(mrcp_message_header_t *header)
+{
+ mrcp_header_destroy(&header->generic_header_accessor);
+ mrcp_header_destroy(&header->resource_header_accessor);
+}
+
+/** Add MRCP header field */
+MRCP_DECLARE(apt_bool_t) mrcp_header_field_add(mrcp_message_header_t *header, apt_header_field_t *header_field, apr_pool_t *pool);
+
+
+/** Set (copy) MRCP header fields */
+MRCP_DECLARE(apt_bool_t) mrcp_header_fields_set(mrcp_message_header_t *header, const mrcp_message_header_t *src_header, apr_pool_t *pool);
+
+/** Get (copy) MRCP header fields */
+MRCP_DECLARE(apt_bool_t) mrcp_header_fields_get(mrcp_message_header_t *header, const mrcp_message_header_t *src_header, apr_pool_t *pool);
+
+/** Inherit (copy) MRCP header fields */
+MRCP_DECLARE(apt_bool_t) mrcp_header_fields_inherit(mrcp_message_header_t *header, const mrcp_message_header_t *src_header, apr_pool_t *pool);
+
+/** Parse MRCP header fields */
+MRCP_DECLARE(apt_bool_t) mrcp_header_fields_parse(mrcp_message_header_t *header, apr_pool_t *pool);
+
+
+/** Initialize MRCP channel-identifier */
+MRCP_DECLARE(void) mrcp_channel_id_init(mrcp_channel_id *channel_id);
+
+/** Parse MRCP channel-identifier */
+MRCP_DECLARE(apt_bool_t) mrcp_channel_id_parse(mrcp_channel_id *channel_id, mrcp_message_header_t *header, apr_pool_t *pool);
+
+/** Generate MRCP channel-identifier */
+MRCP_DECLARE(apt_bool_t) mrcp_channel_id_generate(mrcp_channel_id *channel_id, apt_text_stream_t *text_stream);
+
+
+
+APT_END_EXTERN_C
+
+#endif /* MRCP_HEADER_H */
diff --git a/libs/unimrcp/libs/mrcp/message/include/mrcp_header_accessor.h b/libs/unimrcp/libs/mrcp/message/include/mrcp_header_accessor.h
index dbd52d2d47..e2c7590f0d 100644
--- a/libs/unimrcp/libs/mrcp/message/include/mrcp_header_accessor.h
+++ b/libs/unimrcp/libs/mrcp/message/include/mrcp_header_accessor.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,18 +12,20 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_header_accessor.h 1632 2010-03-30 20:46:25Z achaloyan $
*/
-#ifndef __MRCP_HEADER_ACCESSOR_H__
-#define __MRCP_HEADER_ACCESSOR_H__
+#ifndef MRCP_HEADER_ACCESSOR_H
+#define MRCP_HEADER_ACCESSOR_H
/**
* @file mrcp_header_accessor.h
* @brief Abstract MRCP Header Accessor
*/
-#include "apt_string_table.h"
#include "apt_text_stream.h"
+#include "apt_header_field.h"
#include "mrcp.h"
APT_BEGIN_EXTERN_C
@@ -40,12 +42,12 @@ struct mrcp_header_vtable_t {
/** Destroy header data */
void (*destroy)(mrcp_header_accessor_t *accessor);
- /** Parse header field */
+ /** Parse header field value */
apt_bool_t (*parse_field)(mrcp_header_accessor_t *accessor, apr_size_t id, const apt_str_t *value, apr_pool_t *pool);
- /** Generate header field */
- apt_bool_t (*generate_field)(mrcp_header_accessor_t *accessor, apr_size_t id, apt_text_stream_t *value);
- /** Duplicate header field */
- apt_bool_t (*duplicate_field)(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *src, apr_size_t id, apr_pool_t *pool);
+ /** Generate header field value */
+ apt_bool_t (*generate_field)(const mrcp_header_accessor_t *accessor, apr_size_t id, apt_str_t *value, apr_pool_t *pool);
+ /** Duplicate header field value */
+ apt_bool_t (*duplicate_field)(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *src, apr_size_t id, const apt_str_t *value, apr_pool_t *pool);
/** Table of fields */
const apt_str_table_item_t *field_table;
@@ -53,6 +55,15 @@ struct mrcp_header_vtable_t {
apr_size_t field_count;
};
+/** MRCP header accessor */
+struct mrcp_header_accessor_t {
+ /** Actual header data allocated by accessor */
+ void *data;
+ /** Header accessor interface */
+ const mrcp_header_vtable_t *vtable;
+};
+
+
/** Initialize header vtable */
static APR_INLINE void mrcp_header_vtable_init(mrcp_header_vtable_t *vtable)
@@ -76,30 +87,13 @@ static APR_INLINE apt_bool_t mrcp_header_vtable_validate(const mrcp_header_vtabl
}
-/** MRCP header accessor */
-struct mrcp_header_accessor_t {
- /** Actual header data allocated by accessor */
- void *data;
-
- /** Array properties (mrcp_header_property_e) */
- char *properties;
- /** Number of filled properties (header fields) */
- apr_size_t counter;
-
- /** Header accessor interface */
- const mrcp_header_vtable_t *vtable;
-};
-
/** Initialize header accessor */
static APR_INLINE void mrcp_header_accessor_init(mrcp_header_accessor_t *accessor)
{
accessor->data = NULL;
- accessor->properties = NULL;
- accessor->counter = 0;
accessor->vtable = NULL;
}
-
/** Allocate header data */
static APR_INLINE void* mrcp_header_allocate(mrcp_header_accessor_t *accessor, apr_pool_t *pool)
{
@@ -109,8 +103,6 @@ static APR_INLINE void* mrcp_header_allocate(mrcp_header_accessor_t *accessor, a
if(!accessor->vtable || !accessor->vtable->allocate) {
return NULL;
}
- accessor->properties = (char*)apr_pcalloc(pool,sizeof(char)*accessor->vtable->field_count);
- accessor->counter = 0;
return accessor->vtable->allocate(accessor,pool);
}
@@ -124,35 +116,16 @@ static APR_INLINE void mrcp_header_destroy(mrcp_header_accessor_t *accessor)
}
-/** Parse header */
-MRCP_DECLARE(apt_bool_t) mrcp_header_parse(mrcp_header_accessor_t *accessor, const apt_pair_t *pair, apr_pool_t *pool);
+/** Parse header field value */
+MRCP_DECLARE(apt_bool_t) mrcp_header_field_value_parse(mrcp_header_accessor_t *accessor, apt_header_field_t *header_field, apr_pool_t *pool);
-/** Generate header */
-MRCP_DECLARE(apt_bool_t) mrcp_header_generate(mrcp_header_accessor_t *accessor, apt_text_stream_t *text_stream);
+/** Generate header field value */
+MRCP_DECLARE(apt_header_field_t*) mrcp_header_field_value_generate(const mrcp_header_accessor_t *accessor, apr_size_t id, apt_bool_t empty_value, apr_pool_t *pool);
-/** Set header */
-MRCP_DECLARE(apt_bool_t) mrcp_header_set(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *src, const mrcp_header_accessor_t *mask, apr_pool_t *pool);
+/** Duplicate header field value */
+MRCP_DECLARE(apt_bool_t) mrcp_header_field_value_duplicate(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *src_accessor, apr_size_t id, const apt_str_t *value, apr_pool_t *pool);
-/** Inherit header */
-MRCP_DECLARE(apt_bool_t) mrcp_header_inherit(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *parent, apr_pool_t *pool);
-
-
-/** Add name:value property */
-MRCP_DECLARE(void) mrcp_header_property_add(mrcp_header_accessor_t *accessor, apr_size_t id);
-
-/** Remove property */
-MRCP_DECLARE(void) mrcp_header_property_remove(mrcp_header_accessor_t *accessor, apr_size_t id);
-
-/** Check the property */
-MRCP_DECLARE(apt_bool_t) mrcp_header_property_check(mrcp_header_accessor_t *accessor, apr_size_t id);
-
-/** Add name only property */
-MRCP_DECLARE(void) mrcp_header_name_property_add(mrcp_header_accessor_t *accessor, apr_size_t id);
-
-
-/** Generate completion-cause */
-MRCP_DECLARE(apt_bool_t) mrcp_completion_cause_generate(const apt_str_table_item_t table[], apr_size_t size, apr_size_t cause, apt_text_stream_t *stream);
APT_END_EXTERN_C
-#endif /*__MRCP_HEADER_ACCESSOR_H__*/
+#endif /* MRCP_HEADER_ACCESSOR_H */
diff --git a/libs/unimrcp/libs/mrcp/message/include/mrcp_message.h b/libs/unimrcp/libs/mrcp/message/include/mrcp_message.h
index 497a14d7c3..3bfe453882 100644
--- a/libs/unimrcp/libs/mrcp/message/include/mrcp_message.h
+++ b/libs/unimrcp/libs/mrcp/message/include/mrcp_message.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_message.h 1721 2010-06-01 05:45:46Z achaloyan $
*/
-#ifndef __MRCP_MESSAGE_H__
-#define __MRCP_MESSAGE_H__
+#ifndef MRCP_MESSAGE_H
+#define MRCP_MESSAGE_H
/**
* @file mrcp_message.h
@@ -24,176 +26,228 @@
#include "mrcp_types.h"
#include "mrcp_start_line.h"
-#include "mrcp_header_accessor.h"
+#include "mrcp_header.h"
+#include "mrcp_generic_header.h"
APT_BEGIN_EXTERN_C
-/** MRCP channel-id declaration */
-typedef struct mrcp_channel_id mrcp_channel_id;
-/** MRCP message header declaration */
-typedef struct mrcp_message_header_t mrcp_message_header_t;
-
-/** MRCP channel-identifier */
-struct mrcp_channel_id {
- /** Unambiguous string identifying the MRCP session */
- apt_str_t session_id;
- /** MRCP resource name */
- apt_str_t resource_name;
-};
-
-/** Initialize MRCP channel-identifier */
-MRCP_DECLARE(void) mrcp_channel_id_init(mrcp_channel_id *channel_id);
-
-/** Parse MRCP channel-identifier */
-MRCP_DECLARE(apt_bool_t) mrcp_channel_id_parse(mrcp_channel_id *channel_id, apt_text_stream_t *text_stream, apr_pool_t *pool);
-
-/** Generate MRCP channel-identifier */
-MRCP_DECLARE(apt_bool_t) mrcp_channel_id_generate(mrcp_channel_id *channel_id, apt_text_stream_t *text_stream);
-
-
-/** MRCP message-header */
-struct mrcp_message_header_t {
- /** MRCP generic-header */
- mrcp_header_accessor_t generic_header_accessor;
- /** MRCP resource specific header */
- mrcp_header_accessor_t resource_header_accessor;
-};
-
-/** Initialize MRCP message-header */
-static APR_INLINE void mrcp_message_header_init(mrcp_message_header_t *message_header)
-{
- mrcp_header_accessor_init(&message_header->generic_header_accessor);
- mrcp_header_accessor_init(&message_header->resource_header_accessor);
-}
-
-/** Destroy MRCP message-header */
-static APR_INLINE void mrcp_message_header_destroy(mrcp_message_header_t *message_header)
-{
- mrcp_header_destroy(&message_header->generic_header_accessor);
- mrcp_header_destroy(&message_header->resource_header_accessor);
-}
-
-
-/** Parse MRCP message-header */
-MRCP_DECLARE(apt_bool_t) mrcp_message_header_parse(mrcp_message_header_t *message_header, apt_text_stream_t *text_stream, apr_pool_t *pool);
-
-/** Generate MRCP message-header */
-MRCP_DECLARE(apt_bool_t) mrcp_message_header_generate(mrcp_message_header_t *message_header, apt_text_stream_t *text_stream);
-
-/** Set MRCP message-header */
-MRCP_DECLARE(apt_bool_t) mrcp_message_header_set(mrcp_message_header_t *message_header, const mrcp_message_header_t *src, apr_pool_t *pool);
-
-/** Get MRCP message-header */
-MRCP_DECLARE(apt_bool_t) mrcp_message_header_get(mrcp_message_header_t *message_header, const mrcp_message_header_t *src, apr_pool_t *pool);
-
-/** Inherit MRCP message-header */
-MRCP_DECLARE(apt_bool_t) mrcp_message_header_inherit(mrcp_message_header_t *message_header, const mrcp_message_header_t *parent, apr_pool_t *pool);
-
-
+/** Macro to log channel identifier of the message */
+#define MRCP_MESSAGE_SIDRES(message) \
+ (message)->channel_id.session_id.buf, (message)->channel_id.resource_name.buf
/** MRCP message */
struct mrcp_message_t {
/** Start-line of MRCP message */
- mrcp_start_line_t start_line;
+ mrcp_start_line_t start_line;
/** Channel-identifier of MRCP message */
- mrcp_channel_id channel_id;
+ mrcp_channel_id channel_id;
/** Header of MRCP message */
- mrcp_message_header_t header;
+ mrcp_message_header_t header;
/** Body of MRCP message */
- apt_str_t body;
+ apt_str_t body;
/** Associated MRCP resource */
- mrcp_resource_t *resource;
- /** Memory pool MRCP message is allocated from */
- apr_pool_t *pool;
+ const mrcp_resource_t *resource;
+ /** Memory pool to allocate memory from */
+ apr_pool_t *pool;
};
-/** Create MRCP message */
+/**
+ * Create an MRCP message.
+ * @param pool the pool to allocate memory from
+ */
MRCP_DECLARE(mrcp_message_t*) mrcp_message_create(apr_pool_t *pool);
-/** Create MRCP request message */
-MRCP_DECLARE(mrcp_message_t*) mrcp_request_create(mrcp_resource_t *resource, mrcp_version_e version, mrcp_method_id method_id, apr_pool_t *pool);
-/** Create MRCP response message */
+/**
+ * Create an MRCP request message.
+ * @param resource the MRCP resource to use
+ * @param version the MRCP version to use
+ * @param method_id the MRCP resource specific method identifier
+ * @param pool the pool to allocate memory from
+ */
+MRCP_DECLARE(mrcp_message_t*) mrcp_request_create(
+ const mrcp_resource_t *resource,
+ mrcp_version_e version,
+ mrcp_method_id method_id,
+ apr_pool_t *pool);
+
+/**
+ * Create an MRCP response message based on given request message.
+ * @param request_message the MRCP request message to create a response for
+ * @param pool the pool to allocate memory from
+ */
MRCP_DECLARE(mrcp_message_t*) mrcp_response_create(const mrcp_message_t *request_message, apr_pool_t *pool);
-/** Create MRCP event message */
-MRCP_DECLARE(mrcp_message_t*) mrcp_event_create(const mrcp_message_t *request_message, mrcp_method_id event_id, apr_pool_t *pool);
-/** Associate MRCP resource specific data by resource name */
-MRCP_DECLARE(apt_bool_t) mrcp_message_resource_set(mrcp_message_t *message, mrcp_resource_t *resource);
+/**
+ * Create an MRCP event message based on given requuest message.
+ * @param request_message the MRCP request message to create an event for
+ * @param event_id the MRCP resource specific event identifier
+ * @param pool the pool to allocate memory from
+ */
+MRCP_DECLARE(mrcp_message_t*) mrcp_event_create(
+ const mrcp_message_t *request_message,
+ mrcp_method_id event_id,
+ apr_pool_t *pool);
-/** Validate MRCP message */
+/**
+ * Associate MRCP resource with message.
+ * @param message the message to associate resource with
+ * @param resource the resource to associate
+ */
+MRCP_DECLARE(apt_bool_t) mrcp_message_resource_set(mrcp_message_t *message, const mrcp_resource_t *resource);
+
+/**
+ * Validate MRCP message.
+ * @param message the message to validate
+ */
MRCP_DECLARE(apt_bool_t) mrcp_message_validate(mrcp_message_t *message);
-/** Destroy MRCP message */
+/**
+ * Destroy MRCP message.
+ * @param message the message to destroy
+ */
MRCP_DECLARE(void) mrcp_message_destroy(mrcp_message_t *message);
-/** Parse MRCP message-body */
-MRCP_DECLARE(apt_bool_t) mrcp_body_parse(mrcp_message_t *message, apt_text_stream_t *text_stream, apr_pool_t *pool);
-/** Generate MRCP message-body */
-MRCP_DECLARE(apt_bool_t) mrcp_body_generate(mrcp_message_t *message, apt_text_stream_t *text_stream);
-
-/** Get MRCP generic-header */
-static APR_INLINE void* mrcp_generic_header_get(mrcp_message_t *mrcp_message)
+/**
+ * Get MRCP generic header.
+ * @param message the message to get generic header from
+ */
+static APR_INLINE mrcp_generic_header_t* mrcp_generic_header_get(const mrcp_message_t *message)
{
- return mrcp_message->header.generic_header_accessor.data;
+ return (mrcp_generic_header_t*) message->header.generic_header_accessor.data;
}
-/** Prepare MRCP generic-header */
-static APR_INLINE void* mrcp_generic_header_prepare(mrcp_message_t *mrcp_message)
+/**
+ * Allocate (if not allocated) and get MRCP generic header.
+ * @param message the message to prepare generic header for
+ */
+static APR_INLINE mrcp_generic_header_t* mrcp_generic_header_prepare(mrcp_message_t *message)
{
- return mrcp_header_allocate(&mrcp_message->header.generic_header_accessor,mrcp_message->pool);
+ return (mrcp_generic_header_t*) mrcp_header_allocate(&message->header.generic_header_accessor,message->pool);
}
-/** Add MRCP generic-header proprerty */
-static APR_INLINE void mrcp_generic_header_property_add(mrcp_message_t *mrcp_message, size_t id)
+/**
+ * Add MRCP generic header field by specified property (numeric identifier).
+ * @param message the message to add property for
+ * @param id the numeric identifier to add
+ */
+MRCP_DECLARE(apt_bool_t) mrcp_generic_header_property_add(mrcp_message_t *message, apr_size_t id);
+
+/**
+ * Add only the name of MRCP generic header field specified by property (numeric identifier).
+ * @param message the message to add property for
+ * @param id the numeric identifier to add
+ * @remark Should be used to construct empty header fiedls for GET-PARAMS requests
+ */
+MRCP_DECLARE(apt_bool_t) mrcp_generic_header_name_property_add(mrcp_message_t *message, apr_size_t id);
+
+/**
+ * Remove MRCP generic header field by specified property (numeric identifier).
+ * @param message the message to remove property from
+ * @param id the numeric identifier to remove
+ */
+static APR_INLINE apt_bool_t mrcp_generic_header_property_remove(mrcp_message_t *message, apr_size_t id)
{
- mrcp_header_property_add(&mrcp_message->header.generic_header_accessor,id);
+ apt_header_field_t *header_field = apt_header_section_field_get(&message->header.header_section,id);
+ if(header_field) {
+ return apt_header_section_field_remove(&message->header.header_section,header_field);
+ }
+ return FALSE;
}
-/** Add MRCP generic-header name only proprerty (should be used to construct empty headers in case of GET-PARAMS request) */
-static APR_INLINE void mrcp_generic_header_name_property_add(mrcp_message_t *mrcp_message, size_t id)
+/**
+ * Check whether specified by property (numeric identifier) MRCP generic header field is set or not.
+ * @param message the message to use
+ * @param id the numeric identifier to check
+ */
+static APR_INLINE apt_bool_t mrcp_generic_header_property_check(const mrcp_message_t *message, apr_size_t id)
{
- mrcp_header_name_property_add(&mrcp_message->header.generic_header_accessor,id);
-}
-
-/** Check MRCP generic-header proprerty */
-static APR_INLINE apt_bool_t mrcp_generic_header_property_check(mrcp_message_t *mrcp_message, size_t id)
-{
- return mrcp_header_property_check(&mrcp_message->header.generic_header_accessor,id);
+ return apt_header_section_field_check(&message->header.header_section,id);
}
-/** Get MRCP resource-header */
-static APR_INLINE void* mrcp_resource_header_get(const mrcp_message_t *mrcp_message)
+/**
+ * Get MRCP resource header.
+ * @param message the message to get resource header from
+ */
+static APR_INLINE void* mrcp_resource_header_get(const mrcp_message_t *message)
{
- return mrcp_message->header.resource_header_accessor.data;
+ return message->header.resource_header_accessor.data;
}
-/** Prepare MRCP resource-header */
+/**
+ * Allocate (if not allocated) and get MRCP resource header.
+ * @param message the message to prepare resource header for
+ */
static APR_INLINE void* mrcp_resource_header_prepare(mrcp_message_t *mrcp_message)
{
return mrcp_header_allocate(&mrcp_message->header.resource_header_accessor,mrcp_message->pool);
}
-/** Add MRCP resource-header proprerty */
-static APR_INLINE void mrcp_resource_header_property_add(mrcp_message_t *mrcp_message, size_t id)
+/**
+ * Add MRCP resource header field by specified property (numeric identifier).
+ * @param message the message to add property for
+ * @param id the numeric identifier to add
+ */
+MRCP_DECLARE(apt_bool_t) mrcp_resource_header_property_add(mrcp_message_t *message, apr_size_t id);
+
+/**
+ * Add only the name of MRCP resource header field specified by property (numeric identifier).
+ * @param message the message to add property for
+ * @param id the numeric identifier to add
+ * @remark Should be used to construct empty header fiedls for GET-PARAMS requests
+ */
+MRCP_DECLARE(apt_bool_t) mrcp_resource_header_name_property_add(mrcp_message_t *message, apr_size_t id);
+
+/**
+ * Remove MRCP resource header field by specified property (numeric identifier).
+ * @param message the message to remove property from
+ * @param id the numeric identifier to remove
+ */
+static APR_INLINE apt_bool_t mrcp_resource_header_property_remove(mrcp_message_t *message, apr_size_t id)
{
- mrcp_header_property_add(&mrcp_message->header.resource_header_accessor,id);
+ apt_header_field_t *header_field = apt_header_section_field_get(&message->header.header_section,id + GENERIC_HEADER_COUNT);
+ if(header_field) {
+ return apt_header_section_field_remove(&message->header.header_section,header_field);
+ }
+ return FALSE;
}
-/** Add MRCP resource-header name only proprerty (should be used to construct empty headers in case of GET-PARAMS request) */
-static APR_INLINE void mrcp_resource_header_name_property_add(mrcp_message_t *mrcp_message, size_t id)
+/**
+ * Check whether specified by property (numeric identifier) MRCP resource header field is set or not.
+ * @param message the message to use
+ * @param id the numeric identifier to check
+ */
+static APR_INLINE apt_bool_t mrcp_resource_header_property_check(const mrcp_message_t *message, apr_size_t id)
{
- mrcp_header_name_property_add(&mrcp_message->header.resource_header_accessor,id);
+ return apt_header_section_field_check(&message->header.header_section,id + GENERIC_HEADER_COUNT);
}
-/** Check MRCP resource-header proprerty */
-static APR_INLINE apt_bool_t mrcp_resource_header_property_check(mrcp_message_t *mrcp_message, size_t id)
+/**
+ * Add MRCP header field.
+ * @param message the message to add header field for
+ * @param header_field the header field to add
+ */
+static APR_INLINE apt_bool_t mrcp_message_header_field_add(mrcp_message_t *message, apt_header_field_t *header_field)
{
- return mrcp_header_property_check(&mrcp_message->header.resource_header_accessor,id);
+ return mrcp_header_field_add(&message->header,header_field,message->pool);
}
+/**
+ * Get the next MRCP header field.
+ * @param message the message to use
+ * @param header_field current header field
+ * @remark Should be used to iterate on header fields
+ *
+ * apt_header_field_t *header_field = NULL;
+ * while( (header_field = mrcp_message_next_header_field_get(message,header_field)) != NULL ) {
+ * }
+ */
+MRCP_DECLARE(apt_header_field_t*) mrcp_message_next_header_field_get(
+ const mrcp_message_t *message,
+ apt_header_field_t *header_field);
+
APT_END_EXTERN_C
-#endif /*__MRCP_MESSAGE_H__*/
+#endif /* MRCP_MESSAGE_H */
diff --git a/libs/unimrcp/libs/mrcp/message/include/mrcp_start_line.h b/libs/unimrcp/libs/mrcp/message/include/mrcp_start_line.h
index 1c6db22d40..0273229b75 100644
--- a/libs/unimrcp/libs/mrcp/message/include/mrcp_start_line.h
+++ b/libs/unimrcp/libs/mrcp/message/include/mrcp_start_line.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_start_line.h 1632 2010-03-30 20:46:25Z achaloyan $
*/
-#ifndef __MRCP_START_LINE_H__
-#define __MRCP_START_LINE_H__
+#ifndef MRCP_START_LINE_H
+#define MRCP_START_LINE_H
/**
* @file mrcp_start_line.h
@@ -59,6 +61,7 @@ typedef enum {
MRCP_STATUS_CODE_METHOD_FAILED = 407,
MRCP_STATUS_CODE_UNRECOGNIZED_MESSAGE = 408,
MRCP_STATUS_CODE_UNSUPPORTED_PARAM_VALUE = 409,
+ MRCP_STATUS_CODE_OUT_OF_ORDER = 410,
MRCP_STATUS_CODE_RESOURCE_SPECIFIC_FAILURE = 421
} mrcp_status_code_e;
@@ -97,7 +100,7 @@ struct mrcp_start_line_t {
/** Initialize MRCP start-line */
MRCP_DECLARE(void) mrcp_start_line_init(mrcp_start_line_t *start_line);
/** Parse MRCP start-line */
-MRCP_DECLARE(apt_bool_t) mrcp_start_line_parse(mrcp_start_line_t *start_line, apt_text_stream_t *text_stream, apr_pool_t *pool);
+MRCP_DECLARE(apt_bool_t) mrcp_start_line_parse(mrcp_start_line_t *start_line, apt_str_t *str, apr_pool_t *pool);
/** Generate MRCP start-line */
MRCP_DECLARE(apt_bool_t) mrcp_start_line_generate(mrcp_start_line_t *start_line, apt_text_stream_t *text_stream);
/** Finalize MRCP start-line generation */
@@ -111,4 +114,4 @@ MRCP_DECLARE(apt_bool_t) mrcp_request_id_generate(mrcp_request_id request_id, ap
APT_END_EXTERN_C
-#endif /*__MRCP_START_LINE_H__*/
+#endif /* MRCP_START_LINE_H */
diff --git a/libs/unimrcp/libs/mrcp/message/src/mrcp_generic_header.c b/libs/unimrcp/libs/mrcp/message/src/mrcp_generic_header.c
index 1b1d1a7d7f..dc8878b446 100644
--- a/libs/unimrcp/libs/mrcp/message/src/mrcp_generic_header.c
+++ b/libs/unimrcp/libs/mrcp/message/src/mrcp_generic_header.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_generic_header.c 1710 2010-05-24 17:36:19Z achaloyan $
*/
#include "mrcp_generic_header.h"
@@ -56,15 +58,20 @@ static apt_bool_t mrcp_request_id_list_parse(mrcp_request_id_list_t *request_id_
}
/** Generate mrcp request-id list */
-static apt_bool_t mrcp_request_id_list_generate(mrcp_request_id_list_t *request_id_list, apt_text_stream_t *stream)
+static apt_bool_t mrcp_request_id_list_generate(mrcp_request_id_list_t *request_id_list, apt_str_t *str, apr_pool_t *pool)
{
- size_t i;
+ apr_size_t i;
+ char buf[256];
+ apt_text_stream_t stream;
+ apt_text_stream_init(&stream,buf,sizeof(buf));
for(i=0; icount; i++) {
- mrcp_request_id_generate(request_id_list->ids[i],stream);
+ mrcp_request_id_generate(request_id_list->ids[i],&stream);
if(i < request_id_list->count-1) {
- *stream->pos++ = ',';
+ *stream.pos++ = ',';
}
}
+
+ apt_string_assign_n(str,stream.text.buf, stream.pos - stream.text.buf, pool);
return TRUE;
}
@@ -84,7 +91,7 @@ static void mrcp_generic_header_init(mrcp_generic_header_t *generic_header)
apt_string_reset(&generic_header->cache_control);
apt_string_reset(&generic_header->logging_tag);
generic_header->vendor_specific_params = NULL;
- /* initializes additionnal MRCP V2 generic headers */
+ /* initializes additionnal MRCP v2 generic header fields */
apt_string_reset(&generic_header->accept);
generic_header->fetch_timeout = 0;
apt_string_reset(&generic_header->set_cookie);
@@ -111,34 +118,34 @@ static apt_bool_t mrcp_generic_header_parse(mrcp_header_accessor_t *accessor, si
mrcp_request_id_list_parse(&generic_header->active_request_id_list,value);
break;
case GENERIC_HEADER_PROXY_SYNC_ID:
- apt_string_copy(&generic_header->proxy_sync_id,value,pool);
+ generic_header->proxy_sync_id = *value;
break;
case GENERIC_HEADER_ACCEPT_CHARSET:
- apt_string_copy(&generic_header->accept_charset,value,pool);
+ generic_header->accept_charset = *value;
break;
case GENERIC_HEADER_CONTENT_TYPE:
- apt_string_copy(&generic_header->content_type,value,pool);
+ generic_header->content_type = *value;
break;
case GENERIC_HEADER_CONTENT_ID:
- apt_string_copy(&generic_header->content_id,value,pool);
+ generic_header->content_id = *value;
break;
case GENERIC_HEADER_CONTENT_BASE:
- apt_string_copy(&generic_header->content_base,value,pool);
+ generic_header->content_base = *value;
break;
case GENERIC_HEADER_CONTENT_ENCODING:
- apt_string_copy(&generic_header->content_encoding,value,pool);
+ generic_header->content_encoding = *value;
break;
case GENERIC_HEADER_CONTENT_LOCATION:
- apt_string_copy(&generic_header->content_location,value,pool);
+ generic_header->content_location = *value;
break;
case GENERIC_HEADER_CONTENT_LENGTH:
generic_header->content_length = apt_size_value_parse(value);
break;
case GENERIC_HEADER_CACHE_CONTROL:
- apt_string_copy(&generic_header->cache_control,value,pool);
+ generic_header->cache_control = *value;
break;
case GENERIC_HEADER_LOGGING_TAG:
- apt_string_copy(&generic_header->logging_tag,value,pool);
+ generic_header->logging_tag = *value;
break;
case GENERIC_HEADER_VENDOR_SPECIFIC_PARAMS:
if(!generic_header->vendor_specific_params) {
@@ -147,16 +154,16 @@ static apt_bool_t mrcp_generic_header_parse(mrcp_header_accessor_t *accessor, si
apt_pair_array_parse(generic_header->vendor_specific_params,value,pool);
break;
case GENERIC_HEADER_ACCEPT:
- apt_string_copy(&generic_header->accept,value,pool);
+ generic_header->accept = *value;
break;
case GENERIC_HEADER_FETCH_TIMEOUT:
generic_header->fetch_timeout = apt_size_value_parse(value);
break;
case GENERIC_HEADER_SET_COOKIE:
- apt_string_copy(&generic_header->set_cookie,value,pool);
+ generic_header->set_cookie = *value;
break;
case GENERIC_HEADER_SET_COOKIE2:
- apt_string_copy(&generic_header->set_cookie2,value,pool);
+ generic_header->set_cookie2 = *value;
break;
default:
status = FALSE;
@@ -165,57 +172,57 @@ static apt_bool_t mrcp_generic_header_parse(mrcp_header_accessor_t *accessor, si
}
/** Generate generic-header */
-static apt_bool_t mrcp_generic_header_generate(mrcp_header_accessor_t *accessor, size_t id, apt_text_stream_t *value)
+static apt_bool_t mrcp_generic_header_generate(const mrcp_header_accessor_t *accessor, apr_size_t id, apt_str_t *value, apr_pool_t *pool)
{
mrcp_generic_header_t *generic_header = accessor->data;
switch(id) {
case GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST:
- mrcp_request_id_list_generate(&generic_header->active_request_id_list,value);
+ mrcp_request_id_list_generate(&generic_header->active_request_id_list,value,pool);
break;
case GENERIC_HEADER_PROXY_SYNC_ID:
- apt_string_value_generate(&generic_header->proxy_sync_id,value);
+ *value = generic_header->proxy_sync_id;
break;
case GENERIC_HEADER_ACCEPT_CHARSET:
- apt_string_value_generate(&generic_header->accept_charset,value);
+ *value = generic_header->accept_charset;
break;
case GENERIC_HEADER_CONTENT_TYPE:
- apt_string_value_generate(&generic_header->content_type,value);
+ *value = generic_header->content_type;
break;
case GENERIC_HEADER_CONTENT_ID:
- apt_string_value_generate(&generic_header->content_id,value);
+ *value = generic_header->content_id;
break;
case GENERIC_HEADER_CONTENT_BASE:
- apt_string_value_generate(&generic_header->content_base,value);
+ *value = generic_header->content_base;
break;
case GENERIC_HEADER_CONTENT_ENCODING:
- apt_string_value_generate(&generic_header->content_encoding,value);
+ *value = generic_header->content_encoding;
break;
case GENERIC_HEADER_CONTENT_LOCATION:
- apt_string_value_generate(&generic_header->content_location,value);
+ *value = generic_header->content_location;
break;
case GENERIC_HEADER_CONTENT_LENGTH:
- apt_size_value_generate(generic_header->content_length,value);
+ apt_size_value_generate(generic_header->content_length,value,pool);
break;
case GENERIC_HEADER_CACHE_CONTROL:
- apt_string_value_generate(&generic_header->cache_control,value);
+ *value = generic_header->cache_control;
break;
case GENERIC_HEADER_LOGGING_TAG:
- apt_string_value_generate(&generic_header->logging_tag,value);
+ *value = generic_header->logging_tag;
break;
case GENERIC_HEADER_VENDOR_SPECIFIC_PARAMS:
- apt_pair_array_generate(generic_header->vendor_specific_params,value);
+ apt_pair_array_generate(generic_header->vendor_specific_params,value,pool);
break;
case GENERIC_HEADER_ACCEPT:
- apt_string_value_generate(&generic_header->accept,value);
+ *value = generic_header->accept;
break;
case GENERIC_HEADER_FETCH_TIMEOUT:
- apt_size_value_generate(generic_header->fetch_timeout,value);
+ apt_size_value_generate(generic_header->fetch_timeout,value,pool);
break;
case GENERIC_HEADER_SET_COOKIE:
- apt_string_value_generate(&generic_header->set_cookie,value);
+ *value = generic_header->set_cookie;
break;
case GENERIC_HEADER_SET_COOKIE2:
- apt_string_value_generate(&generic_header->set_cookie2,value);
+ *value = generic_header->set_cookie2;
break;
default:
break;
@@ -224,7 +231,7 @@ static apt_bool_t mrcp_generic_header_generate(mrcp_header_accessor_t *accessor,
}
/** Duplicate generic-header */
-static apt_bool_t mrcp_generic_header_duplicate(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *src, size_t id, apr_pool_t *pool)
+static apt_bool_t mrcp_generic_header_duplicate(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *src, apr_size_t id, const apt_str_t *value, apr_pool_t *pool)
{
mrcp_generic_header_t *generic_header = accessor->data;
const mrcp_generic_header_t *src_generic_header = src->data;
@@ -238,49 +245,49 @@ static apt_bool_t mrcp_generic_header_duplicate(mrcp_header_accessor_t *accessor
case GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST:
break;
case GENERIC_HEADER_PROXY_SYNC_ID:
- apt_string_copy(&generic_header->proxy_sync_id,&src_generic_header->proxy_sync_id,pool);
+ generic_header->proxy_sync_id = *value;
break;
case GENERIC_HEADER_ACCEPT_CHARSET:
- apt_string_copy(&generic_header->accept_charset,&src_generic_header->accept_charset,pool);
+ generic_header->accept_charset = *value;
break;
case GENERIC_HEADER_CONTENT_TYPE:
- apt_string_copy(&generic_header->content_type,&src_generic_header->content_type,pool);
+ generic_header->content_type = *value;
break;
case GENERIC_HEADER_CONTENT_ID:
- apt_string_copy(&generic_header->content_id,&src_generic_header->content_id,pool);
+ generic_header->content_id = *value;
break;
case GENERIC_HEADER_CONTENT_BASE:
- apt_string_copy(&generic_header->content_base,&src_generic_header->content_base,pool);
+ generic_header->content_base = *value;
break;
case GENERIC_HEADER_CONTENT_ENCODING:
- apt_string_copy(&generic_header->content_encoding,&src_generic_header->content_encoding,pool);
+ generic_header->content_encoding = *value;
break;
case GENERIC_HEADER_CONTENT_LOCATION:
- apt_string_copy(&generic_header->content_location,&src_generic_header->content_location,pool);
+ generic_header->content_location = *value;
break;
case GENERIC_HEADER_CONTENT_LENGTH:
generic_header->content_length = src_generic_header->content_length;
break;
case GENERIC_HEADER_CACHE_CONTROL:
- apt_string_copy(&generic_header->cache_control,&src_generic_header->cache_control,pool);
+ generic_header->cache_control = *value;
break;
case GENERIC_HEADER_LOGGING_TAG:
- apt_string_copy(&generic_header->logging_tag,&src_generic_header->logging_tag,pool);
+ generic_header->logging_tag = *value;
break;
case GENERIC_HEADER_VENDOR_SPECIFIC_PARAMS:
generic_header->vendor_specific_params = apt_pair_array_copy(src_generic_header->vendor_specific_params,pool);
break;
case GENERIC_HEADER_ACCEPT:
- apt_string_copy(&generic_header->accept,&src_generic_header->accept,pool);
+ generic_header->accept = *value;
break;
case GENERIC_HEADER_FETCH_TIMEOUT:
generic_header->fetch_timeout = src_generic_header->fetch_timeout;
break;
case GENERIC_HEADER_SET_COOKIE:
- apt_string_copy(&generic_header->set_cookie,&src_generic_header->set_cookie,pool);
+ generic_header->set_cookie = *value;
break;
case GENERIC_HEADER_SET_COOKIE2:
- apt_string_copy(&generic_header->set_cookie2,&src_generic_header->set_cookie2,pool);
+ generic_header->set_cookie2 = *value;
break;
default:
status = FALSE;
@@ -317,10 +324,10 @@ MRCP_DECLARE(apt_bool_t) active_request_id_list_append(mrcp_generic_header_t *ge
}
/** Find request id in active request id list */
-MRCP_DECLARE(apt_bool_t) active_request_id_list_find(mrcp_generic_header_t *generic_header, mrcp_request_id request_id)
+MRCP_DECLARE(apt_bool_t) active_request_id_list_find(const mrcp_generic_header_t *generic_header, mrcp_request_id request_id)
{
size_t i;
- mrcp_request_id_list_t *request_id_list = &generic_header->active_request_id_list;
+ const mrcp_request_id_list_t *request_id_list = &generic_header->active_request_id_list;
for(i=0; icount; i++) {
if(request_id_list->ids[i] == request_id) {
return TRUE;
diff --git a/libs/unimrcp/libs/mrcp/message/src/mrcp_header.c b/libs/unimrcp/libs/mrcp/message/src/mrcp_header.c
new file mode 100644
index 0000000000..864baedc42
--- /dev/null
+++ b/libs/unimrcp/libs/mrcp/message/src/mrcp_header.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: mrcp_header.c 1737 2010-06-15 18:29:17Z achaloyan $
+ */
+
+#include "mrcp_header.h"
+#include "mrcp_generic_header.h"
+#include "apt_text_message.h"
+#include "apt_log.h"
+
+#define MRCP_CHANNEL_ID "Channel-Identifier"
+#define MRCP_CHANNEL_ID_LENGTH (sizeof(MRCP_CHANNEL_ID)-1)
+
+
+/** Allocate MRCP message-header data */
+MRCP_DECLARE(apt_bool_t) mrcp_message_header_data_alloc(
+ mrcp_message_header_t *header,
+ const mrcp_header_vtable_t *generic_header_vtable,
+ const mrcp_header_vtable_t *resource_header_vtable,
+ apr_pool_t *pool)
+{
+ if(!generic_header_vtable || !resource_header_vtable) {
+ return FALSE;
+ }
+
+ header->generic_header_accessor.data = NULL;
+ header->generic_header_accessor.vtable = generic_header_vtable;
+
+ header->resource_header_accessor.data = NULL;
+ header->resource_header_accessor.vtable = resource_header_vtable;
+
+ apt_header_section_array_alloc(
+ &header->header_section,
+ header->generic_header_accessor.vtable->field_count +
+ header->resource_header_accessor.vtable->field_count,
+ pool);
+
+ mrcp_header_allocate(&header->generic_header_accessor,pool);
+ mrcp_header_allocate(&header->resource_header_accessor,pool);
+ return TRUE;
+}
+
+MRCP_DECLARE(mrcp_message_header_t*) mrcp_message_header_create(
+ const mrcp_header_vtable_t *generic_header_vtable,
+ const mrcp_header_vtable_t *resource_header_vtable,
+ apr_pool_t *pool)
+{
+ mrcp_message_header_t *header = apr_palloc(pool,sizeof(mrcp_message_header_t));
+ apt_header_section_init(&header->header_section);
+ mrcp_message_header_data_alloc(header,generic_header_vtable,resource_header_vtable,pool);
+ return header;
+}
+
+/** Add MRCP header field */
+MRCP_DECLARE(apt_bool_t) mrcp_header_field_add(mrcp_message_header_t *header, apt_header_field_t *header_field, apr_pool_t *pool)
+{
+ apt_bool_t status = FALSE;
+ if(apt_string_is_empty(&header_field->name) == FALSE) {
+ /* normal header */
+ if(mrcp_header_field_value_parse(&header->resource_header_accessor,header_field,pool) == TRUE) {
+ header_field->id += GENERIC_HEADER_COUNT;
+ }
+ else if(mrcp_header_field_value_parse(&header->generic_header_accessor,header_field,pool) == TRUE) {
+ status = apt_header_section_field_add(&header->header_section,header_field);
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Unknown MRCP header field: %s",header_field->name.buf);
+ }
+ status = apt_header_section_field_add(&header->header_section,header_field);
+ }
+ return status;
+}
+
+/** Parse MRCP header fields */
+MRCP_DECLARE(apt_bool_t) mrcp_header_fields_parse(mrcp_message_header_t *header, apr_pool_t *pool)
+{
+ apt_header_field_t *header_field;
+ for(header_field = APR_RING_FIRST(&header->header_section.ring);
+ header_field != APR_RING_SENTINEL(&header->header_section.ring, apt_header_field_t, link);
+ header_field = APR_RING_NEXT(header_field, link)) {
+
+ if(mrcp_header_field_value_parse(&header->resource_header_accessor,header_field,pool) == TRUE) {
+ header_field->id += GENERIC_HEADER_COUNT;
+ apt_header_section_field_set(&header->header_section,header_field);
+ }
+ else if(mrcp_header_field_value_parse(&header->generic_header_accessor,header_field,pool) == TRUE) {
+ apt_header_section_field_set(&header->header_section,header_field);
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown MRCP header field: %s",header_field->name.buf);
+ }
+ }
+
+ return TRUE;
+}
+
+/** Set (copy) MRCP header fields */
+MRCP_DECLARE(apt_bool_t) mrcp_header_fields_set(mrcp_message_header_t *header, const mrcp_message_header_t *src_header, apr_pool_t *pool)
+{
+ apt_header_field_t *header_field;
+ const apt_header_field_t *src_header_field;
+ for(src_header_field = APR_RING_FIRST(&src_header->header_section.ring);
+ src_header_field != APR_RING_SENTINEL(&src_header->header_section.ring, apt_header_field_t, link);
+ src_header_field = APR_RING_NEXT(src_header_field, link)) {
+
+ header_field = apt_header_field_copy(src_header_field,pool);
+ if(header_field->id < GENERIC_HEADER_COUNT) {
+ if(mrcp_header_field_value_duplicate(
+ &header->generic_header_accessor,
+ &src_header->generic_header_accessor,
+ header_field->id,
+ &header_field->value,
+ pool) == TRUE) {
+ apt_header_section_field_add(&header->header_section,header_field);
+ }
+ }
+ else {
+ if(mrcp_header_field_value_duplicate(
+ &header->resource_header_accessor,
+ &src_header->resource_header_accessor,
+ header_field->id - GENERIC_HEADER_COUNT,
+ &header_field->value,
+ pool) == TRUE) {
+ apt_header_section_field_add(&header->header_section,header_field);
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/** Get (copy) MRCP header fields */
+MRCP_DECLARE(apt_bool_t) mrcp_header_fields_get(mrcp_message_header_t *header, const mrcp_message_header_t *src_header, apr_pool_t *pool)
+{
+ apt_header_field_t *header_field;
+ const apt_header_field_t *src_header_field;
+ for(header_field = APR_RING_FIRST(&header->header_section.ring);
+ header_field != APR_RING_SENTINEL(&header->header_section.ring, apt_header_field_t, link);
+ header_field = APR_RING_NEXT(header_field, link)) {
+
+ src_header_field = apt_header_section_field_get(&src_header->header_section,header_field->id);
+ if(src_header_field) {
+ if(header_field->id < GENERIC_HEADER_COUNT) {
+ apt_string_copy(&header_field->value,&src_header_field->value,pool);
+ mrcp_header_field_value_duplicate(
+ &header->generic_header_accessor,
+ &src_header->generic_header_accessor,
+ header_field->id,
+ &header_field->value,
+ pool);
+ }
+ else {
+ apt_string_copy(&header_field->value,&src_header_field->value,pool);
+ mrcp_header_field_value_duplicate(
+ &header->resource_header_accessor,
+ &src_header->resource_header_accessor,
+ header_field->id - GENERIC_HEADER_COUNT,
+ &header_field->value,
+ pool);
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/** Inherit (copy) MRCP header fields */
+MRCP_DECLARE(apt_bool_t) mrcp_header_fields_inherit(mrcp_message_header_t *header, const mrcp_message_header_t *src_header, apr_pool_t *pool)
+{
+ apt_header_field_t *header_field;
+ const apt_header_field_t *src_header_field;
+ for(src_header_field = APR_RING_FIRST(&src_header->header_section.ring);
+ src_header_field != APR_RING_SENTINEL(&src_header->header_section.ring, apt_header_field_t, link);
+ src_header_field = APR_RING_NEXT(src_header_field, link)) {
+
+ header_field = apt_header_section_field_get(&header->header_section,src_header_field->id);
+ if(!header_field) {
+ header_field = apt_header_field_copy(src_header_field,pool);
+ if(header_field->id < GENERIC_HEADER_COUNT) {
+ if(mrcp_header_field_value_duplicate(
+ &header->generic_header_accessor,
+ &src_header->generic_header_accessor,
+ header_field->id,
+ &header_field->value,
+ pool) == TRUE) {
+ apt_header_section_field_add(&header->header_section,header_field);
+ }
+ }
+ else {
+ if(mrcp_header_field_value_duplicate(
+ &header->resource_header_accessor,
+ &src_header->resource_header_accessor,
+ header_field->id - GENERIC_HEADER_COUNT,
+ &header_field->value,
+ pool) == TRUE) {
+ apt_header_section_field_add(&header->header_section,header_field);
+ }
+ }
+ }
+ }
+ return TRUE;
+}
+
+
+/** Initialize MRCP channel-identifier */
+MRCP_DECLARE(void) mrcp_channel_id_init(mrcp_channel_id *channel_id)
+{
+ apt_string_reset(&channel_id->session_id);
+ apt_string_reset(&channel_id->resource_name);
+}
+
+/** Parse MRCP channel-identifier */
+MRCP_DECLARE(apt_bool_t) mrcp_channel_id_parse(mrcp_channel_id *channel_id, mrcp_message_header_t *header, apr_pool_t *pool)
+{
+ apt_header_field_t *header_field;
+ for(header_field = APR_RING_FIRST(&header->header_section.ring);
+ header_field != APR_RING_SENTINEL(&header->header_section.ring, apt_header_field_t, link);
+ header_field = APR_RING_NEXT(header_field, link)) {
+
+ if(header_field->value.length && strncasecmp(header_field->name.buf,MRCP_CHANNEL_ID,MRCP_CHANNEL_ID_LENGTH) == 0) {
+ apt_id_resource_parse(&header_field->value,'@',&channel_id->session_id,&channel_id->resource_name,pool);
+ apt_header_section_field_remove(&header->header_section,header_field);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/** Generate MRCP channel-identifier */
+MRCP_DECLARE(apt_bool_t) mrcp_channel_id_generate(mrcp_channel_id *channel_id, apt_text_stream_t *stream)
+{
+ apt_str_t *str;
+ char *pos = stream->pos;
+ if(pos + MRCP_CHANNEL_ID_LENGTH + 2 + channel_id->session_id.length + 1 +
+ channel_id->resource_name.length >= stream->end) {
+ return FALSE;
+ }
+ memcpy(pos,MRCP_CHANNEL_ID,MRCP_CHANNEL_ID_LENGTH);
+ pos += MRCP_CHANNEL_ID_LENGTH;
+ *pos++ = ':';
+ *pos++ = APT_TOKEN_SP;
+
+ str = &channel_id->session_id;
+ memcpy(pos,str->buf,str->length);
+ pos += str->length;
+ *pos++ = '@';
+
+ str = &channel_id->resource_name;
+ memcpy(pos,str->buf,str->length);
+ pos += str->length;
+
+ stream->pos = pos;
+ return apt_text_eol_insert(stream);
+}
diff --git a/libs/unimrcp/libs/mrcp/message/src/mrcp_header_accessor.c b/libs/unimrcp/libs/mrcp/message/src/mrcp_header_accessor.c
index ae80b1aa50..c7148129cd 100644
--- a/libs/unimrcp/libs/mrcp/message/src/mrcp_header_accessor.c
+++ b/libs/unimrcp/libs/mrcp/message/src/mrcp_header_accessor.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,202 +12,73 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_header_accessor.c 1737 2010-06-15 18:29:17Z achaloyan $
*/
-#include
#include "mrcp_header_accessor.h"
-typedef enum {
- MRCP_HEADER_FIELD_NONE = 0x0,
- MRCP_HEADER_FIELD_NAME = 0x1,
- MRCP_HEADER_FIELD_VALUE = 0x2,
- MRCP_HEADER_FIELD_NAME_VALUE = MRCP_HEADER_FIELD_NAME | MRCP_HEADER_FIELD_VALUE
-} mrcp_header_property_e;
-
-MRCP_DECLARE(apt_bool_t) mrcp_header_parse(mrcp_header_accessor_t *accessor, const apt_pair_t *pair, apr_pool_t *pool)
+/** Parse header field value */
+MRCP_DECLARE(apt_bool_t) mrcp_header_field_value_parse(mrcp_header_accessor_t *accessor, apt_header_field_t *header_field, apr_pool_t *pool)
{
- size_t id;
+ apr_size_t id;
if(!accessor->vtable) {
return FALSE;
}
- id = apt_string_table_id_find(accessor->vtable->field_table,accessor->vtable->field_count,&pair->name);
+ id = apt_string_table_id_find(accessor->vtable->field_table,accessor->vtable->field_count,&header_field->name);
if(id >= accessor->vtable->field_count) {
return FALSE;
}
+ header_field->id = id;
- if(!pair->value.length) {
- mrcp_header_name_property_add(accessor,id);
- return TRUE;
+ if(header_field->value.length) {
+ if(accessor->vtable->parse_field(accessor,header_field->id,&header_field->value,pool) == FALSE) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/** Generate header field value */
+MRCP_DECLARE(apt_header_field_t*) mrcp_header_field_value_generate(const mrcp_header_accessor_t *accessor, apr_size_t id, apt_bool_t empty_value, apr_pool_t *pool)
+{
+ apt_header_field_t *header_field;
+ const apt_str_t *name;
+
+ if(!accessor->vtable) {
+ return NULL;
+ }
+
+ header_field = apt_header_field_alloc(pool);
+ name = apt_string_table_str_get(accessor->vtable->field_table,accessor->vtable->field_count,id);
+ if(name) {
+ header_field->name = *name;
}
- if(accessor->vtable->parse_field(accessor,id,&pair->value,pool) == FALSE) {
+ if(empty_value == FALSE) {
+ if(accessor->vtable->generate_field(accessor,id,&header_field->value,pool) == FALSE) {
+ return NULL;
+ }
+ }
+
+ return header_field;
+}
+
+/** Duplicate header field value */
+MRCP_DECLARE(apt_bool_t) mrcp_header_field_value_duplicate(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *src_accessor, apr_size_t id, const apt_str_t *value, apr_pool_t *pool)
+{
+ if(!accessor->vtable) {
return FALSE;
}
- mrcp_header_property_add(accessor,id);
- return TRUE;
-}
-
-MRCP_DECLARE(apt_bool_t) mrcp_header_generate(mrcp_header_accessor_t *accessor, apt_text_stream_t *text_stream)
-{
- const apt_str_t *name;
- apr_size_t i,j;
- char prop;
-
- if(!accessor->vtable) {
- return FALSE;
- }
-
- for(i=0, j=0; ivtable->field_count && jcounter; i++) {
- prop = accessor->properties[i];
- if((prop & MRCP_HEADER_FIELD_NAME) == MRCP_HEADER_FIELD_NAME) {
- j++;
- name = apt_string_table_str_get(accessor->vtable->field_table,accessor->vtable->field_count,i);
- if(!name) continue;
-
- apt_text_header_name_generate(name,text_stream);
- if((prop & MRCP_HEADER_FIELD_VALUE) == MRCP_HEADER_FIELD_VALUE) {
- accessor->vtable->generate_field(accessor,i,text_stream);
- }
- apt_text_eol_insert(text_stream);
+ if(value->length) {
+ if(accessor->vtable->duplicate_field(accessor,src_accessor,id,value,pool) == FALSE) {
+ return FALSE;
}
}
return TRUE;
}
-
-MRCP_DECLARE(void) mrcp_header_property_add(mrcp_header_accessor_t *accessor, apr_size_t id)
-{
- if(!accessor->vtable) {
- return;
- }
-
- if(id < accessor->vtable->field_count) {
- char *prop = &accessor->properties[id];
- if((*prop & MRCP_HEADER_FIELD_NAME) != MRCP_HEADER_FIELD_NAME) {
- accessor->counter++;
- }
- *prop = MRCP_HEADER_FIELD_NAME_VALUE;
- }
-}
-
-MRCP_DECLARE(void) mrcp_header_name_property_add(mrcp_header_accessor_t *accessor, apr_size_t id)
-{
- if(!accessor->vtable) {
- return;
- }
-
- if(id < accessor->vtable->field_count) {
- char *prop = &accessor->properties[id];
- if((*prop & MRCP_HEADER_FIELD_NAME) != MRCP_HEADER_FIELD_NAME) {
- *prop = MRCP_HEADER_FIELD_NAME;
- accessor->counter++;
- }
- }
-}
-
-
-MRCP_DECLARE(void) mrcp_header_property_remove(mrcp_header_accessor_t *accessor, apr_size_t id)
-{
- if(!accessor->vtable) {
- return;
- }
-
- if(id < accessor->vtable->field_count) {
- char *prop = &accessor->properties[id];
- if((*prop & MRCP_HEADER_FIELD_NAME) == MRCP_HEADER_FIELD_NAME) {
- accessor->counter--;
- }
- *prop = MRCP_HEADER_FIELD_NONE;
- }
-}
-
-MRCP_DECLARE(apt_bool_t) mrcp_header_property_check(mrcp_header_accessor_t *accessor, apr_size_t id)
-{
- if(!accessor->vtable) {
- return FALSE;
- }
-
- if((id < accessor->vtable->field_count) && accessor->properties) {
- if((accessor->properties[id] & MRCP_HEADER_FIELD_NAME) == MRCP_HEADER_FIELD_NAME) {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-
-MRCP_DECLARE(apt_bool_t) mrcp_header_set(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *src, const mrcp_header_accessor_t *mask, apr_pool_t *pool)
-{
- apr_size_t i,j;
-
- if(!accessor->vtable || !src->vtable) {
- return FALSE;
- }
-
- mrcp_header_allocate(accessor,pool);
-
- for(i=0, j=0; i < src->vtable->field_count && j < src->counter; i++) {
- if((mask->properties[i] & src->properties[i] & MRCP_HEADER_FIELD_NAME) == MRCP_HEADER_FIELD_NAME) {
- j++;
- if((src->properties[i] & MRCP_HEADER_FIELD_VALUE) == MRCP_HEADER_FIELD_VALUE) {
- accessor->vtable->duplicate_field(accessor,src,i,pool);
- mrcp_header_property_add(accessor,i);
- }
- else {
- mrcp_header_name_property_add(accessor,i);
- }
- }
- }
-
- return TRUE;
-}
-
-MRCP_DECLARE(apt_bool_t) mrcp_header_inherit(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *parent, apr_pool_t *pool)
-{
- apr_size_t i,j;
-
- if(!accessor->vtable || !parent->vtable) {
- return FALSE;
- }
-
- mrcp_header_allocate(accessor,pool);
-
- for(i=0, j=0; ivtable->field_count && j < parent->counter; i++) {
- if((parent->properties[i] & MRCP_HEADER_FIELD_NAME) == MRCP_HEADER_FIELD_NAME) {
- j++;
- if((accessor->properties[i] & MRCP_HEADER_FIELD_NAME) != MRCP_HEADER_FIELD_NAME) {
- if((parent->properties[i] & MRCP_HEADER_FIELD_VALUE) == MRCP_HEADER_FIELD_VALUE) {
- accessor->vtable->duplicate_field(accessor,parent,i,pool);
- mrcp_header_property_add(accessor,i);
- }
- else {
- mrcp_header_name_property_add(accessor,i);
- }
- }
- }
- }
-
- return TRUE;
-}
-
-/** Generate completion-cause */
-MRCP_DECLARE(apt_bool_t) mrcp_completion_cause_generate(const apt_str_table_item_t table[], apr_size_t size, apr_size_t cause, apt_text_stream_t *stream)
-{
- int length;
- const apt_str_t *name = apt_string_table_str_get(table,size,cause);
- if(!name) {
- return FALSE;
- }
- length = sprintf(stream->pos,"%03"APR_SIZE_T_FMT" ",cause);
- if(length <= 0) {
- return FALSE;
- }
- stream->pos += length;
-
- memcpy(stream->pos,name->buf,name->length);
- stream->pos += name->length;
- return TRUE;
-}
diff --git a/libs/unimrcp/libs/mrcp/message/src/mrcp_message.c b/libs/unimrcp/libs/mrcp/message/src/mrcp_message.c
index 96b52784f5..3a37b2900f 100644
--- a/libs/unimrcp/libs/mrcp/message/src/mrcp_message.c
+++ b/libs/unimrcp/libs/mrcp/message/src/mrcp_message.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,214 +12,29 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_message.c 1701 2010-05-22 16:38:10Z achaloyan $
*/
#include "mrcp_message.h"
#include "mrcp_generic_header.h"
#include "mrcp_resource.h"
+#include "apt_text_message.h"
#include "apt_log.h"
-#define MRCP_CHANNEL_ID "Channel-Identifier"
-#define MRCP_CHANNEL_ID_LENGTH (sizeof(MRCP_CHANNEL_ID)-1)
-
-/** Initialize MRCP channel-identifier */
-MRCP_DECLARE(void) mrcp_channel_id_init(mrcp_channel_id *channel_id)
-{
- apt_string_reset(&channel_id->session_id);
- apt_string_reset(&channel_id->resource_name);
-}
-
-/** Parse MRCP channel-identifier */
-MRCP_DECLARE(apt_bool_t) mrcp_channel_id_parse(mrcp_channel_id *channel_id, apt_text_stream_t *text_stream, apr_pool_t *pool)
-{
- apt_bool_t match = FALSE;
- apt_pair_t pair;
- do {
- if(apt_text_header_read(text_stream,&pair) == TRUE) {
- if(pair.name.length) {
- if(pair.value.length && strncasecmp(pair.name.buf,MRCP_CHANNEL_ID,MRCP_CHANNEL_ID_LENGTH) == 0) {
- match = TRUE;
- apt_id_resource_parse(&pair.value,'@',&channel_id->session_id,&channel_id->resource_name,pool);
- break;
- }
- /* skip this header, expecting channel identifier first */
- }
- else {
- /* empty header */
- break;
- }
- }
- }
- while(apt_text_is_eos(text_stream) == FALSE);
- return match;
-}
-
-/** Generate MRCP channel-identifier */
-MRCP_DECLARE(apt_bool_t) mrcp_channel_id_generate(mrcp_channel_id *channel_id, apt_text_stream_t *text_stream)
-{
- apt_str_t *str;
- char *pos = text_stream->pos;
-
- memcpy(pos,MRCP_CHANNEL_ID,MRCP_CHANNEL_ID_LENGTH);
- pos += MRCP_CHANNEL_ID_LENGTH;
- *pos++ = ':';
- *pos++ = ' ';
-
- str = &channel_id->session_id;
- memcpy(pos,str->buf,str->length);
- pos += str->length;
- *pos++ = '@';
-
- str = &channel_id->resource_name;
- memcpy(pos,str->buf,str->length);
- pos += str->length;
-
- text_stream->pos = pos;
- apt_text_eol_insert(text_stream);
- return TRUE;
-}
-
-/** Parse MRCP message-header */
-MRCP_DECLARE(apt_bool_t) mrcp_message_header_parse(mrcp_message_header_t *message_header, apt_text_stream_t *text_stream, apr_pool_t *pool)
-{
- apt_pair_t pair;
- apt_bool_t result = FALSE;
-
- mrcp_header_allocate(&message_header->generic_header_accessor,pool);
- mrcp_header_allocate(&message_header->resource_header_accessor,pool);
-
- do {
- if(apt_text_header_read(text_stream,&pair) == TRUE) {
- if(pair.name.length) {
- /* normal header */
- if(mrcp_header_parse(&message_header->resource_header_accessor,&pair,pool) != TRUE) {
- if(mrcp_header_parse(&message_header->generic_header_accessor,&pair,pool) != TRUE) {
- /* unknown MRCP header */
- }
- }
- }
- else {
- /* empty header -> exit */
- result = TRUE;
- break;
- }
- }
- else {
- /* malformed header, skip to the next one */
- }
- }
- while(apt_text_is_eos(text_stream) == FALSE);
-
- return result;
-}
-
-/** Generate MRCP message-header */
-MRCP_DECLARE(apt_bool_t) mrcp_message_header_generate(mrcp_message_header_t *message_header, apt_text_stream_t *text_stream)
-{
- mrcp_header_generate(&message_header->resource_header_accessor,text_stream);
- mrcp_header_generate(&message_header->generic_header_accessor,text_stream);
- apt_text_eol_insert(text_stream);
- return TRUE;
-}
-
-/** Set MRCP message-header */
-MRCP_DECLARE(apt_bool_t) mrcp_message_header_set(mrcp_message_header_t *message_header, const mrcp_message_header_t *src, apr_pool_t *pool)
-{
- mrcp_header_set(
- &message_header->resource_header_accessor,
- &src->resource_header_accessor,
- &src->resource_header_accessor,pool);
- mrcp_header_set(
- &message_header->generic_header_accessor,
- &src->generic_header_accessor,
- &src->generic_header_accessor,pool);
- return TRUE;
-}
-
-/** Get MRCP message-header */
-MRCP_DECLARE(apt_bool_t) mrcp_message_header_get(mrcp_message_header_t *message_header, const mrcp_message_header_t *src, apr_pool_t *pool)
-{
- mrcp_header_set(
- &message_header->resource_header_accessor,
- &src->resource_header_accessor,
- &message_header->resource_header_accessor,
- pool);
- mrcp_header_set(
- &message_header->generic_header_accessor,
- &src->generic_header_accessor,
- &message_header->generic_header_accessor,
- pool);
- return TRUE;
-}
-
-/** Inherit MRCP message-header */
-MRCP_DECLARE(apt_bool_t) mrcp_message_header_inherit(mrcp_message_header_t *message_header, const mrcp_message_header_t *parent, apr_pool_t *pool)
-{
- mrcp_header_inherit(&message_header->resource_header_accessor,&parent->resource_header_accessor,pool);
- mrcp_header_inherit(&message_header->generic_header_accessor,&parent->generic_header_accessor,pool);
- return TRUE;
-}
-
-
-/** Parse MRCP message-body */
-MRCP_DECLARE(apt_bool_t) mrcp_body_parse(mrcp_message_t *message, apt_text_stream_t *text_stream, apr_pool_t *pool)
-{
- if(mrcp_generic_header_property_check(message,GENERIC_HEADER_CONTENT_LENGTH) == TRUE) {
- mrcp_generic_header_t *generic_header = mrcp_generic_header_get(message);
- if(generic_header && generic_header->content_length) {
- apt_str_t *body = &message->body;
- body->length = generic_header->content_length;
- if(body->length > (text_stream->text.length - (text_stream->pos - text_stream->text.buf))) {
- body->length = text_stream->text.length - (text_stream->pos - text_stream->text.buf);
- }
- body->buf = apr_pstrmemdup(pool,text_stream->pos,body->length);
- text_stream->pos += body->length;
- }
- }
- return TRUE;
-}
-
-/** Generate MRCP message-body */
-MRCP_DECLARE(apt_bool_t) mrcp_body_generate(mrcp_message_t *message, apt_text_stream_t *text_stream)
-{
- apt_str_t *body = &message->body;
- if(body->length) {
- memcpy(text_stream->pos,body->buf,body->length);
- text_stream->pos += body->length;
- }
- return TRUE;
-}
-
-/** Initialize MRCP message */
-static void mrcp_message_init(mrcp_message_t *message, apr_pool_t *pool)
-{
- mrcp_start_line_init(&message->start_line);
- mrcp_channel_id_init(&message->channel_id);
- mrcp_message_header_init(&message->header);
- apt_string_reset(&message->body);
- message->resource = NULL;
- message->pool = pool;
-}
-
-/** Set header accessor interface */
-static APR_INLINE void mrcp_generic_header_accessor_set(mrcp_message_t *message)
-{
- message->header.generic_header_accessor.vtable = mrcp_generic_header_vtable_get(message->start_line.version);
-}
-
-/** Associate MRCP resource specific data by resource identifier */
-MRCP_DECLARE(apt_bool_t) mrcp_message_resource_set_by_id(mrcp_message_t *message, mrcp_resource_t *resource)
+/** Associate MRCP resource with message */
+static apt_bool_t mrcp_message_resource_set_by_id(mrcp_message_t *message, const mrcp_resource_t *resource)
{
if(!resource) {
return FALSE;
}
message->resource = resource;
-
message->channel_id.resource_name = resource->name;
-
- mrcp_generic_header_accessor_set(message);
- message->header.resource_header_accessor.vtable =
- resource->get_resource_header_vtable(message->start_line.version);
+ mrcp_message_header_data_alloc(
+ &message->header,
+ mrcp_generic_header_vtable_get(message->start_line.version),
+ resource->get_resource_header_vtable(message->start_line.version),
+ message->pool);
/* associate method_name and method_id */
if(message->start_line.message_type == MRCP_MESSAGE_TYPE_REQUEST) {
@@ -247,16 +62,17 @@ MRCP_DECLARE(apt_bool_t) mrcp_message_resource_set_by_id(mrcp_message_t *message
}
/** Associate MRCP resource specific data by resource name */
-MRCP_DECLARE(apt_bool_t) mrcp_message_resource_set(mrcp_message_t *message, mrcp_resource_t *resource)
+MRCP_DECLARE(apt_bool_t) mrcp_message_resource_set(mrcp_message_t *message, const mrcp_resource_t *resource)
{
if(!resource) {
return FALSE;
}
message->resource = resource;
-
- mrcp_generic_header_accessor_set(message);
- message->header.resource_header_accessor.vtable =
- resource->get_resource_header_vtable(message->start_line.version);
+ mrcp_message_header_data_alloc(
+ &message->header,
+ mrcp_generic_header_vtable_get(message->start_line.version),
+ resource->get_resource_header_vtable(message->start_line.version),
+ message->pool);
/* associate method_name and method_id */
if(message->start_line.message_type == MRCP_MESSAGE_TYPE_REQUEST) {
@@ -281,16 +97,21 @@ MRCP_DECLARE(apt_bool_t) mrcp_message_resource_set(mrcp_message_t *message, mrcp
return TRUE;
}
-/** Create MRCP message */
+/** Create an MRCP message */
MRCP_DECLARE(mrcp_message_t*) mrcp_message_create(apr_pool_t *pool)
{
mrcp_message_t *message = apr_palloc(pool,sizeof(mrcp_message_t));
- mrcp_message_init(message,pool);
+ mrcp_start_line_init(&message->start_line);
+ mrcp_channel_id_init(&message->channel_id);
+ mrcp_message_header_init(&message->header);
+ apt_string_reset(&message->body);
+ message->resource = NULL;
+ message->pool = pool;
return message;
}
-/** Create MRCP request message */
-MRCP_DECLARE(mrcp_message_t*) mrcp_request_create(mrcp_resource_t *resource, mrcp_version_e version, mrcp_method_id method_id, apr_pool_t *pool)
+/** Create an MRCP request message */
+MRCP_DECLARE(mrcp_message_t*) mrcp_request_create(const mrcp_resource_t *resource, mrcp_version_e version, mrcp_method_id method_id, apr_pool_t *pool)
{
mrcp_message_t *request_message = mrcp_message_create(pool);
request_message->start_line.message_type = MRCP_MESSAGE_TYPE_REQUEST;
@@ -300,7 +121,7 @@ MRCP_DECLARE(mrcp_message_t*) mrcp_request_create(mrcp_resource_t *resource, mrc
return request_message;
}
-/** Create MRCP response message */
+/** Create an MRCP response message */
MRCP_DECLARE(mrcp_message_t*) mrcp_response_create(const mrcp_message_t *request_message, apr_pool_t *pool)
{
mrcp_message_t *response_message = mrcp_message_create(pool);
@@ -312,12 +133,13 @@ MRCP_DECLARE(mrcp_message_t*) mrcp_response_create(const mrcp_message_t *request
response_message->start_line.request_id = request_message->start_line.request_id;
response_message->start_line.version = request_message->start_line.version;
response_message->start_line.method_id = request_message->start_line.method_id;
+ response_message->start_line.method_name = request_message->start_line.method_name;
mrcp_message_resource_set_by_id(response_message,request_message->resource);
}
return response_message;
}
-/** Create MRCP event message */
+/** Create an MRCP event message */
MRCP_DECLARE(mrcp_message_t*) mrcp_event_create(const mrcp_message_t *request_message, mrcp_method_id event_id, apr_pool_t *pool)
{
mrcp_message_t *event_message = mrcp_message_create(pool);
@@ -357,3 +179,81 @@ MRCP_DECLARE(apt_bool_t) mrcp_message_validate(mrcp_message_t *message)
return TRUE;
}
+
+/** Add MRCP generic header field by specified property (numeric identifier) */
+MRCP_DECLARE(apt_bool_t) mrcp_generic_header_property_add(mrcp_message_t *message, apr_size_t id)
+{
+ apt_header_field_t *header_field = mrcp_header_field_value_generate(
+ &message->header.generic_header_accessor,
+ id,
+ FALSE,
+ message->pool);
+ if(!header_field) {
+ return FALSE;
+ }
+ header_field->id = id;
+ return apt_header_section_field_add(&message->header.header_section,header_field);
+}
+
+/** Add only the name of MRCP generic header field specified by property (numeric identifier) */
+MRCP_DECLARE(apt_bool_t) mrcp_generic_header_name_property_add(mrcp_message_t *message, apr_size_t id)
+{
+ apt_header_field_t *header_field = mrcp_header_field_value_generate(
+ &message->header.generic_header_accessor,
+ id,
+ TRUE,
+ message->pool);
+ if(!header_field) {
+ return FALSE;
+ }
+ header_field->id = id;
+ return apt_header_section_field_add(&message->header.header_section,header_field);
+}
+
+/** Add MRCP resource header field by specified property (numeric identifier) */
+MRCP_DECLARE(apt_bool_t) mrcp_resource_header_property_add(mrcp_message_t *message, apr_size_t id)
+{
+ apt_header_field_t *header_field = mrcp_header_field_value_generate(
+ &message->header.resource_header_accessor,
+ id,
+ FALSE,
+ message->pool);
+ if(!header_field) {
+ return FALSE;
+ }
+ header_field->id = id + GENERIC_HEADER_COUNT;
+ return apt_header_section_field_add(&message->header.header_section,header_field);
+}
+
+/** Add only the name of MRCP resource header field specified by property (numeric identifier) */
+MRCP_DECLARE(apt_bool_t) mrcp_resource_header_name_property_add(mrcp_message_t *message, apr_size_t id)
+{
+ apt_header_field_t *header_field = mrcp_header_field_value_generate(
+ &message->header.resource_header_accessor,
+ id,
+ TRUE,
+ message->pool);
+ if(!header_field) {
+ return FALSE;
+ }
+ header_field->id = id + GENERIC_HEADER_COUNT;
+ return apt_header_section_field_add(&message->header.header_section,header_field);
+}
+
+/** Get the next MRCP header field */
+MRCP_DECLARE(apt_header_field_t*) mrcp_message_next_header_field_get(const mrcp_message_t *message, apt_header_field_t *header_field)
+{
+ const apt_header_section_t *header_section = &message->header.header_section;
+ if(header_field) {
+ apt_header_field_t *next = APR_RING_NEXT(header_field,link);
+ if(next == APR_RING_SENTINEL(&header_section->ring,apt_header_field_t,link)) {
+ return NULL;
+ }
+ return next;
+ }
+
+ if(APR_RING_EMPTY(&header_section->ring,apt_header_field_t,link)) {
+ return NULL;
+ }
+ return APR_RING_FIRST(&header_section->ring);
+}
diff --git a/libs/unimrcp/libs/mrcp/message/src/mrcp_start_line.c b/libs/unimrcp/libs/mrcp/message/src/mrcp_start_line.c
index 2a406663fa..f2a36b0351 100644
--- a/libs/unimrcp/libs/mrcp/message/src/mrcp_start_line.c
+++ b/libs/unimrcp/libs/mrcp/message/src/mrcp_start_line.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_start_line.c 1671 2010-04-28 19:50:29Z achaloyan $
*/
#include
@@ -65,10 +67,20 @@ static mrcp_version_e mrcp_version_parse(const apt_str_t *field)
/** Generate MRCP version */
static apt_bool_t mrcp_version_generate(mrcp_version_e version, apt_text_stream_t *stream)
{
+ if(stream->pos + MRCP_NAME_LENGTH + 1 >= stream->end) {
+ return FALSE;
+ }
memcpy(stream->pos,MRCP_NAME,MRCP_NAME_LENGTH);
stream->pos += MRCP_NAME_LENGTH;
*stream->pos++ = MRCP_NAME_VERSION_SEPARATOR;
- apt_size_value_generate(version,stream);
+
+ if(apt_text_size_value_insert(stream,version) == FALSE) {
+ return FALSE;
+ }
+
+ if(stream->pos + 2 >= stream->end) {
+ return FALSE;
+ }
*stream->pos++ = MRCP_VERSION_MAJOR_MINOR_SEPARATOR;
*stream->pos++ = '0';
return TRUE;
@@ -102,7 +114,7 @@ static APR_INLINE mrcp_status_code_e mrcp_status_code_parse(const apt_str_t *fie
/** Generate MRCP status-code */
static APR_INLINE size_t mrcp_status_code_generate(mrcp_status_code_e status_code, apt_text_stream_t *stream)
{
- return apt_size_value_generate(status_code,stream);
+ return apt_text_size_value_insert(stream,status_code);
}
@@ -318,18 +330,14 @@ MRCP_DECLARE(void) mrcp_start_line_init(mrcp_start_line_t *start_line)
}
/** Parse MRCP start-line */
-MRCP_DECLARE(apt_bool_t) mrcp_start_line_parse(mrcp_start_line_t *start_line, apt_text_stream_t *text_stream, apr_pool_t *pool)
+MRCP_DECLARE(apt_bool_t) mrcp_start_line_parse(mrcp_start_line_t *start_line, apt_str_t *str, apr_pool_t *pool)
{
apt_text_stream_t line;
apt_str_t field;
apt_bool_t status = TRUE;
+
start_line->message_type = MRCP_MESSAGE_TYPE_UNKNOWN;
- if(apt_text_line_read(text_stream,&line.text) == FALSE) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot parse MRCP start-line");
- return FALSE;
- }
-
- apt_text_stream_reset(&line);
+ apt_text_stream_init(&line,str->buf,str->length);
if(apt_text_field_read(&line,APT_TOKEN_SP,TRUE,&field) == FALSE) {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot read the first field in start-line");
return FALSE;
@@ -383,11 +391,11 @@ MRCP_DECLARE(apt_bool_t) mrcp_start_line_generate(mrcp_start_line_t *start_line,
status = mrcp_v2_start_line_generate(start_line,text_stream);
}
- if(status == TRUE) {
- apt_text_eol_insert(text_stream);
+ if(status == FALSE) {
+ return FALSE;
}
-
- return status;
+
+ return apt_text_eol_insert(text_stream);
}
/** Finalize MRCP start-line generation */
diff --git a/libs/unimrcp/libs/mrcp/mrcp.2008.vcproj b/libs/unimrcp/libs/mrcp/mrcp.2008.vcproj
deleted file mode 100644
index ae656d2749..0000000000
--- a/libs/unimrcp/libs/mrcp/mrcp.2008.vcproj
+++ /dev/null
@@ -1,422 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/libs/mrcp/mrcp.2010.vcxproj b/libs/unimrcp/libs/mrcp/mrcp.2010.vcxproj
deleted file mode 100644
index e525a96146..0000000000
--- a/libs/unimrcp/libs/mrcp/mrcp.2010.vcxproj
+++ /dev/null
@@ -1,148 +0,0 @@
-
-
-
-
- Debug
- Win32
-
-
- Debug
- x64
-
-
- Release
- Win32
-
-
- Release
- x64
-
-
-
- mrcp
- {1C320193-46A6-4B34-9C56-8AB584FC1B56}
- mrcp
- Win32Proj
-
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
-
-
-
- %(AdditionalIncludeDirectories)
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- %(AdditionalIncludeDirectories)
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;%(PreprocessorDefinitions)
- ProgramDatabase
-
-
-
-
- %(AdditionalIncludeDirectories)
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- %(AdditionalIncludeDirectories)
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/libs/mrcp/mrcp.2010.vcxproj.filters b/libs/unimrcp/libs/mrcp/mrcp.2010.vcxproj.filters
deleted file mode 100644
index 119921b34b..0000000000
--- a/libs/unimrcp/libs/mrcp/mrcp.2010.vcxproj.filters
+++ /dev/null
@@ -1,133 +0,0 @@
-
-
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hpp;hxx;hm;inl;inc;xsd
-
-
- {19ad4bde-c4f4-4937-9073-ca2780341d76}
-
-
- {8ec996ac-8a0a-4bf0-9b3c-535616585109}
- h;hpp;hxx;hm;inl;inc;xsd
-
-
- {5ba77874-7c17-4748-b5ba-b07b7f0a2169}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
- {f30fd049-a10d-4aea-b4bb-3eb674690fdd}
-
-
- {7e71717b-6f22-4c59-ba50-7b5a15516b2f}
- h;hpp;hxx;hm;inl;inc;xsd
-
-
- {c66dbb84-ce9d-4408-b54d-4d0ec51069fb}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
- {f20cfd62-4bb9-42de-bf1c-d578c8cd1a18}
-
-
- {039a4834-7ddb-40e7-9177-55d11ef1e733}
- h;hpp;hxx;hm;inl;inc;xsd
-
-
- {dc087d31-8ecf-473c-baa1-f3091e16014d}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
-
-
- include
-
-
- include
-
-
- message\include
-
-
- message\include
-
-
- message\include
-
-
- message\include
-
-
- control\include
-
-
- control\include
-
-
- control\include
-
-
- control\include
-
-
- resources\include
-
-
- resources\include
-
-
- resources\include
-
-
- resources\include
-
-
- resources\include
-
-
- resources\include
-
-
-
-
- message\src
-
-
- message\src
-
-
- message\src
-
-
- message\src
-
-
- control\src
-
-
- control\src
-
-
- control\src
-
-
- resources\src
-
-
- resources\src
-
-
- resources\src
-
-
- resources\src
-
-
- resources\src
-
-
- resources\src
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/libs/mrcp/mrcp.vcproj b/libs/unimrcp/libs/mrcp/mrcp.vcproj
index de0721096c..dc421663c7 100644
--- a/libs/unimrcp/libs/mrcp/mrcp.vcproj
+++ b/libs/unimrcp/libs/mrcp/mrcp.vcproj
@@ -264,6 +264,10 @@
RelativePath=".\message\include\mrcp_generic_header.h"
>
+
+
@@ -285,6 +289,10 @@
RelativePath=".\message\src\mrcp_generic_header.c"
>
+
+
@@ -372,6 +380,14 @@
RelativePath=".\resources\include\mrcp_synth_resource.h"
>
+
+
+
+
+
+
+
+
diff --git a/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_header.h b/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_header.h
index 4b2192b399..40556d5790 100644
--- a/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_header.h
+++ b/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_header.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_recog_header.h 1736 2010-06-14 20:16:22Z achaloyan $
*/
-#ifndef __MRCP_RECOG_HEADER_H__
-#define __MRCP_RECOG_HEADER_H__
+#ifndef MRCP_RECOG_HEADER_H
+#define MRCP_RECOG_HEADER_H
/**
* @file mrcp_recog_header.h
@@ -27,7 +29,7 @@
APT_BEGIN_EXTERN_C
-/** MRCP recognizer headers */
+/** MRCP recognizer header fields */
typedef enum {
RECOGNIZER_HEADER_CONFIDENCE_THRESHOLD,
RECOGNIZER_HEADER_SENSITIVITY_LEVEL,
@@ -50,7 +52,7 @@ typedef enum {
RECOGNIZER_HEADER_NEW_AUDIO_CHANNEL,
RECOGNIZER_HEADER_SPEECH_LANGUAGE,
- /** Additional headers for MRCP v2 */
+ /** Additional header fields for MRCP v2 */
RECOGNIZER_HEADER_INPUT_TYPE,
RECOGNIZER_HEADER_INPUT_WAVEFORM_URI,
RECOGNIZER_HEADER_COMPLETION_REASON,
@@ -64,6 +66,18 @@ typedef enum {
RECOGNIZER_HEADER_DTMF_BUFFER_TIME,
RECOGNIZER_HEADER_CLEAR_DTMF_BUFFER,
RECOGNIZER_HEADER_EARLY_NO_MATCH,
+ RECOGNIZER_HEADER_NUM_MIN_CONSISTENT_PRONUNCIATIONS,
+ RECOGNIZER_HEADER_CONSISTENCY_THRESHOLD,
+ RECOGNIZER_HEADER_CLASH_THRESHOLD,
+ RECOGNIZER_HEADER_PERSONAL_GRAMMAR_URI,
+ RECOGNIZER_HEADER_ENROLL_UTTERANCE,
+ RECOGNIZER_HEADER_PHRASE_ID,
+ RECOGNIZER_HEADER_PHRASE_NL,
+ RECOGNIZER_HEADER_WEIGHT,
+ RECOGNIZER_HEADER_SAVE_BEST_WAVEFORM,
+ RECOGNIZER_HEADER_NEW_PHRASE_ID,
+ RECOGNIZER_HEADER_CONFUSABLE_PHRASES_URI,
+ RECOGNIZER_HEADER_ABORT_PHRASE_ENROLLMENT,
RECOGNIZER_HEADER_COUNT
} mrcp_recognizer_header_id;
@@ -160,7 +174,7 @@ struct mrcp_recog_header_t {
a session or request, if it is not specified within the data */
apt_str_t speech_language;
- /** Additional headers for MRCP v2 */
+ /** Additional header fields for MRCP v2 */
/** Specifies if the input that caused a barge-in was DTMF or speech */
apt_str_t input_type;
/** Optional header specifies a URI pointing to audio content to be
@@ -169,10 +183,10 @@ struct mrcp_recog_header_t {
/** MAY be specified in a RECOGNITION-COMPLETE event coming from
the recognizer resource to the client */
apt_str_t completion_reason;
- /** tells the server resource the Media Type in which to store captured
+ /** Tells the server resource the Media Type in which to store captured
audio such as the one captured and returned by the Waveform-URI header */
apt_str_t media_type;
- /** lets the client request the server to buffer the
+ /** Lets the client request the server to buffer the
utterance associated with this recognition request into a buffer
available to a co-resident verification resource */
apt_bool_t ver_buffer_utterance;
@@ -202,6 +216,49 @@ struct mrcp_recog_header_t {
tell the recognizer that it MUST not wait for the end of speech
before processing the collected speech to match active grammars */
apt_bool_t early_no_match;
+ /** MAY be specified in a START-PHRASE-ENROLLMENT, "SET-PARAMS", or
+ "GET-PARAMS" method and is used to specify the minimum number of
+ consistent pronunciations that must be obtained to voice enroll a new phrase */
+ apr_size_t num_min_consistent_pronunciations;
+ /** MAY be sent as part of the START-PHRASE-ENROLLMENT,"SET-PARAMS", or
+ "GET-PARAMS" method and is used during voice-enrollment to specify how similar
+ to a previously enrolled pronunciation of the same phrase an utterance needs
+ to be in order to be considered "consistent" */
+ float consistency_threshold;
+ /** MAY be sent as part of the START-PHRASE-ENROLLMENT, SET-PARAMS, or
+ "GET-PARAMS" method and is used during voice-enrollment to specify
+ how similar the pronunciations of two different phrases can be
+ before they are considered to be clashing */
+ float clash_threshold;
+ /** Specifies the speaker-trained grammar to be used or
+ referenced during enrollment operations */
+ apt_str_t personal_grammar_uri;
+ /** MAY be specified in the RECOGNIZE method. If this header
+ is set to "true" and an Enrollment is active, the RECOGNIZE command
+ MUST add the collected utterance to the personal grammar that is
+ being enrolled */
+ apt_bool_t enroll_utterance;
+ /** Identifies a phrase in an existing personal grammar for which
+ enrollment is desired. It is also returned to the client in the
+ RECOGNIZE complete event */
+ apt_str_t phrase_id;
+ /** Specifies the interpreted text to be returned when the
+ phrase is recognized */
+ apt_str_t phrase_nl;
+ /** Represents the occurrence likelihood of a phrase in an enrolled grammar */
+ float weight;
+ /** Allows the client to request the recognizer resource to
+ save the audio stream for the best repetition of the phrase that was
+ used during the enrollment session */
+ apt_bool_t save_best_waveform;
+ /** Replaces the id used to identify the phrase in a personal grammar */
+ apt_str_t new_phrase_id;
+ /** Specifies a grammar that defines invalid phrases for enrollment */
+ apt_str_t confusable_phrases_uri;
+ /** Can optionally be specified in the END-PHRASE-ENROLLMENT
+ method to abort the phrase enrollment, rather than committing the
+ phrase to the personal grammar */
+ apt_bool_t abort_phrase_enrollment;
};
@@ -213,4 +270,4 @@ MRCP_DECLARE(const apt_str_t*) mrcp_recog_completion_cause_get(mrcp_recog_comple
APT_END_EXTERN_C
-#endif /*__MRCP_RECOG_HEADER_H__*/
+#endif /* MRCP_RECOG_HEADER_H */
diff --git a/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_resource.h b/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_resource.h
index 0131e9caed..64eddd9290 100644
--- a/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_resource.h
+++ b/libs/unimrcp/libs/mrcp/resources/include/mrcp_recog_resource.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_recog_resource.h 1781 2010-09-01 07:33:00Z achaloyan $
*/
-#ifndef __MRCP_RECOG_RESOURCE_H__
-#define __MRCP_RECOG_RESOURCE_H__
+#ifndef MRCP_RECOG_RESOURCE_H
+#define MRCP_RECOG_RESOURCE_H
/**
* @file mrcp_recog_resource.h
@@ -32,9 +34,15 @@ typedef enum {
RECOGNIZER_GET_PARAMS,
RECOGNIZER_DEFINE_GRAMMAR,
RECOGNIZER_RECOGNIZE,
+ RECOGNIZER_INTERPRET,
RECOGNIZER_GET_RESULT,
RECOGNIZER_START_INPUT_TIMERS,
RECOGNIZER_STOP,
+ RECOGNIZER_START_PHRASE_ENROLLMENT,
+ RECOGNIZER_ENROLLMENT_ROLLBACK,
+ RECOGNIZER_END_PHRASE_ENROLLMENT,
+ RECOGNIZER_MODIFY_PHRASE,
+ RECOGNIZER_DELETE_PHRASE,
RECOGNIZER_METHOD_COUNT
} mrcp_recognizer_method_id;
@@ -43,6 +51,7 @@ typedef enum {
typedef enum {
RECOGNIZER_START_OF_INPUT,
RECOGNIZER_RECOGNITION_COMPLETE,
+ RECOGNIZER_INTERPRETATION_COMPLETE,
RECOGNIZER_EVENT_COUNT
} mrcp_recognizer_event_id;
@@ -52,4 +61,4 @@ MRCP_DECLARE(mrcp_resource_t*) mrcp_recog_resource_create(apr_pool_t *pool);
APT_END_EXTERN_C
-#endif /*__MRCP_RECOG_RESOURCE_H__*/
+#endif /* MRCP_RECOG_RESOURCE_H */
diff --git a/libs/unimrcp/libs/mrcp/resources/include/mrcp_recorder_header.h b/libs/unimrcp/libs/mrcp/resources/include/mrcp_recorder_header.h
index af1772337a..2fadba5ea8 100644
--- a/libs/unimrcp/libs/mrcp/resources/include/mrcp_recorder_header.h
+++ b/libs/unimrcp/libs/mrcp/resources/include/mrcp_recorder_header.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_recorder_header.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_RECORDER_HEADER_H__
-#define __MRCP_RECORDER_HEADER_H__
+#ifndef MRCP_RECORDER_HEADER_H
+#define MRCP_RECORDER_HEADER_H
/**
* @file mrcp_recorder_header.h
@@ -133,4 +135,4 @@ MRCP_DECLARE(const apt_str_t*) mrcp_recorder_completion_cause_get(
APT_END_EXTERN_C
-#endif /*__MRCP_RECORDER_HEADER_H__*/
+#endif /* MRCP_RECORDER_HEADER_H */
diff --git a/libs/unimrcp/libs/mrcp/resources/include/mrcp_recorder_resource.h b/libs/unimrcp/libs/mrcp/resources/include/mrcp_recorder_resource.h
index b9afa34999..090992ba62 100644
--- a/libs/unimrcp/libs/mrcp/resources/include/mrcp_recorder_resource.h
+++ b/libs/unimrcp/libs/mrcp/resources/include/mrcp_recorder_resource.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_recorder_resource.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_RECORDER_RESOURCE_H__
-#define __MRCP_RECORDER_RESOURCE_H__
+#ifndef MRCP_RECORDER_RESOURCE_H
+#define MRCP_RECORDER_RESOURCE_H
/**
* @file mrcp_recorder_resource.h
@@ -50,4 +52,4 @@ MRCP_DECLARE(mrcp_resource_t*) mrcp_recorder_resource_create(apr_pool_t *pool);
APT_END_EXTERN_C
-#endif /*__MRCP_RECORDER_RESOURCE_H__*/
+#endif /* MRCP_RECORDER_RESOURCE_H */
diff --git a/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_header.h b/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_header.h
index 359af6bd59..c711414471 100644
--- a/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_header.h
+++ b/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_header.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_synth_header.h 1643 2010-04-08 13:40:09Z achaloyan $
*/
-#ifndef __MRCP_SYNTH_HEADER_H__
-#define __MRCP_SYNTH_HEADER_H__
+#ifndef MRCP_SYNTH_HEADER_H
+#define MRCP_SYNTH_HEADER_H
/**
* @file mrcp_synth_header.h
@@ -27,7 +29,7 @@
APT_BEGIN_EXTERN_C
-/** MRCP synthesizer headers */
+/** MRCP synthesizer header fields */
typedef enum {
SYNTHESIZER_HEADER_JUMP_SIZE,
SYNTHESIZER_HEADER_KILL_ON_BARGE_IN,
@@ -248,9 +250,9 @@ struct mrcp_synth_header_t {
/** MAY be specified in a "SPEAK-COMPLETE" event coming from
the synthesizer resource to the client */
apt_str_t completion_reason;
- /** This set of headers defines the voice of the speaker */
+ /** This set of header fields defines the voice of the speaker */
mrcp_voice_param_t voice_param;
- /** This set of headers defines the prosody of the speech */
+ /** This set of header fields defines the prosody of the speech */
mrcp_prosody_param_t prosody_param;
/** Contains timestamp information in a "timestamp" field */
apt_str_t speech_marker;
@@ -285,7 +287,7 @@ struct mrcp_synth_header_t {
mrcp_speech_length_value_t speak_length;
/** Used to indicate whether a lexicon has to be loaded or unloaded */
apt_bool_t load_lexicon;
- /** used to specify a list of active Lexicon URIs and the
+ /** Used to specify a list of active Lexicon URIs and the
search order among the active lexicons */
apt_str_t lexicon_search_order;
};
@@ -299,4 +301,4 @@ MRCP_DECLARE(const apt_str_t*) mrcp_synth_completion_cause_get(mrcp_synth_comple
APT_END_EXTERN_C
-#endif /*__MRCP_SYNTH_HEADER_H__*/
+#endif /* MRCP_SYNTH_HEADER_H */
diff --git a/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_resource.h b/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_resource.h
index d63fbdbfe3..256be1ac3c 100644
--- a/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_resource.h
+++ b/libs/unimrcp/libs/mrcp/resources/include/mrcp_synth_resource.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_synth_resource.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_SYNTH_RESOURCE_H__
-#define __MRCP_SYNTH_RESOURCE_H__
+#ifndef MRCP_SYNTH_RESOURCE_H
+#define MRCP_SYNTH_RESOURCE_H
/**
* @file mrcp_synth_resource.h
@@ -55,4 +57,4 @@ MRCP_DECLARE(mrcp_resource_t*) mrcp_synth_resource_create(apr_pool_t *pool);
APT_END_EXTERN_C
-#endif /*__MRCP_SYNTH_RESOURCE_H__*/
+#endif /* MRCP_SYNTH_RESOURCE_H */
diff --git a/libs/unimrcp/libs/mrcp/resources/include/mrcp_verifier_header.h b/libs/unimrcp/libs/mrcp/resources/include/mrcp_verifier_header.h
new file mode 100644
index 0000000000..cac29e01d1
--- /dev/null
+++ b/libs/unimrcp/libs/mrcp/resources/include/mrcp_verifier_header.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id:
+ */
+
+#ifndef MRCP_VERIFIER_HEADER_H
+#define MRCP_VERIFIER_HEADER_H
+
+/**
+ * @file mrcp_verifier_header.h
+ * @brief MRCP Verifier Header
+ */
+
+#include "mrcp_types.h"
+#include "mrcp_header_accessor.h"
+
+APT_BEGIN_EXTERN_C
+
+/** MRCP verifier header fields */
+typedef enum {
+ VERIFIER_HEADER_REPOSITORY_URI,
+ VERIFIER_HEADER_VOICEPRINT_IDENTIFIER,
+ VERIFIER_HEADER_VERIFICATION_MODE,
+ VERIFIER_HEADER_ADAPT_MODEL,
+ VERIFIER_HEADER_ABORT_MODEL,
+ VERIFIER_HEADER_MIN_VERIFICATION_SCORE,
+ VERIFIER_HEADER_NUM_MIN_VERIFICATION_PHRASES,
+ VERIFIER_HEADER_NUM_MAX_VERIFICATION_PHRASES,
+ VERIFIER_HEADER_NO_INPUT_TIMEOUT,
+ VERIFIER_HEADER_SAVE_WAVEFORM,
+ VERIFIER_HEADER_MEDIA_TYPE,
+ VERIFIER_HEADER_WAVEFORM_URI,
+ VERIFIER_HEADER_VOICEPRINT_EXISTS,
+ VERIFIER_HEADER_VER_BUFFER_UTTERANCE,
+ VERIFIER_HEADER_INPUT_WAVEFORM_URI,
+ VERIFIER_HEADER_COMPLETION_CAUSE,
+ VERIFIER_HEADER_COMPLETION_REASON,
+ VERIFIER_HEADER_SPEECH_COMPLETE_TIMEOUT,
+ VERIFIER_HEADER_NEW_AUDIO_CHANNEL,
+ VERIFIER_HEADER_ABORT_VERIFICATION,
+ VERIFIER_HEADER_START_INPUT_TIMERS,
+
+ VERIFIER_HEADER_COUNT
+} mrcp_verifier_header_id;
+
+
+/** MRCP verifier completion-cause */
+typedef enum {
+ VERIFIER_COMPLETION_CAUSE_SUCCESS = 0,
+ VERIFIER_COMPLETION_CAUSE_ERROR = 1,
+ VERIFIER_COMPLETION_CAUSE_NO_INPUT_TIMEOUT = 2,
+ VERIFIER_COMPLETION_CAUSE_TOO_MUCH_SPEECH_TIMEOUT = 3,
+ VERIFIER_COMPLETION_CAUSE_SPEECH_TOO_EARLY = 4,
+ VERIFIER_COMPLETION_CAUSE_BUFFER_EMPTY = 5,
+ VERIFIER_COMPLETION_CAUSE_OUT_OF_SEQUENCE = 6,
+ VERIFIER_COMPLETION_CAUSE_REPOSITORY_URI_FAILURE = 7,
+ VERIFIER_COMPLETION_CAUSE_REPOSITORY_URI_MISSING = 8,
+ VERIFIER_COMPLETION_CAUSE_VOICEPRINT_ID_MISSING = 9,
+ VERIFIER_COMPLETION_CAUSE_VOICEPRINT_ID_NOT_EXIST = 10,
+ VERIFIER_COMPLETION_CAUSE_SPEECH_NOT_USABLE = 11,
+
+ VERIFIER_COMPLETION_CAUSE_COUNT = 12,
+ VERIFIER_COMPLETION_CAUSE_UNKNOWN = VERIFIER_COMPLETION_CAUSE_COUNT
+} mrcp_verifier_completion_cause_e;
+
+
+
+/** MRCP verifier-header declaration */
+typedef struct mrcp_verifier_header_t mrcp_verifier_header_t;
+
+/** MRCP verifier-header */
+struct mrcp_verifier_header_t {
+ /** Specifies the voiceprint repository to be used or referenced during
+ speaker verification or identification operations */
+ apt_str_t repository_uri;
+ /** Specifies the claimed identity for verification applications */
+ apt_str_t voiceprint_identifier;
+ /** Specifies the mode of the verification resource */
+ apt_str_t verification_mode;
+ /** Indicates the desired behavior of the verification resource
+ after a successful verification operation */
+ apt_bool_t adapt_model;
+ /** Indicates the desired behavior of the verification resource
+ upon session termination */
+ apt_bool_t abort_model;
+ /** Determines the minimum verification score for which a verification
+ decision of "accepted" may be declared by the server */
+ float min_verification_score;
+ /** Specifies the minimum number of valid utterances
+ before a positive decision is given for verification */
+ apr_size_t num_min_verification_phrases;
+ /** Specifies the number of valid utterances required
+ before a decision is forced for verification */
+ apr_size_t num_max_verification_phrases;
+ /** Sets the length of time from the start of the verification timers
+ (see START-INPUT-TIMERS) until the declaration of a no-input event
+ in the VERIFICATION-COMPLETE server event message */
+ apr_size_t no_input_timeout;
+ /** Allows the client to request the verification resource to save
+ the audio stream that was used for verification/identification */
+ apt_bool_t save_waveform;
+ /** Tells the server resource the Media Type of the captured audio or video
+ such as the one captured and returned by the Waveform-URI header field */
+ apt_str_t media_type;
+ /** If the Save-Waveform header field is set to true, the verification resource
+ MUST attempt to record the incoming audio stream of the verification into
+ a file and provide a URI for the client to access it */
+ apt_str_t waveform_uri;
+ /** Shows the status of the voiceprint specified
+ in the QUERY-VOICEPRINT method */
+ apt_bool_t voiceprint_exists;
+ /** Indicates that this utterance could be
+ later considered for Speaker Verification */
+ apt_bool_t ver_buffer_utterance;
+ /** Specifies stored audio content that the client requests the server
+ to fetch and process according to the current verification mode,
+ either to train the voiceprint or verify a claimed identity */
+ apt_str_t input_waveform_uri;
+ /** Indicates the cause of VERIFY or VERIFY-FROM-BUFFER method completion */
+ mrcp_verifier_completion_cause_e completion_cause;
+ /** MAY be specified in a VERIFICATION-COMPLETE event
+ coming from the verifier resource to the client */
+ apt_str_t completion_reason;
+ /** Specifies the length of silence required following user
+ speech before the speech verifier finalizes a result */
+ apr_size_t speech_complete_timeout;
+ /** MAY be specified in a VERIFIER request and allows the
+ client to tell the server that, from this point on, further input
+ audio comes from a different audio source */
+ apt_bool_t new_audio_channel;
+ /** MUST be sent in a STOP request to indicate
+ whether or not to abort a VERIFY method in progress */
+ apt_bool_t abort_verification;
+ /** MAY be sent as part of a VERIFY request. A value of false
+ tells the verification resource to start the VERIFY operation,
+ but not to start the no-input timer yet */
+ apt_bool_t start_input_timers;
+};
+
+
+/** Get verifier header vtable */
+const mrcp_header_vtable_t* mrcp_verifier_header_vtable_get(mrcp_version_e version);
+
+/** Get verifier completion cause string */
+MRCP_DECLARE(const apt_str_t*) mrcp_verifier_completion_cause_get(mrcp_verifier_completion_cause_e completion_cause, mrcp_version_e version);
+
+APT_END_EXTERN_C
+
+#endif /* MRCP_VERIFIER_HEADER_H */
diff --git a/libs/unimrcp/libs/mrcp/resources/include/mrcp_verifier_resource.h b/libs/unimrcp/libs/mrcp/resources/include/mrcp_verifier_resource.h
new file mode 100644
index 0000000000..5fcfaef2ce
--- /dev/null
+++ b/libs/unimrcp/libs/mrcp/resources/include/mrcp_verifier_resource.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id:
+ */
+
+#ifndef MRCP_VERIFIER_RESOURCE_H
+#define MRCP_VERIFIER_RESOURCE_H
+
+/**
+ * @file mrcp_verifier_resource.h
+ * @brief MRCP Verifier Resource
+ */
+
+#include "mrcp_types.h"
+
+APT_BEGIN_EXTERN_C
+
+/** MRCP verifier methods */
+typedef enum {
+ VERIFIER_SET_PARAMS,
+ VERIFIER_GET_PARAMS,
+ VERIFIER_START_SESSION,
+ VERIFIER_END_SESSION,
+ VERIFIER_QUERY_VOICEPRINT,
+ VERIFIER_DELETE_VOICEPRINT,
+ VERIFIER_VERIFY,
+ VERIFIER_VERIFY_FROM_BUFFER,
+ VERIFIER_VERIFY_ROLLBACK,
+ VERIFIER_STOP,
+ VERIFIER_CLEAR_BUFFER,
+ VERIFIER_START_INPUT_TIMERS,
+ VERIFIER_GET_INTERMIDIATE_RESULT,
+
+ VERIFIER_METHOD_COUNT
+} mrcp_verifier_method_id;
+
+/** MRCP verifier events */
+typedef enum {
+ VERIFIER_START_OF_INPUT,
+ VERIFIER_VERIFICATION_COMPLETE,
+
+ VERIFIER_EVENT_COUNT
+} mrcp_verifier_event_id;
+
+/** Create MRCP verifier resource */
+MRCP_DECLARE(mrcp_resource_t*) mrcp_verifier_resource_create(apr_pool_t *pool);
+
+APT_END_EXTERN_C
+
+#endif /* MRCP_VERIFIER_RESOURCE_H */
diff --git a/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_header.c b/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_header.c
index 4bfbcbe16e..81ae07507d 100644
--- a/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_header.c
+++ b/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_header.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,82 +12,108 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_recog_header.c 1736 2010-06-14 20:16:22Z achaloyan $
*/
#include "mrcp_recog_header.h"
-/** String table of MRCPv1 recognizer headers (mrcp_recog_header_id) */
+/** String table of MRCPv1 recognizer header fields (mrcp_recog_header_id) */
static const apt_str_table_item_t v1_recog_header_string_table[] = {
- {{"Confidence-Threshold", 20},7},
- {{"Sensitivity-Level", 17},3},
- {{"Speed-Vs-Accuracy", 17},4},
- {{"N-Best-List-Length", 18},1},
- {{"No-Input-Timeout", 16},2},
- {{"Recognition-Timeout", 19},16},
- {{"Waveform-Url", 12},0},
- {{"Completion-Cause", 16},16},
- {{"Recognizer-Context-Block", 24},12},
- {{"Recognizer-Start-Timers", 23},11},
- {{"Speech-Complete-Timeout", 23},7},
- {{"Speech-Incomplete-Timeout", 25},8},
- {{"DTMF-Interdigit-Timeout", 23},5},
- {{"DTMF-Term-Timeout", 17},14},
- {{"DTMF-Term-Char", 14},14},
- {{"Failed-Uri", 10},10},
- {{"Failed-Uri-Cause", 16},16},
- {{"Save-Waveform", 13},5},
- {{"New-Audio-Channel", 17},2},
- {{"Speech-Language", 15},8},
- {{"Input-Type", 10},10},
- {{"Input-Waveform-Uri", 18},6},
- {{"Completion-Reason", 17},15},
- {{"Media-Type", 10},0},
- {{"Ver-Buffer-Utterance", 20},0},
- {{"Recognition-Mode", 16},14},
- {{"Cancel-If-Queue", 15},3},
- {{"Hotword-Max-Duration", 20},10},
- {{"Hotword-Min-Duration", 20},20},
- {{"Interpret-Text", 14},7},
- {{"DTMF-Buffer-Time", 16},5},
- {{"Clear-DTMF-Buffer", 17},1},
- {{"Early-No-Match", 14},0}
+ {{"Confidence-Threshold", 20},16},
+ {{"Sensitivity-Level", 17},14},
+ {{"Speed-Vs-Accuracy", 17},4},
+ {{"N-Best-List-Length", 18},1},
+ {{"No-Input-Timeout", 16},2},
+ {{"Recognition-Timeout", 19},19},
+ {{"Waveform-Url", 12},4},
+ {{"Completion-Cause", 16},16},
+ {{"Recognizer-Context-Block", 24},16},
+ {{"Recognizer-Start-Timers", 23},18},
+ {{"Speech-Complete-Timeout", 23},7},
+ {{"Speech-Incomplete-Timeout", 25},12},
+ {{"DTMF-Interdigit-Timeout", 23},10},
+ {{"DTMF-Term-Timeout", 17},14},
+ {{"DTMF-Term-Char", 14},14},
+ {{"Failed-Uri", 10},10},
+ {{"Failed-Uri-Cause", 16},16},
+ {{"Save-Waveform", 13},5},
+ {{"New-Audio-Channel", 17},17},
+ {{"Speech-Language", 15},8},
+ {{"Input-Type", 10},10},
+ {{"Input-Waveform-Uri", 18},6},
+ {{"Completion-Reason", 17},17},
+ {{"Media-Type", 10},0},
+ {{"Ver-Buffer-Utterance", 20},0},
+ {{"Recognition-Mode", 16},16},
+ {{"Cancel-If-Queue", 15},3},
+ {{"Hotword-Max-Duration", 20},10},
+ {{"Hotword-Min-Duration", 20},20},
+ {{"Interpret-Text", 14},12},
+ {{"DTMF-Buffer-Time", 16},16},
+ {{"Clear-DTMF-Buffer", 17},11},
+ {{"Early-No-Match", 14},4},
+ {{"Num-Min-Consistent-Pronunciations",33},1},
+ {{"Consistency-Threshold", 21},16},
+ {{"Clash-Threshold", 15},2},
+ {{"Personal-Grammar-URI", 20},9},
+ {{"Enroll-Utterance", 16},10},
+ {{"Phrase-ID", 9},8},
+ {{"Phrase-NL", 9},9},
+ {{"Weight", 6},3},
+ {{"Save-Best-Waveform", 18},10},
+ {{"New-Phrase-ID", 13},4},
+ {{"Confusable-Phrases-URI", 22},4},
+ {{"Abort-Phrase-Enrollment", 23},0}
};
-/** String table of MRCPv2 recognizer headers (mrcp_recog_header_id) */
+/** String table of MRCPv2 recognizer header fields (mrcp_recog_header_id) */
static const apt_str_table_item_t v2_recog_header_string_table[] = {
- {{"Confidence-Threshold", 20},8},
- {{"Sensitivity-Level", 17},3},
- {{"Speed-Vs-Accuracy", 17},4},
- {{"N-Best-List-Length", 18},1},
- {{"No-Input-Timeout", 16},2},
- {{"Recognition-Timeout", 19},16},
- {{"Waveform-Uri", 12},0},
- {{"Completion-Cause", 16},16},
- {{"Recognizer-Context-Block", 24},7},
- {{"Start-Input-Timers", 18},2},
- {{"Speech-Complete-Timeout", 23},7},
- {{"Speech-Incomplete-Timeout", 25},8},
- {{"DTMF-Interdigit-Timeout", 23},5},
- {{"DTMF-Term-Timeout", 17},14},
- {{"DTMF-Term-Char", 14},14},
- {{"Failed-Uri", 10},10},
- {{"Failed-Uri-Cause", 16},16},
- {{"Save-Waveform", 13},5},
- {{"New-Audio-Channel", 17},2},
- {{"Speech-Language", 15},8},
- {{"Input-Type", 10},10},
- {{"Input-Waveform-Uri", 18},6},
- {{"Completion-Reason", 17},13},
- {{"Media-Type", 10},0},
- {{"Ver-Buffer-Utterance", 20},0},
- {{"Recognition-Mode", 16},14},
- {{"Cancel-If-Queue", 15},3},
- {{"Hotword-Max-Duration", 20},10},
- {{"Hotword-Min-Duration", 20},20},
- {{"Interpret-Text", 14},7},
- {{"DTMF-Buffer-Time", 16},5},
- {{"Clear-DTMF-Buffer", 17},1},
- {{"Early-No-Match", 14},0}
+ {{"Confidence-Threshold", 20},16},
+ {{"Sensitivity-Level", 17},14},
+ {{"Speed-Vs-Accuracy", 17},4},
+ {{"N-Best-List-Length", 18},1},
+ {{"No-Input-Timeout", 16},2},
+ {{"Recognition-Timeout", 19},19},
+ {{"Waveform-Uri", 12},4},
+ {{"Completion-Cause", 16},16},
+ {{"Recognizer-Context-Block", 24},7},
+ {{"Start-Input-Timers", 18},18},
+ {{"Speech-Complete-Timeout", 23},7},
+ {{"Speech-Incomplete-Timeout", 25},12},
+ {{"DTMF-Interdigit-Timeout", 23},10},
+ {{"DTMF-Term-Timeout", 17},14},
+ {{"DTMF-Term-Char", 14},14},
+ {{"Failed-Uri", 10},10},
+ {{"Failed-Uri-Cause", 16},16},
+ {{"Save-Waveform", 13},5},
+ {{"New-Audio-Channel", 17},17},
+ {{"Speech-Language", 15},8},
+ {{"Input-Type", 10},10},
+ {{"Input-Waveform-Uri", 18},6},
+ {{"Completion-Reason", 17},13},
+ {{"Media-Type", 10},0},
+ {{"Ver-Buffer-Utterance", 20},0},
+ {{"Recognition-Mode", 16},16},
+ {{"Cancel-If-Queue", 15},3},
+ {{"Hotword-Max-Duration", 20},10},
+ {{"Hotword-Min-Duration", 20},20},
+ {{"Interpret-Text", 14},12},
+ {{"DTMF-Buffer-Time", 16},16},
+ {{"Clear-DTMF-Buffer", 17},11},
+ {{"Early-No-Match", 14},4},
+ {{"Num-Min-Consistent-Pronunciations",33},1},
+ {{"Consistency-Threshold", 21},16},
+ {{"Clash-Threshold", 15},15},
+ {{"Personal-Grammar-URI", 20},9},
+ {{"Enroll-Utterance", 16},10},
+ {{"Phrase-ID", 9},8},
+ {{"Phrase-NL", 9},9},
+ {{"Weight", 6},3},
+ {{"Save-Best-Waveform", 18},10},
+ {{"New-Phrase-ID", 13},4},
+ {{"Confusable-Phrases-URI", 22},4},
+ {{"Abort-Phrase-Enrollment", 23},0}
};
/** String table of MRCPv1 recognizer completion-cause fields (mrcp_recog_completion_cause_e) */
@@ -156,7 +182,7 @@ static void mrcp_recog_header_init(mrcp_recog_header_t *recog_header)
recog_header->save_waveform = FALSE;
recog_header->new_audio_channel = FALSE;
apt_string_reset(&recog_header->speech_language);
- /* initializes additionnal MRCPV2 recog headers */
+ /* initializes additionnal MRCPV2 recog header fields */
apt_string_reset(&recog_header->input_type);
apt_string_reset(&recog_header->input_waveform_uri);
apt_string_reset(&recog_header->completion_reason);
@@ -170,6 +196,18 @@ static void mrcp_recog_header_init(mrcp_recog_header_t *recog_header)
recog_header->dtmf_buffer_time = 0;
recog_header->clear_dtmf_buffer = FALSE;
recog_header->early_no_match = FALSE;
+ recog_header->num_min_consistent_pronunciations = 0;
+ recog_header->consistency_threshold = 0.0;
+ recog_header->clash_threshold = 0.0;
+ apt_string_reset(&recog_header->personal_grammar_uri);
+ recog_header->enroll_utterance = FALSE;
+ apt_string_reset(&recog_header->phrase_id);
+ apt_string_reset(&recog_header->phrase_nl);
+ recog_header->weight = 0.0;
+ recog_header->save_best_waveform = FALSE;
+ apt_string_reset(&recog_header->new_phrase_id);
+ apt_string_reset(&recog_header->confusable_phrases_uri);
+ recog_header->abort_phrase_enrollment = FALSE;
}
/** Allocate MRCP recognizer header */
@@ -196,13 +234,13 @@ static apt_bool_t mrcp_recog_header_parse(mrcp_recog_header_t *recog_header, apr
recog_header->recognition_timeout = apt_size_value_parse(value);
break;
case RECOGNIZER_HEADER_WAVEFORM_URI:
- apt_string_copy(&recog_header->waveform_uri,value,pool);
+ recog_header->waveform_uri = *value;
break;
case RECOGNIZER_HEADER_COMPLETION_CAUSE:
recog_header->completion_cause = apt_size_value_parse(value);
break;
case RECOGNIZER_HEADER_RECOGNIZER_CONTEXT_BLOCK:
- apt_string_copy(&recog_header->recognizer_context_block,value,pool);
+ recog_header->recognizer_context_block = *value;
break;
case RECOGNIZER_HEADER_START_INPUT_TIMERS:
apt_boolean_value_parse(value,&recog_header->start_input_timers);
@@ -223,10 +261,10 @@ static apt_bool_t mrcp_recog_header_parse(mrcp_recog_header_t *recog_header, apr
recog_header->dtmf_term_char = *value->buf;
break;
case RECOGNIZER_HEADER_FAILED_URI:
- apt_string_copy(&recog_header->failed_uri,value,pool);
+ recog_header->failed_uri = *value;
break;
case RECOGNIZER_HEADER_FAILED_URI_CAUSE:
- apt_string_copy(&recog_header->failed_uri_cause,value,pool);
+ recog_header->failed_uri_cause = *value;
break;
case RECOGNIZER_HEADER_SAVE_WAVEFORM:
apt_boolean_value_parse(value,&recog_header->save_waveform);
@@ -235,25 +273,25 @@ static apt_bool_t mrcp_recog_header_parse(mrcp_recog_header_t *recog_header, apr
apt_boolean_value_parse(value,&recog_header->new_audio_channel);
break;
case RECOGNIZER_HEADER_SPEECH_LANGUAGE:
- apt_string_copy(&recog_header->speech_language,value,pool);
+ recog_header->speech_language = *value;
break;
case RECOGNIZER_HEADER_INPUT_TYPE:
- apt_string_copy(&recog_header->input_type,value,pool);
+ recog_header->input_type = *value;
break;
case RECOGNIZER_HEADER_MEDIA_TYPE:
- apt_string_copy(&recog_header->media_type,value,pool);
+ recog_header->media_type = *value;
break;
case RECOGNIZER_HEADER_INPUT_WAVEFORM_URI:
- apt_string_copy(&recog_header->input_waveform_uri,value,pool);
+ recog_header->input_waveform_uri = *value;
break;
case RECOGNIZER_HEADER_COMPLETION_REASON:
- apt_string_copy(&recog_header->completion_reason,value,pool);
+ recog_header->completion_reason = *value;
break;
case RECOGNIZER_HEADER_VER_BUFFER_UTTERANCE:
apt_boolean_value_parse(value,&recog_header->ver_buffer_utterance);
break;
case RECOGNIZER_HEADER_RECOGNITION_MODE:
- apt_string_copy(&recog_header->recognition_mode,value,pool);
+ recog_header->recognition_mode = *value;
break;
case RECOGNIZER_HEADER_CANCEL_IF_QUEUE:
apt_boolean_value_parse(value,&recog_header->cancel_if_queue);
@@ -265,7 +303,7 @@ static apt_bool_t mrcp_recog_header_parse(mrcp_recog_header_t *recog_header, apr
recog_header->hotword_min_duration = apt_size_value_parse(value);
break;
case RECOGNIZER_HEADER_INTERPRET_TEXT:
- apt_string_copy(&recog_header->interpret_text,value,pool);
+ recog_header->interpret_text = *value;
break;
case RECOGNIZER_HEADER_DTMF_BUFFER_TIME:
recog_header->dtmf_buffer_time = apt_size_value_parse(value);
@@ -276,6 +314,42 @@ static apt_bool_t mrcp_recog_header_parse(mrcp_recog_header_t *recog_header, apr
case RECOGNIZER_HEADER_EARLY_NO_MATCH:
apt_boolean_value_parse(value,&recog_header->early_no_match);
break;
+ case RECOGNIZER_HEADER_NUM_MIN_CONSISTENT_PRONUNCIATIONS:
+ recog_header->num_min_consistent_pronunciations = apt_size_value_parse(value);
+ break;
+ case RECOGNIZER_HEADER_CONSISTENCY_THRESHOLD:
+ recog_header->consistency_threshold = apt_float_value_parse(value);
+ break;
+ case RECOGNIZER_HEADER_CLASH_THRESHOLD:
+ recog_header->clash_threshold = apt_float_value_parse(value);
+ break;
+ case RECOGNIZER_HEADER_PERSONAL_GRAMMAR_URI:
+ recog_header->personal_grammar_uri = *value;
+ break;
+ case RECOGNIZER_HEADER_ENROLL_UTTERANCE:
+ apt_boolean_value_parse(value,&recog_header->enroll_utterance);
+ break;
+ case RECOGNIZER_HEADER_PHRASE_ID:
+ recog_header->phrase_id = *value;
+ break;
+ case RECOGNIZER_HEADER_PHRASE_NL:
+ recog_header->phrase_nl = *value;
+ break;
+ case RECOGNIZER_HEADER_WEIGHT:
+ recog_header->weight = apt_float_value_parse(value);
+ break;
+ case RECOGNIZER_HEADER_SAVE_BEST_WAVEFORM:
+ apt_boolean_value_parse(value,&recog_header->save_best_waveform);
+ break;
+ case RECOGNIZER_HEADER_NEW_PHRASE_ID:
+ recog_header->new_phrase_id = *value;
+ break;
+ case RECOGNIZER_HEADER_CONFUSABLE_PHRASES_URI:
+ recog_header->confusable_phrases_uri = *value;
+ break;
+ case RECOGNIZER_HEADER_ABORT_PHRASE_ENROLLMENT:
+ apt_boolean_value_parse(value,&recog_header->abort_phrase_enrollment);
+ break;
default:
status = FALSE;
}
@@ -288,10 +362,10 @@ static APR_INLINE float apt_size_value_parse_as_float(const apt_str_t *value)
return f / 100;
}
-static APR_INLINE apt_bool_t apt_size_value_generate_from_float(float value, apt_text_stream_t *stream)
+static APR_INLINE apt_bool_t apt_size_value_generate_from_float(float value, apt_str_t *str, apr_pool_t *pool)
{
apr_size_t s = (apr_size_t)((value + 0.001f) * 100);
- return apt_size_value_generate(s,stream);
+ return apt_size_value_generate(s,str,pool);
}
/** Parse MRCPv1 recognizer header */
@@ -333,95 +407,133 @@ static apt_bool_t mrcp_v2_recog_header_parse(mrcp_header_accessor_t *accessor, a
}
/** Generate MRCP recognizer header */
-static apt_bool_t mrcp_recog_header_generate(mrcp_recog_header_t *recog_header, apr_size_t id, apt_text_stream_t *value)
+static apt_bool_t mrcp_recog_header_generate(const mrcp_recog_header_t *recog_header, apr_size_t id, apt_str_t *value, apr_pool_t *pool)
{
switch(id) {
case RECOGNIZER_HEADER_N_BEST_LIST_LENGTH:
- apt_size_value_generate(recog_header->n_best_list_length,value);
+ apt_size_value_generate(recog_header->n_best_list_length,value,pool);
break;
case RECOGNIZER_HEADER_NO_INPUT_TIMEOUT:
- apt_size_value_generate(recog_header->no_input_timeout,value);
+ apt_size_value_generate(recog_header->no_input_timeout,value,pool);
break;
case RECOGNIZER_HEADER_RECOGNITION_TIMEOUT:
- apt_size_value_generate(recog_header->recognition_timeout,value);
+ apt_size_value_generate(recog_header->recognition_timeout,value,pool);
break;
case RECOGNIZER_HEADER_WAVEFORM_URI:
- apt_string_value_generate(&recog_header->waveform_uri,value);
+ *value = recog_header->waveform_uri;
break;
case RECOGNIZER_HEADER_RECOGNIZER_CONTEXT_BLOCK:
- apt_string_value_generate(&recog_header->recognizer_context_block,value);
+ *value = recog_header->recognizer_context_block;
break;
case RECOGNIZER_HEADER_START_INPUT_TIMERS:
- apt_boolean_value_generate(recog_header->start_input_timers,value);
+ apt_boolean_value_generate(recog_header->start_input_timers,value,pool);
break;
case RECOGNIZER_HEADER_SPEECH_COMPLETE_TIMEOUT:
- apt_size_value_generate(recog_header->speech_complete_timeout,value);
+ apt_size_value_generate(recog_header->speech_complete_timeout,value,pool);
break;
case RECOGNIZER_HEADER_SPEECH_INCOMPLETE_TIMEOUT:
- apt_size_value_generate(recog_header->speech_incomplete_timeout,value);
+ apt_size_value_generate(recog_header->speech_incomplete_timeout,value,pool);
break;
case RECOGNIZER_HEADER_DTMF_INTERDIGIT_TIMEOUT:
- apt_size_value_generate(recog_header->dtmf_interdigit_timeout,value);
+ apt_size_value_generate(recog_header->dtmf_interdigit_timeout,value,pool);
break;
case RECOGNIZER_HEADER_DTMF_TERM_TIMEOUT:
- apt_size_value_generate(recog_header->dtmf_term_timeout,value);
+ apt_size_value_generate(recog_header->dtmf_term_timeout,value,pool);
break;
case RECOGNIZER_HEADER_DTMF_TERM_CHAR:
- *value->pos++ = recog_header->dtmf_term_char;
+ value->length = 1;
+ value->buf = apr_palloc(pool,value->length);
+ *value->buf = recog_header->dtmf_term_char;
break;
case RECOGNIZER_HEADER_FAILED_URI:
- apt_string_value_generate(&recog_header->failed_uri,value);
+ *value = recog_header->failed_uri;
break;
case RECOGNIZER_HEADER_FAILED_URI_CAUSE:
- apt_string_value_generate(&recog_header->failed_uri_cause,value);
+ *value = recog_header->failed_uri_cause;
break;
case RECOGNIZER_HEADER_SAVE_WAVEFORM:
- apt_boolean_value_generate(recog_header->save_waveform,value);
+ apt_boolean_value_generate(recog_header->save_waveform,value,pool);
break;
case RECOGNIZER_HEADER_NEW_AUDIO_CHANNEL:
- apt_boolean_value_generate(recog_header->new_audio_channel,value);
+ apt_boolean_value_generate(recog_header->new_audio_channel,value,pool);
break;
case RECOGNIZER_HEADER_SPEECH_LANGUAGE:
- apt_string_value_generate(&recog_header->speech_language,value);
+ *value = recog_header->speech_language;
break;
case RECOGNIZER_HEADER_INPUT_TYPE:
- apt_string_value_generate(&recog_header->input_type,value);
+ *value = recog_header->input_type;
break;
case RECOGNIZER_HEADER_INPUT_WAVEFORM_URI:
- apt_string_value_generate(&recog_header->input_waveform_uri,value);
+ *value = recog_header->input_waveform_uri;
break;
case RECOGNIZER_HEADER_COMPLETION_REASON:
- apt_string_value_generate(&recog_header->completion_reason,value);
+ *value = recog_header->completion_reason;
break;
case RECOGNIZER_HEADER_MEDIA_TYPE:
- apt_string_value_generate(&recog_header->media_type,value);
+ *value = recog_header->media_type;
break;
case RECOGNIZER_HEADER_VER_BUFFER_UTTERANCE:
- apt_boolean_value_generate(recog_header->ver_buffer_utterance,value);
+ apt_boolean_value_generate(recog_header->ver_buffer_utterance,value,pool);
break;
case RECOGNIZER_HEADER_RECOGNITION_MODE:
- apt_string_value_generate(&recog_header->recognition_mode,value);
+ *value = recog_header->recognition_mode;
break;
case RECOGNIZER_HEADER_CANCEL_IF_QUEUE:
- apt_boolean_value_generate(recog_header->cancel_if_queue,value);
+ apt_boolean_value_generate(recog_header->cancel_if_queue,value,pool);
break;
case RECOGNIZER_HEADER_HOTWORD_MAX_DURATION:
- apt_size_value_generate(recog_header->hotword_max_duration,value);
+ apt_size_value_generate(recog_header->hotword_max_duration,value,pool);
break;
case RECOGNIZER_HEADER_HOTWORD_MIN_DURATION:
- apt_size_value_generate(recog_header->hotword_min_duration,value);
+ apt_size_value_generate(recog_header->hotword_min_duration,value,pool);
break;
case RECOGNIZER_HEADER_INTERPRET_TEXT:
- apt_string_value_generate(&recog_header->interpret_text,value);
+ *value = recog_header->interpret_text;
break;
case RECOGNIZER_HEADER_DTMF_BUFFER_TIME:
- apt_size_value_generate(recog_header->dtmf_buffer_time,value);
+ apt_size_value_generate(recog_header->dtmf_buffer_time,value,pool);
break;
case RECOGNIZER_HEADER_CLEAR_DTMF_BUFFER:
- apt_boolean_value_generate(recog_header->clear_dtmf_buffer,value);
+ apt_boolean_value_generate(recog_header->clear_dtmf_buffer,value,pool);
break;
case RECOGNIZER_HEADER_EARLY_NO_MATCH:
- apt_boolean_value_generate(recog_header->early_no_match,value);
+ apt_boolean_value_generate(recog_header->early_no_match,value,pool);
+ break;
+ case RECOGNIZER_HEADER_NUM_MIN_CONSISTENT_PRONUNCIATIONS:
+ apt_size_value_generate(recog_header->num_min_consistent_pronunciations,value,pool);
+ break;
+ case RECOGNIZER_HEADER_CONSISTENCY_THRESHOLD:
+ apt_float_value_generate(recog_header->consistency_threshold,value,pool);
+ break;
+ case RECOGNIZER_HEADER_CLASH_THRESHOLD:
+ apt_float_value_generate(recog_header->clash_threshold,value,pool);
+ break;
+ case RECOGNIZER_HEADER_PERSONAL_GRAMMAR_URI:
+ *value = recog_header->personal_grammar_uri;
+ break;
+ case RECOGNIZER_HEADER_ENROLL_UTTERANCE:
+ apt_boolean_value_generate(recog_header->enroll_utterance,value,pool);
+ break;
+ case RECOGNIZER_HEADER_PHRASE_ID:
+ *value = recog_header->phrase_id;
+ break;
+ case RECOGNIZER_HEADER_PHRASE_NL:
+ *value = recog_header->phrase_nl;
+ break;
+ case RECOGNIZER_HEADER_WEIGHT:
+ apt_float_value_generate(recog_header->weight,value,pool);
+ break;
+ case RECOGNIZER_HEADER_SAVE_BEST_WAVEFORM:
+ apt_boolean_value_generate(recog_header->save_best_waveform,value,pool);
+ break;
+ case RECOGNIZER_HEADER_NEW_PHRASE_ID:
+ *value = recog_header->new_phrase_id;
+ break;
+ case RECOGNIZER_HEADER_CONFUSABLE_PHRASES_URI:
+ *value = recog_header->confusable_phrases_uri;
+ break;
+ case RECOGNIZER_HEADER_ABORT_PHRASE_ENROLLMENT:
+ apt_boolean_value_generate(recog_header->abort_phrase_enrollment,value,pool);
break;
default:
break;
@@ -430,53 +542,55 @@ static apt_bool_t mrcp_recog_header_generate(mrcp_recog_header_t *recog_header,
}
/** Generate MRCPv1 recognizer header */
-static apt_bool_t mrcp_v1_recog_header_generate(mrcp_header_accessor_t *accessor, apr_size_t id, apt_text_stream_t *value)
+static apt_bool_t mrcp_v1_recog_header_generate(const mrcp_header_accessor_t *accessor, apr_size_t id, apt_str_t *value, apr_pool_t *pool)
{
mrcp_recog_header_t *recog_header = accessor->data;
if(id == RECOGNIZER_HEADER_CONFIDENCE_THRESHOLD) {
- return apt_size_value_generate_from_float(recog_header->confidence_threshold,value);
+ return apt_size_value_generate_from_float(recog_header->confidence_threshold,value,pool);
}
else if(id == RECOGNIZER_HEADER_SENSITIVITY_LEVEL) {
- return apt_size_value_generate_from_float(recog_header->sensitivity_level,value);
+ return apt_size_value_generate_from_float(recog_header->sensitivity_level,value,pool);
}
else if(id == RECOGNIZER_HEADER_SPEED_VS_ACCURACY) {
- return apt_size_value_generate_from_float(recog_header->speed_vs_accuracy,value);
+ return apt_size_value_generate_from_float(recog_header->speed_vs_accuracy,value,pool);
}
else if(id == RECOGNIZER_HEADER_COMPLETION_CAUSE) {
- return mrcp_completion_cause_generate(
+ return apt_completion_cause_generate(
v1_completion_cause_string_table,
RECOGNIZER_COMPLETION_CAUSE_COUNT,
recog_header->completion_cause,
- value);
+ value,
+ pool);
}
- return mrcp_recog_header_generate(recog_header,id,value);
+ return mrcp_recog_header_generate(recog_header,id,value,pool);
}
/** Generate MRCPv2 recognizer header */
-static apt_bool_t mrcp_v2_recog_header_generate(mrcp_header_accessor_t *accessor, apr_size_t id, apt_text_stream_t *value)
+static apt_bool_t mrcp_v2_recog_header_generate(const mrcp_header_accessor_t *accessor, apr_size_t id, apt_str_t *value, apr_pool_t *pool)
{
mrcp_recog_header_t *recog_header = accessor->data;
if(id == RECOGNIZER_HEADER_CONFIDENCE_THRESHOLD) {
- return apt_float_value_generate(recog_header->confidence_threshold,value);
+ return apt_float_value_generate(recog_header->confidence_threshold,value,pool);
}
else if(id == RECOGNIZER_HEADER_SENSITIVITY_LEVEL) {
- return apt_float_value_generate(recog_header->sensitivity_level,value);
+ return apt_float_value_generate(recog_header->sensitivity_level,value,pool);
}
else if(id == RECOGNIZER_HEADER_SPEED_VS_ACCURACY) {
- return apt_float_value_generate(recog_header->speed_vs_accuracy,value);
+ return apt_float_value_generate(recog_header->speed_vs_accuracy,value,pool);
}
else if(id == RECOGNIZER_HEADER_COMPLETION_CAUSE) {
- return mrcp_completion_cause_generate(
+ return apt_completion_cause_generate(
v2_completion_cause_string_table,
RECOGNIZER_COMPLETION_CAUSE_COUNT,
recog_header->completion_cause,
- value);
+ value,
+ pool);
}
- return mrcp_recog_header_generate(recog_header,id,value);
+ return mrcp_recog_header_generate(recog_header,id,value,pool);
}
/** Duplicate MRCP recognizer header */
-static apt_bool_t mrcp_recog_header_duplicate(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *src, apr_size_t id, apr_pool_t *pool)
+static apt_bool_t mrcp_recog_header_duplicate(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *src, apr_size_t id, const apt_str_t *value, apr_pool_t *pool)
{
mrcp_recog_header_t *recog_header = accessor->data;
const mrcp_recog_header_t *src_recog_header = src->data;
@@ -506,13 +620,13 @@ static apt_bool_t mrcp_recog_header_duplicate(mrcp_header_accessor_t *accessor,
recog_header->recognition_timeout = src_recog_header->recognition_timeout;
break;
case RECOGNIZER_HEADER_WAVEFORM_URI:
- apt_string_copy(&recog_header->waveform_uri,&src_recog_header->waveform_uri,pool);
+ recog_header->waveform_uri = *value;
break;
case RECOGNIZER_HEADER_COMPLETION_CAUSE:
recog_header->completion_cause = src_recog_header->completion_cause;
break;
case RECOGNIZER_HEADER_RECOGNIZER_CONTEXT_BLOCK:
- apt_string_copy(&recog_header->recognizer_context_block,&src_recog_header->recognizer_context_block,pool);
+ recog_header->recognizer_context_block = *value;
break;
case RECOGNIZER_HEADER_START_INPUT_TIMERS:
recog_header->start_input_timers = src_recog_header->start_input_timers;
@@ -533,10 +647,10 @@ static apt_bool_t mrcp_recog_header_duplicate(mrcp_header_accessor_t *accessor,
recog_header->dtmf_term_char = src_recog_header->dtmf_term_char;
break;
case RECOGNIZER_HEADER_FAILED_URI:
- apt_string_copy(&recog_header->failed_uri,&src_recog_header->failed_uri,pool);
+ recog_header->failed_uri = *value;
break;
case RECOGNIZER_HEADER_FAILED_URI_CAUSE:
- apt_string_copy(&recog_header->failed_uri_cause,&src_recog_header->failed_uri_cause,pool);
+ recog_header->failed_uri_cause = *value;
break;
case RECOGNIZER_HEADER_SAVE_WAVEFORM:
recog_header->save_waveform = src_recog_header->save_waveform;
@@ -545,25 +659,25 @@ static apt_bool_t mrcp_recog_header_duplicate(mrcp_header_accessor_t *accessor,
recog_header->new_audio_channel = src_recog_header->new_audio_channel;
break;
case RECOGNIZER_HEADER_SPEECH_LANGUAGE:
- apt_string_copy(&recog_header->speech_language,&src_recog_header->speech_language,pool);
+ recog_header->speech_language = *value;
break;
case RECOGNIZER_HEADER_INPUT_TYPE:
- apt_string_copy(&recog_header->input_type,&src_recog_header->input_type,pool);
+ recog_header->input_type = *value;
break;
case RECOGNIZER_HEADER_INPUT_WAVEFORM_URI:
- apt_string_copy(&recog_header->input_waveform_uri,&src_recog_header->input_waveform_uri,pool);
+ recog_header->input_waveform_uri = *value;
break;
case RECOGNIZER_HEADER_COMPLETION_REASON:
- apt_string_copy(&recog_header->completion_reason,&src_recog_header->completion_reason,pool);
+ recog_header->completion_reason = *value;
break;
case RECOGNIZER_HEADER_MEDIA_TYPE:
- apt_string_copy(&recog_header->media_type,&src_recog_header->media_type,pool);
+ recog_header->media_type = *value;
break;
case RECOGNIZER_HEADER_VER_BUFFER_UTTERANCE:
recog_header->ver_buffer_utterance = src_recog_header->ver_buffer_utterance;
break;
case RECOGNIZER_HEADER_RECOGNITION_MODE:
- apt_string_copy(&recog_header->recognition_mode,&src_recog_header->recognition_mode,pool);
+ recog_header->recognition_mode = *value;
break;
case RECOGNIZER_HEADER_CANCEL_IF_QUEUE:
recog_header->cancel_if_queue = src_recog_header->cancel_if_queue;
@@ -575,7 +689,7 @@ static apt_bool_t mrcp_recog_header_duplicate(mrcp_header_accessor_t *accessor,
recog_header->hotword_min_duration = src_recog_header->hotword_min_duration;
break;
case RECOGNIZER_HEADER_INTERPRET_TEXT:
- apt_string_copy(&recog_header->interpret_text,&src_recog_header->interpret_text,pool);
+ recog_header->interpret_text = *value;
break;
case RECOGNIZER_HEADER_DTMF_BUFFER_TIME:
recog_header->dtmf_buffer_time = src_recog_header->dtmf_buffer_time;
@@ -586,20 +700,48 @@ static apt_bool_t mrcp_recog_header_duplicate(mrcp_header_accessor_t *accessor,
case RECOGNIZER_HEADER_EARLY_NO_MATCH:
recog_header->early_no_match = src_recog_header->early_no_match;
break;
+ case RECOGNIZER_HEADER_NUM_MIN_CONSISTENT_PRONUNCIATIONS:
+ recog_header->num_min_consistent_pronunciations = src_recog_header->num_min_consistent_pronunciations;
+ break;
+ case RECOGNIZER_HEADER_CONSISTENCY_THRESHOLD:
+ recog_header->consistency_threshold = src_recog_header->consistency_threshold;
+ break;
+ case RECOGNIZER_HEADER_CLASH_THRESHOLD:
+ recog_header->clash_threshold = src_recog_header->clash_threshold;
+ break;
+ case RECOGNIZER_HEADER_PERSONAL_GRAMMAR_URI:
+ recog_header->personal_grammar_uri = *value;
+ break;
+ case RECOGNIZER_HEADER_ENROLL_UTTERANCE:
+ recog_header->enroll_utterance = src_recog_header->enroll_utterance;
+ break;
+ case RECOGNIZER_HEADER_PHRASE_ID:
+ recog_header->phrase_id = *value;
+ break;
+ case RECOGNIZER_HEADER_PHRASE_NL:
+ recog_header->phrase_nl = *value;
+ break;
+ case RECOGNIZER_HEADER_WEIGHT:
+ recog_header->weight = src_recog_header->weight;
+ break;
+ case RECOGNIZER_HEADER_SAVE_BEST_WAVEFORM:
+ recog_header->save_best_waveform = src_recog_header->save_best_waveform;
+ break;
+ case RECOGNIZER_HEADER_NEW_PHRASE_ID:
+ recog_header->new_phrase_id = *value;
+ break;
+ case RECOGNIZER_HEADER_CONFUSABLE_PHRASES_URI:
+ recog_header->confusable_phrases_uri = *value;
+ break;
+ case RECOGNIZER_HEADER_ABORT_PHRASE_ENROLLMENT:
+ recog_header->abort_phrase_enrollment = src_recog_header->abort_phrase_enrollment;
+ break;
default:
status = FALSE;
}
return status;
}
-static APR_INLINE const apt_str_table_item_t* recog_header_string_table_get(mrcp_version_e version)
-{
- if(version == MRCP_VERSION_1) {
- return v1_recog_header_string_table;
- }
- return v2_recog_header_string_table;
-}
-
static const mrcp_header_vtable_t v1_vtable = {
mrcp_recog_header_allocate,
NULL, /* nothing to destroy */
diff --git a/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_resource.c b/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_resource.c
index bf9dc56f3a..108e1f638a 100644
--- a/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_resource.c
+++ b/libs/unimrcp/libs/mrcp/resources/src/mrcp_recog_resource.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_recog_resource.c 1781 2010-09-01 07:33:00Z achaloyan $
*/
#include "mrcp_recog_resource.h"
@@ -22,34 +24,48 @@
static const apt_str_table_item_t v1_recog_method_string_table[] = {
{{"SET-PARAMS", 10},10},
{{"GET-PARAMS", 10},10},
- {{"DEFINE-GRAMMAR", 14},0},
+ {{"DEFINE-GRAMMAR", 14},2},
{{"RECOGNIZE", 9},7},
- {{"GET-RESULT", 10},4},
+ {{"INTERPRET", 9},0},
+ {{"GET-RESULT", 10},6},
{{"RECOGNITION-START-TIMERS", 24},7},
- {{"STOP", 4},1}
+ {{"STOP", 4},2},
+ {{"START-PHRASE-ENROLLMENT", 23},2},
+ {{"ENROLLMENT-ROLLBACK", 19},2},
+ {{"END-PHRASE-ENROLLMENT", 21},5},
+ {{"MODIFY-PHRASE", 13},0},
+ {{"DELETE-PHRASE", 13},2}
};
-/** String table of mrcpv2 recognizer methods (mrcp_recognizer_method_id) */
+/** String table of MRCPv2 recognizer methods (mrcp_recognizer_method_id) */
static const apt_str_table_item_t v2_recog_method_string_table[] = {
{{"SET-PARAMS", 10},10},
{{"GET-PARAMS", 10},10},
- {{"DEFINE-GRAMMAR", 14},0},
- {{"RECOGNIZE", 9},7},
- {{"GET-RESULT", 10},4},
- {{"START-INPUT-TIMERS", 18},2},
- {{"STOP", 4},2}
+ {{"DEFINE-GRAMMAR", 14},2},
+ {{"RECOGNIZE", 9},0},
+ {{"INTERPRET", 9},0},
+ {{"GET-RESULT", 10},6},
+ {{"START-INPUT-TIMERS", 18},7},
+ {{"STOP", 4},2},
+ {{"START-PHRASE-ENROLLMENT", 23},6},
+ {{"ENROLLMENT-ROLLBACK", 19},2},
+ {{"END-PHRASE-ENROLLMENT", 21},5},
+ {{"MODIFY-PHRASE", 13},0},
+ {{"DELETE-PHRASE", 13},2}
};
/** String table of MRCP recognizer events (mrcp_recognizer_event_id) */
static const apt_str_table_item_t v1_recog_event_string_table[] = {
{{"START-OF-SPEECH", 15},0},
- {{"RECOGNITION-COMPLETE", 20},0}
+ {{"RECOGNITION-COMPLETE", 20},0},
+ {{"INTERPRETATION-COMPLETE", 23},0}
};
-/** String table of mrcpv2 recognizer events (mrcp_recognizer_event_id) */
+/** String table of MRCPv2 recognizer events (mrcp_recognizer_event_id) */
static const apt_str_table_item_t v2_recog_event_string_table[] = {
{{"START-OF-INPUT", 14},0},
- {{"RECOGNITION-COMPLETE", 20},0}
+ {{"RECOGNITION-COMPLETE", 20},0},
+ {{"INTERPRETATION-COMPLETE", 23},0}
};
diff --git a/libs/unimrcp/libs/mrcp/resources/src/mrcp_recorder_header.c b/libs/unimrcp/libs/mrcp/resources/src/mrcp_recorder_header.c
index 34902c12c8..fdfea41373 100644
--- a/libs/unimrcp/libs/mrcp/resources/src/mrcp_recorder_header.c
+++ b/libs/unimrcp/libs/mrcp/resources/src/mrcp_recorder_header.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,11 +12,13 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_recorder_header.c 1632 2010-03-30 20:46:25Z achaloyan $
*/
#include "mrcp_recorder_header.h"
-/** String table of recorder headers (mrcp_recorder_header_id) */
+/** String table of recorder header fields (mrcp_recorder_header_id) */
static const apt_str_table_item_t recorder_header_string_table[] = {
{{"Sensitivity-Level", 17},3},
{{"No-Input-Timeout", 16},2},
@@ -90,19 +92,19 @@ static apt_bool_t mrcp_recorder_header_parse(mrcp_header_accessor_t *accessor, a
recorder_header->completion_cause = apt_size_value_parse(value);
break;
case RECORDER_HEADER_COMPLETION_REASON:
- apt_string_copy(&recorder_header->completion_reason,value,pool);
+ recorder_header->completion_reason = *value;
break;
case RECORDER_HEADER_FAILED_URI:
- apt_string_copy(&recorder_header->failed_uri,value,pool);
+ recorder_header->failed_uri = *value;
break;
case RECORDER_HEADER_FAILED_URI_CAUSE:
- apt_string_copy(&recorder_header->failed_uri_cause,value,pool);
+ recorder_header->failed_uri_cause = *value;
break;
case RECORDER_HEADER_RECORD_URI:
- apt_string_copy(&recorder_header->record_uri,value,pool);
+ recorder_header->record_uri = *value;
break;
case RECORDER_HEADER_MEDIA_TYPE:
- apt_string_copy(&recorder_header->media_type,value,pool);
+ recorder_header->media_type = *value;
break;
case RECORDER_HEADER_MAX_TIME:
recorder_header->max_time = apt_size_value_parse(value);
@@ -132,60 +134,61 @@ static apt_bool_t mrcp_recorder_header_parse(mrcp_header_accessor_t *accessor, a
}
/** Generate MRCP recorder header */
-static apt_bool_t mrcp_recorder_header_generate(mrcp_header_accessor_t *accessor, apr_size_t id, apt_text_stream_t *value)
+static apt_bool_t mrcp_recorder_header_generate(const mrcp_header_accessor_t *accessor, apr_size_t id, apt_str_t *value, apr_pool_t *pool)
{
mrcp_recorder_header_t *recorder_header = accessor->data;
switch(id) {
case RECORDER_HEADER_SENSITIVITY_LEVEL:
- apt_float_value_generate(recorder_header->sensitivity_level,value);
+ apt_float_value_generate(recorder_header->sensitivity_level,value,pool);
break;
case RECORDER_HEADER_NO_INPUT_TIMEOUT:
- apt_size_value_generate(recorder_header->no_input_timeout,value);
+ apt_size_value_generate(recorder_header->no_input_timeout,value,pool);
break;
case RECORDER_HEADER_COMPLETION_CAUSE:
{
- mrcp_completion_cause_generate(
+ apt_completion_cause_generate(
completion_cause_string_table,
RECORDER_COMPLETION_CAUSE_COUNT,
recorder_header->completion_cause,
- value);
+ value,
+ pool);
break;
}
case RECORDER_HEADER_COMPLETION_REASON:
- apt_string_value_generate(&recorder_header->completion_reason,value);
+ *value = recorder_header->completion_reason;
break;
case RECORDER_HEADER_FAILED_URI:
- apt_string_value_generate(&recorder_header->failed_uri,value);
+ *value = recorder_header->failed_uri;
break;
case RECORDER_HEADER_FAILED_URI_CAUSE:
- apt_string_value_generate(&recorder_header->failed_uri_cause,value);
+ *value = recorder_header->failed_uri_cause;
break;
case RECORDER_HEADER_RECORD_URI:
- apt_string_value_generate(&recorder_header->record_uri,value);
+ *value = recorder_header->record_uri;
break;
case RECORDER_HEADER_MEDIA_TYPE:
- apt_string_value_generate(&recorder_header->media_type,value);
+ *value = recorder_header->media_type;
break;
case RECORDER_HEADER_MAX_TIME:
- apt_size_value_generate(recorder_header->max_time,value);
+ apt_size_value_generate(recorder_header->max_time,value,pool);
break;
case RECORDER_HEADER_TRIM_LENGTH:
- apt_size_value_generate(recorder_header->trim_length,value);
+ apt_size_value_generate(recorder_header->trim_length,value,pool);
break;
case RECORDER_HEADER_FINAL_SILENCE:
- apt_size_value_generate(recorder_header->final_silence,value);
+ apt_size_value_generate(recorder_header->final_silence,value,pool);
break;
case RECORDER_HEADER_CAPTURE_ON_SPEECH:
- apt_boolean_value_generate(recorder_header->capture_on_speech,value);
+ apt_boolean_value_generate(recorder_header->capture_on_speech,value,pool);
break;
case RECORDER_HEADER_VER_BUFFER_UTTERANCE:
- apt_boolean_value_generate(recorder_header->ver_buffer_utterance,value);
+ apt_boolean_value_generate(recorder_header->ver_buffer_utterance,value,pool);
break;
case RECORDER_HEADER_START_INPUT_TIMERS:
- apt_boolean_value_generate(recorder_header->start_input_timers,value);
+ apt_boolean_value_generate(recorder_header->start_input_timers,value,pool);
break;
case RECORDER_HEADER_NEW_AUDIO_CHANNEL:
- apt_boolean_value_generate(recorder_header->new_audio_channel,value);
+ apt_boolean_value_generate(recorder_header->new_audio_channel,value,pool);
break;
default:
break;
@@ -194,7 +197,7 @@ static apt_bool_t mrcp_recorder_header_generate(mrcp_header_accessor_t *accessor
}
/** Duplicate MRCP recorder header */
-static apt_bool_t mrcp_recorder_header_duplicate(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *src, apr_size_t id, apr_pool_t *pool)
+static apt_bool_t mrcp_recorder_header_duplicate(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *src, apr_size_t id, const apt_str_t *value, apr_pool_t *pool)
{
mrcp_recorder_header_t *recorder_header = accessor->data;
const mrcp_recorder_header_t *src_recorder_header = src->data;
@@ -215,19 +218,19 @@ static apt_bool_t mrcp_recorder_header_duplicate(mrcp_header_accessor_t *accesso
recorder_header->completion_cause = src_recorder_header->completion_cause;
break;
case RECORDER_HEADER_COMPLETION_REASON:
- apt_string_copy(&recorder_header->completion_reason,&src_recorder_header->completion_reason,pool);
+ recorder_header->completion_reason = *value;
break;
case RECORDER_HEADER_FAILED_URI:
- apt_string_copy(&recorder_header->failed_uri,&src_recorder_header->failed_uri,pool);
+ recorder_header->failed_uri = *value;
break;
case RECORDER_HEADER_FAILED_URI_CAUSE:
- apt_string_copy(&recorder_header->failed_uri_cause,&src_recorder_header->failed_uri_cause,pool);
+ recorder_header->failed_uri_cause = *value;
break;
case RECORDER_HEADER_RECORD_URI:
- apt_string_copy(&recorder_header->record_uri,&src_recorder_header->record_uri,pool);
+ recorder_header->record_uri = *value;
break;
case RECORDER_HEADER_MEDIA_TYPE:
- apt_string_copy(&recorder_header->media_type,&src_recorder_header->media_type,pool);
+ recorder_header->media_type = *value;
break;
case RECORDER_HEADER_MAX_TIME:
recorder_header->max_time = src_recorder_header->max_time;
diff --git a/libs/unimrcp/libs/mrcp/resources/src/mrcp_recorder_resource.c b/libs/unimrcp/libs/mrcp/resources/src/mrcp_recorder_resource.c
index edb047c5a9..24254c1a7c 100644
--- a/libs/unimrcp/libs/mrcp/resources/src/mrcp_recorder_resource.c
+++ b/libs/unimrcp/libs/mrcp/resources/src/mrcp_recorder_resource.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_recorder_resource.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "mrcp_recorder_resource.h"
diff --git a/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_header.c b/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_header.c
index 51ec8667c7..45b88087d3 100644
--- a/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_header.c
+++ b/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_header.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,11 +12,13 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_synth_header.c 1632 2010-03-30 20:46:25Z achaloyan $
*/
#include "mrcp_synth_header.h"
-/** String table of MRCP synthesizer headers (mrcp_synthesizer_header_id) */
+/** String table of MRCP synthesizer header fields (mrcp_synthesizer_header_id) */
static const apt_str_table_item_t synth_header_string_table[] = {
{{"Jump-Size", 9},0},
{{"Kill-On-Barge-In", 16},0},
@@ -95,7 +97,7 @@ static APR_INLINE apr_size_t apt_string_table_value_parse(const apt_str_table_it
return apt_string_table_id_find(string_table,count,value);
}
-static apt_bool_t apt_string_table_value_generate(const apt_str_table_item_t *string_table, size_t count, size_t id, apt_text_stream_t *stream)
+static apt_bool_t apt_string_table_value_generate(const apt_str_table_item_t *string_table, apr_size_t count, apr_size_t id, apt_text_stream_t *stream)
{
const apt_str_t *name = apt_string_table_str_get(string_table,count,id);
if(!name) {
@@ -107,6 +109,17 @@ static apt_bool_t apt_string_table_value_generate(const apt_str_table_item_t *st
return TRUE;
}
+static apt_bool_t apt_string_table_value_pgenerate(const apt_str_table_item_t *string_table, apr_size_t count, apr_size_t id, apt_str_t *str, apr_pool_t *pool)
+{
+ const apt_str_t *name = apt_string_table_str_get(string_table,count,id);
+ if(!name) {
+ return FALSE;
+ }
+
+ apt_string_copy(str,name,pool);
+ return TRUE;
+}
+
/** Parse MRCP prosody-rate value */
static apt_bool_t mrcp_prosody_param_rate_parse(mrcp_prosody_rate_t *prosody_rate, const apt_str_t *value, apr_pool_t *pool)
{
@@ -133,13 +146,18 @@ static apt_bool_t mrcp_prosody_param_rate_parse(mrcp_prosody_rate_t *prosody_rat
}
/** Generate MRCP prosody-rate value */
-static apt_bool_t mrcp_prosody_rate_generate(mrcp_prosody_rate_t *prosody_rate, apt_text_stream_t *stream)
+static apt_bool_t mrcp_prosody_rate_generate(mrcp_prosody_rate_t *prosody_rate, apt_str_t *str, apr_pool_t *pool)
{
if(prosody_rate->type == PROSODY_RATE_TYPE_LABEL) {
- apt_string_table_value_generate(prosody_rate_string_table,PROSODY_RATE_COUNT,prosody_rate->value.label,stream);
+ apt_string_table_value_pgenerate(
+ prosody_rate_string_table,
+ PROSODY_RATE_COUNT,
+ prosody_rate->value.label,
+ str,
+ pool);
}
else {
- apt_float_value_generate(prosody_rate->value.relative, stream);
+ apt_float_value_generate(prosody_rate->value.relative,str,pool);
}
return TRUE;
@@ -177,16 +195,21 @@ static apt_bool_t mrcp_prosody_param_volume_parse(mrcp_prosody_volume_t *prosody
}
/** Generate MRCP prosody-volume value */
-static apt_bool_t mrcp_prosody_volume_generate(mrcp_prosody_volume_t *prosody_volume, apt_text_stream_t *stream)
+static apt_bool_t mrcp_prosody_volume_generate(mrcp_prosody_volume_t *prosody_volume, apt_str_t *str, apr_pool_t *pool)
{
if(prosody_volume->type == PROSODY_VOLUME_TYPE_LABEL) {
- apt_string_table_value_generate(prosody_volume_string_table,PROSODY_VOLUME_COUNT,prosody_volume->value.label,stream);
+ apt_string_table_value_pgenerate(
+ prosody_volume_string_table,
+ PROSODY_VOLUME_COUNT,
+ prosody_volume->value.label,
+ str,
+ pool);
}
else if (prosody_volume->type == PROSODY_VOLUME_TYPE_NUMERIC) {
- apt_float_value_generate(prosody_volume->value.numeric, stream);
+ apt_float_value_generate(prosody_volume->value.numeric,str,pool);
}
else {
- apt_float_value_generate(prosody_volume->value.relative, stream);
+ apt_float_value_generate(prosody_volume->value.relative,str,pool);
}
return TRUE;
@@ -229,25 +252,29 @@ static apt_bool_t mrcp_speech_length_value_parse(mrcp_speech_length_value_t *spe
}
/** Generate MRCP speech-length value */
-static apt_bool_t mrcp_speech_length_generate(mrcp_speech_length_value_t *speech_length, apt_text_stream_t *stream)
+static apt_bool_t mrcp_speech_length_generate(mrcp_speech_length_value_t *speech_length, apt_str_t *str, apr_pool_t *pool)
{
if(speech_length->type == SPEECH_LENGTH_TYPE_TEXT) {
apt_str_t *tag = &speech_length->value.tag;
if(tag->length) {
- memcpy(stream->pos,tag->buf,tag->length);
- stream->pos += tag->length;
+ apt_string_copy(str,tag,pool);
}
}
else {
+ char buf[256];
+ apt_text_stream_t stream;
+ apt_text_stream_init(&stream,buf,sizeof(buf));
if(speech_length->type == SPEECH_LENGTH_TYPE_NUMERIC_POSITIVE) {
- *stream->pos++ = '+';
+ *stream.pos++ = '+';
}
else {
- *stream->pos++ = '-';
+ *stream.pos++ = '-';
}
- apt_size_value_generate(speech_length->value.numeric.length,stream);
- *stream->pos++ = ' ';
- apt_string_table_value_generate(speech_unit_string_table,SPEECH_UNIT_COUNT,speech_length->value.numeric.unit,stream);
+ apt_text_size_value_insert(&stream,speech_length->value.numeric.length);
+ *stream.pos++ = APT_TOKEN_SP;
+ apt_string_table_value_generate(speech_unit_string_table,SPEECH_UNIT_COUNT,speech_length->value.numeric.unit,&stream);
+
+ apt_string_assign_n(str,stream.text.buf, stream.pos - stream.text.buf, pool);
}
return TRUE;
}
@@ -301,13 +328,13 @@ static apt_bool_t mrcp_synth_header_parse(mrcp_header_accessor_t *accessor, size
apt_boolean_value_parse(value,&synth_header->kill_on_barge_in);
break;
case SYNTHESIZER_HEADER_SPEAKER_PROFILE:
- apt_string_copy(&synth_header->speaker_profile,value,pool);
+ synth_header->speaker_profile = *value;
break;
case SYNTHESIZER_HEADER_COMPLETION_CAUSE:
synth_header->completion_cause = apt_size_value_parse(value);
break;
case SYNTHESIZER_HEADER_COMPLETION_REASON:
- apt_string_copy(&synth_header->completion_reason,value,pool);
+ synth_header->completion_reason = *value;
break;
case SYNTHESIZER_HEADER_VOICE_GENDER:
synth_header->voice_param.gender = apt_string_table_value_parse(voice_gender_string_table,VOICE_GENDER_COUNT,value);
@@ -319,7 +346,7 @@ static apt_bool_t mrcp_synth_header_parse(mrcp_header_accessor_t *accessor, size
synth_header->voice_param.variant = apt_size_value_parse(value);
break;
case SYNTHESIZER_HEADER_VOICE_NAME:
- apt_string_copy(&synth_header->voice_param.name,value,pool);
+ synth_header->voice_param.name = *value;
break;
case SYNTHESIZER_HEADER_PROSODY_VOLUME:
mrcp_prosody_param_volume_parse(&synth_header->prosody_param.volume,value,pool);
@@ -328,22 +355,22 @@ static apt_bool_t mrcp_synth_header_parse(mrcp_header_accessor_t *accessor, size
mrcp_prosody_param_rate_parse(&synth_header->prosody_param.rate,value,pool);
break;
case SYNTHESIZER_HEADER_SPEECH_MARKER:
- apt_string_copy(&synth_header->speech_marker,value,pool);
+ synth_header->speech_marker = *value;
break;
case SYNTHESIZER_HEADER_SPEECH_LANGUAGE:
- apt_string_copy(&synth_header->speech_language,value,pool);
+ synth_header->speech_language = *value;
break;
case SYNTHESIZER_HEADER_FETCH_HINT:
- apt_string_copy(&synth_header->fetch_hint,value,pool);
+ synth_header->fetch_hint = *value;
break;
case SYNTHESIZER_HEADER_AUDIO_FETCH_HINT:
- apt_string_copy(&synth_header->audio_fetch_hint,value,pool);
+ synth_header->audio_fetch_hint = *value;
break;
case SYNTHESIZER_HEADER_FAILED_URI:
- apt_string_copy(&synth_header->failed_uri,value,pool);
+ synth_header->failed_uri = *value;
break;
case SYNTHESIZER_HEADER_FAILED_URI_CAUSE:
- apt_string_copy(&synth_header->failed_uri_cause,value,pool);
+ synth_header->failed_uri_cause = *value;
break;
case SYNTHESIZER_HEADER_SPEAK_RESTART:
apt_boolean_value_parse(value,&synth_header->speak_restart);
@@ -355,7 +382,7 @@ static apt_bool_t mrcp_synth_header_parse(mrcp_header_accessor_t *accessor, size
apt_boolean_value_parse(value,&synth_header->load_lexicon);
break;
case SYNTHESIZER_HEADER_LEXICON_SEARCH_ORDER:
- apt_string_copy(&synth_header->lexicon_search_order,value,pool);
+ synth_header->lexicon_search_order = *value;
break;
default:
status = FALSE;
@@ -364,76 +391,82 @@ static apt_bool_t mrcp_synth_header_parse(mrcp_header_accessor_t *accessor, size
}
/** Generate MRCP synthesizer header */
-static apt_bool_t mrcp_synth_header_generate(mrcp_header_accessor_t *accessor, size_t id, apt_text_stream_t *value)
+static apt_bool_t mrcp_synth_header_generate(const mrcp_header_accessor_t *accessor, size_t id, apt_str_t *value, apr_pool_t *pool)
{
mrcp_synth_header_t *synth_header = accessor->data;
switch(id) {
case SYNTHESIZER_HEADER_JUMP_SIZE:
- mrcp_speech_length_generate(&synth_header->jump_size,value);
+ mrcp_speech_length_generate(&synth_header->jump_size,value,pool);
break;
case SYNTHESIZER_HEADER_KILL_ON_BARGE_IN:
- apt_boolean_value_generate(synth_header->kill_on_barge_in,value);
+ apt_boolean_value_generate(synth_header->kill_on_barge_in,value,pool);
break;
case SYNTHESIZER_HEADER_SPEAKER_PROFILE:
- apt_string_value_generate(&synth_header->speaker_profile,value);
+ *value = synth_header->speaker_profile,value;
break;
case SYNTHESIZER_HEADER_COMPLETION_CAUSE:
- mrcp_completion_cause_generate(
+ apt_completion_cause_generate(
completion_cause_string_table,
SYNTHESIZER_COMPLETION_CAUSE_COUNT,
synth_header->completion_cause,
- value);
+ value,
+ pool);
break;
case SYNTHESIZER_HEADER_COMPLETION_REASON:
- apt_string_value_generate(&synth_header->completion_reason,value);
+ *value = synth_header->completion_reason;
break;
case SYNTHESIZER_HEADER_VOICE_GENDER:
- apt_string_table_value_generate(voice_gender_string_table,VOICE_GENDER_COUNT,synth_header->voice_param.gender,value);
+ apt_string_table_value_pgenerate(
+ voice_gender_string_table,
+ VOICE_GENDER_COUNT,
+ synth_header->voice_param.gender,
+ value,
+ pool);
break;
case SYNTHESIZER_HEADER_VOICE_AGE:
- apt_size_value_generate(synth_header->voice_param.age,value);
+ apt_size_value_generate(synth_header->voice_param.age,value,pool);
break;
case SYNTHESIZER_HEADER_VOICE_VARIANT:
- apt_size_value_generate(synth_header->voice_param.variant,value);
+ apt_size_value_generate(synth_header->voice_param.variant,value,pool);
break;
case SYNTHESIZER_HEADER_VOICE_NAME:
- apt_string_value_generate(&synth_header->voice_param.name,value);
+ *value = synth_header->voice_param.name,value;
break;
case SYNTHESIZER_HEADER_PROSODY_VOLUME:
- mrcp_prosody_volume_generate(&synth_header->prosody_param.volume,value);
+ mrcp_prosody_volume_generate(&synth_header->prosody_param.volume,value,pool);
break;
case SYNTHESIZER_HEADER_PROSODY_RATE:
- mrcp_prosody_rate_generate(&synth_header->prosody_param.rate,value);
+ mrcp_prosody_rate_generate(&synth_header->prosody_param.rate,value,pool);
break;
case SYNTHESIZER_HEADER_SPEECH_MARKER:
- apt_string_value_generate(&synth_header->speech_marker,value);
+ *value = synth_header->speech_marker;
break;
case SYNTHESIZER_HEADER_SPEECH_LANGUAGE:
- apt_string_value_generate(&synth_header->speech_language,value);
+ *value = synth_header->speech_language;
break;
case SYNTHESIZER_HEADER_FETCH_HINT:
- apt_string_value_generate(&synth_header->fetch_hint,value);
+ *value = synth_header->fetch_hint;
break;
case SYNTHESIZER_HEADER_AUDIO_FETCH_HINT:
- apt_string_value_generate(&synth_header->audio_fetch_hint,value);
+ *value = synth_header->audio_fetch_hint;
break;
case SYNTHESIZER_HEADER_FAILED_URI:
- apt_string_value_generate(&synth_header->failed_uri,value);
+ *value = synth_header->failed_uri;
break;
case SYNTHESIZER_HEADER_FAILED_URI_CAUSE:
- apt_string_value_generate(&synth_header->failed_uri_cause,value);
+ *value = synth_header->failed_uri_cause;
break;
case SYNTHESIZER_HEADER_SPEAK_RESTART:
- apt_boolean_value_generate(synth_header->speak_restart,value);
+ apt_boolean_value_generate(synth_header->speak_restart,value,pool);
break;
case SYNTHESIZER_HEADER_SPEAK_LENGTH:
- mrcp_speech_length_generate(&synth_header->speak_length,value);
+ mrcp_speech_length_generate(&synth_header->speak_length,value,pool);
break;
case SYNTHESIZER_HEADER_LOAD_LEXICON:
- apt_boolean_value_generate(synth_header->load_lexicon,value);
+ apt_boolean_value_generate(synth_header->load_lexicon,value,pool);
break;
case SYNTHESIZER_HEADER_LEXICON_SEARCH_ORDER:
- apt_string_value_generate(&synth_header->lexicon_search_order,value);
+ *value = synth_header->lexicon_search_order;
break;
default:
break;
@@ -442,7 +475,7 @@ static apt_bool_t mrcp_synth_header_generate(mrcp_header_accessor_t *accessor, s
}
/** Duplicate MRCP synthesizer header */
-static apt_bool_t mrcp_synth_header_duplicate(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *src, size_t id, apr_pool_t *pool)
+static apt_bool_t mrcp_synth_header_duplicate(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *src, size_t id, const apt_str_t *value, apr_pool_t *pool)
{
mrcp_synth_header_t *synth_header = accessor->data;
const mrcp_synth_header_t *src_synth_header = src->data;
@@ -460,13 +493,13 @@ static apt_bool_t mrcp_synth_header_duplicate(mrcp_header_accessor_t *accessor,
synth_header->kill_on_barge_in = src_synth_header->kill_on_barge_in;
break;
case SYNTHESIZER_HEADER_SPEAKER_PROFILE:
- apt_string_copy(&synth_header->speaker_profile,&src_synth_header->speaker_profile,pool);
+ synth_header->speaker_profile = *value;
break;
case SYNTHESIZER_HEADER_COMPLETION_CAUSE:
synth_header->completion_cause = src_synth_header->completion_cause;
break;
case SYNTHESIZER_HEADER_COMPLETION_REASON:
- apt_string_copy(&synth_header->completion_reason,&src_synth_header->completion_reason,pool);
+ synth_header->completion_reason = *value;
break;
case SYNTHESIZER_HEADER_VOICE_GENDER:
synth_header->voice_param.gender = src_synth_header->voice_param.gender;
@@ -478,7 +511,7 @@ static apt_bool_t mrcp_synth_header_duplicate(mrcp_header_accessor_t *accessor,
synth_header->voice_param.variant = src_synth_header->voice_param.variant;
break;
case SYNTHESIZER_HEADER_VOICE_NAME:
- apt_string_copy(&synth_header->voice_param.name,&src_synth_header->voice_param.name,pool);
+ synth_header->voice_param.name = *value;
break;
case SYNTHESIZER_HEADER_PROSODY_VOLUME:
synth_header->prosody_param.volume = src_synth_header->prosody_param.volume;
@@ -487,22 +520,22 @@ static apt_bool_t mrcp_synth_header_duplicate(mrcp_header_accessor_t *accessor,
synth_header->prosody_param.rate = src_synth_header->prosody_param.rate;
break;
case SYNTHESIZER_HEADER_SPEECH_MARKER:
- apt_string_copy(&synth_header->speech_marker,&src_synth_header->speech_marker,pool);
+ synth_header->speech_marker = *value;
break;
case SYNTHESIZER_HEADER_SPEECH_LANGUAGE:
- apt_string_copy(&synth_header->speech_language,&src_synth_header->speech_language,pool);
+ synth_header->speech_language = *value;
break;
case SYNTHESIZER_HEADER_FETCH_HINT:
- apt_string_copy(&synth_header->fetch_hint,&src_synth_header->fetch_hint,pool);
+ synth_header->fetch_hint = *value;
break;
case SYNTHESIZER_HEADER_AUDIO_FETCH_HINT:
- apt_string_copy(&synth_header->audio_fetch_hint,&src_synth_header->audio_fetch_hint,pool);
+ synth_header->audio_fetch_hint = *value;
break;
case SYNTHESIZER_HEADER_FAILED_URI:
- apt_string_copy(&synth_header->failed_uri,&src_synth_header->failed_uri,pool);
+ synth_header->failed_uri = *value;
break;
case SYNTHESIZER_HEADER_FAILED_URI_CAUSE:
- apt_string_copy(&synth_header->failed_uri_cause,&src_synth_header->failed_uri_cause,pool);
+ synth_header->failed_uri_cause = *value;
break;
case SYNTHESIZER_HEADER_SPEAK_RESTART:
synth_header->speak_restart = src_synth_header->speak_restart;
@@ -514,7 +547,7 @@ static apt_bool_t mrcp_synth_header_duplicate(mrcp_header_accessor_t *accessor,
synth_header->load_lexicon = src_synth_header->load_lexicon;
break;
case SYNTHESIZER_HEADER_LEXICON_SEARCH_ORDER:
- apt_string_copy(&synth_header->lexicon_search_order,&src_synth_header->lexicon_search_order,pool);
+ synth_header->lexicon_search_order = *value;
break;
default:
status = FALSE;
diff --git a/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_resource.c b/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_resource.c
index 702af0a6e5..fb17ce67e1 100644
--- a/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_resource.c
+++ b/libs/unimrcp/libs/mrcp/resources/src/mrcp_synth_resource.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_synth_resource.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "mrcp_synth_resource.h"
diff --git a/libs/unimrcp/libs/mrcp/resources/src/mrcp_verifier_header.c b/libs/unimrcp/libs/mrcp/resources/src/mrcp_verifier_header.c
new file mode 100644
index 0000000000..9a15924b43
--- /dev/null
+++ b/libs/unimrcp/libs/mrcp/resources/src/mrcp_verifier_header.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id:
+ */
+
+#include "mrcp_verifier_header.h"
+
+/** String table of MRCP verifier header fields (mrcp_verifier_header_id) */
+static const apt_str_table_item_t verifier_header_string_table[] = {
+ {{"Repository-URI", 14},0},
+ {{"Voiceprint-Identifier", 21},12},
+ {{"Verification-Mode", 17},6},
+ {{"Adapt-Model", 11},1},
+ {{"Abort-Model", 11},11},
+ {{"Min-Verification-Score", 22},1},
+ {{"Num-Min-Verification-Phrases",28},6},
+ {{"Num-Max-Verification-Phrases",28},5},
+ {{"No-Input-Timeout", 16},2},
+ {{"Save-Waveform", 13},4},
+ {{"Media-Type", 10},2},
+ {{"Waveform-URI", 12},0},
+ {{"Voiceprint-Exists", 17},11},
+ {{"Ver-Buffer-Utterance", 20},4},
+ {{"Input-Waveform-URI", 18},0},
+ {{"Completion-Cause", 16},11},
+ {{"Completion-Reason", 17},15},
+ {{"Speech-Complete-Timeout", 23},1},
+ {{"New-Audio-Channel", 17},2},
+ {{"Abort-Verification", 18},6},
+ {{"Start-Input-Timers", 18},1}
+};
+
+/** String table of MRCP verifier completion-cause fields (mrcp_verifier_completion_cause_e) */
+static const apt_str_table_item_t completion_cause_string_table[] = {
+ {{"success", 7},2},
+ {{"error", 5},0},
+ {{"no-input-timeout", 16},0},
+ {{"too-much-speech-timeout",23},0},
+ {{"speech-too-early", 16},9},
+ {{"buffer-empty", 12},0},
+ {{"out-of-sequence", 15},0},
+ {{"repository-uri-failure", 22},15},
+ {{"repository-uri-missing", 22},15},
+ {{"voiceprint-id-missing", 21},14},
+ {{"voiceprint-id-not-exist",23},14},
+ {{"speech-not-usable", 17},7}
+};
+
+
+/** Initialize verifier header */
+static void mrcp_verifier_header_init(mrcp_verifier_header_t *verifier_header)
+{
+ apt_string_reset(&verifier_header->repository_uri);
+ apt_string_reset(&verifier_header->voiceprint_identifier);
+ apt_string_reset(&verifier_header->verification_mode);
+ verifier_header->adapt_model = FALSE;
+ verifier_header->abort_model = FALSE;
+ verifier_header->min_verification_score = 0.0;
+ verifier_header->num_min_verification_phrases = 0;
+ verifier_header->num_max_verification_phrases = 0;
+ verifier_header->no_input_timeout = 0;
+ verifier_header->save_waveform = FALSE;
+ apt_string_reset(&verifier_header->media_type);
+ apt_string_reset(&verifier_header->waveform_uri);
+ verifier_header->voiceprint_exists = FALSE;
+ verifier_header->ver_buffer_utterance = FALSE;
+ apt_string_reset(&verifier_header->input_waveform_uri);
+ verifier_header->completion_cause = VERIFIER_COMPLETION_CAUSE_UNKNOWN;
+ apt_string_reset(&verifier_header->completion_reason);
+ verifier_header->speech_complete_timeout = 0;
+ verifier_header->new_audio_channel = FALSE;
+ verifier_header->abort_verification = FALSE;
+ verifier_header->start_input_timers = FALSE;
+}
+
+/** Allocate MRCP verifier header */
+static void* mrcp_verifier_header_allocate(mrcp_header_accessor_t *accessor, apr_pool_t *pool)
+{
+ mrcp_verifier_header_t *verifier_header = apr_palloc(pool,sizeof(mrcp_verifier_header_t));
+ mrcp_verifier_header_init(verifier_header);
+ accessor->data = verifier_header;
+ return accessor->data;
+}
+
+/** Parse MRCP verifier header */
+static apt_bool_t mrcp_verifier_header_parse(mrcp_header_accessor_t *accessor, apr_size_t id, const apt_str_t *value, apr_pool_t *pool)
+{
+ mrcp_verifier_header_t *verifier_header = accessor->data;
+ apt_bool_t status = TRUE;
+ switch(id) {
+ case VERIFIER_HEADER_REPOSITORY_URI:
+ verifier_header->repository_uri = *value;
+ break;
+ case VERIFIER_HEADER_VOICEPRINT_IDENTIFIER:
+ verifier_header->voiceprint_identifier = *value;
+ break;
+ case VERIFIER_HEADER_VERIFICATION_MODE:
+ verifier_header->verification_mode = *value;
+ break;
+ case VERIFIER_HEADER_ADAPT_MODEL:
+ apt_boolean_value_parse(value,&verifier_header->adapt_model);
+ break;
+ case VERIFIER_HEADER_ABORT_MODEL:
+ apt_boolean_value_parse(value,&verifier_header->abort_model);
+ break;
+ case VERIFIER_HEADER_MIN_VERIFICATION_SCORE:
+ verifier_header->min_verification_score = apt_float_value_parse(value);
+ break;
+ case VERIFIER_HEADER_NUM_MIN_VERIFICATION_PHRASES:
+ verifier_header->num_min_verification_phrases = apt_size_value_parse(value);
+ break;
+ case VERIFIER_HEADER_NUM_MAX_VERIFICATION_PHRASES:
+ verifier_header->num_max_verification_phrases = apt_size_value_parse(value);
+ break;
+ case VERIFIER_HEADER_NO_INPUT_TIMEOUT:
+ verifier_header->no_input_timeout = apt_size_value_parse(value);
+ break;
+ case VERIFIER_HEADER_SAVE_WAVEFORM:
+ apt_boolean_value_parse(value,&verifier_header->save_waveform);
+ break;
+ case VERIFIER_HEADER_MEDIA_TYPE:
+ verifier_header->media_type = *value;
+ break;
+ case VERIFIER_HEADER_WAVEFORM_URI:
+ verifier_header->waveform_uri = *value;
+ break;
+ case VERIFIER_HEADER_VOICEPRINT_EXISTS:
+ apt_boolean_value_parse(value,&verifier_header->voiceprint_exists);
+ break;
+ case VERIFIER_HEADER_VER_BUFFER_UTTERANCE:
+ apt_boolean_value_parse(value,&verifier_header->ver_buffer_utterance);
+ break;
+ case VERIFIER_HEADER_INPUT_WAVEFORM_URI:
+ verifier_header->input_waveform_uri = *value;
+ break;
+ case VERIFIER_HEADER_COMPLETION_CAUSE:
+ verifier_header->completion_cause = apt_size_value_parse(value);
+ break;
+ case VERIFIER_HEADER_COMPLETION_REASON:
+ verifier_header->completion_reason = *value;
+ break;
+ case VERIFIER_HEADER_SPEECH_COMPLETE_TIMEOUT:
+ verifier_header->speech_complete_timeout = apt_size_value_parse(value);
+ break;
+ case VERIFIER_HEADER_NEW_AUDIO_CHANNEL:
+ apt_boolean_value_parse(value,&verifier_header->new_audio_channel);
+ break;
+ case VERIFIER_HEADER_ABORT_VERIFICATION:
+ apt_boolean_value_parse(value,&verifier_header->abort_verification);
+ break;
+ case VERIFIER_HEADER_START_INPUT_TIMERS:
+ apt_boolean_value_parse(value,&verifier_header->start_input_timers);
+ break;
+ default:
+ status = FALSE;
+ }
+ return status;
+}
+
+/** Generate MRCP verifier header */
+static apt_bool_t mrcp_verifier_header_generate(const mrcp_header_accessor_t *accessor, apr_size_t id, apt_str_t *value, apr_pool_t *pool)
+{
+ mrcp_verifier_header_t *verifier_header = accessor->data;
+ switch(id) {
+ case VERIFIER_HEADER_REPOSITORY_URI:
+ *value = verifier_header->repository_uri;
+ break;
+ case VERIFIER_HEADER_VOICEPRINT_IDENTIFIER:
+ *value = verifier_header->voiceprint_identifier;
+ break;
+ case VERIFIER_HEADER_VERIFICATION_MODE:
+ *value = verifier_header->verification_mode;
+ break;
+ case VERIFIER_HEADER_ADAPT_MODEL:
+ apt_boolean_value_generate(verifier_header->adapt_model,value,pool);
+ break;
+ case VERIFIER_HEADER_ABORT_MODEL:
+ apt_boolean_value_generate(verifier_header->abort_model,value,pool);
+ break;
+ case VERIFIER_HEADER_MIN_VERIFICATION_SCORE:
+ apt_float_value_generate(verifier_header->min_verification_score,value,pool);
+ break;
+ case VERIFIER_HEADER_NUM_MIN_VERIFICATION_PHRASES:
+ apt_size_value_generate(verifier_header->num_min_verification_phrases,value,pool);
+ break;
+ case VERIFIER_HEADER_NUM_MAX_VERIFICATION_PHRASES:
+ apt_size_value_generate(verifier_header->num_max_verification_phrases,value,pool);
+ break;
+ case VERIFIER_HEADER_NO_INPUT_TIMEOUT:
+ apt_size_value_generate(verifier_header->no_input_timeout,value,pool);
+ break;
+ case VERIFIER_HEADER_SAVE_WAVEFORM:
+ apt_boolean_value_generate(verifier_header->save_waveform,value,pool);
+ break;
+ case VERIFIER_HEADER_MEDIA_TYPE:
+ *value = verifier_header->media_type;
+ break;
+ case VERIFIER_HEADER_WAVEFORM_URI:
+ *value = verifier_header->waveform_uri;
+ break;
+ case VERIFIER_HEADER_VOICEPRINT_EXISTS:
+ apt_boolean_value_generate(verifier_header->voiceprint_exists,value,pool);
+ break;
+ case VERIFIER_HEADER_VER_BUFFER_UTTERANCE:
+ apt_boolean_value_generate(verifier_header->ver_buffer_utterance,value,pool);
+ break;
+ case VERIFIER_HEADER_INPUT_WAVEFORM_URI:
+ *value = verifier_header->input_waveform_uri;
+ break;
+ case VERIFIER_HEADER_COMPLETION_CAUSE:
+ apt_completion_cause_generate(
+ completion_cause_string_table,
+ VERIFIER_COMPLETION_CAUSE_COUNT,
+ verifier_header->completion_cause,
+ value,
+ pool);
+ break;
+ case VERIFIER_HEADER_COMPLETION_REASON:
+ *value = verifier_header->completion_reason;
+ break;
+ case VERIFIER_HEADER_SPEECH_COMPLETE_TIMEOUT:
+ apt_size_value_generate(verifier_header->speech_complete_timeout,value,pool);
+ break;
+ case VERIFIER_HEADER_NEW_AUDIO_CHANNEL:
+ apt_boolean_value_generate(verifier_header->new_audio_channel,value,pool);
+ break;
+ case VERIFIER_HEADER_ABORT_VERIFICATION:
+ apt_boolean_value_generate(verifier_header->abort_verification,value,pool);
+ break;
+ case VERIFIER_HEADER_START_INPUT_TIMERS:
+ apt_boolean_value_generate(verifier_header->start_input_timers,value,pool);
+ break;
+ default:
+ break;
+ }
+ return TRUE;
+}
+
+/** Duplicate MRCP verifier header */
+static apt_bool_t mrcp_verifier_header_duplicate(mrcp_header_accessor_t *accessor, const mrcp_header_accessor_t *src, apr_size_t id, const apt_str_t *value, apr_pool_t *pool)
+{
+ mrcp_verifier_header_t *verifier_header = accessor->data;
+ const mrcp_verifier_header_t *src_verifier_header = src->data;
+ apt_bool_t status = TRUE;
+
+ if(!verifier_header || !src_verifier_header) {
+ return FALSE;
+ }
+
+ switch(id) {
+ case VERIFIER_HEADER_REPOSITORY_URI:
+ verifier_header->repository_uri = *value;
+ break;
+ case VERIFIER_HEADER_VOICEPRINT_IDENTIFIER:
+ verifier_header->voiceprint_identifier = *value;
+ break;
+ case VERIFIER_HEADER_VERIFICATION_MODE:
+ verifier_header->verification_mode = *value;
+ break;
+ case VERIFIER_HEADER_ADAPT_MODEL:
+ verifier_header->adapt_model = src_verifier_header->adapt_model;
+ break;
+ case VERIFIER_HEADER_ABORT_MODEL:
+ verifier_header->abort_model = src_verifier_header->abort_model;
+ break;
+ case VERIFIER_HEADER_MIN_VERIFICATION_SCORE:
+ verifier_header->min_verification_score = src_verifier_header->min_verification_score;
+ break;
+ case VERIFIER_HEADER_NUM_MIN_VERIFICATION_PHRASES:
+ verifier_header->num_min_verification_phrases = src_verifier_header->num_min_verification_phrases;
+ break;
+ case VERIFIER_HEADER_NUM_MAX_VERIFICATION_PHRASES:
+ verifier_header->num_max_verification_phrases = src_verifier_header->num_max_verification_phrases;
+ break;
+ case VERIFIER_HEADER_NO_INPUT_TIMEOUT:
+ verifier_header->no_input_timeout = src_verifier_header->no_input_timeout;
+ break;
+ case VERIFIER_HEADER_SAVE_WAVEFORM:
+ verifier_header->save_waveform = src_verifier_header->save_waveform;
+ break;
+ case VERIFIER_HEADER_MEDIA_TYPE:
+ verifier_header->media_type = *value;
+ break;
+ case VERIFIER_HEADER_WAVEFORM_URI:
+ verifier_header->waveform_uri = *value;
+ break;
+ case VERIFIER_HEADER_VOICEPRINT_EXISTS:
+ verifier_header->voiceprint_exists = src_verifier_header->voiceprint_exists;
+ break;
+ case VERIFIER_HEADER_VER_BUFFER_UTTERANCE:
+ verifier_header->ver_buffer_utterance = src_verifier_header->ver_buffer_utterance;
+ break;
+ case VERIFIER_HEADER_INPUT_WAVEFORM_URI:
+ verifier_header->input_waveform_uri = *value;
+ break;
+ case VERIFIER_HEADER_COMPLETION_CAUSE:
+ verifier_header->completion_cause = src_verifier_header->completion_cause;
+ break;
+ case VERIFIER_HEADER_COMPLETION_REASON:
+ verifier_header->completion_reason = *value;
+ break;
+ case VERIFIER_HEADER_SPEECH_COMPLETE_TIMEOUT:
+ verifier_header->speech_complete_timeout = src_verifier_header->speech_complete_timeout;
+ break;
+ case VERIFIER_HEADER_NEW_AUDIO_CHANNEL:
+ verifier_header->new_audio_channel = src_verifier_header->new_audio_channel;
+ break;
+ case VERIFIER_HEADER_ABORT_VERIFICATION:
+ verifier_header->abort_verification = src_verifier_header->abort_verification;
+ break;
+ case VERIFIER_HEADER_START_INPUT_TIMERS:
+ verifier_header->start_input_timers = src_verifier_header->start_input_timers;
+ break;
+ default:
+ status = FALSE;
+ }
+ return status;
+}
+
+static const mrcp_header_vtable_t header_vtable = {
+ mrcp_verifier_header_allocate,
+ NULL, /* nothing to destroy */
+ mrcp_verifier_header_parse,
+ mrcp_verifier_header_generate,
+ mrcp_verifier_header_duplicate,
+ verifier_header_string_table,
+ VERIFIER_HEADER_COUNT
+};
+
+const mrcp_header_vtable_t* mrcp_verifier_header_vtable_get(mrcp_version_e version)
+{
+ return &header_vtable;
+}
+
+MRCP_DECLARE(const apt_str_t*) mrcp_verifier_completion_cause_get(mrcp_verifier_completion_cause_e completion_cause, mrcp_version_e version)
+{
+ const apt_str_table_item_t *table = completion_cause_string_table;
+ return apt_string_table_str_get(table,VERIFIER_COMPLETION_CAUSE_COUNT,completion_cause);
+}
diff --git a/libs/unimrcp/libs/mrcp/resources/src/mrcp_verifier_resource.c b/libs/unimrcp/libs/mrcp/resources/src/mrcp_verifier_resource.c
new file mode 100644
index 0000000000..71d6b28c1f
--- /dev/null
+++ b/libs/unimrcp/libs/mrcp/resources/src/mrcp_verifier_resource.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id:
+ */
+
+#include "mrcp_verifier_resource.h"
+#include "mrcp_verifier_header.h"
+#include "mrcp_resource.h"
+
+/** String table of MRCP verifier methods (mrcp_verifier_method_id) */
+static const apt_str_table_item_t verifier_method_string_table[] = {
+ {{"SET-PARAMS", 10},10},
+ {{"GET-PARAMS", 10},10},
+ {{"START-SESSION", 13},8},
+ {{"END-SESSION", 11},0},
+ {{"QUERY-VOICEPRINT", 16},0},
+ {{"DELETE-VOICEPRINT", 17},0},
+ {{"VERIFY", 6},6},
+ {{"VERIFY-FROM-BUFFER", 18},7},
+ {{"VERIFY-ROLLBACK", 15},7},
+ {{"STOP", 4},2},
+ {{"CLEAR-BUFFER", 12},0},
+ {{"START-INPUT-TIMERS", 18},6},
+ {{"GET-INTERMEDIATE-RESULT",23},4},
+};
+
+/** String table of MRCP verifier events (mrcp_verifier_event_id) */
+static const apt_str_table_item_t verifier_event_string_table[] = {
+ {{"START-OF-INPUT", 14},0},
+ {{"VERIFICATION-COMPLETE",21},0},
+};
+
+static APR_INLINE const apt_str_table_item_t* verifier_method_string_table_get(mrcp_version_e version)
+{
+ return verifier_method_string_table;
+}
+
+static APR_INLINE const apt_str_table_item_t* verifier_event_string_table_get(mrcp_version_e version)
+{
+ return verifier_event_string_table;
+}
+
+
+/** Create MRCP verifier resource */
+MRCP_DECLARE(mrcp_resource_t*) mrcp_verifier_resource_create(apr_pool_t *pool)
+{
+ mrcp_resource_t *resource = mrcp_resource_create(pool);
+
+ resource->method_count = VERIFIER_METHOD_COUNT;
+ resource->event_count = VERIFIER_EVENT_COUNT;
+ resource->get_method_str_table = verifier_method_string_table_get;
+ resource->get_event_str_table = verifier_event_string_table_get;
+ resource->get_resource_header_vtable = mrcp_verifier_header_vtable_get;
+ return resource;
+}
diff --git a/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_client_connection.h b/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_client_connection.h
index 29181692cc..b8e83f5a5d 100644
--- a/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_client_connection.h
+++ b/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_client_connection.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_client_connection.h 1792 2011-01-10 21:08:52Z achaloyan $
*/
-#ifndef __MRCP_CLIENT_CONNECTION_H__
-#define __MRCP_CLIENT_CONNECTION_H__
+#ifndef MRCP_CLIENT_CONNECTION_H
+#define MRCP_CLIENT_CONNECTION_H
/**
* @file mrcp_client_connection.h
@@ -29,12 +31,14 @@ APT_BEGIN_EXTERN_C
/**
* Create connection agent.
+ * @param id the identifier of the agent
* @param max_connection_count the number of max MRCPv2 connections
* @param offer_new_connection the connection establishment policy in o/a
* @param pool the pool to allocate memory from
*/
MRCP_DECLARE(mrcp_connection_agent_t*) mrcp_client_connection_agent_create(
- apr_size_t max_connection_count,
+ const char *id,
+ apr_size_t max_connection_count,
apt_bool_t offer_new_connection,
apr_pool_t *pool);
@@ -74,20 +78,51 @@ MRCP_DECLARE(void) mrcp_client_connection_agent_handler_set(
* @param resource_factory the MRCP resource factory to set
*/
MRCP_DECLARE(void) mrcp_client_connection_resource_factory_set(
- mrcp_connection_agent_t *agent,
- mrcp_resource_factory_t *resource_factory);
+ mrcp_connection_agent_t *agent,
+ const mrcp_resource_factory_t *resource_factory);
+/**
+ * Set rx buffer size.
+ * @param agent the agent to set buffer size for
+ * @param size the size of rx buffer to set
+ */
+MRCP_DECLARE(void) mrcp_client_connection_rx_size_set(
+ mrcp_connection_agent_t *agent,
+ apr_size_t size);
+
+/**
+ * Set tx buffer size.
+ * @param agent the agent to set buffer size for
+ * @param size the size of the rx buffer to set
+ */
+MRCP_DECLARE(void) mrcp_client_connection_tx_size_set(
+ mrcp_connection_agent_t *agent,
+ apr_size_t size);
+/**
+ * Set request timeout.
+ * @param agent the agent to set timeout for
+ * @param timeout the timeout to set
+ */
+MRCP_DECLARE(void) mrcp_client_connection_timeout_set(
+ mrcp_connection_agent_t *agent,
+ apr_size_t timeout);
/**
* Get task.
* @param agent the agent to get task from
*/
-MRCP_DECLARE(apt_task_t*) mrcp_client_connection_agent_task_get(mrcp_connection_agent_t *agent);
+MRCP_DECLARE(apt_task_t*) mrcp_client_connection_agent_task_get(const mrcp_connection_agent_t *agent);
/**
* Get external object.
* @param agent the agent to get object from
*/
-MRCP_DECLARE(void*) mrcp_client_connection_agent_object_get(mrcp_connection_agent_t *agent);
+MRCP_DECLARE(void*) mrcp_client_connection_agent_object_get(const mrcp_connection_agent_t *agent);
+
+/**
+ * Get string identifier.
+ * @param agent the agent to get identifier of
+ */
+MRCP_DECLARE(const char*) mrcp_client_connection_agent_id_get(const mrcp_connection_agent_t *agent);
/**
@@ -96,21 +131,28 @@ MRCP_DECLARE(void*) mrcp_client_connection_agent_object_get(mrcp_connection_agen
* @param obj the external object to associate with the control channel
* @param pool the pool to allocate memory from
*/
-MRCP_DECLARE(mrcp_control_channel_t*) mrcp_client_control_channel_create(mrcp_connection_agent_t *agent, void *obj, apr_pool_t *pool);
+MRCP_DECLARE(mrcp_control_channel_t*) mrcp_client_control_channel_create(
+ mrcp_connection_agent_t *agent,
+ void *obj,
+ apr_pool_t *pool);
/**
* Add MRCPv2 control channel.
* @param channel the control channel to add
* @param descriptor the control descriptor
*/
-MRCP_DECLARE(apt_bool_t) mrcp_client_control_channel_add(mrcp_control_channel_t *channel, mrcp_control_descriptor_t *descriptor);
+MRCP_DECLARE(apt_bool_t) mrcp_client_control_channel_add(
+ mrcp_control_channel_t *channel,
+ mrcp_control_descriptor_t *descriptor);
/**
* Modify MRCPv2 control channel.
* @param channel the control channel to modify
* @param descriptor the control descriptor
*/
-MRCP_DECLARE(apt_bool_t) mrcp_client_control_channel_modify(mrcp_control_channel_t *channel, mrcp_control_descriptor_t *descriptor);
+MRCP_DECLARE(apt_bool_t) mrcp_client_control_channel_modify(
+ mrcp_control_channel_t *channel,
+ mrcp_control_descriptor_t *descriptor);
/**
* Remove MRCPv2 control channel.
@@ -131,7 +173,14 @@ MRCP_DECLARE(apt_bool_t) mrcp_client_control_channel_destroy(mrcp_control_channe
*/
MRCP_DECLARE(apt_bool_t) mrcp_client_control_message_send(mrcp_control_channel_t *channel, mrcp_message_t *message);
+/**
+ * Set the logger object.
+ * @param channel the control channel to set the object for
+ * @param log_obj the object to set
+ */
+MRCP_DECLARE(void) mrcp_client_control_channel_log_obj_set(mrcp_control_channel_t *channel, void *log_obj);
+
APT_END_EXTERN_C
-#endif /*__MRCP_CLIENT_CONNECTION_H__*/
+#endif /* MRCP_CLIENT_CONNECTION_H */
diff --git a/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_connection.h b/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_connection.h
index 82d44ea865..08031c3a55 100644
--- a/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_connection.h
+++ b/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_connection.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_connection.h 1710 2010-05-24 17:36:19Z achaloyan $
*/
-#ifndef __MRCP_CONNECTION_H__
-#define __MRCP_CONNECTION_H__
+#ifndef MRCP_CONNECTION_H
+#define MRCP_CONNECTION_H
/**
* @file mrcp_connection.h
@@ -50,6 +52,9 @@ struct mrcp_connection_t {
apt_str_t remote_ip;
/** String identifier used for traces */
const char *id;
+ /** Transparently dump whatever received/sent on transport layer,
+ if verbose is set to TRUE (default) */
+ apt_bool_t verbose;
/** Reference count */
apr_size_t access_count;
@@ -62,22 +67,24 @@ struct mrcp_connection_t {
apr_hash_t *channel_table;
/** Rx buffer */
- char rx_buffer[MRCP_STREAM_BUFFER_SIZE];
+ char *rx_buffer;
+ /** Rx buffer size */
+ apr_size_t rx_buffer_size;
/** Rx stream */
apt_text_stream_t rx_stream;
/** MRCP parser to parser MRCP messages out of rx stream */
mrcp_parser_t *parser;
/** Tx buffer */
- char tx_buffer[MRCP_STREAM_BUFFER_SIZE];
- /** Tx stream */
- apt_text_stream_t tx_stream;
- /** MRCP generator to generate MRCP messages out of tx stream */
+ char *tx_buffer;
+ /** Tx buffer size */
+ apr_size_t tx_buffer_size;
+ /** MRCP generator to generate MRCP messages into tx stream */
mrcp_generator_t *generator;
};
/** Create MRCP connection. */
-mrcp_connection_t* mrcp_connection_create(void);
+mrcp_connection_t* mrcp_connection_create();
/** Destroy MRCP connection. */
void mrcp_connection_destroy(mrcp_connection_t *connection);
@@ -86,7 +93,7 @@ void mrcp_connection_destroy(mrcp_connection_t *connection);
apt_bool_t mrcp_connection_channel_add(mrcp_connection_t *connection, mrcp_control_channel_t *channel);
/** Find Control Channel by Channel Identifier. */
-mrcp_control_channel_t* mrcp_connection_channel_find(mrcp_connection_t *connection, const apt_str_t *identifier);
+mrcp_control_channel_t* mrcp_connection_channel_find(const mrcp_connection_t *connection, const apt_str_t *identifier);
/** Remove Control Channel from MRCP connection. */
apt_bool_t mrcp_connection_channel_remove(mrcp_connection_t *connection, mrcp_control_channel_t *channel);
@@ -96,4 +103,4 @@ apt_bool_t mrcp_connection_disconnect_raise(mrcp_connection_t *connection, const
APT_END_EXTERN_C
-#endif /*__MRCP_CONNECTION_H__*/
+#endif /* MRCP_CONNECTION_H */
diff --git a/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_connection_types.h b/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_connection_types.h
index c7a02c0419..e61c66cafa 100644
--- a/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_connection_types.h
+++ b/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_connection_types.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_connection_types.h 1792 2011-01-10 21:08:52Z achaloyan $
*/
-#ifndef __MRCP_CONNECTION_TYPES_H__
-#define __MRCP_CONNECTION_TYPES_H__
+#ifndef MRCP_CONNECTION_TYPES_H
+#define MRCP_CONNECTION_TYPES_H
/**
* @file mrcp_connection_types.h
@@ -24,6 +26,7 @@
#include
#include "apt_string.h"
+#include "apt_timer_queue.h"
#include "mrcp_types.h"
APT_BEGIN_EXTERN_C
@@ -63,10 +66,16 @@ struct mrcp_control_channel_t {
mrcp_connection_agent_t *agent;
/** MRCPv2 (shared) connection */
mrcp_connection_t *connection;
+ /** Request sent to the server and waiting for a response */
+ mrcp_message_t *active_request;
+ /** Timer used for request timeouts */
+ apt_timer_t *request_timer;
/** Indicate removed connection (safe to destroy) */
apt_bool_t removed;
/** External object associated with the channel */
void *obj;
+ /** External logger object associated with the channel */
+ void *log_obj;
/** Pool to allocate memory from */
apr_pool_t *pool;
/** Channel identifier (id at resource) */
@@ -125,4 +134,4 @@ static APR_INLINE apt_bool_t mrcp_connection_message_receive(
APT_END_EXTERN_C
-#endif /*__MRCP_CONNECTION_TYPES_H__*/
+#endif /* MRCP_CONNECTION_TYPES_H */
diff --git a/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_control_descriptor.h b/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_control_descriptor.h
index b5dbc44c5f..40535d4b5b 100644
--- a/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_control_descriptor.h
+++ b/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_control_descriptor.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_control_descriptor.h 1710 2010-05-24 17:36:19Z achaloyan $
*/
-#ifndef __MRCP_CONTROL_DESCRIPTOR_H__
-#define __MRCP_CONTROL_DESCRIPTOR_H__
+#ifndef MRCP_CONTROL_DESCRIPTOR_H
+#define MRCP_CONTROL_DESCRIPTOR_H
/**
* @file mrcp_control_descriptor.h
@@ -110,7 +112,7 @@ MRCP_DECLARE(mrcp_control_descriptor_t*) mrcp_control_answer_create(mrcp_control
MRCP_DECLARE(void) mrcp_cmid_add(apr_array_header_t *cmid_arr, apr_size_t cmid);
/** Find cmid in cmid_arr */
-MRCP_DECLARE(apt_bool_t) mrcp_cmid_find(apr_array_header_t *cmid_arr, apr_size_t cmid);
+MRCP_DECLARE(apt_bool_t) mrcp_cmid_find(const apr_array_header_t *cmid_arr, apr_size_t cmid);
/** Get MRCP protocol transport name by identifier */
MRCP_DECLARE(const apt_str_t*) mrcp_proto_get(mrcp_proto_type_e proto);
@@ -142,4 +144,4 @@ MRCP_DECLARE(mrcp_connection_type_e) mrcp_connection_type_find(const apt_str_t *
APT_END_EXTERN_C
-#endif /*__MRCP_CONTROL_DESCRIPTOR_H__*/
+#endif /* MRCP_CONTROL_DESCRIPTOR_H */
diff --git a/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_server_connection.h b/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_server_connection.h
index c72b9c5ef8..a5ee18c1a2 100644
--- a/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_server_connection.h
+++ b/libs/unimrcp/libs/mrcpv2-transport/include/mrcp_server_connection.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_server_connection.h 1721 2010-06-01 05:45:46Z achaloyan $
*/
-#ifndef __MRCP_SERVER_CONNECTION_H__
-#define __MRCP_SERVER_CONNECTION_H__
+#ifndef MRCP_SERVER_CONNECTION_H
+#define MRCP_SERVER_CONNECTION_H
/**
* @file mrcp_server_connection.h
@@ -29,13 +31,15 @@ APT_BEGIN_EXTERN_C
/**
* Create connection agent.
- * @param listen_ip the listen IP address
- * @param listen_port the listen port
+ * @param id the identifier of the engine
+ * @param listen_ip the IP address to listen on
+ * @param listen_port the port to listen on
* @param max_connection_count the number of max MRCPv2 connections
- * @param force_new_connection the connection establishment policy in o/a
+ * @param force_new_connection the policy used in o/a for connection establishment
* @param pool the pool to allocate memory from
*/
MRCP_DECLARE(mrcp_connection_agent_t*) mrcp_server_connection_agent_create(
+ const char *id,
const char *listen_ip,
apr_port_t listen_port,
apr_size_t max_connection_count,
@@ -77,20 +81,44 @@ MRCP_DECLARE(void) mrcp_server_connection_agent_handler_set(
* @param resource_factory the MRCP resource factory to set
*/
MRCP_DECLARE(void) mrcp_server_connection_resource_factory_set(
- mrcp_connection_agent_t *agent,
- mrcp_resource_factory_t *resource_factory);
+ mrcp_connection_agent_t *agent,
+ const mrcp_resource_factory_t *resource_factory);
+
+/**
+ * Set rx buffer size.
+ * @param agent the agent to set buffer size for
+ * @param size the size of rx buffer to set
+ */
+MRCP_DECLARE(void) mrcp_server_connection_rx_size_set(
+ mrcp_connection_agent_t *agent,
+ apr_size_t size);
+
+/**
+ * Set tx buffer size.
+ * @param agent the agent to set buffer size for
+ * @param size the size of the rx buffer to set
+ */
+MRCP_DECLARE(void) mrcp_server_connection_tx_size_set(
+ mrcp_connection_agent_t *agent,
+ apr_size_t size);
/**
* Get task.
* @param agent the agent to get task from
*/
-MRCP_DECLARE(apt_task_t*) mrcp_server_connection_agent_task_get(mrcp_connection_agent_t *agent);
+MRCP_DECLARE(apt_task_t*) mrcp_server_connection_agent_task_get(const mrcp_connection_agent_t *agent);
/**
* Get external object.
* @param agent the agent to get object from
*/
-MRCP_DECLARE(void*) mrcp_server_connection_agent_object_get(mrcp_connection_agent_t *agent);
+MRCP_DECLARE(void*) mrcp_server_connection_agent_object_get(const mrcp_connection_agent_t *agent);
+
+/**
+ * Get string identifier.
+ * @param agent the agent to get identifier of
+ */
+MRCP_DECLARE(const char*) mrcp_server_connection_agent_id_get(const mrcp_connection_agent_t *agent);
/**
@@ -99,21 +127,28 @@ MRCP_DECLARE(void*) mrcp_server_connection_agent_object_get(mrcp_connection_agen
* @param obj the external object to associate with the control channel
* @param pool the pool to allocate memory from
*/
-MRCP_DECLARE(mrcp_control_channel_t*) mrcp_server_control_channel_create(mrcp_connection_agent_t *agent, void *obj, apr_pool_t *pool);
+MRCP_DECLARE(mrcp_control_channel_t*) mrcp_server_control_channel_create(
+ mrcp_connection_agent_t *agent,
+ void *obj,
+ apr_pool_t *pool);
/**
* Add MRCPv2 control channel.
* @param channel the control channel to add
* @param descriptor the control descriptor
*/
-MRCP_DECLARE(apt_bool_t) mrcp_server_control_channel_add(mrcp_control_channel_t *channel, mrcp_control_descriptor_t *descriptor);
+MRCP_DECLARE(apt_bool_t) mrcp_server_control_channel_add(
+ mrcp_control_channel_t *channel,
+ mrcp_control_descriptor_t *descriptor);
/**
* Modify MRCPv2 control channel.
* @param channel the control channel to modify
* @param descriptor the control descriptor
*/
-MRCP_DECLARE(apt_bool_t) mrcp_server_control_channel_modify(mrcp_control_channel_t *channel, mrcp_control_descriptor_t *descriptor);
+MRCP_DECLARE(apt_bool_t) mrcp_server_control_channel_modify(
+ mrcp_control_channel_t *channel,
+ mrcp_control_descriptor_t *descriptor);
/**
* Remove MRCPv2 control channel.
@@ -137,4 +172,4 @@ MRCP_DECLARE(apt_bool_t) mrcp_server_control_message_send(mrcp_control_channel_t
APT_END_EXTERN_C
-#endif /*__MRCP_SERVER_CONNECTION_H__*/
+#endif /* MRCP_SERVER_CONNECTION_H */
diff --git a/libs/unimrcp/libs/mrcpv2-transport/mrcpv2transport.2008.vcproj b/libs/unimrcp/libs/mrcpv2-transport/mrcpv2transport.2008.vcproj
deleted file mode 100644
index 87ed8335a3..0000000000
--- a/libs/unimrcp/libs/mrcpv2-transport/mrcpv2transport.2008.vcproj
+++ /dev/null
@@ -1,301 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/libs/mrcpv2-transport/mrcpv2transport.2010.vcxproj b/libs/unimrcp/libs/mrcpv2-transport/mrcpv2transport.2010.vcxproj
deleted file mode 100644
index 33ed618305..0000000000
--- a/libs/unimrcp/libs/mrcpv2-transport/mrcpv2transport.2010.vcxproj
+++ /dev/null
@@ -1,124 +0,0 @@
-
-
-
-
- Debug
- Win32
-
-
- Debug
- x64
-
-
- Release
- Win32
-
-
- Release
- x64
-
-
-
- mrcpv2transport
- {A9EDAC04-6A5F-4BA7-BC0D-CCE7B255B6EA}
- mrcpv2transport
- Win32Proj
-
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
-
-
-
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;%(PreprocessorDefinitions)
- ProgramDatabase
-
-
-
-
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/libs/mrcpv2-transport/mrcpv2transport.2010.vcxproj.filters b/libs/unimrcp/libs/mrcpv2-transport/mrcpv2transport.2010.vcxproj.filters
deleted file mode 100644
index 452f77e19d..0000000000
--- a/libs/unimrcp/libs/mrcpv2-transport/mrcpv2transport.2010.vcxproj.filters
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hpp;hxx;hm;inl;inc;xsd
-
-
- {a92d3b8c-d54d-416c-b458-dc57ac24d2e9}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_client_connection.c b/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_client_connection.c
index 94b25bad26..5d67271fa8 100644
--- a/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_client_connection.c
+++ b/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_client_connection.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_client_connection.c 1792 2011-01-10 21:08:52Z achaloyan $
*/
#include "mrcp_connection.h"
@@ -20,27 +22,21 @@
#include "mrcp_resource_factory.h"
#include "mrcp_message.h"
#include "apt_text_stream.h"
-#include "apt_task.h"
-#include "apt_pollset.h"
-#include "apt_cyclic_queue.h"
+#include "apt_poller_task.h"
#include "apt_log.h"
-#define MRCPV2_CONNECTION_TASK_NAME "TCP/MRCPv2 Connection Agent"
struct mrcp_connection_agent_t {
- apr_pool_t *pool;
- apt_task_t *task;
+ apr_pool_t *pool;
+ apt_poller_task_t *task;
+ const mrcp_resource_factory_t *resource_factory;
- mrcp_resource_factory_t *resource_factory;
+ apt_obj_list_t *connection_list;
- apt_obj_list_t *connection_list;
-
- apt_bool_t offer_new_connection;
- apr_size_t max_connection_count;
-
- apr_thread_mutex_t *guard;
- apt_cyclic_queue_t *msg_queue;
- apt_pollset_t *pollset;
+ apr_uint32_t request_timeout;
+ apt_bool_t offer_new_connection;
+ apr_size_t tx_buffer_size;
+ apr_size_t rx_buffer_size;
void *obj;
const mrcp_connection_event_vtable_t *vtable;
@@ -50,8 +46,7 @@ typedef enum {
CONNECTION_TASK_MSG_ADD_CHANNEL,
CONNECTION_TASK_MSG_MODIFY_CHANNEL,
CONNECTION_TASK_MSG_REMOVE_CHANNEL,
- CONNECTION_TASK_MSG_SEND_MESSAGE,
- CONNECTION_TASK_MSG_TERMINATE
+ CONNECTION_TASK_MSG_SEND_MESSAGE
} connection_task_msg_type_e;
typedef struct connection_task_msg_t connection_task_msg_t;
@@ -64,79 +59,75 @@ struct connection_task_msg_t {
};
-static apt_bool_t mrcp_client_agent_task_run(apt_task_t *task);
-static apt_bool_t mrcp_client_agent_task_terminate(apt_task_t *task);
-static apt_bool_t mrcp_client_agent_task_on_destroy(apt_task_t *task);
+static apt_bool_t mrcp_client_agent_msg_process(apt_task_t *task, apt_task_msg_t *task_msg);
+static apt_bool_t mrcp_client_poller_signal_process(void *obj, const apr_pollfd_t *descriptor);
+static void mrcp_client_timer_proc(apt_timer_t *timer, void *obj);
/** Create connection agent. */
MRCP_DECLARE(mrcp_connection_agent_t*) mrcp_client_connection_agent_create(
+ const char *id,
apr_size_t max_connection_count,
apt_bool_t offer_new_connection,
apr_pool_t *pool)
{
+ apt_task_t *task;
apt_task_vtable_t *vtable;
+ apt_task_msg_pool_t *msg_pool;
mrcp_connection_agent_t *agent;
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create "MRCPV2_CONNECTION_TASK_NAME" [%"APR_SIZE_T_FMT"]",max_connection_count);
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create MRCPv2 Agent [%s] [%"APR_SIZE_T_FMT"]",
+ id, max_connection_count);
agent = apr_palloc(pool,sizeof(mrcp_connection_agent_t));
agent->pool = pool;
- agent->pollset = NULL;
- agent->max_connection_count = max_connection_count;
+ agent->request_timeout = 0;
agent->offer_new_connection = offer_new_connection;
+ agent->rx_buffer_size = MRCP_STREAM_BUFFER_SIZE;
+ agent->tx_buffer_size = MRCP_STREAM_BUFFER_SIZE;
- agent->task = apt_task_create(agent,NULL,pool);
+ msg_pool = apt_task_msg_pool_create_dynamic(sizeof(connection_task_msg_t),pool);
+
+ agent->task = apt_poller_task_create(
+ max_connection_count,
+ mrcp_client_poller_signal_process,
+ agent,
+ msg_pool,
+ pool);
if(!agent->task) {
return NULL;
}
- apt_task_name_set(agent->task,MRCPV2_CONNECTION_TASK_NAME);
- vtable = apt_task_vtable_get(agent->task);
- if(vtable) {
- vtable->run = mrcp_client_agent_task_run;
- vtable->terminate = mrcp_client_agent_task_terminate;
- vtable->destroy = mrcp_client_agent_task_on_destroy;
+ task = apt_poller_task_base_get(agent->task);
+ if(task) {
+ apt_task_name_set(task,id);
+ }
+
+ vtable = apt_poller_task_vtable_get(agent->task);
+ if(vtable) {
+ vtable->process_msg = mrcp_client_agent_msg_process;
}
- apt_task_auto_ready_set(agent->task,FALSE);
agent->connection_list = apt_list_create(pool);
-
- agent->msg_queue = apt_cyclic_queue_create(CYCLIC_QUEUE_DEFAULT_SIZE);
- apr_thread_mutex_create(&agent->guard,APR_THREAD_MUTEX_UNNESTED,pool);
return agent;
}
-/** Virtual destroy handler. */
-static apt_bool_t mrcp_client_agent_task_on_destroy(apt_task_t *task)
-{
- mrcp_connection_agent_t *agent = apt_task_object_get(task);
- if(agent->guard) {
- apr_thread_mutex_destroy(agent->guard);
- agent->guard = NULL;
- }
- if(agent->msg_queue) {
- apt_cyclic_queue_destroy(agent->msg_queue);
- agent->msg_queue = NULL;
- }
- return TRUE;
-}
-
/** Destroy connection agent. */
MRCP_DECLARE(apt_bool_t) mrcp_client_connection_agent_destroy(mrcp_connection_agent_t *agent)
{
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Destroy MRCPv2 Agent");
- return apt_task_destroy(agent->task);
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Destroy MRCPv2 Agent [%s]",
+ mrcp_client_connection_agent_id_get(agent));
+ return apt_poller_task_destroy(agent->task);
}
/** Start connection agent. */
MRCP_DECLARE(apt_bool_t) mrcp_client_connection_agent_start(mrcp_connection_agent_t *agent)
{
- return apt_task_start(agent->task);
+ return apt_poller_task_start(agent->task);
}
/** Terminate connection agent. */
MRCP_DECLARE(apt_bool_t) mrcp_client_connection_agent_terminate(mrcp_connection_agent_t *agent)
{
- return apt_task_terminate(agent->task,TRUE);
+ return apt_poller_task_terminate(agent->task);
}
/** Set connection event handler. */
@@ -151,24 +142,61 @@ MRCP_DECLARE(void) mrcp_client_connection_agent_handler_set(
/** Set MRCP resource factory */
MRCP_DECLARE(void) mrcp_client_connection_resource_factory_set(
- mrcp_connection_agent_t *agent,
- mrcp_resource_factory_t *resource_factroy)
+ mrcp_connection_agent_t *agent,
+ const mrcp_resource_factory_t *resource_factroy)
{
agent->resource_factory = resource_factroy;
}
-/** Get task */
-MRCP_DECLARE(apt_task_t*) mrcp_client_connection_agent_task_get(mrcp_connection_agent_t *agent)
+/** Set rx buffer size */
+MRCP_DECLARE(void) mrcp_client_connection_rx_size_set(
+ mrcp_connection_agent_t *agent,
+ apr_size_t size)
{
- return agent->task;
+ if(size < MRCP_STREAM_BUFFER_SIZE) {
+ size = MRCP_STREAM_BUFFER_SIZE;
+ }
+ agent->rx_buffer_size = size;
+}
+
+/** Set tx buffer size */
+MRCP_DECLARE(void) mrcp_client_connection_tx_size_set(
+ mrcp_connection_agent_t *agent,
+ apr_size_t size)
+{
+ if(size < MRCP_STREAM_BUFFER_SIZE) {
+ size = MRCP_STREAM_BUFFER_SIZE;
+ }
+ agent->tx_buffer_size = size;
+}
+
+/** Set request timeout */
+MRCP_DECLARE(void) mrcp_client_connection_timeout_set(
+ mrcp_connection_agent_t *agent,
+ apr_size_t timeout)
+{
+ agent->request_timeout = (apr_uint32_t)timeout;
+}
+
+/** Get task */
+MRCP_DECLARE(apt_task_t*) mrcp_client_connection_agent_task_get(const mrcp_connection_agent_t *agent)
+{
+ return apt_poller_task_base_get(agent->task);
}
/** Get external object */
-MRCP_DECLARE(void*) mrcp_client_connection_agent_object_get(mrcp_connection_agent_t *agent)
+MRCP_DECLARE(void*) mrcp_client_connection_agent_object_get(const mrcp_connection_agent_t *agent)
{
return agent->obj;
}
+/** Get string identifier */
+MRCP_DECLARE(const char*) mrcp_client_connection_agent_id_get(const mrcp_connection_agent_t *agent)
+{
+ apt_task_t *task = apt_poller_task_base_get(agent->task);
+ return apt_task_name_get(task);
+}
+
/** Create control channel */
MRCP_DECLARE(mrcp_control_channel_t*) mrcp_client_control_channel_create(mrcp_connection_agent_t *agent, void *obj, apr_pool_t *pool)
@@ -176,12 +204,27 @@ MRCP_DECLARE(mrcp_control_channel_t*) mrcp_client_control_channel_create(mrcp_co
mrcp_control_channel_t *channel = apr_palloc(pool,sizeof(mrcp_control_channel_t));
channel->agent = agent;
channel->connection = NULL;
+ channel->active_request = NULL;
+ channel->request_timer = NULL;
channel->removed = FALSE;
channel->obj = obj;
+ channel->log_obj = NULL;
channel->pool = pool;
+
+ channel->request_timer = apt_poller_task_timer_create(
+ agent->task,
+ mrcp_client_timer_proc,
+ channel,
+ pool);
return channel;
}
+/** Set the logger object */
+MRCP_DECLARE(void) mrcp_client_control_channel_log_obj_set(mrcp_control_channel_t *channel, void *log_obj)
+{
+ channel->log_obj = log_obj;
+}
+
/** Destroy MRCPv2 control channel */
MRCP_DECLARE(apt_bool_t) mrcp_client_control_channel_destroy(mrcp_control_channel_t *channel)
{
@@ -194,6 +237,7 @@ MRCP_DECLARE(apt_bool_t) mrcp_client_control_channel_destroy(mrcp_control_channe
return TRUE;
}
+/** Signal task message */
static apt_bool_t mrcp_client_control_message_signal(
connection_task_msg_type_e type,
mrcp_connection_agent_t *agent,
@@ -201,22 +245,18 @@ static apt_bool_t mrcp_client_control_message_signal(
mrcp_control_descriptor_t *descriptor,
mrcp_message_t *message)
{
- apt_bool_t status;
- connection_task_msg_t *msg = apr_palloc(channel->pool,sizeof(connection_task_msg_t));
- msg->type = type;
- msg->agent = agent;
- msg->channel = channel;
- msg->descriptor = descriptor;
- msg->message = message;
-
- apr_thread_mutex_lock(agent->guard);
- status = apt_cyclic_queue_push(agent->msg_queue,msg);
- apr_thread_mutex_unlock(agent->guard);
- if(apt_pollset_wakeup(agent->pollset) != TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Signal Control Message");
- status = FALSE;
+ apt_task_t *task = apt_poller_task_base_get(agent->task);
+ apt_task_msg_t *task_msg = apt_task_msg_get(task);
+ if(task_msg) {
+ connection_task_msg_t *msg = (connection_task_msg_t*)task_msg->data;
+ msg->type = type;
+ msg->agent = agent;
+ msg->channel = channel;
+ msg->descriptor = descriptor;
+ msg->message = message;
+ apt_task_msg_signal(task,task_msg);
}
- return status;
+ return TRUE;
}
/** Add MRCPv2 control channel */
@@ -247,6 +287,7 @@ static mrcp_connection_t* mrcp_client_agent_connection_create(mrcp_connection_ag
{
char *local_ip = NULL;
char *remote_ip = NULL;
+ apt_pollset_t *pollset = apt_poller_task_pollset_get(agent->task);
mrcp_connection_t *connection = mrcp_connection_create();
apr_sockaddr_info_get(&connection->r_sockaddr,descriptor->ip.buf,APR_INET,descriptor->port,0,connection->pool);
@@ -287,7 +328,8 @@ static mrcp_connection_t* mrcp_client_agent_connection_create(mrcp_connection_ag
connection->sock_pfd.reqevents = APR_POLLIN;
connection->sock_pfd.desc.s = connection->sock;
connection->sock_pfd.client_data = connection;
- if(apt_pollset_add(agent->pollset, &connection->sock_pfd) != TRUE) {
+ if(apt_pollset_add(pollset, &connection->sock_pfd) != TRUE) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Add to Pollset %s",connection->id);
apr_socket_close(connection->sock);
mrcp_connection_destroy(connection);
return NULL;
@@ -296,8 +338,23 @@ static mrcp_connection_t* mrcp_client_agent_connection_create(mrcp_connection_ag
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Established TCP/MRCPv2 Connection %s",connection->id);
connection->agent = agent;
connection->it = apt_list_push_back(agent->connection_list,connection,connection->pool);
+
connection->parser = mrcp_parser_create(agent->resource_factory,connection->pool);
connection->generator = mrcp_generator_create(agent->resource_factory,connection->pool);
+
+ connection->tx_buffer_size = agent->tx_buffer_size;
+ connection->tx_buffer = apr_palloc(connection->pool,connection->tx_buffer_size+1);
+
+ connection->rx_buffer_size = agent->rx_buffer_size;
+ connection->rx_buffer = apr_palloc(connection->pool,connection->rx_buffer_size+1);
+ apt_text_stream_init(&connection->rx_stream,connection->rx_buffer,connection->rx_buffer_size);
+
+ if(apt_log_masking_get() != APT_LOG_MASKING_NONE) {
+ connection->verbose = FALSE;
+ mrcp_parser_verbose_set(connection->parser,TRUE);
+ mrcp_generator_verbose_set(connection->generator,TRUE);
+ }
+
return connection;
}
@@ -324,12 +381,17 @@ static mrcp_connection_t* mrcp_client_agent_connection_find(mrcp_connection_agen
static apt_bool_t mrcp_client_agent_connection_remove(mrcp_connection_agent_t *agent, mrcp_connection_t *connection)
{
+ apt_pollset_t *pollset = apt_poller_task_pollset_get(agent->task);
+
/* remove from the list */
if(connection->it) {
apt_list_elem_remove(agent->connection_list,connection->it);
connection->it = NULL;
}
- apt_pollset_remove(agent->pollset,&connection->sock_pfd);
+
+ if(pollset) {
+ apt_pollset_remove(pollset,&connection->sock_pfd);
+ }
if(connection->sock) {
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Close TCP/MRCPv2 Connection %s",connection->id);
apr_socket_close(connection->sock);
@@ -338,7 +400,6 @@ static apt_bool_t mrcp_client_agent_connection_remove(mrcp_connection_agent_t *a
return TRUE;
}
-
static apt_bool_t mrcp_client_agent_channel_add(mrcp_connection_agent_t *agent, mrcp_control_channel_t *channel, mrcp_control_descriptor_t *descriptor)
{
if(agent->offer_new_connection == TRUE) {
@@ -367,20 +428,20 @@ static apt_bool_t mrcp_client_agent_channel_modify(mrcp_connection_agent_t *agen
/* try to find existing connection */
connection = mrcp_client_agent_connection_find(agent,descriptor);
if(!connection) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Found No Existing TCP/MRCPv2 Connection");
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_WARNING,channel->log_obj,"Found No Existing TCP/MRCPv2 Connection");
}
}
if(!connection) {
/* create new connection */
connection = mrcp_client_agent_connection_create(agent,descriptor);
if(!connection) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Establish TCP/MRCPv2 Connection");
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_WARNING,channel->log_obj,"Failed to Establish TCP/MRCPv2 Connection");
}
}
if(connection) {
mrcp_connection_channel_add(connection,channel);
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Add Control Channel <%s> %s [%d]",
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,channel->log_obj,"Add Control Channel <%s> %s [%d]",
channel->identifier.buf,
connection->id,
apr_hash_count(connection->channel_table));
@@ -404,7 +465,7 @@ static apt_bool_t mrcp_client_agent_channel_remove(mrcp_connection_agent_t *agen
if(channel->connection) {
mrcp_connection_t *connection = channel->connection;
mrcp_connection_channel_remove(connection,channel);
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Remove Control Channel <%s> [%d]",
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,channel->log_obj,"Remove Control Channel <%s> [%d]",
channel->identifier.buf,
apr_hash_count(connection->channel_table));
if(!connection->access_count) {
@@ -419,71 +480,124 @@ static apt_bool_t mrcp_client_agent_channel_remove(mrcp_connection_agent_t *agen
return mrcp_control_channel_remove_respond(agent->vtable,channel,TRUE);
}
-static apt_bool_t mrcp_client_agent_messsage_send(mrcp_connection_agent_t *agent, mrcp_control_channel_t *channel, mrcp_message_t *message)
+static apt_bool_t mrcp_client_agent_request_cancel(mrcp_connection_agent_t *agent, mrcp_control_channel_t *channel, mrcp_message_t *message)
{
- apt_bool_t status = FALSE;
- mrcp_connection_t *connection = channel->connection;
- apt_text_stream_t *stream;
- mrcp_stream_status_e result;
+ mrcp_message_t *response;
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_WARNING,channel->log_obj,"Cancel MRCP Request <%s@%s> [%d]",
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
+ response = mrcp_response_create(message,message->pool);
+ response->start_line.status_code = MRCP_STATUS_CODE_METHOD_FAILED;
+ return mrcp_connection_message_receive(agent->vtable,channel,response);
+}
- if(!connection || !connection->sock) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No MRCPv2 Connection");
- return FALSE;
- }
- stream = &connection->tx_stream;
+static apt_bool_t mrcp_client_agent_disconnect_raise(mrcp_connection_agent_t *agent, mrcp_connection_t *connection)
+{
+ mrcp_control_channel_t *channel;
+ void *val;
+ apr_hash_index_t *it = apr_hash_first(connection->pool,connection->channel_table);
+ /* walk through the list of channels and raise disconnect event for them */
+ for(; it; it = apr_hash_next(it)) {
+ apr_hash_this(it,NULL,NULL,&val);
+ channel = val;
+ if(!channel) continue;
- mrcp_generator_message_set(connection->generator,message);
- do {
- apt_text_stream_init(&connection->tx_stream,connection->tx_buffer,sizeof(connection->tx_buffer)-1);
- result = mrcp_generator_run(connection->generator,stream);
- if(result != MRCP_STREAM_STATUS_INVALID) {
- stream->text.length = stream->pos - stream->text.buf;
- *stream->pos = '\0';
-
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Send MRCPv2 Stream %s [%lu bytes]\n%s",
- connection->id,
- stream->text.length,
- stream->text.buf);
- if(apr_socket_send(connection->sock,stream->text.buf,&stream->text.length) == APR_SUCCESS) {
- status = TRUE;
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Send MRCPv2 Stream");
+ if(channel->active_request) {
+ mrcp_client_agent_request_cancel(channel->agent,channel,channel->active_request);
+ channel->active_request = NULL;
+ if(channel->request_timer) {
+ apt_timer_kill(channel->request_timer);
}
}
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Generate MRCPv2 Stream");
+ else if(agent->vtable->on_disconnect){
+ agent->vtable->on_disconnect(channel);
}
}
- while(result == MRCP_STREAM_STATUS_INCOMPLETE);
-
- if(status == FALSE) {
- mrcp_message_t *response = mrcp_response_create(message,message->pool);
- response->start_line.method_id = message->start_line.method_id;
- response->start_line.method_name = message->start_line.method_name;
- response->start_line.status_code = MRCP_STATUS_CODE_METHOD_FAILED;
- mrcp_connection_message_receive(agent->vtable,channel,response);
- }
return TRUE;
}
-static apt_bool_t mrcp_client_message_handler(void *obj, mrcp_message_t *message, mrcp_stream_status_e status)
+static apt_bool_t mrcp_client_agent_messsage_send(mrcp_connection_agent_t *agent, mrcp_control_channel_t *channel, mrcp_message_t *message)
{
- if(status == MRCP_STREAM_STATUS_COMPLETE) {
+ apt_bool_t status = FALSE;
+ mrcp_connection_t *connection = channel->connection;
+ apt_text_stream_t stream;
+ apt_message_status_e result;
+
+ if(!connection || !connection->sock) {
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_WARNING,channel->log_obj,"Null MRCPv2 Connection "APT_SIDRES_FMT,MRCP_MESSAGE_SIDRES(message));
+ mrcp_client_agent_request_cancel(agent,channel,message);
+ return FALSE;
+ }
+
+ do {
+ apt_text_stream_init(&stream,connection->tx_buffer,connection->tx_buffer_size);
+ result = mrcp_generator_run(connection->generator,message,&stream);
+ if(result != APT_MESSAGE_STATUS_INVALID) {
+ stream.text.length = stream.pos - stream.text.buf;
+ *stream.pos = '\0';
+
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,channel->log_obj,"Send MRCPv2 Stream %s [%"APR_SIZE_T_FMT" bytes]\n%.*s",
+ connection->id,
+ stream.text.length,
+ connection->verbose == TRUE ? stream.text.length : 0,
+ stream.text.buf);
+
+ if(apr_socket_send(connection->sock,stream.text.buf,&stream.text.length) == APR_SUCCESS) {
+ status = TRUE;
+ }
+ else {
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_WARNING,channel->log_obj,"Failed to Send MRCPv2 Stream %s",
+ connection->id);
+ }
+ }
+ else {
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_WARNING,channel->log_obj,"Failed to Generate MRCPv2 Stream %s",
+ connection->id);
+ }
+ }
+ while(result == APT_MESSAGE_STATUS_INCOMPLETE);
+
+ if(status == TRUE) {
+ channel->active_request = message;
+ if(channel->request_timer && agent->request_timeout) {
+ apt_timer_set(channel->request_timer,agent->request_timeout);
+ }
+ }
+ else {
+ mrcp_client_agent_request_cancel(agent,channel,message);
+ }
+ return status;
+}
+
+static apt_bool_t mrcp_client_message_handler(mrcp_connection_t *connection, mrcp_message_t *message, apt_message_status_e status)
+{
+ if(status == APT_MESSAGE_STATUS_COMPLETE) {
/* message is completely parsed */
- mrcp_connection_t *connection = obj;
mrcp_control_channel_t *channel;
apt_str_t identifier;
apt_id_resource_generate(&message->channel_id.session_id,&message->channel_id.resource_name,'@',&identifier,message->pool);
channel = mrcp_connection_channel_find(connection,&identifier);
if(channel) {
mrcp_connection_agent_t *agent = connection->agent;
+ if(message->start_line.message_type == MRCP_MESSAGE_TYPE_RESPONSE) {
+ if(!channel->active_request ||
+ channel->active_request->start_line.request_id != message->start_line.request_id) {
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_WARNING,channel->log_obj,"Unexpected MRCP Response "APT_SIDRES_FMT" [%d]",
+ MRCP_MESSAGE_SIDRES(message),
+ message->start_line.request_id);
+ return FALSE;
+ }
+ if(channel->request_timer) {
+ apt_timer_kill(channel->request_timer);
+ }
+ channel->active_request = NULL;
+ }
+
mrcp_connection_message_receive(agent->vtable,channel,message);
}
else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Find Channel <%s@%s> in Connection %s [%d]",
- message->channel_id.session_id.buf,
- message->channel_id.resource_name.buf,
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Find Channel "APT_SIDRES_FMT" in Connection %s [%d]",
+ MRCP_MESSAGE_SIDRES(message),
connection->id,
apr_hash_count(connection->channel_table));
}
@@ -491,151 +605,104 @@ static apt_bool_t mrcp_client_message_handler(void *obj, mrcp_message_t *message
return TRUE;
}
-static apt_bool_t mrcp_client_agent_messsage_receive(mrcp_connection_agent_t *agent, mrcp_connection_t *connection)
+/* Receive MRCP message through TCP/MRCPv2 connection */
+static apt_bool_t mrcp_client_poller_signal_process(void *obj, const apr_pollfd_t *descriptor)
{
+ mrcp_connection_agent_t *agent = obj;
+ mrcp_connection_t *connection = descriptor->client_data;
apr_status_t status;
apr_size_t offset;
apr_size_t length;
apt_text_stream_t *stream;
+ mrcp_message_t *message;
+ apt_message_status_e msg_status;
if(!connection || !connection->sock) {
return FALSE;
}
stream = &connection->rx_stream;
- /* init length of the stream */
- stream->text.length = sizeof(connection->rx_buffer)-1;
/* calculate offset remaining from the previous receive / if any */
offset = stream->pos - stream->text.buf;
/* calculate available length */
- length = stream->text.length - offset;
+ length = connection->rx_buffer_size - offset;
+
status = apr_socket_recv(connection->sock,stream->pos,&length);
if(status == APR_EOF || length == 0) {
+ apt_pollset_t *pollset = apt_poller_task_pollset_get(agent->task);
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"TCP/MRCPv2 Peer Disconnected %s",connection->id);
- apt_pollset_remove(agent->pollset,&connection->sock_pfd);
+ if(pollset) {
+ apt_pollset_remove(pollset,&connection->sock_pfd);
+ }
apr_socket_close(connection->sock);
connection->sock = NULL;
- mrcp_connection_disconnect_raise(connection,agent->vtable);
+ mrcp_client_agent_disconnect_raise(agent,connection);
return TRUE;
}
+
/* calculate actual length of the stream */
stream->text.length = offset + length;
stream->pos[length] = '\0';
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive MRCPv2 Stream %s [%lu bytes]\n%s",
- connection->id,
- length,
- stream->pos);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive MRCPv2 Stream %s [%"APR_SIZE_T_FMT" bytes]\n%.*s",
+ connection->id,
+ length,
+ connection->verbose == TRUE ? length : 0,
+ stream->pos);
/* reset pos */
apt_text_stream_reset(stream);
- /* walk through the stream parsing MRCP messages */
- return mrcp_stream_walk(connection->parser,stream,mrcp_client_message_handler,connection);
-}
-
-static apt_bool_t mrcp_client_agent_control_process(mrcp_connection_agent_t *agent)
-{
- apt_bool_t status = TRUE;
- apt_bool_t running = TRUE;
- connection_task_msg_t *msg;
do {
- apr_thread_mutex_lock(agent->guard);
- msg = apt_cyclic_queue_pop(agent->msg_queue);
- apr_thread_mutex_unlock(agent->guard);
- if(msg) {
- switch(msg->type) {
- case CONNECTION_TASK_MSG_ADD_CHANNEL:
- mrcp_client_agent_channel_add(agent,msg->channel,msg->descriptor);
- break;
- case CONNECTION_TASK_MSG_MODIFY_CHANNEL:
- mrcp_client_agent_channel_modify(agent,msg->channel,msg->descriptor);
- break;
- case CONNECTION_TASK_MSG_REMOVE_CHANNEL:
- mrcp_client_agent_channel_remove(agent,msg->channel);
- break;
- case CONNECTION_TASK_MSG_SEND_MESSAGE:
- mrcp_client_agent_messsage_send(agent,msg->channel,msg->message);
- break;
- case CONNECTION_TASK_MSG_TERMINATE:
- status = FALSE;
- break;
- }
- }
- else {
- running = FALSE;
+ msg_status = mrcp_parser_run(connection->parser,stream,&message);
+ if(mrcp_client_message_handler(connection,message,msg_status) == FALSE) {
+ return FALSE;
}
}
- while(running == TRUE);
- return status;
-}
+ while(apt_text_is_eos(stream) == FALSE);
-static apt_bool_t mrcp_client_agent_task_run(apt_task_t *task)
-{
- mrcp_connection_agent_t *agent = apt_task_object_get(task);
- apt_bool_t running = TRUE;
- apr_status_t status;
- apr_int32_t num;
- const apr_pollfd_t *ret_pfd;
- int i;
-
- if(!agent) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Start MRCPv2 Agent");
- return FALSE;
- }
-
- agent->pollset = apt_pollset_create((apr_uint32_t)agent->max_connection_count,agent->pool);
- if(!agent->pollset) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Pollset");
- return FALSE;
- }
-
- /* explicitly indicate task is ready to process messages */
- apt_task_ready(agent->task);
-
- while(running) {
- status = apt_pollset_poll(agent->pollset, -1, &num, &ret_pfd);
- if(status != APR_SUCCESS) {
- continue;
- }
- for(i = 0; i < num; i++) {
- if(apt_pollset_is_wakeup(agent->pollset,&ret_pfd[i])) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Process Control Message");
- if(mrcp_client_agent_control_process(agent) == FALSE) {
- running = FALSE;
- break;
- }
- continue;
- }
-
- mrcp_client_agent_messsage_receive(agent,ret_pfd[i].client_data);
- }
- }
-
- apt_pollset_destroy(agent->pollset);
- agent->pollset = NULL;
-
- apt_task_child_terminate(agent->task);
+ /* scroll remaining stream */
+ apt_text_stream_scroll(stream);
return TRUE;
}
-static apt_bool_t mrcp_client_agent_task_terminate(apt_task_t *task)
+/* Process task message */
+static apt_bool_t mrcp_client_agent_msg_process(apt_task_t *task, apt_task_msg_t *task_msg)
{
- apt_bool_t status = FALSE;
- mrcp_connection_agent_t *agent = apt_task_object_get(task);
- if(agent->pollset) {
- connection_task_msg_t *msg = apr_pcalloc(agent->pool,sizeof(connection_task_msg_t));
- msg->type = CONNECTION_TASK_MSG_TERMINATE;
+ apt_poller_task_t *poller_task = apt_task_object_get(task);
+ mrcp_connection_agent_t *agent = apt_poller_task_object_get(poller_task);
+ connection_task_msg_t *msg = (connection_task_msg_t*) task_msg->data;
- apr_thread_mutex_lock(agent->guard);
- status = apt_cyclic_queue_push(agent->msg_queue,msg);
- apr_thread_mutex_unlock(agent->guard);
- if(apt_pollset_wakeup(agent->pollset) == TRUE) {
- status = TRUE;
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Signal Control Message");
+ switch(msg->type) {
+ case CONNECTION_TASK_MSG_ADD_CHANNEL:
+ mrcp_client_agent_channel_add(agent,msg->channel,msg->descriptor);
+ break;
+ case CONNECTION_TASK_MSG_MODIFY_CHANNEL:
+ mrcp_client_agent_channel_modify(agent,msg->channel,msg->descriptor);
+ break;
+ case CONNECTION_TASK_MSG_REMOVE_CHANNEL:
+ mrcp_client_agent_channel_remove(agent,msg->channel);
+ break;
+ case CONNECTION_TASK_MSG_SEND_MESSAGE:
+ mrcp_client_agent_messsage_send(agent,msg->channel,msg->message);
+ break;
+ }
+
+ return TRUE;
+}
+
+/* Timer callback */
+static void mrcp_client_timer_proc(apt_timer_t *timer, void *obj)
+{
+ mrcp_control_channel_t *channel = obj;
+ if(!channel) {
+ return;
+ }
+
+ if(channel->request_timer == timer) {
+ if(channel->active_request) {
+ mrcp_client_agent_request_cancel(channel->agent,channel,channel->active_request);
+ channel->active_request = NULL;
}
}
- return status;
}
diff --git a/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_connection.c b/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_connection.c
index d174cb78d0..29a06abd87 100644
--- a/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_connection.c
+++ b/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_connection.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_connection.c 1710 2010-05-24 17:36:19Z achaloyan $
*/
#include "mrcp_connection.h"
@@ -32,13 +34,17 @@ mrcp_connection_t* mrcp_connection_create()
connection->r_sockaddr = NULL;
connection->sock = NULL;
connection->id = NULL;
+ connection->verbose = TRUE;
connection->access_count = 0;
connection->it = NULL;
connection->channel_table = apr_hash_make(pool);
- apt_text_stream_init(&connection->rx_stream,connection->rx_buffer,sizeof(connection->rx_buffer)-1);
- apt_text_stream_init(&connection->tx_stream,connection->tx_buffer,sizeof(connection->tx_buffer)-1);
connection->parser = NULL;
connection->generator = NULL;
+ connection->rx_buffer = NULL;
+ connection->rx_buffer_size = 0;
+ connection->tx_buffer = NULL;
+ connection->tx_buffer_size = 0;
+
return connection;
}
@@ -60,7 +66,7 @@ apt_bool_t mrcp_connection_channel_add(mrcp_connection_t *connection, mrcp_contr
return TRUE;
}
-mrcp_control_channel_t* mrcp_connection_channel_find(mrcp_connection_t *connection, const apt_str_t *identifier)
+mrcp_control_channel_t* mrcp_connection_channel_find(const mrcp_connection_t *connection, const apt_str_t *identifier)
{
if(!connection || !identifier) {
return NULL;
diff --git a/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_control_descriptor.c b/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_control_descriptor.c
index de0de51aa9..0f8fd8b1f4 100644
--- a/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_control_descriptor.c
+++ b/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_control_descriptor.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_control_descriptor.c 1710 2010-05-24 17:36:19Z achaloyan $
*/
#include "apt_string_table.h"
@@ -133,7 +135,7 @@ MRCP_DECLARE(void) mrcp_cmid_add(apr_array_header_t *cmid_arr, apr_size_t cmid)
}
/** Find cmid in cmid_arr */
-MRCP_DECLARE(apt_bool_t) mrcp_cmid_find(apr_array_header_t *cmid_arr, apr_size_t cmid)
+MRCP_DECLARE(apt_bool_t) mrcp_cmid_find(const apr_array_header_t *cmid_arr, apr_size_t cmid)
{
int i;
for(i=0; inelts; i++) {
diff --git a/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_server_connection.c b/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_server_connection.c
index 0b370a6498..f85a3813cd 100644
--- a/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_server_connection.c
+++ b/libs/unimrcp/libs/mrcpv2-transport/src/mrcp_server_connection.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_server_connection.c 1792 2011-01-10 21:08:52Z achaloyan $
*/
#include "mrcp_connection.h"
@@ -20,33 +22,27 @@
#include "mrcp_resource_factory.h"
#include "mrcp_message.h"
#include "apt_text_stream.h"
-#include "apt_task.h"
+#include "apt_poller_task.h"
#include "apt_pool.h"
-#include "apt_pollset.h"
-#include "apt_cyclic_queue.h"
#include "apt_log.h"
-#define MRCPV2_CONNECTION_TASK_NAME "TCP/MRCPv2 Connection Agent"
struct mrcp_connection_agent_t {
- apr_pool_t *pool;
- apt_task_t *task;
- mrcp_resource_factory_t *resource_factory;
+ apr_pool_t *pool;
+ apt_poller_task_t *task;
+ const mrcp_resource_factory_t *resource_factory;
- apt_obj_list_t *connection_list;
- mrcp_connection_t *null_connection;
+ apt_obj_list_t *connection_list;
+ mrcp_connection_t *null_connection;
- apt_bool_t force_new_connection;
- apr_size_t max_connection_count;
+ apt_bool_t force_new_connection;
+ apr_size_t tx_buffer_size;
+ apr_size_t rx_buffer_size;
- apr_sockaddr_t *sockaddr;
/* Listening socket */
- apr_socket_t *listen_sock;
- apr_pollfd_t listen_sock_pfd;
-
- apr_thread_mutex_t *guard;
- apt_cyclic_queue_t *msg_queue;
- apt_pollset_t *pollset;
+ apr_sockaddr_t *sockaddr;
+ apr_socket_t *listen_sock;
+ apr_pollfd_t listen_sock_pfd;
void *obj;
const mrcp_connection_event_vtable_t *vtable;
@@ -56,8 +52,7 @@ typedef enum {
CONNECTION_TASK_MSG_ADD_CHANNEL,
CONNECTION_TASK_MSG_MODIFY_CHANNEL,
CONNECTION_TASK_MSG_REMOVE_CHANNEL,
- CONNECTION_TASK_MSG_SEND_MESSAGE,
- CONNECTION_TASK_MSG_TERMINATE
+ CONNECTION_TASK_MSG_SEND_MESSAGE
} connection_task_msg_type_e;
typedef struct connection_task_msg_t connection_task_msg_t;
@@ -69,94 +64,125 @@ struct connection_task_msg_t {
mrcp_message_t *message;
};
-static apt_bool_t mrcp_server_agent_task_run(apt_task_t *task);
-static apt_bool_t mrcp_server_agent_task_terminate(apt_task_t *task);
-static apt_bool_t mrcp_server_agent_task_on_destroy(apt_task_t *task);
+static apt_bool_t mrcp_server_agent_on_destroy(apt_task_t *task);
+static apt_bool_t mrcp_server_agent_msg_process(apt_task_t *task, apt_task_msg_t *task_msg);
+static apt_bool_t mrcp_server_poller_signal_process(void *obj, const apr_pollfd_t *descriptor);
+
+static apt_bool_t mrcp_server_agent_listening_socket_create(mrcp_connection_agent_t *agent);
+static void mrcp_server_agent_listening_socket_destroy(mrcp_connection_agent_t *agent);
+
/** Create connection agent */
MRCP_DECLARE(mrcp_connection_agent_t*) mrcp_server_connection_agent_create(
+ const char *id,
const char *listen_ip,
apr_port_t listen_port,
apr_size_t max_connection_count,
apt_bool_t force_new_connection,
apr_pool_t *pool)
{
+ apt_task_t *task;
apt_task_vtable_t *vtable;
+ apt_task_msg_pool_t *msg_pool;
mrcp_connection_agent_t *agent;
if(!listen_ip) {
return NULL;
}
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create "MRCPV2_CONNECTION_TASK_NAME" %s:%hu [%"APR_SIZE_T_FMT"]",
- listen_ip,listen_port,max_connection_count);
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create MRCPv2 Agent [%s] %s:%hu [%"APR_SIZE_T_FMT"]",
+ id,listen_ip,listen_port,max_connection_count);
agent = apr_palloc(pool,sizeof(mrcp_connection_agent_t));
agent->pool = pool;
agent->sockaddr = NULL;
agent->listen_sock = NULL;
- agent->pollset = NULL;
- agent->max_connection_count = max_connection_count;
agent->force_new_connection = force_new_connection;
+ agent->rx_buffer_size = MRCP_STREAM_BUFFER_SIZE;
+ agent->tx_buffer_size = MRCP_STREAM_BUFFER_SIZE;
apr_sockaddr_info_get(&agent->sockaddr,listen_ip,APR_INET,listen_port,0,agent->pool);
if(!agent->sockaddr) {
return NULL;
}
- agent->task = apt_task_create(agent,NULL,pool);
+ msg_pool = apt_task_msg_pool_create_dynamic(sizeof(connection_task_msg_t),pool);
+
+ agent->task = apt_poller_task_create(
+ max_connection_count + 1,
+ mrcp_server_poller_signal_process,
+ agent,
+ msg_pool,
+ pool);
if(!agent->task) {
return NULL;
}
- apt_task_name_set(agent->task,MRCPV2_CONNECTION_TASK_NAME);
- vtable = apt_task_vtable_get(agent->task);
- if(vtable) {
- vtable->run = mrcp_server_agent_task_run;
- vtable->terminate = mrcp_server_agent_task_terminate;
- vtable->destroy = mrcp_server_agent_task_on_destroy;
+ task = apt_poller_task_base_get(agent->task);
+ if(task) {
+ apt_task_name_set(task,id);
}
- apt_task_auto_ready_set(agent->task,FALSE);
- agent->msg_queue = apt_cyclic_queue_create(CYCLIC_QUEUE_DEFAULT_SIZE);
- apr_thread_mutex_create(&agent->guard,APR_THREAD_MUTEX_UNNESTED,pool);
+ vtable = apt_poller_task_vtable_get(agent->task);
+ if(vtable) {
+ vtable->destroy = mrcp_server_agent_on_destroy;
+ vtable->process_msg = mrcp_server_agent_msg_process;
+ }
agent->connection_list = NULL;
agent->null_connection = NULL;
+
+ if(mrcp_server_agent_listening_socket_create(agent) == TRUE) {
+ /* add listening socket to pollset */
+ apt_pollset_t *pollset = apt_poller_task_pollset_get(agent->task);
+ memset(&agent->listen_sock_pfd,0,sizeof(apr_pollfd_t));
+ agent->listen_sock_pfd.desc_type = APR_POLL_SOCKET;
+ agent->listen_sock_pfd.reqevents = APR_POLLIN;
+ agent->listen_sock_pfd.desc.s = agent->listen_sock;
+ agent->listen_sock_pfd.client_data = agent->listen_sock;
+ if(apt_pollset_add(pollset, &agent->listen_sock_pfd) != TRUE) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Add Listening Socket to Pollset");
+ mrcp_server_agent_listening_socket_destroy(agent);
+ }
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Listening Socket");
+ }
return agent;
}
-/** Virtual destroy handler. */
-static apt_bool_t mrcp_server_agent_task_on_destroy(apt_task_t *task)
+static apt_bool_t mrcp_server_agent_on_destroy(apt_task_t *task)
{
- mrcp_connection_agent_t *agent = apt_task_object_get(task);
- if(agent->guard) {
- apr_thread_mutex_destroy(agent->guard);
- agent->guard = NULL;
- }
- if(agent->msg_queue) {
- apt_cyclic_queue_destroy(agent->msg_queue);
- agent->msg_queue = NULL;
+ apt_poller_task_t *poller_task = apt_task_object_get(task);
+ mrcp_connection_agent_t *agent = apt_poller_task_object_get(poller_task);
+
+ apt_pollset_t *pollset = apt_poller_task_pollset_get(poller_task);
+ if(pollset) {
+ apt_pollset_remove(pollset,&agent->listen_sock_pfd);
}
+ mrcp_server_agent_listening_socket_destroy(agent);
+
+ apt_poller_task_cleanup(poller_task);
return TRUE;
}
/** Destroy connection agent. */
MRCP_DECLARE(apt_bool_t) mrcp_server_connection_agent_destroy(mrcp_connection_agent_t *agent)
{
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Destroy MRCPv2 Agent");
- return apt_task_destroy(agent->task);
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Destroy MRCPv2 Agent [%s]",
+ mrcp_server_connection_agent_id_get(agent));
+ return apt_poller_task_destroy(agent->task);
}
/** Start connection agent. */
MRCP_DECLARE(apt_bool_t) mrcp_server_connection_agent_start(mrcp_connection_agent_t *agent)
{
- return apt_task_start(agent->task);
+ return apt_poller_task_start(agent->task);
}
/** Terminate connection agent. */
MRCP_DECLARE(apt_bool_t) mrcp_server_connection_agent_terminate(mrcp_connection_agent_t *agent)
{
- return apt_task_terminate(agent->task,TRUE);
+ return apt_poller_task_terminate(agent->task);
}
/** Set connection event handler. */
@@ -172,31 +198,64 @@ MRCP_DECLARE(void) mrcp_server_connection_agent_handler_set(
/** Set MRCP resource factory */
MRCP_DECLARE(void) mrcp_server_connection_resource_factory_set(
mrcp_connection_agent_t *agent,
- mrcp_resource_factory_t *resource_factroy)
+ const mrcp_resource_factory_t *resource_factroy)
{
agent->resource_factory = resource_factroy;
}
-/** Get task */
-MRCP_DECLARE(apt_task_t*) mrcp_server_connection_agent_task_get(mrcp_connection_agent_t *agent)
+/** Set rx buffer size */
+MRCP_DECLARE(void) mrcp_server_connection_rx_size_set(
+ mrcp_connection_agent_t *agent,
+ apr_size_t size)
{
- return agent->task;
+ if(size < MRCP_STREAM_BUFFER_SIZE) {
+ size = MRCP_STREAM_BUFFER_SIZE;
+ }
+ agent->rx_buffer_size = size;
+}
+
+/** Set tx buffer size */
+MRCP_DECLARE(void) mrcp_server_connection_tx_size_set(
+ mrcp_connection_agent_t *agent,
+ apr_size_t size)
+{
+ if(size < MRCP_STREAM_BUFFER_SIZE) {
+ size = MRCP_STREAM_BUFFER_SIZE;
+ }
+ agent->tx_buffer_size = size;
+}
+
+/** Get task */
+MRCP_DECLARE(apt_task_t*) mrcp_server_connection_agent_task_get(const mrcp_connection_agent_t *agent)
+{
+ return apt_poller_task_base_get(agent->task);
}
/** Get external object */
-MRCP_DECLARE(void*) mrcp_server_connection_agent_object_get(mrcp_connection_agent_t *agent)
+MRCP_DECLARE(void*) mrcp_server_connection_agent_object_get(const mrcp_connection_agent_t *agent)
{
return agent->obj;
}
+/** Get string identifier */
+MRCP_DECLARE(const char*) mrcp_server_connection_agent_id_get(const mrcp_connection_agent_t *agent)
+{
+ apt_task_t *task = apt_poller_task_base_get(agent->task);
+ return apt_task_name_get(task);
+}
+
+
/** Create MRCPv2 control channel */
MRCP_DECLARE(mrcp_control_channel_t*) mrcp_server_control_channel_create(mrcp_connection_agent_t *agent, void *obj, apr_pool_t *pool)
{
mrcp_control_channel_t *channel = apr_palloc(pool,sizeof(mrcp_control_channel_t));
channel->agent = agent;
channel->connection = NULL;
+ channel->active_request = NULL;
+ channel->request_timer = NULL;
channel->removed = FALSE;
channel->obj = obj;
+ channel->log_obj = NULL;
channel->pool = pool;
return channel;
}
@@ -213,6 +272,7 @@ MRCP_DECLARE(apt_bool_t) mrcp_server_control_channel_destroy(mrcp_control_channe
return TRUE;
}
+/** Signal task message */
static apt_bool_t mrcp_server_control_message_signal(
connection_task_msg_type_e type,
mrcp_connection_agent_t *agent,
@@ -220,22 +280,18 @@ static apt_bool_t mrcp_server_control_message_signal(
mrcp_control_descriptor_t *descriptor,
mrcp_message_t *message)
{
- apt_bool_t status;
- connection_task_msg_t *msg = apr_palloc(channel->pool,sizeof(connection_task_msg_t));
- msg->type = type;
- msg->agent = agent;
- msg->channel = channel;
- msg->descriptor = descriptor;
- msg->message = message;
-
- apr_thread_mutex_lock(agent->guard);
- status = apt_cyclic_queue_push(agent->msg_queue,msg);
- apr_thread_mutex_unlock(agent->guard);
- if(apt_pollset_wakeup(agent->pollset) != TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Signal Control Message");
- status = FALSE;
+ apt_task_t *task = apt_poller_task_base_get(agent->task);
+ apt_task_msg_t *task_msg = apt_task_msg_get(task);
+ if(task_msg) {
+ connection_task_msg_t *msg = (connection_task_msg_t*)task_msg->data;
+ msg->type = type;
+ msg->agent = agent;
+ msg->channel = channel;
+ msg->descriptor = descriptor;
+ msg->message = message;
+ apt_task_msg_signal(task,task_msg);
}
- return status;
+ return TRUE;
}
/** Add MRCPv2 control channel */
@@ -262,8 +318,7 @@ MRCP_DECLARE(apt_bool_t) mrcp_server_control_message_send(mrcp_control_channel_t
return mrcp_server_control_message_signal(CONNECTION_TASK_MSG_SEND_MESSAGE,channel->agent,channel,NULL,message);
}
-
-static apt_bool_t mrcp_server_agent_listen_socket_create(mrcp_connection_agent_t *agent)
+static apt_bool_t mrcp_server_agent_listening_socket_create(mrcp_connection_agent_t *agent)
{
apr_status_t status;
if(!agent->sockaddr) {
@@ -296,7 +351,7 @@ static apt_bool_t mrcp_server_agent_listen_socket_create(mrcp_connection_agent_t
return TRUE;
}
-static void mrcp_server_agent_listen_socket_destroy(mrcp_connection_agent_t *agent)
+static void mrcp_server_agent_listening_socket_destroy(mrcp_connection_agent_t *agent)
{
if(agent->listen_sock) {
apr_socket_close(agent->listen_sock);
@@ -304,44 +359,6 @@ static void mrcp_server_agent_listen_socket_destroy(mrcp_connection_agent_t *age
}
}
-static apt_bool_t mrcp_server_agent_pollset_create(mrcp_connection_agent_t *agent)
-{
- /* create pollset */
- agent->pollset = apt_pollset_create((apr_uint32_t)agent->max_connection_count + 1, agent->pool);
- if(!agent->pollset) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Pollset");
- return FALSE;
- }
-
- if(mrcp_server_agent_listen_socket_create(agent) == TRUE) {
- /* add listen socket to pollset */
- memset(&agent->listen_sock_pfd,0,sizeof(apr_pollfd_t));
- agent->listen_sock_pfd.desc_type = APR_POLL_SOCKET;
- agent->listen_sock_pfd.reqevents = APR_POLLIN;
- agent->listen_sock_pfd.desc.s = agent->listen_sock;
- agent->listen_sock_pfd.client_data = agent->listen_sock;
- if(apt_pollset_add(agent->pollset, &agent->listen_sock_pfd) != TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Add Listen Socket to Pollset");
- mrcp_server_agent_listen_socket_destroy(agent);
- }
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Listen Socket");
- }
-
- return TRUE;
-}
-
-static void mrcp_server_agent_pollset_destroy(mrcp_connection_agent_t *agent)
-{
- mrcp_server_agent_listen_socket_destroy(agent);
- if(agent->pollset) {
- apt_pollset_destroy(agent->pollset);
- agent->pollset = NULL;
- }
-}
-
-
static mrcp_control_channel_t* mrcp_connection_channel_associate(mrcp_connection_agent_t *agent, mrcp_connection_t *connection, const mrcp_message_t *message)
{
apt_str_t identifier;
@@ -356,7 +373,7 @@ static mrcp_control_channel_t* mrcp_connection_channel_associate(mrcp_connection
if(channel) {
mrcp_connection_channel_remove(agent->null_connection,channel);
mrcp_connection_channel_add(connection,channel);
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Move Control Channel <%s> to Connection %s [%d]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Attach Control Channel <%s> to Connection %s [%d]",
channel->identifier.buf,
connection->id,
apr_hash_count(connection->channel_table));
@@ -395,7 +412,7 @@ static apt_bool_t mrcp_connection_remove(mrcp_connection_agent_t *agent, mrcp_co
}
if(agent->null_connection) {
if(apt_list_is_empty(agent->connection_list) == TRUE && apr_hash_count(agent->null_connection->channel_table) == 0) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Destroy Pending Connection");
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Destroy Container for Pending Control Channels");
mrcp_connection_destroy(agent->null_connection);
agent->null_connection = NULL;
agent->connection_list = NULL;
@@ -410,11 +427,13 @@ static apt_bool_t mrcp_server_agent_connection_accept(mrcp_connection_agent_t *a
char *remote_ip = NULL;
apr_socket_t *sock;
apr_pool_t *pool;
+ apt_pollset_t *pollset = apt_poller_task_pollset_get(agent->task);
mrcp_connection_t *connection;
if(!agent->null_connection) {
pool = apt_pool_create();
if(apr_socket_accept(&sock,agent->listen_sock,pool) != APR_SUCCESS) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Accept Connection");
return FALSE;
}
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Rejected TCP/MRCPv2 Connection");
@@ -425,6 +444,7 @@ static apt_bool_t mrcp_server_agent_connection_accept(mrcp_connection_agent_t *a
pool = agent->null_connection->pool;
if(apr_socket_accept(&sock,agent->listen_sock,pool) != APR_SUCCESS) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Accept Connection");
return FALSE;
}
@@ -433,6 +453,7 @@ static apt_bool_t mrcp_server_agent_connection_accept(mrcp_connection_agent_t *a
if(apr_socket_addr_get(&connection->r_sockaddr,APR_REMOTE,sock) != APR_SUCCESS ||
apr_socket_addr_get(&connection->l_sockaddr,APR_LOCAL,sock) != APR_SUCCESS) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Get Socket Address");
apr_socket_close(sock);
mrcp_connection_destroy(connection);
return FALSE;
@@ -450,8 +471,8 @@ static apt_bool_t mrcp_server_agent_connection_accept(mrcp_connection_agent_t *a
connection->sock_pfd.reqevents = APR_POLLIN;
connection->sock_pfd.desc.s = connection->sock;
connection->sock_pfd.client_data = connection;
- if(apt_pollset_add(agent->pollset, &connection->sock_pfd) != TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Add to Pollset");
+ if(apt_pollset_add(pollset, &connection->sock_pfd) != TRUE) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Add to Pollset %s",connection->id);
apr_socket_close(sock);
mrcp_connection_destroy(connection);
return FALSE;
@@ -460,15 +481,30 @@ static apt_bool_t mrcp_server_agent_connection_accept(mrcp_connection_agent_t *a
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Accepted TCP/MRCPv2 Connection %s",connection->id);
connection->agent = agent;
connection->it = apt_list_push_back(agent->connection_list,connection,connection->pool);
+
connection->parser = mrcp_parser_create(agent->resource_factory,connection->pool);
connection->generator = mrcp_generator_create(agent->resource_factory,connection->pool);
+
+ connection->tx_buffer_size = agent->tx_buffer_size;
+ connection->tx_buffer = apr_palloc(connection->pool,connection->tx_buffer_size+1);
+
+ connection->rx_buffer_size = agent->rx_buffer_size;
+ connection->rx_buffer = apr_palloc(connection->pool,connection->rx_buffer_size+1);
+ apt_text_stream_init(&connection->rx_stream,connection->rx_buffer,connection->rx_buffer_size);
+
+ if(apt_log_masking_get() != APT_LOG_MASKING_NONE) {
+ connection->verbose = FALSE;
+ mrcp_parser_verbose_set(connection->parser,TRUE);
+ mrcp_generator_verbose_set(connection->generator,TRUE);
+ }
return TRUE;
}
static apt_bool_t mrcp_server_agent_connection_close(mrcp_connection_agent_t *agent, mrcp_connection_t *connection)
{
+ apt_pollset_t *pollset = apt_poller_task_pollset_get(agent->task);
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"TCP/MRCPv2 Peer Disconnected %s",connection->id);
- apt_pollset_remove(agent->pollset,&connection->sock_pfd);
+ apt_pollset_remove(pollset,&connection->sock_pfd);
apr_socket_close(connection->sock);
connection->sock = NULL;
if(!connection->access_count) {
@@ -503,12 +539,12 @@ static apt_bool_t mrcp_server_agent_channel_add(mrcp_connection_agent_t *agent,
}
if(!agent->null_connection) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Create Pending Connection");
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Create Container for Pending Control Channels");
agent->null_connection = mrcp_connection_create();
agent->connection_list = apt_list_create(agent->null_connection->pool);
}
mrcp_connection_channel_add(agent->null_connection,channel);
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Add Control Channel <%s> to Pending Connection [%d]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Add Pending Control Channel <%s> [%d]",
channel->identifier.buf,
apr_hash_count(agent->null_connection->channel_table));
/* send response */
@@ -536,7 +572,7 @@ static apt_bool_t mrcp_server_agent_channel_remove(mrcp_connection_agent_t *agen
if(!connection->access_count) {
if(connection == agent->null_connection) {
if(apt_list_is_empty(agent->connection_list) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Destroy Pending Connection");
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Destroy Container for Pending Control Channels");
mrcp_connection_destroy(agent->null_connection);
agent->null_connection = NULL;
agent->connection_list = NULL;
@@ -545,7 +581,7 @@ static apt_bool_t mrcp_server_agent_channel_remove(mrcp_connection_agent_t *agen
else if(!connection->sock) {
mrcp_connection_remove(agent,connection);
/* set connection to be destroyed on channel destroy */
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Mark Connection for Late Destroy");
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Mark Connection for Removal %s",connection->id);
channel->connection = connection;
channel->removed = TRUE;
}
@@ -557,27 +593,27 @@ static apt_bool_t mrcp_server_agent_channel_remove(mrcp_connection_agent_t *agen
static apt_bool_t mrcp_server_agent_messsage_send(mrcp_connection_agent_t *agent, mrcp_connection_t *connection, mrcp_message_t *message)
{
apt_bool_t status = FALSE;
- apt_text_stream_t *stream;
- mrcp_stream_status_e result;
+ apt_text_stream_t stream;
+ apt_message_status_e result;
if(!connection || !connection->sock) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No MRCPv2 Connection");
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Null MRCPv2 Connection "APT_SIDRES_FMT,MRCP_MESSAGE_SIDRES(message));
return FALSE;
}
- stream = &connection->tx_stream;
- mrcp_generator_message_set(connection->generator,message);
do {
- apt_text_stream_init(&connection->tx_stream,connection->tx_buffer,sizeof(connection->tx_buffer)-1);
- result = mrcp_generator_run(connection->generator,stream);
- if(result != MRCP_STREAM_STATUS_INVALID) {
- stream->text.length = stream->pos - stream->text.buf;
- *stream->pos = '\0';
+ apt_text_stream_init(&stream,connection->tx_buffer,connection->tx_buffer_size);
+ result = mrcp_generator_run(connection->generator,message,&stream);
+ if(result != APT_MESSAGE_STATUS_INVALID) {
+ stream.text.length = stream.pos - stream.text.buf;
+ *stream.pos = '\0';
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Send MRCPv2 Stream %s [%lu bytes]\n%s",
- connection->id,
- stream->text.length,
- stream->text.buf);
- if(apr_socket_send(connection->sock,stream->text.buf,&stream->text.length) == APR_SUCCESS) {
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Send MRCPv2 Stream %s [%"APR_SIZE_T_FMT" bytes]\n%.*s",
+ connection->id,
+ stream.text.length,
+ connection->verbose == TRUE ? stream.text.length : 0,
+ stream.text.buf);
+
+ if(apr_socket_send(connection->sock,stream.text.buf,&stream.text.length) == APR_SUCCESS) {
status = TRUE;
}
else {
@@ -588,32 +624,30 @@ static apt_bool_t mrcp_server_agent_messsage_send(mrcp_connection_agent_t *agent
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Generate MRCPv2 Stream");
}
}
- while(result == MRCP_STREAM_STATUS_INCOMPLETE);
+ while(result == APT_MESSAGE_STATUS_INCOMPLETE);
return status;
}
-static apt_bool_t mrcp_server_message_handler(void *obj, mrcp_message_t *message, mrcp_stream_status_e status)
+static apt_bool_t mrcp_server_message_handler(mrcp_connection_t *connection, mrcp_message_t *message, apt_message_status_e status)
{
- mrcp_connection_t *connection = obj;
mrcp_connection_agent_t *agent = connection->agent;
- if(status == MRCP_STREAM_STATUS_COMPLETE) {
+ if(status == APT_MESSAGE_STATUS_COMPLETE) {
/* message is completely parsed */
mrcp_control_channel_t *channel = mrcp_connection_channel_associate(agent,connection,message);
if(channel) {
mrcp_connection_message_receive(agent->vtable,channel,message);
}
else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Find Channel <%s@%s> in Connection %s",
- message->channel_id.session_id.buf,
- message->channel_id.resource_name.buf,
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Find Channel "APT_SIDRES_FMT" in Connection %s",
+ MRCP_MESSAGE_SIDRES(message),
connection->id);
}
}
- else if(status == MRCP_STREAM_STATUS_INVALID) {
+ else if(status == APT_MESSAGE_STATUS_INVALID) {
/* error case */
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Parse MRCPv2 Stream");
- if(message->resource) {
+ if(message && message->resource) {
mrcp_message_t *response;
response = mrcp_response_create(message,message->pool);
response->start_line.status_code = MRCP_STATUS_CODE_UNRECOGNIZED_MESSAGE;
@@ -625,149 +659,83 @@ static apt_bool_t mrcp_server_message_handler(void *obj, mrcp_message_t *message
return TRUE;
}
-static apt_bool_t mrcp_server_agent_messsage_receive(mrcp_connection_agent_t *agent, mrcp_connection_t *connection)
+/* Receive MRCP message through TCP/MRCPv2 connection */
+static apt_bool_t mrcp_server_poller_signal_process(void *obj, const apr_pollfd_t *descriptor)
{
+ mrcp_connection_agent_t *agent = obj;
+ mrcp_connection_t *connection = descriptor->client_data;
apr_status_t status;
apr_size_t offset;
apr_size_t length;
apt_text_stream_t *stream;
+ mrcp_message_t *message;
+ apt_message_status_e msg_status;
+ if(descriptor->desc.s == agent->listen_sock) {
+ return mrcp_server_agent_connection_accept(agent);
+ }
+
if(!connection || !connection->sock) {
return FALSE;
}
stream = &connection->rx_stream;
-
- /* init length of the stream */
- stream->text.length = sizeof(connection->rx_buffer)-1;
+
/* calculate offset remaining from the previous receive / if any */
offset = stream->pos - stream->text.buf;
/* calculate available length */
- length = stream->text.length - offset;
+ length = connection->rx_buffer_size - offset;
+
status = apr_socket_recv(connection->sock,stream->pos,&length);
if(status == APR_EOF || length == 0) {
return mrcp_server_agent_connection_close(agent,connection);
}
+
/* calculate actual length of the stream */
stream->text.length = offset + length;
stream->pos[length] = '\0';
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive MRCPv2 Stream %s [%lu bytes]\n%s",
- connection->id,
- length,
- stream->pos);
+
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive MRCPv2 Stream %s [%"APR_SIZE_T_FMT" bytes]\n%.*s",
+ connection->id,
+ length,
+ connection->verbose == TRUE ? length : 0,
+ stream->pos);
/* reset pos */
apt_text_stream_reset(stream);
- /* walk through the stream parsing MRCP messages */
- return mrcp_stream_walk(connection->parser,stream,mrcp_server_message_handler,connection);
-}
-
-static apt_bool_t mrcp_server_agent_control_process(mrcp_connection_agent_t *agent)
-{
- apt_bool_t status = TRUE;
- apt_bool_t running = TRUE;
- connection_task_msg_t *msg;
do {
- apr_thread_mutex_lock(agent->guard);
- msg = apt_cyclic_queue_pop(agent->msg_queue);
- apr_thread_mutex_unlock(agent->guard);
- if(msg) {
- switch(msg->type) {
- case CONNECTION_TASK_MSG_ADD_CHANNEL:
- mrcp_server_agent_channel_add(agent,msg->channel,msg->descriptor);
- break;
- case CONNECTION_TASK_MSG_MODIFY_CHANNEL:
- mrcp_server_agent_channel_modify(agent,msg->channel,msg->descriptor);
- break;
- case CONNECTION_TASK_MSG_REMOVE_CHANNEL:
- mrcp_server_agent_channel_remove(agent,msg->channel);
- break;
- case CONNECTION_TASK_MSG_SEND_MESSAGE:
- mrcp_server_agent_messsage_send(agent,msg->channel->connection,msg->message);
- break;
- case CONNECTION_TASK_MSG_TERMINATE:
- status = FALSE;
- break;
- }
- }
- else {
- running = FALSE;
+ msg_status = mrcp_parser_run(connection->parser,stream,&message);
+ if(mrcp_server_message_handler(connection,message,msg_status) == FALSE) {
+ return FALSE;
}
}
- while(running == TRUE);
- return status;
-}
+ while(apt_text_is_eos(stream) == FALSE);
-static apt_bool_t mrcp_server_agent_task_run(apt_task_t *task)
-{
- mrcp_connection_agent_t *agent = apt_task_object_get(task);
- apt_bool_t running = TRUE;
- apr_status_t status;
- apr_int32_t num;
- const apr_pollfd_t *ret_pfd;
- int i;
-
- if(!agent) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Start MRCPv2 Agent");
- return FALSE;
- }
-
- if(mrcp_server_agent_pollset_create(agent) == FALSE) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Pollset");
- return FALSE;
- }
-
- /* explicitly indicate task is ready to process messages */
- apt_task_ready(agent->task);
-
- while(running) {
- status = apt_pollset_poll(agent->pollset, -1, &num, &ret_pfd);
- if(status != APR_SUCCESS) {
- continue;
- }
- for(i = 0; i < num; i++) {
- if(ret_pfd[i].desc.s == agent->listen_sock) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Accept MRCPv2 Connection");
- mrcp_server_agent_connection_accept(agent);
- continue;
- }
- if(apt_pollset_is_wakeup(agent->pollset,&ret_pfd[i])) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Process Control Message");
- if(mrcp_server_agent_control_process(agent) == FALSE) {
- running = FALSE;
- break;
- }
- continue;
- }
-
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Process MRCPv2 Message");
- mrcp_server_agent_messsage_receive(agent,ret_pfd[i].client_data);
- }
- }
-
- mrcp_server_agent_pollset_destroy(agent);
-
- apt_task_child_terminate(agent->task);
+ /* scroll remaining stream */
+ apt_text_stream_scroll(stream);
return TRUE;
}
-static apt_bool_t mrcp_server_agent_task_terminate(apt_task_t *task)
+/* Process task message */
+static apt_bool_t mrcp_server_agent_msg_process(apt_task_t *task, apt_task_msg_t *task_msg)
{
- apt_bool_t status = FALSE;
- mrcp_connection_agent_t *agent = apt_task_object_get(task);
- if(agent->pollset) {
- connection_task_msg_t *msg = apr_pcalloc(agent->pool,sizeof(connection_task_msg_t));
- msg->type = CONNECTION_TASK_MSG_TERMINATE;
-
- apr_thread_mutex_lock(agent->guard);
- status = apt_cyclic_queue_push(agent->msg_queue,msg);
- apr_thread_mutex_unlock(agent->guard);
- if(apt_pollset_wakeup(agent->pollset) == TRUE) {
- status = TRUE;
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Signal Control Message");
- }
+ apt_poller_task_t *poller_task = apt_task_object_get(task);
+ mrcp_connection_agent_t *agent = apt_poller_task_object_get(poller_task);
+ connection_task_msg_t *msg = (connection_task_msg_t*) task_msg->data;
+ switch(msg->type) {
+ case CONNECTION_TASK_MSG_ADD_CHANNEL:
+ mrcp_server_agent_channel_add(agent,msg->channel,msg->descriptor);
+ break;
+ case CONNECTION_TASK_MSG_MODIFY_CHANNEL:
+ mrcp_server_agent_channel_modify(agent,msg->channel,msg->descriptor);
+ break;
+ case CONNECTION_TASK_MSG_REMOVE_CHANNEL:
+ mrcp_server_agent_channel_remove(agent,msg->channel);
+ break;
+ case CONNECTION_TASK_MSG_SEND_MESSAGE:
+ mrcp_server_agent_messsage_send(agent,msg->channel->connection,msg->message);
+ break;
}
- return status;
+
+ return TRUE;
}
diff --git a/libs/unimrcp/libs/uni-rtsp/include/rtsp.h b/libs/unimrcp/libs/uni-rtsp/include/rtsp.h
index d2d029f635..fbc55d6ef1 100644
--- a/libs/unimrcp/libs/uni-rtsp/include/rtsp.h
+++ b/libs/unimrcp/libs/uni-rtsp/include/rtsp.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: rtsp.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __RTSP_H__
-#define __RTSP_H__
+#ifndef RTSP_H
+#define RTSP_H
/**
* @file rtsp.h
@@ -40,4 +42,4 @@
#define RTSP_DECLARE(type) type
#endif
-#endif /*__RTSP_H__*/
+#endif /* RTSP_H */
diff --git a/libs/unimrcp/libs/uni-rtsp/include/rtsp_client.h b/libs/unimrcp/libs/uni-rtsp/include/rtsp_client.h
index 4d3bd1f1c6..0209e7211a 100644
--- a/libs/unimrcp/libs/uni-rtsp/include/rtsp_client.h
+++ b/libs/unimrcp/libs/uni-rtsp/include/rtsp_client.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: rtsp_client.h 1710 2010-05-24 17:36:19Z achaloyan $
*/
-#ifndef __RTSP_CLIENT_H__
-#define __RTSP_CLIENT_H__
+#ifndef RTSP_CLIENT_H
+#define RTSP_CLIENT_H
/**
* @file rtsp_client.h
@@ -50,12 +52,14 @@ struct rtsp_client_vtable_t {
/**
* Create RTSP client.
* @param max_connection_count the number of max RTSP connections
+ * @param request_timeout the request timeout to set
* @param obj the external object to send event to
* @param handler the response/event handler
* @param pool the pool to allocate memory from
*/
RTSP_DECLARE(rtsp_client_t*) rtsp_client_create(
apr_size_t max_connection_count,
+ apr_size_t request_timeout,
void *obj,
const rtsp_client_vtable_t *handler,
apr_pool_t *pool);
@@ -82,13 +86,13 @@ RTSP_DECLARE(apt_bool_t) rtsp_client_terminate(rtsp_client_t *client);
* Get task.
* @param client the client to get task from
*/
-RTSP_DECLARE(apt_task_t*) rtsp_client_task_get(rtsp_client_t *client);
+RTSP_DECLARE(apt_task_t*) rtsp_client_task_get(const rtsp_client_t *client);
/**
* Get external object.
* @param client the client to get object from
*/
-RTSP_DECLARE(void*) rtsp_client_object_get(rtsp_client_t *client);
+RTSP_DECLARE(void*) rtsp_client_object_get(const rtsp_client_t *client);
/**
@@ -146,4 +150,4 @@ RTSP_DECLARE(const apt_str_t*) rtsp_client_session_id_get(const rtsp_client_sess
APT_END_EXTERN_C
-#endif /*__RTSP_CLIENT_H__*/
+#endif /* RTSP_CLIENT_H */
diff --git a/libs/unimrcp/libs/uni-rtsp/include/rtsp_header.h b/libs/unimrcp/libs/uni-rtsp/include/rtsp_header.h
index 2a71c6ed2d..4345ad4606 100644
--- a/libs/unimrcp/libs/uni-rtsp/include/rtsp_header.h
+++ b/libs/unimrcp/libs/uni-rtsp/include/rtsp_header.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: rtsp_header.h 1648 2010-04-12 20:03:59Z achaloyan $
*/
-#ifndef __RTSP_HEADER_H__
-#define __RTSP_HEADER_H__
+#ifndef RTSP_HEADER_H
+#define RTSP_HEADER_H
/**
* @file rtsp_header.h
@@ -23,7 +25,7 @@
*/
#include "rtsp.h"
-#include "apt_text_stream.h"
+#include "apt_header_field.h"
APT_BEGIN_EXTERN_C
@@ -99,9 +101,6 @@ typedef enum {
} rtsp_content_type_e;
-/** Bit field masks are used to define property set */
-typedef int rtsp_header_property_t;
-
/** RTSP/RTP port range declaration */
typedef struct rtsp_port_range_t rtsp_port_range_t;
@@ -156,8 +155,8 @@ struct rtsp_header_t {
/** Content length */
apr_size_t content_length;
- /** Property set */
- rtsp_header_property_t property_set;
+ /** Header section (collection of header fields)*/
+ apt_header_section_t header_section;
};
@@ -188,7 +187,7 @@ static APR_INLINE void rtsp_transport_init(rtsp_transport_t *transport)
}
/** Initialize header */
-static APR_INLINE void rtsp_header_init(rtsp_header_t *header)
+static APR_INLINE void rtsp_header_init(rtsp_header_t *header, apr_pool_t *pool)
{
header->cseq = 0;
rtsp_transport_init(&header->transport);
@@ -196,37 +195,38 @@ static APR_INLINE void rtsp_header_init(rtsp_header_t *header)
apt_string_reset(&header->rtp_info);
header->content_type = RTSP_CONTENT_TYPE_NONE;
header->content_length = 0;
- header->property_set = 0;
+
+ apt_header_section_init(&header->header_section);
+ apt_header_section_array_alloc(&header->header_section,RTSP_HEADER_FIELD_COUNT,pool);
}
-/** Parse RTSP message */
-RTSP_DECLARE(apt_bool_t) rtsp_header_parse(rtsp_header_t *header, apt_text_stream_t *text_stream, apr_pool_t *pool);
-/** Generate RTSP message */
-RTSP_DECLARE(apt_bool_t) rtsp_header_generate(rtsp_header_t *header, apt_text_stream_t *text_stream);
+/** Add RTSP header field */
+RTSP_DECLARE(apt_bool_t) rtsp_header_field_add(rtsp_header_t *header, apt_header_field_t *header_field, apr_pool_t *pool);
+/** Parse RTSP header fields */
+RTSP_DECLARE(apt_bool_t) rtsp_header_fields_parse(rtsp_header_t *header, apr_pool_t *pool);
-/** Add property to property set */
-static APR_INLINE void rtsp_header_property_add(rtsp_header_property_t *property_set, apr_size_t id)
+/** Add RTSP header field property */
+RTSP_DECLARE(apt_bool_t) rtsp_header_property_add(rtsp_header_t *header, rtsp_header_field_id id, apr_pool_t *pool);
+
+/** Remove RTSP header field property */
+static APR_INLINE apt_bool_t rtsp_header_property_remove(rtsp_header_t *header, rtsp_header_field_id id)
{
- int mask = 1 << id;
- *property_set |= mask;
+ apt_header_field_t *header_field = apt_header_section_field_get(&header->header_section,id);
+ if(header_field) {
+ return apt_header_section_field_remove(&header->header_section,header_field);
+ }
+ return FALSE;
}
-/** Remove property from property set */
-static APR_INLINE void rtsp_header_property_remove(rtsp_header_property_t *property_set, apr_size_t id)
+/** Check RTSP header field property */
+static APR_INLINE apt_bool_t rtsp_header_property_check(const rtsp_header_t *header, rtsp_header_field_id id)
{
- int mask = 1 << id;
- *property_set &= ~mask;
+ return apt_header_section_field_check(&header->header_section,id);
}
-/** Check property in property set */
-static APR_INLINE apt_bool_t rtsp_header_property_check(const rtsp_header_property_t *property_set, apr_size_t id)
-{
- int mask = 1 << id;
- return ((*property_set & mask) == mask) ? TRUE : FALSE;
-}
APT_END_EXTERN_C
-#endif /*__RTSP_HEADER_H__*/
+#endif /* RTSP_HEADER_H */
diff --git a/libs/unimrcp/libs/uni-rtsp/include/rtsp_message.h b/libs/unimrcp/libs/uni-rtsp/include/rtsp_message.h
index ae57237614..71546d31e5 100644
--- a/libs/unimrcp/libs/uni-rtsp/include/rtsp_message.h
+++ b/libs/unimrcp/libs/uni-rtsp/include/rtsp_message.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: rtsp_message.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __RTSP_MESSAGE_H__
-#define __RTSP_MESSAGE_H__
+#ifndef RTSP_MESSAGE_H
+#define RTSP_MESSAGE_H
/**
* @file rtsp_message.h
@@ -73,4 +75,4 @@ RTSP_DECLARE(void) rtsp_message_destroy(rtsp_message_t *message);
APT_END_EXTERN_C
-#endif /*__RTSP_MESSAGE_H__*/
+#endif /* RTSP_MESSAGE_H */
diff --git a/libs/unimrcp/libs/uni-rtsp/include/rtsp_server.h b/libs/unimrcp/libs/uni-rtsp/include/rtsp_server.h
index bf57ce176f..19e2131fb3 100644
--- a/libs/unimrcp/libs/uni-rtsp/include/rtsp_server.h
+++ b/libs/unimrcp/libs/uni-rtsp/include/rtsp_server.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: rtsp_server.h 1710 2010-05-24 17:36:19Z achaloyan $
*/
-#ifndef __RTSP_SERVER_H__
-#define __RTSP_SERVER_H__
+#ifndef RTSP_SERVER_H
+#define RTSP_SERVER_H
/**
* @file rtsp_server.h
@@ -84,13 +86,13 @@ RTSP_DECLARE(apt_bool_t) rtsp_server_terminate(rtsp_server_t *server);
* Get task.
* @param server the server to get task from
*/
-RTSP_DECLARE(apt_task_t*) rtsp_server_task_get(rtsp_server_t *server);
+RTSP_DECLARE(apt_task_t*) rtsp_server_task_get(const rtsp_server_t *server);
/**
* Get external object.
* @param server the server to get object from
*/
-RTSP_DECLARE(void*) rtsp_server_object_get(rtsp_server_t *server);
+RTSP_DECLARE(void*) rtsp_server_object_get(const rtsp_server_t *server);
/**
* Send RTSP message.
@@ -140,4 +142,4 @@ RTSP_DECLARE(const char*) rtsp_server_session_destination_get(const rtsp_server_
APT_END_EXTERN_C
-#endif /*__RTSP_SERVER_H__*/
+#endif /* RTSP_SERVER_H */
diff --git a/libs/unimrcp/libs/uni-rtsp/include/rtsp_start_line.h b/libs/unimrcp/libs/uni-rtsp/include/rtsp_start_line.h
index 99b73880e6..8fe8c85c37 100644
--- a/libs/unimrcp/libs/uni-rtsp/include/rtsp_start_line.h
+++ b/libs/unimrcp/libs/uni-rtsp/include/rtsp_start_line.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: rtsp_start_line.h 1632 2010-03-30 20:46:25Z achaloyan $
*/
-#ifndef __RTSP_START_LINE_H__
-#define __RTSP_START_LINE_H__
+#ifndef RTSP_START_LINE_H
+#define RTSP_START_LINE_H
/**
* @file rtsp_start_line.h
@@ -65,6 +67,8 @@ typedef enum {
RTSP_STATUS_CODE_NOT_FOUND = 404,
RTSP_STATUS_CODE_METHOD_NOT_ALLOWED = 405,
RTSP_STATUS_CODE_NOT_ACCEPTABLE = 406,
+ RTSP_STATUS_CODE_PROXY_AUTH_REQUIRED = 407,
+ RTSP_STATUS_CODE_REQUEST_TIMEOUT = 408,
RTSP_STATUS_CODE_SESSION_NOT_FOUND = 454,
RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR = 500,
@@ -80,6 +84,8 @@ typedef enum {
RTSP_REASON_PHRASE_NOT_FOUND,
RTSP_REASON_PHRASE_METHOD_NOT_ALLOWED,
RTSP_REASON_PHRASE_NOT_ACCEPTABLE,
+ RTSP_REASON_PHRASE_PROXY_AUTH_REQUIRED,
+ RTSP_REASON_PHRASE_REQUEST_TIMEOUT,
RTSP_REASON_PHRASE_SESSION_NOT_FOUND,
RTSP_REASON_PHRASE_INTERNAL_SERVER_ERROR,
RTSP_REASON_PHRASE_NOT_IMPLEMENTED,
@@ -162,7 +168,7 @@ static APR_INLINE void rtsp_start_line_init(rtsp_start_line_t *start_line, rtsp_
}
/** Parse RTSP start-line */
-RTSP_DECLARE(apt_bool_t) rtsp_start_line_parse(rtsp_start_line_t *start_line, apt_text_stream_t *text_stream, apr_pool_t *pool);
+RTSP_DECLARE(apt_bool_t) rtsp_start_line_parse(rtsp_start_line_t *start_line, apt_str_t *str, apr_pool_t *pool);
/** Generate RTSP start-line */
RTSP_DECLARE(apt_bool_t) rtsp_start_line_generate(rtsp_start_line_t *start_line, apt_text_stream_t *text_stream);
@@ -172,4 +178,4 @@ RTSP_DECLARE(const apt_str_t*) rtsp_reason_phrase_get(rtsp_reason_phrase_e reaso
APT_END_EXTERN_C
-#endif /*__RTSP_START_LINE_H__*/
+#endif /* RTSP_START_LINE_H */
diff --git a/libs/unimrcp/libs/uni-rtsp/include/rtsp_stream.h b/libs/unimrcp/libs/uni-rtsp/include/rtsp_stream.h
index 3d9e31b260..ecebef6055 100644
--- a/libs/unimrcp/libs/uni-rtsp/include/rtsp_stream.h
+++ b/libs/unimrcp/libs/uni-rtsp/include/rtsp_stream.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: rtsp_stream.h 1632 2010-03-30 20:46:25Z achaloyan $
*/
-#ifndef __RTSP_STREAM_H__
-#define __RTSP_STREAM_H__
+#ifndef RTSP_STREAM_H
+#define RTSP_STREAM_H
/**
* @file rtsp_stream.h
@@ -23,47 +25,30 @@
*/
#include "rtsp_message.h"
+#include "apt_text_message.h"
APT_BEGIN_EXTERN_C
-/** Status of RTSP stream processing (parse/generate) */
-typedef enum {
- RTSP_STREAM_STATUS_COMPLETE,
- RTSP_STREAM_STATUS_INCOMPLETE,
- RTSP_STREAM_STATUS_INVALID
-} rtsp_stream_status_e;
-
/** Opaque RTSP parser declaration */
typedef struct rtsp_parser_t rtsp_parser_t;
/** Opaque RTSP generator declaration */
typedef struct rtsp_generator_t rtsp_generator_t;
-/** RTSP message handler */
-typedef apt_bool_t (*rtsp_message_handler_f)(void *obj, rtsp_message_t *message, rtsp_stream_status_e status);
/** Create RTSP stream parser */
RTSP_DECLARE(rtsp_parser_t*) rtsp_parser_create(apr_pool_t *pool);
/** Parse RTSP stream */
-RTSP_DECLARE(rtsp_stream_status_e) rtsp_parser_run(rtsp_parser_t *parser, apt_text_stream_t *stream);
-
-/** Get parsed RTSP message */
-RTSP_DECLARE(rtsp_message_t*) rtsp_parser_message_get(const rtsp_parser_t *parser);
+RTSP_DECLARE(apt_message_status_e) rtsp_parser_run(rtsp_parser_t *parser, apt_text_stream_t *stream, rtsp_message_t **message);
/** Create RTSP stream generator */
RTSP_DECLARE(rtsp_generator_t*) rtsp_generator_create(apr_pool_t *pool);
-/** Set RTSP message to generate */
-RTSP_DECLARE(apt_bool_t) rtsp_generator_message_set(rtsp_generator_t *generator, rtsp_message_t *message);
-
/** Generate RTSP stream */
-RTSP_DECLARE(rtsp_stream_status_e) rtsp_generator_run(rtsp_generator_t *generator, apt_text_stream_t *stream);
+RTSP_DECLARE(apt_message_status_e) rtsp_generator_run(rtsp_generator_t *generator, rtsp_message_t *message, apt_text_stream_t *stream);
-/** Walk through RTSP stream and call message handler for each parsed message */
-RTSP_DECLARE(apt_bool_t) rtsp_stream_walk(rtsp_parser_t *parser, apt_text_stream_t *stream, rtsp_message_handler_f handler, void *obj);
-
APT_END_EXTERN_C
-#endif /*__RTSP_STREAM_H__*/
+#endif /* RTSP_STREAM_H */
diff --git a/libs/unimrcp/libs/uni-rtsp/src/rtsp_client.c b/libs/unimrcp/libs/uni-rtsp/src/rtsp_client.c
index 044dd0623e..9c4d23ba90 100644
--- a/libs/unimrcp/libs/uni-rtsp/src/rtsp_client.c
+++ b/libs/unimrcp/libs/uni-rtsp/src/rtsp_client.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,12 +12,14 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: rtsp_client.c 1710 2010-05-24 17:36:19Z achaloyan $
*/
#include
#include "rtsp_client.h"
#include "rtsp_stream.h"
-#include "apt_net_client_task.h"
+#include "apt_poller_task.h"
#include "apt_text_stream.h"
#include "apt_pool.h"
#include "apt_obj_list.h"
@@ -36,42 +38,50 @@ typedef enum {
/** RTSP client */
struct rtsp_client_t {
apr_pool_t *pool;
- apt_net_client_task_t *task;
+ apt_poller_task_t *task;
apr_pool_t *sub_pool;
apt_obj_list_t *connection_list;
+ apr_uint32_t request_timeout;
+
void *obj;
const rtsp_client_vtable_t *vtable;
};
/** RTSP connection */
struct rtsp_client_connection_t {
- /** Connection base */
- apt_net_client_connection_t *base;
+ /** Memory pool */
+ apr_pool_t *pool;
+ /** Connected socket */
+ apr_socket_t *sock;
+ /** Socket poll descriptor */
+ apr_pollfd_t sock_pfd;
+ /** String identifier used for traces */
+ const char *id;
/** RTSP client, connection belongs to */
- rtsp_client_t *client;
+ rtsp_client_t *client;
/** Element of the connection list in agent */
- apt_list_elem_t *it;
+ apt_list_elem_t *it;
/** Handle table (rtsp_client_session_t*) */
- apr_hash_t *handle_table;
+ apr_hash_t *handle_table;
/** Session table (rtsp_client_session_t*) */
- apr_hash_t *session_table;
+ apr_hash_t *session_table;
/** Inprogress request/session queue (rtsp_client_session_t*) */
- apt_obj_list_t *inprogress_request_queue;
+ apt_obj_list_t *inprogress_request_queue;
/** Last CSeq sent */
- apr_size_t last_cseq;
+ apr_size_t last_cseq;
- char rx_buffer[RTSP_STREAM_BUFFER_SIZE];
- apt_text_stream_t rx_stream;
- rtsp_parser_t *parser;
+ char rx_buffer[RTSP_STREAM_BUFFER_SIZE];
+ apt_text_stream_t rx_stream;
+ rtsp_parser_t *parser;
- char tx_buffer[RTSP_STREAM_BUFFER_SIZE];
- apt_text_stream_t tx_stream;
- rtsp_generator_t *generator;
+ char tx_buffer[RTSP_STREAM_BUFFER_SIZE];
+ apt_text_stream_t tx_stream;
+ rtsp_generator_t *generator;
};
/** RTSP session */
@@ -93,6 +103,9 @@ struct rtsp_client_session_t {
/** Pending request queue (rtsp_message_t*) */
apt_obj_list_t *pending_request_queue;
+ /** Timer used for request timeouts */
+ apt_timer_t *request_timer;
+
/** Resource table */
apr_hash_t *resource_table;
@@ -116,23 +129,22 @@ struct task_msg_data_t {
static apt_bool_t rtsp_client_task_msg_process(apt_task_t *task, apt_task_msg_t *msg);
-static apt_bool_t rtsp_client_message_receive(apt_net_client_task_t *task, apt_net_client_connection_t *connection);
+static apt_bool_t rtsp_client_poller_signal_process(void *obj, const apr_pollfd_t *descriptor);
-static const apt_net_client_vtable_t client_vtable = {
- rtsp_client_message_receive
-};
-
-static apt_bool_t rtsp_client_message_send(rtsp_client_t *client, apt_net_client_connection_t *connection, rtsp_message_t *message);
+static apt_bool_t rtsp_client_message_send(rtsp_client_t *client, rtsp_client_connection_t *connection, rtsp_message_t *message);
static apt_bool_t rtsp_client_session_message_process(rtsp_client_t *client, rtsp_client_session_t *session, rtsp_message_t *message);
static apt_bool_t rtsp_client_session_request_process(rtsp_client_t *client, rtsp_client_session_t *session, rtsp_message_t *message);
static apt_bool_t rtsp_client_session_response_process(rtsp_client_t *client, rtsp_client_session_t *session, rtsp_message_t *request, rtsp_message_t *response);
+static void rtsp_client_timer_proc(apt_timer_t *timer, void *obj);
+
/** Create RTSP client */
RTSP_DECLARE(rtsp_client_t*) rtsp_client_create(
- apr_size_t max_connection_count,
- void *obj,
- const rtsp_client_vtable_t *handler,
- apr_pool_t *pool)
+ apr_size_t max_connection_count,
+ apr_size_t request_timeout,
+ void *obj,
+ const rtsp_client_vtable_t *handler,
+ apr_pool_t *pool)
{
apt_task_vtable_t *vtable;
apt_task_msg_pool_t *msg_pool;
@@ -146,18 +158,24 @@ RTSP_DECLARE(rtsp_client_t*) rtsp_client_create(
msg_pool = apt_task_msg_pool_create_dynamic(sizeof(task_msg_data_t),pool);
- client->task = apt_net_client_task_create(max_connection_count,client,&client_vtable,msg_pool,pool);
+ client->task = apt_poller_task_create(
+ max_connection_count,
+ rtsp_client_poller_signal_process,
+ client,
+ msg_pool,
+ pool);
if(!client->task) {
return NULL;
}
- vtable = apt_net_client_task_vtable_get(client->task);
+ vtable = apt_poller_task_vtable_get(client->task);
if(vtable) {
vtable->process_msg = rtsp_client_task_msg_process;
}
client->sub_pool = apt_subpool_create(pool);
client->connection_list = NULL;
+ client->request_timeout = (apr_uint32_t)request_timeout;
return client;
}
@@ -165,29 +183,29 @@ RTSP_DECLARE(rtsp_client_t*) rtsp_client_create(
RTSP_DECLARE(apt_bool_t) rtsp_client_destroy(rtsp_client_t *client)
{
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Destroy RTSP Client");
- return apt_net_client_task_destroy(client->task);
+ return apt_poller_task_destroy(client->task);
}
/** Start connection agent */
RTSP_DECLARE(apt_bool_t) rtsp_client_start(rtsp_client_t *client)
{
- return apt_net_client_task_start(client->task);
+ return apt_poller_task_start(client->task);
}
/** Terminate connection agent */
RTSP_DECLARE(apt_bool_t) rtsp_client_terminate(rtsp_client_t *client)
{
- return apt_net_client_task_terminate(client->task);
+ return apt_poller_task_terminate(client->task);
}
/** Get task */
-RTSP_DECLARE(apt_task_t*) rtsp_client_task_get(rtsp_client_t *client)
+RTSP_DECLARE(apt_task_t*) rtsp_client_task_get(const rtsp_client_t *client)
{
- return apt_net_client_task_base_get(client->task);
+ return apt_poller_task_base_get(client->task);
}
/** Get external object */
-RTSP_DECLARE(void*) rtsp_client_object_get(rtsp_client_t *client)
+RTSP_DECLARE(void*) rtsp_client_object_get(const rtsp_client_t *client)
{
return client->obj;
}
@@ -217,7 +235,7 @@ static apt_bool_t rtsp_client_control_message_signal(
rtsp_client_session_t *session,
rtsp_message_t *message)
{
- apt_task_t *task = apt_net_client_task_base_get(client->task);
+ apt_task_t *task = apt_poller_task_base_get(client->task);
apt_task_msg_t *task_msg = apt_task_msg_get(task);
if(task_msg) {
task_msg_data_t *data = (task_msg_data_t*)task_msg->data;
@@ -245,6 +263,11 @@ RTSP_DECLARE(rtsp_client_session_t*) rtsp_client_session_create(
session->connection = NULL;
session->active_request = NULL;
session->pending_request_queue = apt_list_create(pool);
+ session->request_timer = apt_poller_task_timer_create(
+ client->task,
+ rtsp_client_timer_proc,
+ session,
+ pool);
session->resource_table = apr_hash_make(pool);
session->term_state = TERMINATION_STATE_NONE;
@@ -277,31 +300,107 @@ RTSP_DECLARE(apt_bool_t) rtsp_client_session_request(rtsp_client_t *client, rtsp
return rtsp_client_control_message_signal(TASK_MSG_SEND_MESSAGE,client,session,message);
}
+
+/** Create connection */
+static apt_bool_t rtsp_client_connect(rtsp_client_connection_t *connection, apt_pollset_t *pollset, const char *ip, apr_port_t port)
+{
+ char *local_ip = NULL;
+ char *remote_ip = NULL;
+ apr_sockaddr_t *l_sockaddr = NULL;
+ apr_sockaddr_t *r_sockaddr = NULL;
+
+ if(apr_sockaddr_info_get(&r_sockaddr,ip,APR_INET,port,0,connection->pool) != APR_SUCCESS) {
+ return FALSE;
+ }
+
+ if(apr_socket_create(&connection->sock,r_sockaddr->family,SOCK_STREAM,APR_PROTO_TCP,connection->pool) != APR_SUCCESS) {
+ return FALSE;
+ }
+
+ apr_socket_opt_set(connection->sock, APR_SO_NONBLOCK, 0);
+ apr_socket_timeout_set(connection->sock, -1);
+ apr_socket_opt_set(connection->sock, APR_SO_REUSEADDR, 1);
+
+ if(apr_socket_connect(connection->sock,r_sockaddr) != APR_SUCCESS) {
+ apr_socket_close(connection->sock);
+ connection->sock = NULL;
+ return FALSE;
+ }
+
+ if(apr_socket_addr_get(&l_sockaddr,APR_LOCAL,connection->sock) != APR_SUCCESS) {
+ apr_socket_close(connection->sock);
+ connection->sock = NULL;
+ return FALSE;
+ }
+
+ apr_sockaddr_ip_get(&local_ip,l_sockaddr);
+ apr_sockaddr_ip_get(&remote_ip,r_sockaddr);
+ connection->id = apr_psprintf(connection->pool,"%s:%hu <-> %s:%hu",
+ local_ip,l_sockaddr->port,
+ remote_ip,r_sockaddr->port);
+
+ memset(&connection->sock_pfd,0,sizeof(apr_pollfd_t));
+ connection->sock_pfd.desc_type = APR_POLL_SOCKET;
+ connection->sock_pfd.reqevents = APR_POLLIN;
+ connection->sock_pfd.desc.s = connection->sock;
+ connection->sock_pfd.client_data = connection;
+ if(apt_pollset_add(pollset,&connection->sock_pfd) != TRUE) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Add to Pollset %s",connection->id);
+ apr_socket_close(connection->sock);
+ connection->sock = NULL;
+ return FALSE;
+ }
+
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Established RTSP Connection %s",connection->id);
+ return TRUE;
+}
+
+/** Close connection */
+static apt_bool_t rtsp_client_connection_close(rtsp_client_connection_t *connection, apt_pollset_t *pollset)
+{
+ if(connection->sock) {
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Close RTSP Connection %s",connection->id);
+ apt_pollset_remove(pollset,&connection->sock_pfd);
+ apr_socket_close(connection->sock);
+ connection->sock = NULL;
+ }
+ return TRUE;
+}
+
+
/* Create RTSP connection */
static apt_bool_t rtsp_client_connection_create(rtsp_client_t *client, rtsp_client_session_t *session)
{
rtsp_client_connection_t *rtsp_connection;
- apt_net_client_connection_t *connection = apt_net_client_connect(client->task,session->server_ip.buf,session->server_port);
- if(!connection) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Connect to RTSP Server %s:%d",session->server_ip.buf,session->server_port);
+ apt_pollset_t *pollset = apt_poller_task_pollset_get(client->task);
+ apr_pool_t *pool = apt_pool_create();
+ if(!pool) {
return FALSE;
}
- rtsp_connection = apr_palloc(connection->pool,sizeof(rtsp_client_connection_t));
- rtsp_connection->handle_table = apr_hash_make(connection->pool);
- rtsp_connection->session_table = apr_hash_make(connection->pool);
- rtsp_connection->inprogress_request_queue = apt_list_create(connection->pool);
+
+ rtsp_connection = apr_palloc(pool,sizeof(rtsp_client_connection_t));
+ rtsp_connection->pool = pool;
+ rtsp_connection->sock = NULL;
+
+ if(rtsp_client_connect(rtsp_connection,pollset,session->server_ip.buf,session->server_port) == FALSE) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Connect to RTSP Server %s:%hu",
+ session->server_ip.buf,session->server_port);
+ apr_pool_destroy(pool);
+ return FALSE;
+ }
+ rtsp_connection->handle_table = apr_hash_make(pool);
+ rtsp_connection->session_table = apr_hash_make(pool);
+ rtsp_connection->inprogress_request_queue = apt_list_create(pool);
apt_text_stream_init(&rtsp_connection->rx_stream,rtsp_connection->rx_buffer,sizeof(rtsp_connection->rx_buffer)-1);
apt_text_stream_init(&rtsp_connection->tx_stream,rtsp_connection->tx_buffer,sizeof(rtsp_connection->tx_buffer)-1);
- rtsp_connection->parser = rtsp_parser_create(connection->pool);
- rtsp_connection->generator = rtsp_generator_create(connection->pool);
+ rtsp_connection->parser = rtsp_parser_create(pool);
+ rtsp_connection->generator = rtsp_generator_create(pool);
rtsp_connection->last_cseq = 0;
- rtsp_connection->base = connection;
- connection->obj = rtsp_connection;
if(!client->connection_list) {
client->connection_list = apt_list_create(client->sub_pool);
}
rtsp_connection->client = client;
- rtsp_connection->it = apt_list_push_back(client->connection_list,rtsp_connection,connection->pool);
+ rtsp_connection->it = apt_list_push_back(client->connection_list,rtsp_connection,pool);
session->connection = rtsp_connection;
return TRUE;
}
@@ -310,8 +409,11 @@ static apt_bool_t rtsp_client_connection_create(rtsp_client_t *client, rtsp_clie
static apt_bool_t rtsp_client_connection_destroy(rtsp_client_connection_t *rtsp_connection)
{
rtsp_client_t *client = rtsp_connection->client;
+ apt_pollset_t *pollset = apt_poller_task_pollset_get(client->task);
apt_list_elem_remove(client->connection_list,rtsp_connection->it);
- apt_net_client_disconnect(client->task,rtsp_connection->base);
+ rtsp_client_connection_close(rtsp_connection,pollset);
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Destroy RTSP Connection %s",rtsp_connection->id);
+ apr_pool_destroy(rtsp_connection->pool);
if(apt_list_is_empty(client->connection_list) == TRUE) {
apr_pool_clear(client->sub_pool);
@@ -389,14 +491,14 @@ static apt_bool_t rtsp_client_session_url_generate(rtsp_client_session_t *sessio
{
apt_str_t *url = &message->start_line.common.request_line.url;
if(session->resource_location.length) {
- url->buf = apr_psprintf(message->pool,"rtsp://%s:%d/%s/%s",
+ url->buf = apr_psprintf(message->pool,"rtsp://%s:%hu/%s/%s",
session->server_ip.buf,
session->server_port,
session->resource_location.buf,
message->start_line.common.request_line.resource_name);
}
else {
- url->buf = apr_psprintf(message->pool,"rtsp://%s:%d/%s",
+ url->buf = apr_psprintf(message->pool,"rtsp://%s:%hu/%s",
session->server_ip.buf,
session->server_port,
message->start_line.common.request_line.resource_name);
@@ -414,6 +516,9 @@ static apt_bool_t rtsp_client_request_push(rtsp_client_connection_t *rtsp_connec
message->header.cseq);
apt_list_push_back(rtsp_connection->inprogress_request_queue,session,session->pool);
session->active_request = message;
+ if(rtsp_connection->client->request_timeout) {
+ apt_timer_set(session->request_timer,rtsp_connection->client->request_timeout);
+ }
return TRUE;
}
@@ -435,6 +540,7 @@ static apt_bool_t rtsp_client_request_pop(rtsp_client_connection_t *rtsp_connect
response->header.cseq);
apt_list_elem_remove(rtsp_connection->inprogress_request_queue,elem);
session->active_request = NULL;
+ apt_timer_kill(session->request_timer);
return TRUE;
}
elem = apt_list_next_elem_get(rtsp_connection->inprogress_request_queue,elem);
@@ -459,13 +565,13 @@ static apt_bool_t rtsp_client_session_request_process(rtsp_client_t *client, rts
if(session->id.length) {
message->header.session_id = session->id;
- rtsp_header_property_add(&message->header.property_set,RTSP_HEADER_FIELD_SESSION_ID);
+ rtsp_header_property_add(&message->header,RTSP_HEADER_FIELD_SESSION_ID,message->pool);
}
message->header.cseq = ++session->connection->last_cseq;
- rtsp_header_property_add(&message->header.property_set,RTSP_HEADER_FIELD_CSEQ);
+ rtsp_header_property_add(&message->header,RTSP_HEADER_FIELD_CSEQ,message->pool);
- if(rtsp_client_message_send(client,session->connection->base,message) == FALSE) {
+ if(rtsp_client_message_send(client,session->connection,message) == FALSE) {
/* respond with error */
return FALSE;
}
@@ -533,7 +639,7 @@ static apt_bool_t rtsp_client_session_event_process(rtsp_client_t *client, rtsp_
{
rtsp_message_t *response = NULL;
rtsp_client_session_t *session = NULL;
- if(rtsp_header_property_check(&message->header.property_set,RTSP_HEADER_FIELD_SESSION_ID) == TRUE) {
+ if(rtsp_header_property_check(&message->header,RTSP_HEADER_FIELD_SESSION_ID) == TRUE) {
/* find existing session */
session = apr_hash_get(
rtsp_connection->session_table,
@@ -543,9 +649,9 @@ static apt_bool_t rtsp_client_session_event_process(rtsp_client_t *client, rtsp_
if(session) {
response = rtsp_response_create(message,RTSP_STATUS_CODE_OK,RTSP_REASON_PHRASE_OK,message->pool);
- if(rtsp_header_property_check(&message->header.property_set,RTSP_HEADER_FIELD_SESSION_ID) == TRUE) {
+ if(rtsp_header_property_check(&message->header,RTSP_HEADER_FIELD_SESSION_ID) == TRUE) {
response->header.session_id = message->header.session_id;
- rtsp_header_property_add(&response->header.property_set,RTSP_HEADER_FIELD_SESSION_ID);
+ rtsp_header_property_add(&response->header,RTSP_HEADER_FIELD_SESSION_ID,message->pool);
}
client->vtable->on_session_event(client,session,message);
}
@@ -553,7 +659,7 @@ static apt_bool_t rtsp_client_session_event_process(rtsp_client_t *client, rtsp_
response = rtsp_response_create(message,RTSP_STATUS_CODE_NOT_FOUND,RTSP_REASON_PHRASE_NOT_FOUND,message->pool);
}
- return rtsp_client_message_send(client,rtsp_connection->base,response);
+ return rtsp_client_message_send(client,rtsp_connection,response);
}
/* Process incoming RTSP response */
@@ -564,7 +670,7 @@ static apt_bool_t rtsp_client_session_response_process(rtsp_client_t *client, rt
response->start_line.common.status_line.status_code == RTSP_STATUS_CODE_OK) {
if(apr_hash_count(session->resource_table) == 0) {
- if(rtsp_header_property_check(&response->header.property_set,RTSP_HEADER_FIELD_SESSION_ID) == TRUE) {
+ if(rtsp_header_property_check(&response->header,RTSP_HEADER_FIELD_SESSION_ID) == TRUE) {
session->id = response->header.session_id;
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Add RTSP Session "APT_PTRSID_FMT,
session,
@@ -629,32 +735,55 @@ static apt_bool_t rtsp_client_session_terminate_raise(rtsp_client_t *client, rts
return TRUE;
}
+/* Cancel RTSP request */
+static apt_bool_t rtsp_client_request_cancel(rtsp_client_t *client, rtsp_client_session_t *session, rtsp_status_code_e status_code, rtsp_reason_phrase_e reason)
+{
+ rtsp_message_t *request;
+ rtsp_message_t *response;
+ if(!session->active_request) {
+ return FALSE;
+ }
+
+ request = session->active_request;
+ session->active_request = NULL;
+
+ response = rtsp_response_create(
+ request,
+ status_code,
+ reason,
+ session->pool);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Cancel RTSP Request "APT_PTRSID_FMT" CSeq:%"APR_SIZE_T_FMT" [%d]",
+ session,
+ request->header.session_id.buf ? request->header.session_id.buf : "new",
+ request->header.cseq,
+ status_code);
+ rtsp_client_session_response_process(client,session,request,response);
+ return TRUE;
+}
+
/* RTSP connection disconnected */
static apt_bool_t rtsp_client_on_disconnect(rtsp_client_t *client, rtsp_client_connection_t *rtsp_connection)
{
rtsp_client_session_t *session;
- rtsp_message_t *request;
- rtsp_message_t *response;
apr_size_t remaining_handles = 0;
apr_size_t cancelled_requests = 0;
+ apt_pollset_t *pollset = apt_poller_task_pollset_get(client->task);
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"TCP Peer Disconnected %s", rtsp_connection->base->id);
- apt_net_client_connection_close(client->task,rtsp_connection->base);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"RTSP Peer Disconnected %s", rtsp_connection->id);
+ rtsp_client_connection_close(rtsp_connection,pollset);
/* Cancel in-progreess requests */
do {
session = apt_list_pop_front(rtsp_connection->inprogress_request_queue);
- if(session && session->active_request) {
- request = session->active_request;
- session->active_request = NULL;
- cancelled_requests++;
-
- response = rtsp_response_create(
- request,
- RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR,
- RTSP_REASON_PHRASE_INTERNAL_SERVER_ERROR,
- session->pool);
- rtsp_client_session_response_process(client,session,request,response);
+ if(session) {
+ if(rtsp_client_request_cancel(
+ client,
+ session,
+ RTSP_STATUS_CODE_INTERNAL_SERVER_ERROR,
+ RTSP_REASON_PHRASE_INTERNAL_SERVER_ERROR) == TRUE) {
+ cancelled_requests++;
+ apt_timer_kill(session->request_timer);
+ }
}
}
while(session);
@@ -665,7 +794,7 @@ static apt_bool_t rtsp_client_on_disconnect(rtsp_client_t *client, rtsp_client_c
void *val;
apr_hash_index_t *it;
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Terminate Remaining RTSP Handles [%"APR_SIZE_T_FMT"]",remaining_handles);
- it = apr_hash_first(rtsp_connection->base->pool,rtsp_connection->session_table);
+ it = apr_hash_first(rtsp_connection->pool,rtsp_connection->session_table);
for(; it; it = apr_hash_next(it)) {
apr_hash_this(it,NULL,NULL,&val);
session = val;
@@ -683,34 +812,31 @@ static apt_bool_t rtsp_client_on_disconnect(rtsp_client_t *client, rtsp_client_c
}
/* Send RTSP message through RTSP connection */
-static apt_bool_t rtsp_client_message_send(rtsp_client_t *client, apt_net_client_connection_t *connection, rtsp_message_t *message)
+static apt_bool_t rtsp_client_message_send(rtsp_client_t *client, rtsp_client_connection_t *rtsp_connection, rtsp_message_t *message)
{
apt_bool_t status = FALSE;
- rtsp_client_connection_t *rtsp_connection;
apt_text_stream_t *stream;
- rtsp_stream_status_e result;
+ apt_message_status_e result;
- if(!connection || !connection->sock) {
+ if(!rtsp_connection || !rtsp_connection->sock) {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No RTSP Connection");
return FALSE;
}
- rtsp_connection = connection->obj;
stream = &rtsp_connection->tx_stream;
- rtsp_generator_message_set(rtsp_connection->generator,message);
do {
stream->text.length = sizeof(rtsp_connection->tx_buffer)-1;
apt_text_stream_reset(stream);
- result = rtsp_generator_run(rtsp_connection->generator,stream);
- if(result != RTSP_STREAM_STATUS_INVALID) {
+ result = rtsp_generator_run(rtsp_connection->generator,message,stream);
+ if(result != APT_MESSAGE_STATUS_INVALID) {
stream->text.length = stream->pos - stream->text.buf;
*stream->pos = '\0';
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Send RTSP Stream %s [%lu bytes]\n%s",
- connection->id,
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Send RTSP Stream %s [%"APR_SIZE_T_FMT" bytes]\n%s",
+ rtsp_connection->id,
stream->text.length,
stream->text.buf);
- if(apr_socket_send(connection->sock,stream->text.buf,&stream->text.length) == APR_SUCCESS) {
+ if(apr_socket_send(rtsp_connection->sock,stream->text.buf,&stream->text.length) == APR_SUCCESS) {
status = TRUE;
}
else {
@@ -721,16 +847,15 @@ static apt_bool_t rtsp_client_message_send(rtsp_client_t *client, apt_net_client
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Generate RTSP Stream");
}
}
- while(result == RTSP_STREAM_STATUS_INCOMPLETE);
+ while(result == APT_MESSAGE_STATUS_INCOMPLETE);
return status;
}
-/** return TRUE to proceed with the next message in the stream (if any) */
-static apt_bool_t rtsp_client_message_handler(void *obj, rtsp_message_t *message, rtsp_stream_status_e status)
+/** Return TRUE to proceed with the next message in the stream (if any) */
+static apt_bool_t rtsp_client_message_handler(rtsp_client_connection_t *rtsp_connection, rtsp_message_t *message, apt_message_status_e status)
{
- rtsp_client_connection_t *rtsp_connection = obj;
- if(status != RTSP_STREAM_STATUS_COMPLETE) {
+ if(status != APT_MESSAGE_STATUS_COMPLETE) {
/* message is not completely parsed, nothing to do */
return TRUE;
}
@@ -776,50 +901,61 @@ static apt_bool_t rtsp_client_message_handler(void *obj, rtsp_message_t *message
}
/* Receive RTSP message through RTSP connection */
-static apt_bool_t rtsp_client_message_receive(apt_net_client_task_t *task, apt_net_client_connection_t *connection)
+static apt_bool_t rtsp_client_poller_signal_process(void *obj, const apr_pollfd_t *descriptor)
{
- rtsp_client_t *client = apt_net_client_task_object_get(task);
- rtsp_client_connection_t *rtsp_connection;
+ rtsp_client_t *client = obj;
+ rtsp_client_connection_t *rtsp_connection = descriptor->client_data;
apr_status_t status;
apr_size_t offset;
apr_size_t length;
apt_text_stream_t *stream;
+ rtsp_message_t *message;
+ apt_message_status_e msg_status;
- if(!connection || !connection->sock) {
+ if(!rtsp_connection || !rtsp_connection->sock) {
return FALSE;
}
- rtsp_connection = connection->obj;
stream = &rtsp_connection->rx_stream;
- /* init length of the stream */
- stream->text.length = sizeof(rtsp_connection->rx_buffer)-1;
/* calculate offset remaining from the previous receive / if any */
offset = stream->pos - stream->text.buf;
/* calculate available length */
- length = stream->text.length - offset;
- status = apr_socket_recv(connection->sock,stream->pos,&length);
+ length = sizeof(rtsp_connection->rx_buffer) - 1 - offset;
+
+ status = apr_socket_recv(rtsp_connection->sock,stream->pos,&length);
if(status == APR_EOF || length == 0) {
return rtsp_client_on_disconnect(client,rtsp_connection);
}
+
/* calculate actual length of the stream */
stream->text.length = offset + length;
stream->pos[length] = '\0';
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive RTSP Stream %s [%lu bytes]\n%s",
- connection->id,
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive RTSP Stream %s [%"APR_SIZE_T_FMT" bytes]\n%s",
+ rtsp_connection->id,
length,
stream->pos);
/* reset pos */
apt_text_stream_reset(stream);
- /* walk through the stream parsing RTSP messages */
- return rtsp_stream_walk(rtsp_connection->parser,stream,rtsp_client_message_handler,rtsp_connection);
+
+ do {
+ msg_status = rtsp_parser_run(rtsp_connection->parser,stream,&message);
+ if(rtsp_client_message_handler(rtsp_connection,message,msg_status) == FALSE) {
+ return FALSE;
+ }
+ }
+ while(apt_text_is_eos(stream) == FALSE);
+
+ /* scroll remaining stream */
+ apt_text_stream_scroll(stream);
+ return TRUE;
}
/* Process task message */
static apt_bool_t rtsp_client_task_msg_process(apt_task_t *task, apt_task_msg_t *task_msg)
{
- apt_net_client_task_t *net_task = apt_task_object_get(task);
- rtsp_client_t *client = apt_net_client_task_object_get(net_task);
+ apt_poller_task_t *poller_task = apt_task_object_get(task);
+ rtsp_client_t *client = apt_poller_task_object_get(poller_task);
task_msg_data_t *data = (task_msg_data_t*) task_msg->data;
switch(data->type) {
@@ -833,3 +969,20 @@ static apt_bool_t rtsp_client_task_msg_process(apt_task_t *task, apt_task_msg_t
return TRUE;
}
+
+/* Timer callback */
+static void rtsp_client_timer_proc(apt_timer_t *timer, void *obj)
+{
+ rtsp_client_session_t *session = obj;
+ if(!session || !session->connection || !session->connection->client) {
+ return;
+ }
+
+ if(session->request_timer == timer) {
+ rtsp_client_request_cancel(
+ session->connection->client,
+ session,
+ RTSP_STATUS_CODE_REQUEST_TIMEOUT,
+ RTSP_REASON_PHRASE_REQUEST_TIMEOUT);
+ }
+}
diff --git a/libs/unimrcp/libs/uni-rtsp/src/rtsp_header.c b/libs/unimrcp/libs/uni-rtsp/src/rtsp_header.c
index b090fd7303..de19f125f4 100644
--- a/libs/unimrcp/libs/uni-rtsp/src/rtsp_header.c
+++ b/libs/unimrcp/libs/uni-rtsp/src/rtsp_header.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,13 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: rtsp_header.c 1718 2010-05-31 13:12:43Z achaloyan $
*/
#include "rtsp_header.h"
#include "apt_string_table.h"
+#include "apt_text_stream.h"
/** String table of RTSP header fields (rtsp_header_field_id) */
static const apt_str_table_item_t rtsp_header_string_table[] = {
@@ -87,12 +90,12 @@ static apt_bool_t rtsp_port_range_generate(rtsp_transport_attrib_e attrib, const
if(!str) {
return FALSE;
}
- apt_string_value_generate(str,text_stream);
+ apt_text_string_insert(text_stream,str);
apt_text_char_insert(text_stream,'=');
- apt_size_value_generate(port_range->min,text_stream);
+ apt_text_size_value_insert(text_stream,port_range->min);
if(port_range->max > port_range->min) {
apt_text_char_insert(text_stream,'-');
- apt_size_value_generate(port_range->max,text_stream);
+ apt_text_size_value_insert(text_stream,port_range->max);
}
return TRUE;
}
@@ -197,13 +200,12 @@ static apt_bool_t rtsp_transport_protocol_parse(rtsp_transport_t *transport, con
}
/** Parse RTSP transport */
-static apt_bool_t rtsp_transport_parse(rtsp_transport_t *transport, const apt_str_t *line, apr_pool_t *pool)
+static apt_bool_t rtsp_transport_parse(rtsp_transport_t *transport, const apt_str_t *value, apr_pool_t *pool)
{
apt_str_t field;
apt_text_stream_t stream;
- stream.text = *line;
- apt_text_stream_reset(&stream);
+ apt_text_stream_init(&stream,value->buf,value->length);
/* read transport protocol (RTP/AVP[/UDP]) */
if(apt_text_field_read(&stream,';',TRUE,&field) == FALSE) {
return FALSE;
@@ -223,16 +225,20 @@ static apt_bool_t rtsp_transport_parse(rtsp_transport_t *transport, const apt_st
}
/** Generate RTSP transport */
-static apt_bool_t rtsp_transport_generate(rtsp_transport_t *transport, apt_text_stream_t *text_stream)
+static apt_bool_t rtsp_transport_generate(const rtsp_transport_t *transport, apt_str_t *value, apr_pool_t *pool)
{
+ char buf[256];
+ apt_text_stream_t text_stream;
const apt_str_t *protocol = apt_string_table_str_get(rtsp_transport_string_table,RTSP_TRANSPORT_COUNT,transport->protocol);
const apt_str_t *profile = apt_string_table_str_get(rtsp_profile_string_table,RTSP_PROFILE_COUNT,transport->profile);
if(!protocol || !profile) {
return FALSE;
}
- apt_string_value_generate(protocol,text_stream);
- apt_text_char_insert(text_stream,'/');
- apt_string_value_generate(profile,text_stream);
+
+ apt_text_stream_init(&text_stream,buf,sizeof(buf));
+ apt_text_string_insert(&text_stream,protocol);
+ apt_text_char_insert(&text_stream,'/');
+ apt_text_string_insert(&text_stream,profile);
if(transport->delivery != RTSP_DELIVERY_NONE) {
const apt_str_t *delivery = NULL;
@@ -248,29 +254,33 @@ static apt_bool_t rtsp_transport_generate(rtsp_transport_t *transport, apt_text_
return FALSE;
}
- apt_text_char_insert(text_stream,';');
- apt_string_value_generate(delivery,text_stream);
+ apt_text_char_insert(&text_stream,';');
+ apt_text_string_insert(&text_stream,delivery);
}
if(rtsp_port_range_is_valid(&transport->client_port_range) == TRUE) {
- apt_text_char_insert(text_stream,';');
- rtsp_port_range_generate(RTSP_TRANSPORT_ATTRIB_CLIENT_PORT,&transport->client_port_range,text_stream);
+ apt_text_char_insert(&text_stream,';');
+ rtsp_port_range_generate(RTSP_TRANSPORT_ATTRIB_CLIENT_PORT,&transport->client_port_range,&text_stream);
}
if(rtsp_port_range_is_valid(&transport->server_port_range) == TRUE) {
- apt_text_char_insert(text_stream,';');
- rtsp_port_range_generate(RTSP_TRANSPORT_ATTRIB_SERVER_PORT,&transport->server_port_range,text_stream);
+ apt_text_char_insert(&text_stream,';');
+ rtsp_port_range_generate(RTSP_TRANSPORT_ATTRIB_SERVER_PORT,&transport->server_port_range,&text_stream);
}
if(transport->mode.length) {
const apt_str_t *str;
str = apt_string_table_str_get(rtsp_transport_attrib_string_table,RTSP_TRANSPORT_ATTRIB_COUNT,RTSP_TRANSPORT_ATTRIB_MODE);
if(str) {
- apt_text_char_insert(text_stream,';');
- apt_string_value_generate(str,text_stream);
- apt_text_char_insert(text_stream,'=');
- apt_string_value_generate(&transport->mode,text_stream);
+ apt_text_char_insert(&text_stream,';');
+ apt_text_string_insert(&text_stream,str);
+ apt_text_char_insert(&text_stream,'=');
+ apt_text_string_insert(&text_stream,&transport->mode);
}
}
+ value->length = text_stream.pos - text_stream.text.buf;
+ value->buf = apr_palloc(pool,value->length + 1);
+ memcpy(value->buf,text_stream.text.buf,value->length);
+ value->buf[value->length] = '\0';
return TRUE;
}
@@ -290,8 +300,8 @@ static apt_bool_t rtsp_session_id_parse(apt_str_t *session_id, const apt_str_t *
return TRUE;
}
-/** Parse RTSP header field */
-static apt_bool_t rtsp_header_field_parse(rtsp_header_t *header, rtsp_header_field_id id, const apt_str_t *value, apr_pool_t *pool)
+/** Parse RTSP header field value */
+static apt_bool_t rtsp_header_field_value_parse(rtsp_header_t *header, rtsp_header_field_id id, const apt_str_t *value, apr_pool_t *pool)
{
apt_bool_t status = TRUE;
switch(id) {
@@ -305,7 +315,7 @@ static apt_bool_t rtsp_header_field_parse(rtsp_header_t *header, rtsp_header_fie
status = rtsp_session_id_parse(&header->session_id,value,pool);
break;
case RTSP_HEADER_FIELD_RTP_INFO:
- apt_string_copy(&header->rtp_info,value,pool);
+ header->rtp_info = *value;
break;
case RTSP_HEADER_FIELD_CONTENT_TYPE:
header->content_type = apt_string_table_id_find(rtsp_content_type_string_table,RTSP_CONTENT_TYPE_COUNT,value);
@@ -319,32 +329,32 @@ static apt_bool_t rtsp_header_field_parse(rtsp_header_t *header, rtsp_header_fie
return status;
}
-/** Generate RTSP header field */
-static apr_size_t rtsp_header_field_generate(rtsp_header_t *header, apr_size_t id, apt_text_stream_t *value)
+/** Generate RTSP header field value */
+static apt_bool_t rtsp_header_field_value_generate(const rtsp_header_t *header, rtsp_header_field_id id, apt_str_t *value, apr_pool_t *pool)
{
switch(id) {
case RTSP_HEADER_FIELD_CSEQ:
- apt_size_value_generate(header->cseq,value);
+ apt_size_value_generate(header->cseq,value,pool);
break;
case RTSP_HEADER_FIELD_TRANSPORT:
- rtsp_transport_generate(&header->transport,value);
+ rtsp_transport_generate(&header->transport,value,pool);
break;
case RTSP_HEADER_FIELD_SESSION_ID:
- apt_string_value_generate(&header->session_id,value);
+ *value = header->session_id;
break;
case RTSP_HEADER_FIELD_RTP_INFO:
- apt_string_value_generate(&header->rtp_info,value);
+ *value = header->rtp_info;
break;
case RTSP_HEADER_FIELD_CONTENT_TYPE:
{
const apt_str_t *name = apt_string_table_str_get(rtsp_content_type_string_table,RTSP_CONTENT_TYPE_COUNT,header->content_type);
if(name) {
- apt_string_value_generate(name,value);
+ *value = *name;
}
break;
}
case RTSP_HEADER_FIELD_CONTENT_LENGTH:
- apt_size_value_generate(header->content_length,value);
+ apt_size_value_generate(header->content_length,value,pool);
break;
default:
break;
@@ -352,58 +362,59 @@ static apr_size_t rtsp_header_field_generate(rtsp_header_t *header, apr_size_t i
return TRUE;
}
-/** Parse RTSP header */
-RTSP_DECLARE(apt_bool_t) rtsp_header_parse(rtsp_header_t *header, apt_text_stream_t *text_stream, apr_pool_t *pool)
+/** Add RTSP header field */
+RTSP_DECLARE(apt_bool_t) rtsp_header_field_add(rtsp_header_t *header, apt_header_field_t *header_field, apr_pool_t *pool)
{
- apt_pair_t pair;
- apt_bool_t result = FALSE;
-
- do {
- if(apt_text_header_read(text_stream,&pair) == TRUE) {
- if(pair.name.length) {
- /* parse header_field (name/value) */
- rtsp_header_field_id id = apt_string_table_id_find(rtsp_header_string_table,RTSP_HEADER_FIELD_COUNT,&pair.name);
- if(id < RTSP_HEADER_FIELD_COUNT) {
- if(rtsp_header_field_parse(header,id,&pair.value,pool) == TRUE) {
- rtsp_header_property_add(&header->property_set,id);
- }
- }
- }
- else {
- /* empty header -> exit */
- result = TRUE;
- break;
- }
- }
+ /* parse header field (name-value) */
+ header_field->id = apt_string_table_id_find(
+ rtsp_header_string_table,
+ RTSP_HEADER_FIELD_COUNT,
+ &header_field->name);
+ if(apt_string_is_empty(&header_field->value) == FALSE) {
+ rtsp_header_field_value_parse(header,header_field->id,&header_field->value,pool);
}
- while(apt_text_is_eos(text_stream) == FALSE);
- return result;
+ return apt_header_section_field_add(&header->header_section,header_field);
}
-/** Generate RTSP header */
-RTSP_DECLARE(apt_bool_t) rtsp_header_generate(rtsp_header_t *header, apt_text_stream_t *text_stream)
+/** Parse RTSP header fields */
+RTSP_DECLARE(apt_bool_t) rtsp_header_fields_parse(rtsp_header_t *header, apr_pool_t *pool)
{
- const apt_str_t *name;
- apr_size_t i;
- rtsp_header_property_t property_set;
+ apt_header_field_t *header_field;
+ for(header_field = APR_RING_FIRST(&header->header_section.ring);
+ header_field != APR_RING_SENTINEL(&header->header_section.ring, apt_header_field_t, link);
+ header_field = APR_RING_NEXT(header_field, link)) {
- property_set = header->property_set;
- for(i=0; iid = apt_string_table_id_find(
+ rtsp_header_string_table,
+ RTSP_HEADER_FIELD_COUNT,
+ &header_field->name);
+ if(apt_string_is_empty(&header_field->value) == FALSE) {
+ rtsp_header_field_value_parse(header,header_field->id,&header_field->value,pool);
}
+ apt_header_section_field_set(&header->header_section,header_field);
}
-
- apt_text_eol_insert(text_stream);
return TRUE;
}
+
+/** Add RTSP header field property */
+RTSP_DECLARE(apt_bool_t) rtsp_header_property_add(rtsp_header_t *header, rtsp_header_field_id id, apr_pool_t *pool)
+{
+ apt_header_field_t *header_field;
+ header_field = apt_header_section_field_get(&header->header_section,id);
+ if(header_field) {
+ /* such header field already exists, just (re)generate value */
+ return rtsp_header_field_value_generate(header,id,&header_field->value,pool);
+ }
+
+ header_field = apt_header_field_alloc(pool);
+ if(rtsp_header_field_value_generate(header,id,&header_field->value,pool) == TRUE) {
+ const apt_str_t *name = apt_string_table_str_get(rtsp_header_string_table,RTSP_HEADER_FIELD_COUNT,id);
+ if(name) {
+ header_field->name = *name;
+ header_field->id = id;
+ return apt_header_section_field_insert(&header->header_section,header_field);
+ }
+ }
+ return FALSE;
+}
diff --git a/libs/unimrcp/libs/uni-rtsp/src/rtsp_message.c b/libs/unimrcp/libs/uni-rtsp/src/rtsp_message.c
index 2bb2ee60d0..4a8eb2a31d 100644
--- a/libs/unimrcp/libs/uni-rtsp/src/rtsp_message.c
+++ b/libs/unimrcp/libs/uni-rtsp/src/rtsp_message.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: rtsp_message.c 1648 2010-04-12 20:03:59Z achaloyan $
*/
#include "rtsp_message.h"
@@ -21,7 +23,7 @@ static APR_INLINE void rtsp_message_init(rtsp_message_t *message, rtsp_message_t
{
message->pool = pool;
rtsp_start_line_init(&message->start_line,message_type);
- rtsp_header_init(&message->header);
+ rtsp_header_init(&message->header,pool);
apt_string_reset(&message->body);
}
@@ -55,17 +57,16 @@ RTSP_DECLARE(rtsp_message_t*) rtsp_response_create(const rtsp_message_t *request
apt_string_copy(&status_line->reason,reason_str,pool);
}
- if(rtsp_header_property_check(&request->header.property_set,RTSP_HEADER_FIELD_CSEQ) == TRUE) {
+ if(rtsp_header_property_check(&request->header,RTSP_HEADER_FIELD_CSEQ) == TRUE) {
response->header.cseq = request->header.cseq;
- rtsp_header_property_add(&response->header.property_set,RTSP_HEADER_FIELD_CSEQ);
+ rtsp_header_property_add(&response->header,RTSP_HEADER_FIELD_CSEQ,response->pool);
}
- if(rtsp_header_property_check(&request->header.property_set,RTSP_HEADER_FIELD_TRANSPORT) == TRUE) {
+ if(rtsp_header_property_check(&request->header,RTSP_HEADER_FIELD_TRANSPORT) == TRUE) {
const rtsp_transport_t *req_transport = &request->header.transport;
rtsp_transport_t *res_transport = &response->header.transport;
if(req_transport->mode.length) {
apt_string_copy(&res_transport->mode,&req_transport->mode,pool);
- rtsp_header_property_add(&response->header.property_set,RTSP_HEADER_FIELD_TRANSPORT);
}
}
diff --git a/libs/unimrcp/libs/uni-rtsp/src/rtsp_server.c b/libs/unimrcp/libs/uni-rtsp/src/rtsp_server.c
index c9f6c8c2b3..e025358388 100644
--- a/libs/unimrcp/libs/uni-rtsp/src/rtsp_server.c
+++ b/libs/unimrcp/libs/uni-rtsp/src/rtsp_server.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,12 +12,14 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: rtsp_server.c 1710 2010-05-24 17:36:19Z achaloyan $
*/
#include
#include "rtsp_server.h"
#include "rtsp_stream.h"
-#include "apt_net_server_task.h"
+#include "apt_poller_task.h"
#include "apt_text_stream.h"
#include "apt_pool.h"
#include "apt_obj_list.h"
@@ -31,35 +33,48 @@ typedef struct rtsp_server_connection_t rtsp_server_connection_t;
/** RTSP server */
struct rtsp_server_t {
apr_pool_t *pool;
- apt_net_server_task_t *task;
+ apt_poller_task_t *task;
apr_pool_t *sub_pool;
apt_obj_list_t *connection_list;
+ /* Listening socket descriptor */
+ apr_sockaddr_t *sockaddr;
+ apr_socket_t *listen_sock;
+ apr_pollfd_t listen_sock_pfd;
+
void *obj;
const rtsp_server_vtable_t *vtable;
};
/** RTSP connection */
struct rtsp_server_connection_t {
- /** Connection base */
- apt_net_server_connection_t *base;
+ /** Memory pool */
+ apr_pool_t *pool;
+ /** Client IP address */
+ char *client_ip;
+ /** Accepted socket */
+ apr_socket_t *sock;
+ /** Socket poll descriptor */
+ apr_pollfd_t sock_pfd;
+ /** String identifier used for traces */
+ const char *id;
/** RTSP server, connection belongs to */
- rtsp_server_t *server;
+ rtsp_server_t *server;
/** Element of the connection list in agent */
- apt_list_elem_t *it;
+ apt_list_elem_t *it;
/** Session table (rtsp_server_session_t*) */
- apr_hash_t *session_table;
+ apr_hash_t *session_table;
- char rx_buffer[RTSP_STREAM_BUFFER_SIZE];
- apt_text_stream_t rx_stream;
- rtsp_parser_t *parser;
+ char rx_buffer[RTSP_STREAM_BUFFER_SIZE];
+ apt_text_stream_t rx_stream;
+ rtsp_parser_t *parser;
- char tx_buffer[RTSP_STREAM_BUFFER_SIZE];
- apt_text_stream_t tx_stream;
- rtsp_generator_t *generator;
+ char tx_buffer[RTSP_STREAM_BUFFER_SIZE];
+ apt_text_stream_t tx_stream;
+ rtsp_generator_t *generator;
};
/** RTSP session */
@@ -100,19 +115,14 @@ struct task_msg_data_t {
rtsp_message_t *message;
};
+static apt_bool_t rtsp_server_on_destroy(apt_task_t *task);
static apt_bool_t rtsp_server_task_msg_process(apt_task_t *task, apt_task_msg_t *msg);
+static apt_bool_t rtsp_server_poller_signal_process(void *obj, const apr_pollfd_t *descriptor);
+static apt_bool_t rtsp_server_message_send(rtsp_server_t *server, rtsp_server_connection_t *connection, rtsp_message_t *message);
-static apt_bool_t rtsp_server_on_connect(apt_net_server_task_t *task, apt_net_server_connection_t *connection);
-static apt_bool_t rtsp_server_on_disconnect(apt_net_server_task_t *task, apt_net_server_connection_t *connection);
-static apt_bool_t rtsp_server_message_receive(apt_net_server_task_t *task, apt_net_server_connection_t *connection);
+static apt_bool_t rtsp_server_listening_socket_create(rtsp_server_t *server);
+static void rtsp_server_listening_socket_destroy(rtsp_server_t *server);
-static const apt_net_server_vtable_t server_vtable = {
- rtsp_server_on_connect,
- rtsp_server_on_disconnect,
- rtsp_server_message_receive
-};
-
-static apt_bool_t rtsp_server_message_send(rtsp_server_t *server, apt_net_server_connection_t *connection, rtsp_message_t *message);
/** Create RTSP server */
RTSP_DECLARE(rtsp_server_t*) rtsp_server_create(
@@ -132,58 +142,83 @@ RTSP_DECLARE(rtsp_server_t*) rtsp_server_create(
}
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Create RTSP Server %s:%hu [%"APR_SIZE_T_FMT"]",
- listen_ip,listen_port,max_connection_count);
+ listen_ip,
+ listen_port,
+ max_connection_count);
server = apr_palloc(pool,sizeof(rtsp_server_t));
server->pool = pool;
server->obj = obj;
server->vtable = handler;
- msg_pool = apt_task_msg_pool_create_dynamic(sizeof(task_msg_data_t),pool);
-
- server->task = apt_net_server_task_create(
- listen_ip,listen_port,max_connection_count,
- server,&server_vtable,msg_pool,pool);
- if(!server->task) {
+ server->listen_sock = NULL;
+ server->sockaddr = NULL;
+ apr_sockaddr_info_get(&server->sockaddr,listen_ip,APR_INET,listen_port,0,pool);
+ if(!server->sockaddr) {
return NULL;
}
- vtable = apt_net_server_task_vtable_get(server->task);
+ msg_pool = apt_task_msg_pool_create_dynamic(sizeof(task_msg_data_t),pool);
+
+ server->task = apt_poller_task_create(
+ max_connection_count + 1,
+ rtsp_server_poller_signal_process,
+ server,
+ msg_pool,
+ pool);
+ if(!server->task) {
+ return NULL;
+ }
+
+ vtable = apt_poller_task_vtable_get(server->task);
if(vtable) {
+ vtable->destroy = rtsp_server_on_destroy;
vtable->process_msg = rtsp_server_task_msg_process;
}
server->sub_pool = apt_subpool_create(pool);
server->connection_list = NULL;
+
+ rtsp_server_listening_socket_create(server);
return server;
}
+static apt_bool_t rtsp_server_on_destroy(apt_task_t *task)
+{
+ apt_poller_task_t *poller_task = apt_task_object_get(task);
+ rtsp_server_t *server = apt_poller_task_object_get(poller_task);
+
+ rtsp_server_listening_socket_destroy(server);
+ apt_poller_task_cleanup(poller_task);
+ return TRUE;
+}
+
/** Destroy RTSP server */
RTSP_DECLARE(apt_bool_t) rtsp_server_destroy(rtsp_server_t *server)
{
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Destroy RTSP Server");
- return apt_net_server_task_destroy(server->task);
+ return apt_poller_task_destroy(server->task);
}
-/** Start connection agent. */
+/** Start connection agent */
RTSP_DECLARE(apt_bool_t) rtsp_server_start(rtsp_server_t *server)
{
- return apt_net_server_task_start(server->task);
+ return apt_poller_task_start(server->task);
}
-/** Terminate connection agent. */
+/** Terminate connection agent */
RTSP_DECLARE(apt_bool_t) rtsp_server_terminate(rtsp_server_t *server)
{
- return apt_net_server_task_terminate(server->task);
+ return apt_poller_task_terminate(server->task);
}
/** Get task */
-RTSP_DECLARE(apt_task_t*) rtsp_server_task_get(rtsp_server_t *server)
+RTSP_DECLARE(apt_task_t*) rtsp_server_task_get(const rtsp_server_t *server)
{
- return apt_net_server_task_base_get(server->task);
+ return apt_poller_task_base_get(server->task);
}
/** Get external object */
-RTSP_DECLARE(void*) rtsp_server_object_get(rtsp_server_t *server)
+RTSP_DECLARE(void*) rtsp_server_object_get(const rtsp_server_t *server)
{
return server->obj;
}
@@ -216,7 +251,7 @@ RTSP_DECLARE(const rtsp_message_t*) rtsp_server_session_request_get(const rtsp_s
RTSP_DECLARE(const char*) rtsp_server_session_destination_get(const rtsp_server_session_t *session)
{
if(session->connection) {
- return session->connection->base->client_ip;
+ return session->connection->client_ip;
}
return NULL;
}
@@ -228,7 +263,7 @@ static apt_bool_t rtsp_server_control_message_signal(
rtsp_server_session_t *session,
rtsp_message_t *message)
{
- apt_task_t *task = apt_net_server_task_base_get(server->task);
+ apt_task_t *task = apt_poller_task_base_get(server->task);
apt_task_msg_t *task_msg = apt_task_msg_get(task);
if(task_msg) {
task_msg_data_t *data = (task_msg_data_t*)task_msg->data;
@@ -285,6 +320,13 @@ static void rtsp_server_session_destroy(rtsp_server_session_t *session)
}
}
+/** Destroy RTSP connection */
+static void rtsp_server_connection_destroy(rtsp_server_connection_t *rtsp_connection)
+{
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Destroy RTSP Connection %s",rtsp_connection->id);
+ apr_pool_destroy(rtsp_connection->pool);
+}
+
/* Finally terminate RTSP session */
static apt_bool_t rtsp_server_session_do_terminate(rtsp_server_t *server, rtsp_server_session_t *session)
{
@@ -296,11 +338,11 @@ static apt_bool_t rtsp_server_session_do_terminate(rtsp_server_t *server, rtsp_s
if(response) {
if(session->id.buf) {
response->header.session_id = session->id;
- rtsp_header_property_add(&response->header.property_set,RTSP_HEADER_FIELD_SESSION_ID);
+ rtsp_header_property_add(&response->header,RTSP_HEADER_FIELD_SESSION_ID,response->pool);
}
if(rtsp_connection) {
- rtsp_server_message_send(server,rtsp_connection->base,response);
+ rtsp_server_message_send(server,rtsp_connection,response);
}
}
}
@@ -311,7 +353,7 @@ static apt_bool_t rtsp_server_session_do_terminate(rtsp_server_t *server, rtsp_s
if(rtsp_connection && !rtsp_connection->it) {
if(apr_hash_count(rtsp_connection->session_table) == 0) {
- apt_net_server_connection_destroy(rtsp_connection->base);
+ rtsp_server_connection_destroy(rtsp_connection);
}
}
return TRUE;
@@ -322,7 +364,7 @@ static apt_bool_t rtsp_server_error_respond(rtsp_server_t *server, rtsp_server_c
{
/* send error response to client */
rtsp_message_t *response = rtsp_response_create(request,status_code,reason,request->pool);
- if(rtsp_server_message_send(server,rtsp_connection->base,response) == FALSE) {
+ if(rtsp_server_message_send(server,rtsp_connection,response) == FALSE) {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Send RTSP Response");
return FALSE;
}
@@ -365,6 +407,9 @@ static rtsp_server_session_t* rtsp_server_session_setup_process(rtsp_server_t *s
if(message->start_line.common.request_line.method_id == RTSP_METHOD_SETUP) {
/* create new session */
session = rtsp_server_session_create(server);
+ if(!session) {
+ return NULL;
+ }
session->connection = rtsp_connection;
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Add RTSP Session "APT_SID_FMT,session->id.buf);
apr_hash_set(rtsp_connection->session_table,session->id.buf,session->id.length,session);
@@ -372,6 +417,9 @@ static rtsp_server_session_t* rtsp_server_session_setup_process(rtsp_server_t *s
else if(message->start_line.common.request_line.method_id == RTSP_METHOD_DESCRIBE) {
/* create new session as a communication object */
session = rtsp_server_session_create(server);
+ if(!session) {
+ return NULL;
+ }
session->connection = rtsp_connection;
apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Add RTSP Session "APT_SID_FMT,session->id.buf);
apr_hash_set(rtsp_connection->session_table,session->id.buf,session->id.length,session);
@@ -395,7 +443,7 @@ static apt_bool_t rtsp_server_session_request_process(rtsp_server_t *server, rts
return TRUE;
}
- if(rtsp_header_property_check(&message->header.property_set,RTSP_HEADER_FIELD_SESSION_ID) != TRUE) {
+ if(rtsp_header_property_check(&message->header,RTSP_HEADER_FIELD_SESSION_ID) != TRUE) {
/* no session-id specified */
session = rtsp_server_session_setup_process(server,rtsp_connection,message);
if(session) {
@@ -404,6 +452,13 @@ static apt_bool_t rtsp_server_session_request_process(rtsp_server_t *server, rts
rtsp_server_session_destroy(session);
}
}
+ else {
+ /* error case, failed to create a session */
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create RTSP Session");
+ return rtsp_server_error_respond(server,rtsp_connection,message,
+ RTSP_STATUS_CODE_NOT_ACCEPTABLE,
+ RTSP_REASON_PHRASE_NOT_ACCEPTABLE);
+ }
return TRUE;
}
@@ -419,7 +474,7 @@ static apt_bool_t rtsp_server_session_request_process(rtsp_server_t *server, rts
RTSP_STATUS_CODE_NOT_FOUND,
RTSP_REASON_PHRASE_NOT_FOUND);
}
-
+
if(session->terminating == TRUE) {
/* error case, session is being terminated */
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Not Acceptable Request "APT_SID_FMT,message->header.session_id.buf);
@@ -456,13 +511,13 @@ static apt_bool_t rtsp_server_session_response_process(rtsp_server_t *server, rt
}
message->start_line.common.request_line.url = request->start_line.common.request_line.url;
message->header.cseq = session->last_cseq;
- rtsp_header_property_add(&message->header.property_set,RTSP_HEADER_FIELD_CSEQ);
+ rtsp_header_property_add(&message->header,RTSP_HEADER_FIELD_CSEQ,message->pool);
if(session->id.buf) {
message->header.session_id = session->id;
- rtsp_header_property_add(&message->header.property_set,RTSP_HEADER_FIELD_SESSION_ID);
+ rtsp_header_property_add(&message->header,RTSP_HEADER_FIELD_SESSION_ID,message->pool);
}
- rtsp_server_message_send(server,session->connection->base,message);
+ rtsp_server_message_send(server,session->connection,message);
return TRUE;
}
@@ -478,7 +533,7 @@ static apt_bool_t rtsp_server_session_response_process(rtsp_server_t *server, rt
else {
if(session->id.buf) {
message->header.session_id = session->id;
- rtsp_header_property_add(&message->header.property_set,RTSP_HEADER_FIELD_SESSION_ID);
+ rtsp_header_property_add(&message->header,RTSP_HEADER_FIELD_SESSION_ID,message->pool);
}
if(request->start_line.common.request_line.method_id == RTSP_METHOD_SETUP) {
if(message->start_line.common.status_line.status_code == RTSP_STATUS_CODE_OK) {
@@ -493,7 +548,7 @@ static apt_bool_t rtsp_server_session_response_process(rtsp_server_t *server, rt
}
session->last_cseq = message->header.cseq;
- rtsp_server_message_send(server,session->connection->base,message);
+ rtsp_server_message_send(server,session->connection,message);
if(terminate == TRUE) {
session->active_request = NULL;
@@ -509,34 +564,31 @@ static apt_bool_t rtsp_server_session_response_process(rtsp_server_t *server, rt
}
/* Send RTSP message through RTSP connection */
-static apt_bool_t rtsp_server_message_send(rtsp_server_t *server, apt_net_server_connection_t *connection, rtsp_message_t *message)
+static apt_bool_t rtsp_server_message_send(rtsp_server_t *server, rtsp_server_connection_t *rtsp_connection, rtsp_message_t *message)
{
apt_bool_t status = FALSE;
- rtsp_server_connection_t *rtsp_connection;
apt_text_stream_t *stream;
- rtsp_stream_status_e result;
+ apt_message_status_e result;
- if(!connection || !connection->sock) {
+ if(!rtsp_connection || !rtsp_connection->sock) {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No RTSP Connection");
return FALSE;
}
- rtsp_connection = connection->obj;
stream = &rtsp_connection->tx_stream;
- rtsp_generator_message_set(rtsp_connection->generator,message);
do {
stream->text.length = sizeof(rtsp_connection->tx_buffer)-1;
apt_text_stream_reset(stream);
- result = rtsp_generator_run(rtsp_connection->generator,stream);
- if(result != RTSP_STREAM_STATUS_INVALID) {
+ result = rtsp_generator_run(rtsp_connection->generator,message,stream);
+ if(result != APT_MESSAGE_STATUS_INVALID) {
stream->text.length = stream->pos - stream->text.buf;
*stream->pos = '\0';
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Send RTSP Stream %s [%lu bytes]\n%s",
- connection->id,
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Send RTSP Stream %s [%"APR_SIZE_T_FMT" bytes]\n%s",
+ rtsp_connection->id,
stream->text.length,
stream->text.buf);
- if(apr_socket_send(connection->sock,stream->text.buf,&stream->text.length) == APR_SUCCESS) {
+ if(apr_socket_send(rtsp_connection->sock,stream->text.buf,&stream->text.length) == APR_SUCCESS) {
status = TRUE;
}
else {
@@ -547,32 +599,30 @@ static apt_bool_t rtsp_server_message_send(rtsp_server_t *server, apt_net_server
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Generate RTSP Stream");
}
}
- while(result == RTSP_STREAM_STATUS_INCOMPLETE);
+ while(result == APT_MESSAGE_STATUS_INCOMPLETE);
return status;
}
-static apt_bool_t rtsp_server_message_handler(void *obj, rtsp_message_t *message, rtsp_stream_status_e status)
+static apt_bool_t rtsp_server_message_handler(rtsp_server_connection_t *rtsp_connection, rtsp_message_t *message, apt_message_status_e status)
{
- rtsp_server_connection_t *rtsp_connection = obj;
- if(status == RTSP_STREAM_STATUS_COMPLETE) {
+ if(status == APT_MESSAGE_STATUS_COMPLETE) {
/* message is completely parsed */
apt_str_t *destination;
- rtsp_message_t *message = rtsp_parser_message_get(rtsp_connection->parser);
destination = &message->header.transport.destination;
- if(!destination->buf && rtsp_connection->base->client_ip) {
- apt_string_assign(destination,rtsp_connection->base->client_ip,rtsp_connection->base->pool);
+ if(!destination->buf && rtsp_connection->client_ip) {
+ apt_string_assign(destination,rtsp_connection->client_ip,rtsp_connection->pool);
}
rtsp_server_session_request_process(rtsp_connection->server,rtsp_connection,message);
}
- else if(status == RTSP_STREAM_STATUS_INVALID) {
+ else if(status == APT_MESSAGE_STATUS_INVALID) {
/* error case */
rtsp_message_t *response;
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Parse RTSP Stream");
if(message) {
response = rtsp_response_create(message,RTSP_STATUS_CODE_BAD_REQUEST,
RTSP_REASON_PHRASE_BAD_REQUEST,message->pool);
- if(rtsp_server_message_send(rtsp_connection->server,rtsp_connection->base,response) == FALSE) {
+ if(rtsp_server_message_send(rtsp_connection->server,rtsp_connection,response) == FALSE) {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Send RTSP Response");
}
}
@@ -580,72 +630,143 @@ static apt_bool_t rtsp_server_message_handler(void *obj, rtsp_message_t *message
return TRUE;
}
-/* Receive RTSP message through RTSP connection */
-static apt_bool_t rtsp_server_message_receive(apt_net_server_task_t *task, apt_net_server_connection_t *connection)
+/** Create listening socket and add to pollset */
+static apt_bool_t rtsp_server_listening_socket_create(rtsp_server_t *server)
{
- rtsp_server_connection_t *rtsp_connection;
apr_status_t status;
- apr_size_t offset;
- apr_size_t length;
- apt_text_stream_t *stream;
-
- if(!connection || !connection->sock) {
+ apt_pollset_t *pollset = apt_poller_task_pollset_get(server->task);
+
+ if(!server->sockaddr || !pollset) {
return FALSE;
}
- rtsp_connection = connection->obj;
- stream = &rtsp_connection->rx_stream;
- /* init length of the stream */
- stream->text.length = sizeof(rtsp_connection->rx_buffer)-1;
- /* calculate offset remaining from the previous receive / if any */
- offset = stream->pos - stream->text.buf;
- /* calculate available length */
- length = stream->text.length - offset;
- status = apr_socket_recv(connection->sock,stream->pos,&length);
- if(status == APR_EOF || length == 0) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"TCP Peer Disconnected %s",connection->id);
- return apt_net_server_connection_close(task,connection);
+ /* create listening socket */
+ status = apr_socket_create(&server->listen_sock, server->sockaddr->family, SOCK_STREAM, APR_PROTO_TCP, server->pool);
+ if(status != APR_SUCCESS) {
+ return FALSE;
}
- /* calculate actual length of the stream */
- stream->text.length = offset + length;
- stream->pos[length] = '\0';
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive RTSP Stream %s [%lu bytes]\n%s",
- connection->id,
- length,
- stream->pos);
- /* reset pos */
- apt_text_stream_reset(stream);
- /* walk through the stream parsing RTSP messages */
- return rtsp_stream_walk(rtsp_connection->parser,stream,rtsp_server_message_handler,rtsp_connection);
+ apr_socket_opt_set(server->listen_sock, APR_SO_NONBLOCK, 0);
+ apr_socket_timeout_set(server->listen_sock, -1);
+ apr_socket_opt_set(server->listen_sock, APR_SO_REUSEADDR, 1);
+
+ status = apr_socket_bind(server->listen_sock, server->sockaddr);
+ if(status != APR_SUCCESS) {
+ apr_socket_close(server->listen_sock);
+ server->listen_sock = NULL;
+ return FALSE;
+ }
+ status = apr_socket_listen(server->listen_sock, SOMAXCONN);
+ if(status != APR_SUCCESS) {
+ apr_socket_close(server->listen_sock);
+ server->listen_sock = NULL;
+ return FALSE;
+ }
+
+ memset(&server->listen_sock_pfd,0,sizeof(apr_pollfd_t));
+ server->listen_sock_pfd.desc_type = APR_POLL_SOCKET;
+ server->listen_sock_pfd.reqevents = APR_POLLIN;
+ server->listen_sock_pfd.desc.s = server->listen_sock;
+ server->listen_sock_pfd.client_data = server->listen_sock;
+ if(apt_pollset_add(pollset, &server->listen_sock_pfd) != TRUE) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Add Listening Socket to Pollset");
+ apr_socket_close(server->listen_sock);
+ server->listen_sock = NULL;
+ }
+
+ return TRUE;
}
-/* New RTSP connection accepted */
-static apt_bool_t rtsp_server_on_connect(apt_net_server_task_t *task, apt_net_server_connection_t *connection)
+/** Remove from pollset and destroy listening socket */
+static void rtsp_server_listening_socket_destroy(rtsp_server_t *server)
{
- rtsp_server_t *server = apt_net_server_task_object_get(task);
- rtsp_server_connection_t *rtsp_connection = apr_palloc(connection->pool,sizeof(rtsp_server_connection_t));
- rtsp_connection->session_table = apr_hash_make(connection->pool);
+ apt_pollset_t *pollset = apt_poller_task_pollset_get(server->task);
+ if(pollset) {
+ apt_pollset_remove(pollset,&server->listen_sock_pfd);
+ }
+
+ if(server->listen_sock) {
+ apr_socket_close(server->listen_sock);
+ server->listen_sock = NULL;
+ }
+}
+
+/* Accept RTSP connection */
+static apt_bool_t rtsp_server_connection_accept(rtsp_server_t *server)
+{
+ rtsp_server_connection_t *rtsp_connection;
+ char *local_ip = NULL;
+ char *remote_ip = NULL;
+ apr_sockaddr_t *l_sockaddr = NULL;
+ apr_sockaddr_t *r_sockaddr = NULL;
+ apt_pollset_t *pollset = apt_poller_task_pollset_get(server->task);
+ apr_pool_t *pool = apt_pool_create();
+ if(!pool) {
+ return FALSE;
+ }
+
+ rtsp_connection = apr_palloc(pool,sizeof(rtsp_server_connection_t));
+ rtsp_connection->pool = pool;
+ rtsp_connection->sock = NULL;
+ rtsp_connection->client_ip = NULL;
+
+ if(apr_socket_accept(&rtsp_connection->sock,server->listen_sock,rtsp_connection->pool) != APR_SUCCESS) {
+ apr_pool_destroy(pool);
+ return FALSE;
+ }
+
+ if(apr_socket_addr_get(&l_sockaddr,APR_LOCAL,rtsp_connection->sock) != APR_SUCCESS ||
+ apr_socket_addr_get(&r_sockaddr,APR_REMOTE,rtsp_connection->sock) != APR_SUCCESS) {
+ apr_pool_destroy(pool);
+ return FALSE;
+ }
+
+ apr_sockaddr_ip_get(&local_ip,l_sockaddr);
+ apr_sockaddr_ip_get(&remote_ip,r_sockaddr);
+ rtsp_connection->client_ip = remote_ip;
+ rtsp_connection->id = apr_psprintf(pool,"%s:%hu <-> %s:%hu",
+ local_ip,l_sockaddr->port,
+ remote_ip,r_sockaddr->port);
+
+ memset(&rtsp_connection->sock_pfd,0,sizeof(apr_pollfd_t));
+ rtsp_connection->sock_pfd.desc_type = APR_POLL_SOCKET;
+ rtsp_connection->sock_pfd.reqevents = APR_POLLIN;
+ rtsp_connection->sock_pfd.desc.s = rtsp_connection->sock;
+ rtsp_connection->sock_pfd.client_data = rtsp_connection;
+ if(apt_pollset_add(pollset,&rtsp_connection->sock_pfd) != TRUE) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Add to Pollset %s",rtsp_connection->id);
+ apr_socket_close(rtsp_connection->sock);
+ apr_pool_destroy(pool);
+ return FALSE;
+ }
+
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Accepted TCP Connection %s",rtsp_connection->id);
+ rtsp_connection->session_table = apr_hash_make(rtsp_connection->pool);
apt_text_stream_init(&rtsp_connection->rx_stream,rtsp_connection->rx_buffer,sizeof(rtsp_connection->rx_buffer)-1);
apt_text_stream_init(&rtsp_connection->tx_stream,rtsp_connection->tx_buffer,sizeof(rtsp_connection->tx_buffer)-1);
- rtsp_connection->parser = rtsp_parser_create(connection->pool);
- rtsp_connection->generator = rtsp_generator_create(connection->pool);
- rtsp_connection->base = connection;
- connection->obj = rtsp_connection;
+ rtsp_connection->parser = rtsp_parser_create(rtsp_connection->pool);
+ rtsp_connection->generator = rtsp_generator_create(rtsp_connection->pool);
if(!server->connection_list) {
server->connection_list = apt_list_create(server->sub_pool);
}
rtsp_connection->server = server;
- rtsp_connection->it = apt_list_push_back(server->connection_list,rtsp_connection,connection->pool);
+ rtsp_connection->it = apt_list_push_back(server->connection_list,rtsp_connection,rtsp_connection->pool);
return TRUE;
}
-/* RTSP connection disconnected */
-static apt_bool_t rtsp_server_on_disconnect(apt_net_server_task_t *task, apt_net_server_connection_t *connection)
+/** Close connection */
+static apt_bool_t rtsp_server_connection_close(rtsp_server_t *server, rtsp_server_connection_t *rtsp_connection)
{
+ apt_pollset_t *pollset = apt_poller_task_pollset_get(server->task);
apr_size_t remaining_sessions = 0;
- rtsp_server_t *server = apt_net_server_task_object_get(task);
- rtsp_server_connection_t *rtsp_connection = connection->obj;
+ if(!rtsp_connection || !rtsp_connection->sock) {
+ return FALSE;
+ }
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Close RTSP Connection %s",rtsp_connection->id);
+ apt_pollset_remove(pollset,&rtsp_connection->sock_pfd);
+ apr_socket_close(rtsp_connection->sock);
+ rtsp_connection->sock = NULL;
+
apt_list_elem_remove(server->connection_list,rtsp_connection->it);
rtsp_connection->it = NULL;
if(apt_list_is_empty(server->connection_list) == TRUE) {
@@ -660,7 +781,7 @@ static apt_bool_t rtsp_server_on_disconnect(apt_net_server_task_t *task, apt_net
apr_hash_index_t *it;
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Terminate Remaining RTSP Sessions [%"APR_SIZE_T_FMT"]",
remaining_sessions);
- it = apr_hash_first(connection->pool,rtsp_connection->session_table);
+ it = apr_hash_first(rtsp_connection->pool,rtsp_connection->session_table);
for(; it; it = apr_hash_next(it)) {
apr_hash_this(it,NULL,NULL,&val);
session = val;
@@ -670,16 +791,72 @@ static apt_bool_t rtsp_server_on_disconnect(apt_net_server_task_t *task, apt_net
}
}
else {
- apt_net_server_connection_destroy(connection);
+ rtsp_server_connection_destroy(rtsp_connection);
}
return TRUE;
}
+
+/* Receive RTSP message through RTSP connection */
+static apt_bool_t rtsp_server_poller_signal_process(void *obj, const apr_pollfd_t *descriptor)
+{
+ rtsp_server_t *server = obj;
+ rtsp_server_connection_t *rtsp_connection = descriptor->client_data;
+ apr_status_t status;
+ apr_size_t offset;
+ apr_size_t length;
+ apt_text_stream_t *stream;
+ rtsp_message_t *message;
+ apt_message_status_e msg_status;
+
+ if(descriptor->desc.s == server->listen_sock) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Accept Connection");
+ return rtsp_server_connection_accept(server);
+ }
+
+ if(!rtsp_connection || !rtsp_connection->sock) {
+ return FALSE;
+ }
+ stream = &rtsp_connection->rx_stream;
+
+ /* calculate offset remaining from the previous receive / if any */
+ offset = stream->pos - stream->text.buf;
+ /* calculate available length */
+ length = sizeof(rtsp_connection->rx_buffer) - 1 - offset;
+
+ status = apr_socket_recv(rtsp_connection->sock,stream->pos,&length);
+ if(status == APR_EOF || length == 0) {
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"RTSP Peer Disconnected %s",rtsp_connection->id);
+ return rtsp_server_connection_close(server,rtsp_connection);
+ }
+
+ /* calculate actual length of the stream */
+ stream->text.length = offset + length;
+ stream->pos[length] = '\0';
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Receive RTSP Stream %s [%"APR_SIZE_T_FMT" bytes]\n%s",
+ rtsp_connection->id,
+ length,
+ stream->pos);
+
+ /* reset pos */
+ apt_text_stream_reset(stream);
+
+ do {
+ msg_status = rtsp_parser_run(rtsp_connection->parser,stream,&message);
+ rtsp_server_message_handler(rtsp_connection,message,msg_status);
+ }
+ while(apt_text_is_eos(stream) == FALSE);
+
+ /* scroll remaining stream */
+ apt_text_stream_scroll(stream);
+ return TRUE;
+}
+
/* Process task message */
static apt_bool_t rtsp_server_task_msg_process(apt_task_t *task, apt_task_msg_t *task_msg)
{
- apt_net_server_task_t *net_task = apt_task_object_get(task);
- rtsp_server_t *server = apt_net_server_task_object_get(net_task);
+ apt_poller_task_t *poller_task = apt_task_object_get(task);
+ rtsp_server_t *server = apt_poller_task_object_get(poller_task);
task_msg_data_t *data = (task_msg_data_t*) task_msg->data;
switch(data->type) {
diff --git a/libs/unimrcp/libs/uni-rtsp/src/rtsp_start_line.c b/libs/unimrcp/libs/uni-rtsp/src/rtsp_start_line.c
index 24449a8976..7e06a2e541 100644
--- a/libs/unimrcp/libs/uni-rtsp/src/rtsp_start_line.c
+++ b/libs/unimrcp/libs/uni-rtsp/src/rtsp_start_line.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: rtsp_start_line.c 1671 2010-04-28 19:50:29Z achaloyan $
*/
#include "rtsp_start_line.h"
@@ -43,6 +45,8 @@ static const apt_str_table_item_t rtsp_reason_string_table[] = {
{{"Not Found", 9},4},
{{"Method Not Allowed", 18},0},
{{"Not Acceptable", 14},4},
+ {{"Proxy Auth Required", 19},0},
+ {{"Request Timeout", 15},0},
{{"Session Not Found", 17},0},
{{"Internal Server Error", 21},0},
{{"Not Implemented", 15},4}
@@ -95,10 +99,20 @@ static rtsp_version_e rtsp_version_parse(const apt_str_t *field)
/** Generate RTSP version */
static apt_bool_t rtsp_version_generate(rtsp_version_e version, apt_text_stream_t *stream)
{
+ if(stream->pos + RTSP_NAME_LENGTH + 1 >= stream->end) {
+ return FALSE;
+ }
memcpy(stream->pos,RTSP_NAME,RTSP_NAME_LENGTH);
stream->pos += RTSP_NAME_LENGTH;
*stream->pos++ = RTSP_NAME_VERSION_SEPARATOR;
- apt_size_value_generate(version,stream);
+
+ if(apt_text_size_value_insert(stream,version) == FALSE) {
+ return FALSE;
+ }
+
+ if(stream->pos + 2 >= stream->end) {
+ return FALSE;
+ }
*stream->pos++ = RTSP_VERSION_MAJOR_MINOR_SEPARATOR;
*stream->pos++ = '0';
return TRUE;
@@ -113,7 +127,7 @@ static APR_INLINE rtsp_status_code_e rtsp_status_code_parse(const apt_str_t *fie
/** Generate RTSP status-code */
static APR_INLINE apt_bool_t rtsp_status_code_generate(rtsp_status_code_e status_code, apt_text_stream_t *stream)
{
- return apt_size_value_generate(status_code,stream);
+ return apt_text_size_value_insert(stream,status_code);
}
/** Generate RTSP request-line */
@@ -124,40 +138,50 @@ static apt_bool_t rtsp_request_line_generate(rtsp_request_line_t *start_line, ap
return FALSE;
}
start_line->method_name = *method_name;
- apt_string_value_generate(&start_line->method_name,stream);
- apt_text_space_insert(stream);
+ if(apt_text_string_insert(stream,&start_line->method_name) == FALSE) {
+ return FALSE;
+ }
+ if(apt_text_space_insert(stream) == FALSE) {
+ return FALSE;
+ }
- apt_string_value_generate(&start_line->url,stream);
- apt_text_space_insert(stream);
+ if(apt_text_string_insert(stream,&start_line->url) == FALSE) {
+ return FALSE;
+ }
+ if(apt_text_space_insert(stream) == FALSE) {
+ return FALSE;
+ }
- rtsp_version_generate(start_line->version,stream);
- return TRUE;
+ return rtsp_version_generate(start_line->version,stream);
}
/** Generate RTSP status-line */
static apt_bool_t rtsp_status_line_generate(rtsp_status_line_t *start_line, apt_text_stream_t *stream)
{
- rtsp_version_generate(start_line->version,stream);
- apt_text_space_insert(stream);
-
- rtsp_status_code_generate(start_line->status_code,stream);
- apt_text_space_insert(stream);
-
- apt_string_value_generate(&start_line->reason,stream);
- return TRUE;
-}
-
-/** Parse RTSP start-line */
-RTSP_DECLARE(apt_bool_t) rtsp_start_line_parse(rtsp_start_line_t *start_line, apt_text_stream_t *stream, apr_pool_t *pool)
-{
- apt_text_stream_t line;
- apt_str_t field;
- if(apt_text_line_read(stream,&line.text) == FALSE) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot parse RTSP start-line");
+ if(rtsp_version_generate(start_line->version,stream) == FALSE) {
+ return FALSE;
+ }
+ if(apt_text_space_insert(stream) == FALSE) {
return FALSE;
}
- apt_text_stream_reset(&line);
+ if(rtsp_status_code_generate(start_line->status_code,stream) == FALSE) {
+ return FALSE;
+ }
+ if(apt_text_space_insert(stream) == FALSE) {
+ return FALSE;
+ }
+
+ return apt_text_string_insert(stream,&start_line->reason);
+}
+
+/** Parse RTSP start-line */
+RTSP_DECLARE(apt_bool_t) rtsp_start_line_parse(rtsp_start_line_t *start_line, apt_str_t *str, apr_pool_t *pool)
+{
+ apt_text_stream_t line;
+ apt_str_t field;
+
+ apt_text_stream_init(&line,str->buf,str->length);
if(apt_text_field_read(&line,APT_TOKEN_SP,TRUE,&field) == FALSE) {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot read the first field in start-line");
return FALSE;
@@ -223,11 +247,11 @@ RTSP_DECLARE(apt_bool_t) rtsp_start_line_generate(rtsp_start_line_t *start_line,
break;
}
- if(status == TRUE) {
- apt_text_eol_insert(stream);
+ if(status == FALSE) {
+ return FALSE;
}
-
- return status;
+
+ return apt_text_eol_insert(stream);
}
/** Get reason phrase by status code */
diff --git a/libs/unimrcp/libs/uni-rtsp/src/rtsp_stream.c b/libs/unimrcp/libs/uni-rtsp/src/rtsp_stream.c
index bb8633fb70..845c17503b 100644
--- a/libs/unimrcp/libs/uni-rtsp/src/rtsp_stream.c
+++ b/libs/unimrcp/libs/uni-rtsp/src/rtsp_stream.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,280 +12,113 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: rtsp_stream.c 1648 2010-04-12 20:03:59Z achaloyan $
*/
#include "rtsp_stream.h"
#include "apt_log.h"
-/** Stage of RTSP stream processing (parse/generate) */
-typedef enum {
- RTSP_STREAM_STAGE_NONE,
- RTSP_STREAM_STAGE_START_LINE,
- RTSP_STREAM_STAGE_HEADER,
- RTSP_STREAM_STAGE_BODY
-} rtsp_stream_stage_e;
-
/** RTSP parser */
struct rtsp_parser_t {
- rtsp_stream_stage_e stage;
- apt_bool_t skip_lf;
- rtsp_message_t *message;
- apr_pool_t *pool;
+ apt_message_parser_t *base;
};
/** RTSP generator */
struct rtsp_generator_t {
- rtsp_stream_status_e stage;
- rtsp_message_t *message;
- apr_pool_t *pool;
+ apt_message_generator_t *base;
};
-/** Read RTSP message-body */
-static apt_bool_t rtsp_message_body_read(rtsp_message_t *message, apt_text_stream_t *stream)
-{
- apt_bool_t status = TRUE;
- if(message->body.buf) {
- /* stream length available to read */
- apr_size_t stream_length = stream->text.length - (stream->pos - stream->text.buf);
- /* required/remaining length to read */
- apr_size_t required_length = message->header.content_length - message->body.length;
- if(required_length > stream_length) {
- required_length = stream_length;
- /* not complete */
- status = FALSE;
- }
- memcpy(message->body.buf+message->body.length,stream->pos,required_length);
- message->body.length += required_length;
- stream->pos += required_length;
- message->body.buf[message->body.length] = '\0';
- }
+/** Create message and read start line */
+static apt_bool_t rtsp_parser_on_start(apt_message_parser_t *parser, apt_message_context_t *context, apt_text_stream_t *stream, apr_pool_t *pool);
+/** Header section handler */
+static apt_bool_t rtsp_parser_on_header_complete(apt_message_parser_t *parser, apt_message_context_t *context);
- return status;
-}
+static const apt_message_parser_vtable_t parser_vtable = {
+ rtsp_parser_on_start,
+ rtsp_parser_on_header_complete,
+ NULL
+};
-/** Write RTSP message-body */
-static apt_bool_t rtsp_message_body_write(rtsp_message_t *message, apt_text_stream_t *stream)
-{
- apt_bool_t status = TRUE;
- if(message->body.length < message->header.content_length) {
- /* stream length available to write */
- apr_size_t stream_length = stream->text.length - (stream->pos - stream->text.buf);
- /* required/remaining length to write */
- apr_size_t required_length = message->header.content_length - message->body.length;
- if(required_length > stream_length) {
- required_length = stream_length;
- /* not complete */
- status = FALSE;
- }
- memcpy(stream->pos,message->body.buf+message->body.length,required_length);
- message->body.length += required_length;
- stream->pos += required_length;
- }
+/** Initialize by generating message start line and return header section and body */
+apt_bool_t rtsp_generator_on_start(apt_message_generator_t *generator, apt_message_context_t *context, apt_text_stream_t *stream);
+
+static const apt_message_generator_vtable_t generator_vtable = {
+ rtsp_generator_on_start,
+ NULL,
+ NULL
+};
- return status;
-}
/** Create RTSP parser */
RTSP_DECLARE(rtsp_parser_t*) rtsp_parser_create(apr_pool_t *pool)
{
rtsp_parser_t *parser = apr_palloc(pool,sizeof(rtsp_parser_t));
- parser->stage = RTSP_STREAM_STAGE_NONE;
- parser->skip_lf = FALSE;
- parser->message = NULL;
- parser->pool = pool;
+ parser->base = apt_message_parser_create(parser,&parser_vtable,pool);
return parser;
}
-static rtsp_stream_status_e rtsp_parser_break(rtsp_parser_t *parser, apt_text_stream_t *stream)
-{
- /* failed to parse message */
- if(apt_text_is_eos(stream) == TRUE) {
- /* end of stream reached */
- return RTSP_STREAM_STATUS_INCOMPLETE;
- }
-
- /* error case */
- parser->stage = RTSP_STREAM_STAGE_NONE;
- return RTSP_STREAM_STATUS_INVALID;
-}
-
/** Parse RTSP stream */
-RTSP_DECLARE(rtsp_stream_status_e) rtsp_parser_run(rtsp_parser_t *parser, apt_text_stream_t *stream)
+RTSP_DECLARE(apt_message_status_e) rtsp_parser_run(rtsp_parser_t *parser, apt_text_stream_t *stream, rtsp_message_t **message)
{
- rtsp_message_t *message = parser->message;
- if(parser->stage == RTSP_STREAM_STAGE_NONE || !message) {
- /* create new RTSP message */
- message = rtsp_message_create(RTSP_MESSAGE_TYPE_UNKNOWN,parser->pool);
- parser->message = message;
- parser->stage = RTSP_STREAM_STAGE_START_LINE;
- }
-
- if(parser->stage == RTSP_STREAM_STAGE_START_LINE) {
- /* parse start-line */
- if(rtsp_start_line_parse(&message->start_line,stream,message->pool) == FALSE) {
- return rtsp_parser_break(parser,stream);
- }
- parser->stage = RTSP_STREAM_STAGE_HEADER;
- }
-
- if(parser->stage == RTSP_STREAM_STAGE_HEADER) {
- /* parse header */
- if(rtsp_header_parse(&message->header,stream,message->pool) == FALSE) {
- return rtsp_parser_break(parser,stream);
- }
-
- parser->stage = RTSP_STREAM_STAGE_NONE;
- if(rtsp_header_property_check(&message->header.property_set,RTSP_HEADER_FIELD_CONTENT_LENGTH) == TRUE) {
- if(message->header.content_length) {
- apt_str_t *body = &message->body;
- body->buf = apr_palloc(message->pool,message->header.content_length+1);
- body->length = 0;
- parser->stage = RTSP_STREAM_STAGE_BODY;
- }
- }
- }
-
- if(parser->stage == RTSP_STREAM_STAGE_BODY) {
- if(rtsp_message_body_read(message,stream) == FALSE) {
- return rtsp_parser_break(parser,stream);
- }
- parser->stage = RTSP_STREAM_STAGE_NONE;
- }
-
- /* in the worst case message segmentation may occur between and
- of the final empty header */
- if(!message->body.length && *(stream->pos-1)== APT_TOKEN_CR) {
- /* if this is the case be prepared to skip */
- parser->skip_lf = TRUE;
- }
-
- return RTSP_STREAM_STATUS_COMPLETE;
+ return apt_message_parser_run(parser->base,stream,(void**)message);
}
-/** Get parsed RTSP message */
-RTSP_DECLARE(rtsp_message_t*) rtsp_parser_message_get(const rtsp_parser_t *parser)
+/** Create message and read start line */
+static apt_bool_t rtsp_parser_on_start(apt_message_parser_t *parser, apt_message_context_t *context, apt_text_stream_t *stream, apr_pool_t *pool)
{
- return parser->message;
+ rtsp_message_t *message;
+ apt_str_t start_line;
+ /* read start line */
+ if(apt_text_line_read(stream,&start_line) == FALSE) {
+ return FALSE;
+ }
+
+ message = rtsp_message_create(RTSP_MESSAGE_TYPE_UNKNOWN,pool);
+ if(rtsp_start_line_parse(&message->start_line,&start_line,message->pool) == FALSE) {
+ return FALSE;
+ }
+
+ context->message = message;
+ context->header = &message->header.header_section;
+ context->body = &message->body;
+ return TRUE;
}
+/** Header section handler */
+static apt_bool_t rtsp_parser_on_header_complete(apt_message_parser_t *parser, apt_message_context_t *context)
+{
+ rtsp_message_t *rtsp_message = context->message;
+ rtsp_header_fields_parse(&rtsp_message->header,rtsp_message->pool);
+
+ if(context->body && rtsp_header_property_check(&rtsp_message->header,RTSP_HEADER_FIELD_CONTENT_LENGTH) == TRUE) {
+ context->body->length = rtsp_message->header.content_length;
+ }
+
+ return TRUE;
+}
/** Create RTSP stream generator */
RTSP_DECLARE(rtsp_generator_t*) rtsp_generator_create(apr_pool_t *pool)
{
rtsp_generator_t *generator = apr_palloc(pool,sizeof(rtsp_generator_t));
- generator->stage = RTSP_STREAM_STAGE_NONE;
- generator->message = NULL;
- generator->pool = pool;
+ generator->base = apt_message_generator_create(generator,&generator_vtable,pool);
return generator;
}
-/** Set RTSP message to generate */
-RTSP_DECLARE(apt_bool_t) rtsp_generator_message_set(rtsp_generator_t *generator, rtsp_message_t *message)
-{
- if(!message) {
- return FALSE;
- }
- generator->message = message;
- return TRUE;
-}
-
-static rtsp_stream_status_e rtsp_generator_break(rtsp_generator_t *generator, apt_text_stream_t *stream)
-{
- /* failed to generate message */
- if(apt_text_is_eos(stream) == TRUE) {
- /* end of stream reached */
- return RTSP_STREAM_STATUS_INCOMPLETE;
- }
-
- /* error case */
- generator->stage = RTSP_STREAM_STAGE_NONE;
- return RTSP_STREAM_STATUS_INVALID;
-}
/** Generate RTSP stream */
-RTSP_DECLARE(rtsp_stream_status_e) rtsp_generator_run(rtsp_generator_t *generator, apt_text_stream_t *stream)
+RTSP_DECLARE(apt_message_status_e) rtsp_generator_run(rtsp_generator_t *generator, rtsp_message_t *message, apt_text_stream_t *stream)
{
- rtsp_message_t *message = generator->message;
- if(!message) {
- return RTSP_STREAM_STATUS_INVALID;
- }
-
- if(generator->stage == RTSP_STREAM_STAGE_NONE) {
- /* generate start-line */
- if(rtsp_start_line_generate(&message->start_line,stream) == FALSE) {
- return rtsp_generator_break(generator,stream);
- }
-
- /* generate header */
- if(rtsp_header_generate(&message->header,stream) == FALSE) {
- return rtsp_generator_break(generator,stream);
- }
-
- generator->stage = RTSP_STREAM_STAGE_NONE;
- if(rtsp_header_property_check(&message->header.property_set,RTSP_HEADER_FIELD_CONTENT_LENGTH) == TRUE) {
- if(message->header.content_length) {
- apt_str_t *body = &message->body;
- body->length = 0;
- generator->stage = RTSP_STREAM_STAGE_BODY;
- }
- }
- }
-
- if(generator->stage == RTSP_STREAM_STAGE_BODY) {
- if(rtsp_message_body_write(message,stream) == FALSE) {
- return rtsp_generator_break(generator,stream);
- }
-
- generator->stage = RTSP_STREAM_STAGE_NONE;
- }
-
- return RTSP_STREAM_STATUS_COMPLETE;
+ return apt_message_generator_run(generator->base,message,stream);
}
-
-/** Walk through RTSP stream and invoke message handler for each parsed message */
-RTSP_DECLARE(apt_bool_t) rtsp_stream_walk(rtsp_parser_t *parser, apt_text_stream_t *stream, rtsp_message_handler_f handler, void *obj)
+/** Initialize by generating message start line and return header section and body */
+apt_bool_t rtsp_generator_on_start(apt_message_generator_t *generator, apt_message_context_t *context, apt_text_stream_t *stream)
{
- rtsp_stream_status_e status;
- if(parser->skip_lf == TRUE) {
- /* skip occurred as a result of message segmentation between and */
- apt_text_char_skip(stream,APT_TOKEN_LF);
- parser->skip_lf = FALSE;
- }
- do {
- status = rtsp_parser_run(parser,stream);
- if(status == RTSP_STREAM_STATUS_COMPLETE) {
- /* message is completely parsed */
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Parsed RTSP Message [%lu]", stream->pos - stream->text.buf);
- /* connection has already been destroyed, if handler return FALSE */
- if(handler(obj,parser->message,status) == FALSE) {
- return TRUE;
- }
- }
- else if(status == RTSP_STREAM_STATUS_INCOMPLETE) {
- /* message is partially parsed, to be continued */
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Truncated RTSP Message [%lu]", stream->pos - stream->text.buf);
- /* prepare stream for further processing */
- if(apt_text_stream_scroll(stream) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Scroll RTSP Stream", stream->text.buf);
- }
- return TRUE;
- }
- else if(status == RTSP_STREAM_STATUS_INVALID){
- /* error case */
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Parse RTSP Message");
- /* invoke message handler */
- if(handler(obj,parser->message,status) == TRUE) {
- /* reset stream pos */
- stream->pos = stream->text.buf;
- }
- return FALSE;
- }
- }
- while(apt_text_is_eos(stream) == FALSE);
-
- /* reset stream pos */
- apt_text_stream_reset(stream);
- return TRUE;
+ rtsp_message_t *rtsp_message = context->message;
+ context->header = &rtsp_message->header.header_section;
+ context->body = &rtsp_message->body;
+ return rtsp_start_line_generate(&rtsp_message->start_line,stream);
}
diff --git a/libs/unimrcp/libs/uni-rtsp/unirtsp.2008.vcproj b/libs/unimrcp/libs/uni-rtsp/unirtsp.2008.vcproj
deleted file mode 100644
index 4189ab121e..0000000000
--- a/libs/unimrcp/libs/uni-rtsp/unirtsp.2008.vcproj
+++ /dev/null
@@ -1,321 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/libs/uni-rtsp/unirtsp.2010.vcxproj b/libs/unimrcp/libs/uni-rtsp/unirtsp.2010.vcxproj
deleted file mode 100644
index 9fad4f7787..0000000000
--- a/libs/unimrcp/libs/uni-rtsp/unirtsp.2010.vcxproj
+++ /dev/null
@@ -1,132 +0,0 @@
-
-
-
-
- Debug
- Win32
-
-
- Debug
- x64
-
-
- Release
- Win32
-
-
- Release
- x64
-
-
-
- unirtsp
- {504B3154-7A4F-459D-9877-B951021C3F1F}
- unirtsp
- Win32Proj
-
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
-
-
-
- codecs;%(AdditionalIncludeDirectories)
- APT_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- codecs;%(AdditionalIncludeDirectories)
- APT_STATIC_LIB;%(PreprocessorDefinitions)
- ProgramDatabase
-
-
-
-
- codecs;%(AdditionalIncludeDirectories)
- APT_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- codecs;%(AdditionalIncludeDirectories)
- APT_STATIC_LIB;%(PreprocessorDefinitions)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/libs/uni-rtsp/unirtsp.2010.vcxproj.filters b/libs/unimrcp/libs/uni-rtsp/unirtsp.2010.vcxproj.filters
deleted file mode 100644
index 5a1581a2c3..0000000000
--- a/libs/unimrcp/libs/uni-rtsp/unirtsp.2010.vcxproj.filters
+++ /dev/null
@@ -1,56 +0,0 @@
-
-
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hpp;hxx;hm;inl;inc;xsd
-
-
- {fd4564ef-9f34-4f23-992d-37f127e289a2}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
- include
-
-
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
- src
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/modules/mrcp-sofiasip/include/mrcp_sdp.h b/libs/unimrcp/modules/mrcp-sofiasip/include/mrcp_sdp.h
index a7938c841a..8061119c58 100644
--- a/libs/unimrcp/modules/mrcp-sofiasip/include/mrcp_sdp.h
+++ b/libs/unimrcp/modules/mrcp-sofiasip/include/mrcp_sdp.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_sdp.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_SDP_H__
-#define __MRCP_SDP_H__
+#ifndef MRCP_SDP_H
+#define MRCP_SDP_H
/**
* @file mrcp_sdp.h
@@ -37,4 +39,4 @@ MRCP_DECLARE(apr_size_t) sdp_resource_discovery_string_generate(const char *ip,
APT_END_EXTERN_C
-#endif /*__MRCP_SDP_H__*/
+#endif /* MRCP_SDP_H */
diff --git a/libs/unimrcp/modules/mrcp-sofiasip/include/mrcp_sofiasip_client_agent.h b/libs/unimrcp/modules/mrcp-sofiasip/include/mrcp_sofiasip_client_agent.h
index 6505c7695e..da9cfdd6eb 100644
--- a/libs/unimrcp/modules/mrcp-sofiasip/include/mrcp_sofiasip_client_agent.h
+++ b/libs/unimrcp/modules/mrcp-sofiasip/include/mrcp_sofiasip_client_agent.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_sofiasip_client_agent.h 1700 2010-05-21 18:56:06Z achaloyan $
*/
-#ifndef __MRCP_SOFIASIP_CLIENT_AGENT_H__
-#define __MRCP_SOFIASIP_CLIENT_AGENT_H__
+#ifndef MRCP_SOFIASIP_CLIENT_AGENT_H
+#define MRCP_SOFIASIP_CLIENT_AGENT_H
/**
* @file mrcp_sofiasip_client_agent.h
@@ -40,30 +42,26 @@ struct mrcp_sofia_client_config_t {
apr_port_t local_port;
/** Local SIP user name */
char *local_user_name;
-
- /** Remote IP address */
- char *remote_ip;
- /** Remote SIP port */
- apr_port_t remote_port;
- /** Remote SIP user name */
- char *remote_user_name;
-
- /** Force destination ip address. Should be used only in case
- SDP contains incorrect connection address (local IP address behind NAT) */
- apt_bool_t force_destination;
-
/** User agent name */
char *user_agent_name;
/** SDP origin */
char *origin;
/** SIP transport */
char *transport;
+ /** SIP T1 timer */
+ apr_size_t sip_t1;
+ /** SIP T2 timer */
+ apr_size_t sip_t2;
+ /** SIP T4 timer */
+ apr_size_t sip_t4;
+ /** SIP T1x64 timer */
+ apr_size_t sip_t1x64;
};
/**
* Create Sofia-SIP signaling agent.
*/
-MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_sofiasip_client_agent_create(mrcp_sofia_client_config_t *config, apr_pool_t *pool);
+MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_sofiasip_client_agent_create(const char *id, mrcp_sofia_client_config_t *config, apr_pool_t *pool);
/**
* Allocate Sofia-SIP config.
@@ -72,4 +70,4 @@ MRCP_DECLARE(mrcp_sofia_client_config_t*) mrcp_sofiasip_client_config_alloc(apr_
APT_END_EXTERN_C
-#endif /*__MRCP_SOFIASIP_CLIENT_AGENT_H__*/
+#endif /* MRCP_SOFIASIP_CLIENT_AGENT_H */
diff --git a/libs/unimrcp/modules/mrcp-sofiasip/include/mrcp_sofiasip_server_agent.h b/libs/unimrcp/modules/mrcp-sofiasip/include/mrcp_sofiasip_server_agent.h
index 85bdea45f4..7876d59f68 100644
--- a/libs/unimrcp/modules/mrcp-sofiasip/include/mrcp_sofiasip_server_agent.h
+++ b/libs/unimrcp/modules/mrcp-sofiasip/include/mrcp_sofiasip_server_agent.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_sofiasip_server_agent.h 1700 2010-05-21 18:56:06Z achaloyan $
*/
-#ifndef __MRCP_SOFIASIP_SERVER_AGENT_H__
-#define __MRCP_SOFIASIP_SERVER_AGENT_H__
+#ifndef MRCP_SOFIASIP_SERVER_AGENT_H
+#define MRCP_SOFIASIP_SERVER_AGENT_H
/**
* @file mrcp_sofiasip_server_agent.h
@@ -38,7 +40,6 @@ struct mrcp_sofia_server_config_t {
char *ext_ip;
/** Local port to bind to */
apr_port_t local_port;
-
/** SIP user name */
char *user_name;
/** User agent name */
@@ -47,16 +48,23 @@ struct mrcp_sofia_server_config_t {
char *origin;
/** SIP transport */
char *transport;
-
/** Force destination ip address. Should be used only in case
SDP contains incorrect connection address (local IP address behind NAT) */
apt_bool_t force_destination;
+ /** SIP T1 timer */
+ apr_size_t sip_t1;
+ /** SIP T2 timer */
+ apr_size_t sip_t2;
+ /** SIP T4 timer */
+ apr_size_t sip_t4;
+ /** SIP T1x64 timer */
+ apr_size_t sip_t1x64;
};
/**
* Create Sofia-SIP signaling agent.
*/
-MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_sofiasip_server_agent_create(mrcp_sofia_server_config_t *config, apr_pool_t *pool);
+MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_sofiasip_server_agent_create(const char *id, mrcp_sofia_server_config_t *config, apr_pool_t *pool);
/**
* Allocate Sofia-SIP config.
@@ -65,4 +73,4 @@ MRCP_DECLARE(mrcp_sofia_server_config_t*) mrcp_sofiasip_server_config_alloc(apr_
APT_END_EXTERN_C
-#endif /*__MRCP_SOFIASIP_SERVER_AGENT_H__*/
+#endif /* MRCP_SOFIASIP_SERVER_AGENT_H */
diff --git a/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2008.vcproj b/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2008.vcproj
deleted file mode 100644
index 5b10a418b3..0000000000
--- a/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2008.vcproj
+++ /dev/null
@@ -1,293 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj b/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj
deleted file mode 100644
index b3931497c7..0000000000
--- a/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj
+++ /dev/null
@@ -1,138 +0,0 @@
-
-
-
-
- Debug
- Win32
-
-
- Debug
- x64
-
-
- Release
- Win32
-
-
- Release
- x64
-
-
-
- mrcpsofiasip
- {746F3632-5BB2-4570-9453-31D6D58A7D8E}
- mrcpsofiasip
- Win32Proj
-
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
-
-
-
- include;%(AdditionalIncludeDirectories)
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;LIBSOFIA_SIP_UA_STATIC;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- include;%(AdditionalIncludeDirectories)
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;LIBSOFIA_SIP_UA_STATIC;%(PreprocessorDefinitions)
- ProgramDatabase
-
-
-
-
- include;%(AdditionalIncludeDirectories)
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;LIBSOFIA_SIP_UA_STATIC;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- include;%(AdditionalIncludeDirectories)
- APT_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;LIBSOFIA_SIP_UA_STATIC;%(PreprocessorDefinitions)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {70a49bc2-7500-41d0-b75d-edcc5be987a0}
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj.filters b/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj.filters
deleted file mode 100644
index d2157eea88..0000000000
--- a/libs/unimrcp/modules/mrcp-sofiasip/mrcpsofiasip.2010.vcxproj.filters
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hpp;hxx;hm;inl;inc;xsd
-
-
- {6e92b598-880e-4fe5-88fb-f69df8e06a57}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
-
-
- include
-
-
- include
-
-
- include
-
-
-
-
- src
-
-
- src
-
-
- src
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sdp.c b/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sdp.c
index 7af406ff1c..23a1efe8d9 100644
--- a/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sdp.c
+++ b/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sdp.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_sdp.c 1647 2010-04-12 19:34:53Z achaloyan $
*/
#include
@@ -331,7 +333,7 @@ static apt_bool_t mrcp_control_media_generate(mrcp_control_descriptor_t *control
apt_string_set(&name,sdp_media->m_proto_name);
control_media->proto = mrcp_proto_find(&name);
if(control_media->proto != MRCP_PROTO_TCP) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Not supported SDP Proto [%s], expected [%s]",sdp_media->m_proto_name,mrcp_proto_get(MRCP_PROTO_TCP));
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Not supported SDP Proto [%s], expected [%s]",sdp_media->m_proto_name,mrcp_proto_get(MRCP_PROTO_TCP)->buf);
return FALSE;
}
diff --git a/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sofiasip_client_agent.c b/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sofiasip_client_agent.c
index aa7a5fb753..6ef4199fbe 100644
--- a/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sofiasip_client_agent.c
+++ b/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sofiasip_client_agent.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_sofiasip_client_agent.c 1799 2011-05-12 02:32:32Z achaloyan $
*/
typedef struct mrcp_sofia_agent_t mrcp_sofia_agent_t;
@@ -35,14 +37,11 @@ typedef struct mrcp_sofia_session_t mrcp_sofia_session_t;
#include "mrcp_sdp.h"
#include "apt_log.h"
-#define SOFIA_TASK_NAME "SofiaSIP Agent"
-
struct mrcp_sofia_agent_t {
mrcp_sig_agent_t *sig_agent;
mrcp_sofia_client_config_t *config;
char *sip_contact_str;
- char *sip_to_str;
char *sip_from_str;
char *sip_bind_str;
@@ -51,12 +50,16 @@ struct mrcp_sofia_agent_t {
};
struct mrcp_sofia_session_t {
- mrcp_session_t *session;
- su_home_t *home;
- nua_handle_t *nh;
+ mrcp_session_t *session;
+ mrcp_sig_settings_t *sip_settings;
+ char *sip_to_str;
- apt_bool_t terminate_requested;
- apr_thread_mutex_t *mutex;
+ su_home_t *home;
+ nua_handle_t *nh;
+
+ apt_bool_t terminate_requested;
+ mrcp_session_descriptor_t *descriptor;
+ apr_thread_mutex_t *mutex;
};
/* Task Interface */
@@ -77,7 +80,7 @@ static const mrcp_session_request_vtable_t session_request_vtable = {
};
static apt_bool_t mrcp_sofia_config_validate(mrcp_sofia_agent_t *sofia_agent, mrcp_sofia_client_config_t *config, apr_pool_t *pool);
-static apt_bool_t mrcp_sofia_session_create(mrcp_session_t *session);
+static apt_bool_t mrcp_sofia_session_create(mrcp_session_t *session, mrcp_sig_settings_t *settings);
static void mrcp_sofia_event_callback( nua_event_t nua_event,
int status,
@@ -91,13 +94,13 @@ static void mrcp_sofia_event_callback( nua_event_t nua_event,
/** Create Sofia-SIP Signaling Agent */
-MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_sofiasip_client_agent_create(mrcp_sofia_client_config_t *config, apr_pool_t *pool)
+MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_sofiasip_client_agent_create(const char *id, mrcp_sofia_client_config_t *config, apr_pool_t *pool)
{
apt_task_t *task;
apt_task_vtable_t *vtable;
mrcp_sofia_agent_t *sofia_agent;
sofia_agent = apr_palloc(pool,sizeof(mrcp_sofia_agent_t));
- sofia_agent->sig_agent = mrcp_signaling_agent_create(sofia_agent,MRCP_VERSION_2,pool);
+ sofia_agent->sig_agent = mrcp_signaling_agent_create(id,sofia_agent,MRCP_VERSION_2,pool);
sofia_agent->sig_agent->create_client_session = mrcp_sofia_session_create;
sofia_agent->root = NULL;
sofia_agent->nua = NULL;
@@ -110,7 +113,7 @@ MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_sofiasip_client_agent_create(mrcp_sofia_cli
if(!task) {
return NULL;
}
- apt_task_name_set(task,SOFIA_TASK_NAME);
+ apt_task_name_set(task,id);
vtable = apt_task_vtable_get(task);
if(vtable) {
vtable->on_pre_run = mrcp_sofia_task_initialize;
@@ -118,10 +121,8 @@ MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_sofiasip_client_agent_create(mrcp_sofia_cli
vtable->terminate = mrcp_sofia_task_terminate;
}
sofia_agent->sig_agent->task = task;
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create "SOFIA_TASK_NAME" ["SOFIA_SIP_VERSION"] %s:%hu -> %s:%hu %s",
- config->local_ip,config->local_port,
- config->remote_ip,config->remote_port,
- config->transport ? config->transport : "");
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create SofiaSIP Agent [%s] ["SOFIA_SIP_VERSION"] %s",
+ id,sofia_agent->sip_bind_str);
return sofia_agent->sig_agent;
}
@@ -133,48 +134,37 @@ MRCP_DECLARE(mrcp_sofia_client_config_t*) mrcp_sofiasip_client_config_alloc(apr_
config->ext_ip = NULL;
config->local_port = 0;
config->local_user_name = NULL;
- config->remote_ip = NULL;
- config->remote_port = 0;
- config->remote_user_name = NULL;
-
- config->force_destination = FALSE;
config->user_agent_name = NULL;
config->origin = NULL;
config->transport = NULL;
+
+ config->sip_t1 = 0;
+ config->sip_t2 = 0;
+ config->sip_t4 = 0;
+ config->sip_t1x64 = 0;
return config;
}
static apt_bool_t mrcp_sofia_config_validate(mrcp_sofia_agent_t *sofia_agent, mrcp_sofia_client_config_t *config, apr_pool_t *pool)
{
const char *local_ip = config->ext_ip ? config->ext_ip : config->local_ip;
- if(!config->local_ip || !config->remote_ip) {
+ if(!config->local_ip) {
return FALSE;
}
sofia_agent->config = config;
- sofia_agent->sip_contact_str = apr_psprintf(pool,"sip:%s:%d", local_ip, config->local_port);
- sofia_agent->sip_from_str = apr_psprintf(pool,"sip:%s:%d", local_ip, config->local_port);
+ sofia_agent->sip_contact_str = apr_psprintf(pool,"sip:%s:%hu", local_ip, config->local_port);
+ sofia_agent->sip_from_str = apr_psprintf(pool,"sip:%s:%hu", local_ip, config->local_port);
- if(config->remote_user_name && config->remote_user_name != '\0') {
- sofia_agent->sip_to_str = apr_psprintf(pool,"sip:%s@%s:%d",
- config->remote_user_name,
- config->remote_ip,
- config->remote_port);
- }
- else {
- sofia_agent->sip_to_str = apr_psprintf(pool,"sip:%s:%d",
- config->remote_ip,
- config->remote_port);
- }
if(config->transport) {
- sofia_agent->sip_bind_str = apr_psprintf(pool,"sip:%s:%d;transport=%s",
+ sofia_agent->sip_bind_str = apr_psprintf(pool,"sip:%s:%hu;transport=%s",
config->local_ip,
config->local_port,
config->transport);
}
else {
- sofia_agent->sip_bind_str = apr_psprintf(pool,"sip:%s:%d",
+ sofia_agent->sip_bind_str = apr_psprintf(pool,"sip:%s:%hu",
config->local_ip,
config->local_port);
}
@@ -184,6 +174,7 @@ static apt_bool_t mrcp_sofia_config_validate(mrcp_sofia_agent_t *sofia_agent, mr
static void mrcp_sofia_task_initialize(apt_task_t *task)
{
mrcp_sofia_agent_t *sofia_agent = apt_task_object_get(task);
+ mrcp_sofia_client_config_t *sofia_config = sofia_agent->config;
/* Initialize Sofia-SIP library and create event loop */
su_init();
@@ -204,7 +195,11 @@ static void mrcp_sofia_task_initialize(apt_task_t *task)
sofia_agent->nua,
NUTAG_AUTOANSWER(0),
NUTAG_APPL_METHOD("OPTIONS"),
- SIPTAG_USER_AGENT_STR(sofia_agent->config->user_agent_name),
+ TAG_IF(sofia_config->sip_t1,NTATAG_SIP_T1(sofia_config->sip_t1)),
+ TAG_IF(sofia_config->sip_t2,NTATAG_SIP_T2(sofia_config->sip_t2)),
+ TAG_IF(sofia_config->sip_t4,NTATAG_SIP_T4(sofia_config->sip_t4)),
+ TAG_IF(sofia_config->sip_t1x64,NTATAG_SIP_T1X64(sofia_config->sip_t1x64)),
+ SIPTAG_USER_AGENT_STR(sofia_config->user_agent_name),
TAG_END());
}
}
@@ -244,7 +239,7 @@ static APR_INLINE mrcp_sofia_agent_t* mrcp_sofia_agent_get(mrcp_session_t *sessi
return session->signaling_agent->obj;
}
-static apt_bool_t mrcp_sofia_session_create(mrcp_session_t *session)
+static apt_bool_t mrcp_sofia_session_create(mrcp_session_t *session, mrcp_sig_settings_t *settings)
{
mrcp_sofia_agent_t *sofia_agent = mrcp_sofia_agent_get(session);
mrcp_sofia_session_t *sofia_session;
@@ -254,15 +249,30 @@ static apt_bool_t mrcp_sofia_session_create(mrcp_session_t *session)
sofia_session->mutex = NULL;
sofia_session->home = su_home_new(sizeof(*sofia_session->home));
sofia_session->session = session;
+ sofia_session->sip_settings = settings;
sofia_session->terminate_requested = FALSE;
+ sofia_session->descriptor = NULL;
session->obj = sofia_session;
-
+
+ if(settings->user_name && settings->user_name != '\0') {
+ sofia_session->sip_to_str = apr_psprintf(session->pool,"sip:%s@%s:%hu",
+ settings->user_name,
+ settings->server_ip,
+ settings->server_port);
+ }
+ else {
+ sofia_session->sip_to_str = apr_psprintf(session->pool,"sip:%s:%hu",
+ settings->server_ip,
+ settings->server_port);
+ }
+
sofia_session->nh = nua_handle(
sofia_agent->nua,
sofia_session,
- SIPTAG_TO_STR(sofia_agent->sip_to_str),
+ SIPTAG_TO_STR(sofia_session->sip_to_str),
SIPTAG_FROM_STR(sofia_agent->sip_from_str),
SIPTAG_CONTACT_STR(sofia_agent->sip_contact_str),
+ TAG_IF(settings->feature_tags,SIPTAG_ACCEPT_CONTACT_STR(settings->feature_tags)),
TAG_END());
apr_thread_mutex_create(&sofia_session->mutex,APR_THREAD_MUTEX_DEFAULT,session->pool);
@@ -313,8 +323,10 @@ static apt_bool_t mrcp_sofia_session_offer(mrcp_session_t *session, mrcp_session
}
if(sdp_string_generate_by_mrcp_descriptor(sdp_str,sizeof(sdp_str),descriptor,TRUE) > 0) {
local_sdp_str = sdp_str;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Local SDP "APT_PTRSID_FMT"\n%s",
- MRCP_SESSION_PTRSID(session),
+ sofia_session->descriptor = descriptor;
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->log_obj,"Local SDP "APT_NAMESID_FMT"\n%s",
+ session->name,
+ MRCP_SESSION_SID(session),
local_sdp_str);
}
@@ -392,14 +404,15 @@ static void mrcp_sofia_on_session_ready(
sdp_parser_t *parser = NULL;
sdp_session_t *sdp = NULL;
const char *force_destination_ip = NULL;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Remote SDP "APT_PTRSID_FMT"\n%s",
- MRCP_SESSION_PTRSID(session),
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->log_obj,"Remote SDP "APT_NAMESID_FMT"\n%s",
+ session->name,
+ MRCP_SESSION_SID(session),
remote_sdp_str);
parser = sdp_parse(sofia_session->home,remote_sdp_str,(int)strlen(remote_sdp_str),0);
sdp = sdp_session(parser);
- if(sofia_agent && sofia_agent->config->force_destination == TRUE) {
- force_destination_ip = sofia_agent->config->remote_ip;
+ if(sofia_session->sip_settings->force_destination == TRUE) {
+ force_destination_ip = sofia_session->sip_settings->server_ip;
}
descriptor = mrcp_descriptor_generate_by_sdp_session(sdp,force_destination_ip,session->pool);
sdp_parser_free(parser);
@@ -409,6 +422,62 @@ static void mrcp_sofia_on_session_ready(
}
}
+static void mrcp_sofia_on_session_redirect(
+ int status,
+ mrcp_sofia_agent_t *sofia_agent,
+ nua_handle_t *nh,
+ mrcp_sofia_session_t *sofia_session,
+ sip_t const *sip,
+ tagi_t tags[])
+{
+ mrcp_session_t *session = sofia_session->session;
+ sip_contact_t *sip_contact;
+ if(!sip) {
+ return;
+ }
+ sip_contact = sip->sip_contact;
+ if(!sip_contact || !sip_contact->m_url) {
+ return;
+ }
+
+ if(sip_contact->m_url->url_user && sip_contact->m_url->url_user != '\0') {
+ sofia_session->sip_to_str = apr_psprintf(session->pool,"sip:%s@%s:%s",
+ sip_contact->m_url->url_user,
+ sip_contact->m_url->url_host,
+ sip_contact->m_url->url_port);
+ }
+ else {
+ sofia_session->sip_to_str = apr_psprintf(session->pool,"sip:%s:%s",
+ sip_contact->m_url->url_host,
+ sip_contact->m_url->url_port);
+ }
+
+ apr_thread_mutex_lock(sofia_session->mutex);
+
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->log_obj,"Redirect "APT_NAMESID_FMT" to %s",
+ session->name,
+ MRCP_SESSION_SID(session),
+ sofia_session->sip_to_str);
+
+ if(sofia_session->nh) {
+ nua_handle_bind(sofia_session->nh, NULL);
+ nua_handle_destroy(sofia_session->nh);
+ sofia_session->nh = NULL;
+ }
+
+ sofia_session->nh = nua_handle(
+ sofia_agent->nua,
+ sofia_session,
+ SIPTAG_TO_STR(sofia_session->sip_to_str),
+ SIPTAG_FROM_STR(sofia_agent->sip_from_str),
+ SIPTAG_CONTACT_STR(sofia_agent->sip_contact_str),
+ TAG_END());
+
+ apr_thread_mutex_unlock(sofia_session->mutex);
+
+ mrcp_sofia_session_offer(sofia_session->session,sofia_session->descriptor);
+}
+
static void mrcp_sofia_on_session_terminate(
int status,
mrcp_sofia_agent_t *sofia_agent,
@@ -450,8 +519,8 @@ static void mrcp_sofia_on_state_change(
NUTAG_CALLSTATE_REF(ss_state),
TAG_END());
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"SIP Call State "APT_PTR_FMT" [%s]",
- sofia_session ? MRCP_SESSION_PTR(sofia_session->session) : NULL,
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"SIP Call State %s [%s]",
+ sofia_session ? sofia_session->session->name : "",
nua_callstate_name(ss_state));
switch(ss_state) {
@@ -477,15 +546,15 @@ static void mrcp_sofia_on_resource_discover(
const char *remote_sdp_str = NULL;
mrcp_session_descriptor_t *descriptor = NULL;
- tl_gets(tags,
- SOATAG_REMOTE_SDP_STR_REF(remote_sdp_str),
- TAG_END());
-
+ if(sip->sip_payload) {
+ remote_sdp_str = sip->sip_payload->pl_data;
+ }
+
if(remote_sdp_str) {
sdp_parser_t *parser = NULL;
sdp_session_t *sdp = NULL;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Resource Discovery SDP "APT_PTR_FMT"\n%s",
- MRCP_SESSION_PTR(session),
+ apt_obj_log(APT_LOG_MARK,APT_PRIO_INFO,session->obj,"Resource Discovery SDP %s\n%s",
+ session->name,
remote_sdp_str);
parser = sdp_parse(sofia_session->home,remote_sdp_str,(int)strlen(remote_sdp_str),0);
@@ -517,6 +586,11 @@ static void mrcp_sofia_event_callback(
case nua_i_state:
mrcp_sofia_on_state_change(status,sofia_agent,nh,sofia_session,sip,tags);
break;
+ case nua_r_invite:
+ if(status >= 300 && status < 400) {
+ mrcp_sofia_on_session_redirect(status,sofia_agent,nh,sofia_session,sip,tags);
+ }
+ break;
case nua_r_options:
mrcp_sofia_on_resource_discover(status,sofia_agent,nh,sofia_session,sip,tags);
break;
diff --git a/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sofiasip_server_agent.c b/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sofiasip_server_agent.c
index c5f81a22b5..e094078a24 100644
--- a/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sofiasip_server_agent.c
+++ b/libs/unimrcp/modules/mrcp-sofiasip/src/mrcp_sofiasip_server_agent.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_sofiasip_server_agent.c 1700 2010-05-21 18:56:06Z achaloyan $
*/
typedef struct mrcp_sofia_agent_t mrcp_sofia_agent_t;
@@ -35,8 +37,6 @@ typedef struct mrcp_sofia_session_t mrcp_sofia_session_t;
#include "mrcp_sdp.h"
#include "apt_log.h"
-#define SOFIA_TASK_NAME "SofiaSIP Agent"
-
struct mrcp_sofia_agent_t {
mrcp_sig_agent_t *sig_agent;
@@ -82,13 +82,13 @@ static void mrcp_sofia_event_callback( nua_event_t nua_event,
/** Create Sofia-SIP Signaling Agent */
-MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_sofiasip_server_agent_create(mrcp_sofia_server_config_t *config, apr_pool_t *pool)
+MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_sofiasip_server_agent_create(const char *id, mrcp_sofia_server_config_t *config, apr_pool_t *pool)
{
apt_task_t *task;
apt_task_vtable_t *vtable;
mrcp_sofia_agent_t *sofia_agent;
sofia_agent = apr_palloc(pool,sizeof(mrcp_sofia_agent_t));
- sofia_agent->sig_agent = mrcp_signaling_agent_create(sofia_agent,MRCP_VERSION_2,pool);
+ sofia_agent->sig_agent = mrcp_signaling_agent_create(id,sofia_agent,MRCP_VERSION_2,pool);
sofia_agent->config = config;
sofia_agent->root = NULL;
sofia_agent->nua = NULL;
@@ -101,7 +101,7 @@ MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_sofiasip_server_agent_create(mrcp_sofia_ser
if(!task) {
return NULL;
}
- apt_task_name_set(task,SOFIA_TASK_NAME);
+ apt_task_name_set(task,id);
vtable = apt_task_vtable_get(task);
if(vtable) {
vtable->on_pre_run = mrcp_sofia_task_initialize;
@@ -109,10 +109,8 @@ MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_sofiasip_server_agent_create(mrcp_sofia_ser
vtable->terminate = mrcp_sofia_task_terminate;
}
sofia_agent->sig_agent->task = task;
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create "SOFIA_TASK_NAME" ["SOFIA_SIP_VERSION"] %s:%hu %s",
- config->local_ip,
- config->local_port,
- config->transport ? config->transport : "");
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create SofiaSIP Agent [%s] ["SOFIA_SIP_VERSION"] %s",
+ id,sofia_agent->sip_bind_str);
return sofia_agent->sig_agent;
}
@@ -128,6 +126,10 @@ MRCP_DECLARE(mrcp_sofia_server_config_t*) mrcp_sofiasip_server_config_alloc(apr_
config->origin = NULL;
config->transport = NULL;
config->force_destination = FALSE;
+ config->sip_t1 = 0;
+ config->sip_t2 = 0;
+ config->sip_t4 = 0;
+ config->sip_t1x64 = 0;
return config;
}
@@ -135,15 +137,15 @@ static apt_bool_t mrcp_sofia_config_validate(mrcp_sofia_agent_t *sofia_agent, mr
{
const char *local_ip = config->ext_ip ? config->ext_ip : config->local_ip;
sofia_agent->config = config;
- sofia_agent->sip_contact_str = apr_psprintf(pool,"sip:%s:%d",local_ip,config->local_port);
+ sofia_agent->sip_contact_str = apr_psprintf(pool,"sip:%s:%hu",local_ip,config->local_port);
if(config->transport) {
- sofia_agent->sip_bind_str = apr_psprintf(pool,"sip:%s:%d;transport=%s",
+ sofia_agent->sip_bind_str = apr_psprintf(pool,"sip:%s:%hu;transport=%s",
config->local_ip,
config->local_port,
config->transport);
}
else {
- sofia_agent->sip_bind_str = apr_psprintf(pool,"sip:%s:%d",
+ sofia_agent->sip_bind_str = apr_psprintf(pool,"sip:%s:%hu",
config->local_ip,
config->local_port);
}
@@ -153,6 +155,7 @@ static apt_bool_t mrcp_sofia_config_validate(mrcp_sofia_agent_t *sofia_agent, mr
static void mrcp_sofia_task_initialize(apt_task_t *task)
{
mrcp_sofia_agent_t *sofia_agent = apt_task_object_get(task);
+ mrcp_sofia_server_config_t *sofia_config = sofia_agent->config;
/* Initialize Sofia-SIP library and create event loop */
su_init();
@@ -173,7 +176,11 @@ static void mrcp_sofia_task_initialize(apt_task_t *task)
sofia_agent->nua,
NUTAG_AUTOANSWER(0),
NUTAG_APPL_METHOD("OPTIONS"),
- SIPTAG_USER_AGENT_STR(sofia_agent->config->user_agent_name),
+ TAG_IF(sofia_config->sip_t1,NTATAG_SIP_T1(sofia_config->sip_t1)),
+ TAG_IF(sofia_config->sip_t2,NTATAG_SIP_T2(sofia_config->sip_t2)),
+ TAG_IF(sofia_config->sip_t4,NTATAG_SIP_T4(sofia_config->sip_t4)),
+ TAG_IF(sofia_config->sip_t1x64,NTATAG_SIP_T1X64(sofia_config->sip_t1x64)),
+ SIPTAG_USER_AGENT_STR(sofia_config->user_agent_name),
TAG_END());
}
}
@@ -270,7 +277,10 @@ static apt_bool_t mrcp_sofia_on_session_answer(mrcp_session_t *session, mrcp_ses
if(sdp_string_generate_by_mrcp_descriptor(sdp_str,sizeof(sdp_str),descriptor,FALSE) > 0) {
local_sdp_str = sdp_str;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Local SDP\n%s", local_sdp_str);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Local SDP "APT_NAMESID_FMT"\n%s",
+ session->name,
+ MRCP_SESSION_SID(session),
+ local_sdp_str);
}
nua_respond(sofia_session->nh, SIP_200_OK,
@@ -333,7 +343,10 @@ static void mrcp_sofia_on_call_receive(mrcp_sofia_agent_t *sofia_agent,
if(remote_sdp_str) {
sdp_parser_t *parser = NULL;
sdp_session_t *sdp = NULL;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Remote SDP\n%s", remote_sdp_str);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Remote SDP "APT_NAMESID_FMT"\n%s",
+ sofia_session->session->name,
+ MRCP_SESSION_SID(sofia_session->session),
+ remote_sdp_str);
parser = sdp_parse(sofia_session->home,remote_sdp_str,(int)strlen(remote_sdp_str),0);
sdp = sdp_session(parser);
@@ -371,7 +384,9 @@ static void mrcp_sofia_on_state_change(mrcp_sofia_agent_t *sofia_agent,
NUTAG_CALLSTATE_REF(ss_state),
TAG_END());
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"SIP Call State [%s]", nua_callstate_name(ss_state));
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"SIP Call State %s [%s]",
+ sofia_session ? sofia_session->session->name : "",
+ nua_callstate_name(ss_state));
switch(ss_state) {
case nua_callstate_received:
@@ -397,7 +412,8 @@ static void mrcp_sofia_on_resource_discover(mrcp_sofia_agent_t *sofia_agent,
if(sdp_resource_discovery_string_generate(ip,sofia_agent->config->origin,sdp_str,sizeof(sdp_str)) > 0) {
local_sdp_str = sdp_str;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Resource Discovery SDP\n[%s]\n", local_sdp_str);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Resource Discovery SDP\n[%s]\n",
+ local_sdp_str);
}
nua_respond(nh, SIP_200_OK,
diff --git a/libs/unimrcp/modules/mrcp-unirtsp/include/mrcp_unirtsp_client_agent.h b/libs/unimrcp/modules/mrcp-unirtsp/include/mrcp_unirtsp_client_agent.h
index fc26929cbe..e455e4476e 100644
--- a/libs/unimrcp/modules/mrcp-unirtsp/include/mrcp_unirtsp_client_agent.h
+++ b/libs/unimrcp/modules/mrcp-unirtsp/include/mrcp_unirtsp_client_agent.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_unirtsp_client_agent.h 1700 2010-05-21 18:56:06Z achaloyan $
*/
-#ifndef __MRCP_UNIRTSP_CLIENT_AGENT_H__
-#define __MRCP_UNIRTSP_CLIENT_AGENT_H__
+#ifndef MRCP_UNIRTSP_CLIENT_AGENT_H
+#define MRCP_UNIRTSP_CLIENT_AGENT_H
/**
* @file mrcp_unirtsp_client_agent.h
@@ -28,41 +30,30 @@
APT_BEGIN_EXTERN_C
-/** UniRTSP config declaration */
+/** Declaration of UniRTSP agent config */
typedef struct rtsp_client_config_t rtsp_client_config_t;
-/** UniRTSP config */
+/** Configuration of UniRTSP agent */
struct rtsp_client_config_t {
- /** Server IP address */
- char *server_ip;
- /** Server port */
- apr_port_t server_port;
- /** Resource location */
- char *resource_location;
/** SDP origin */
char *origin;
-
- /** Map of the MRCP resource names */
- apr_table_t *resource_map;
-
/** Number of max RTSP connections */
apr_size_t max_connection_count;
-
- /** Force destination ip address. Should be used only in case
- SDP contains incorrect connection address (local IP address behind NAT) */
- apt_bool_t force_destination;
+ /** Request timeout */
+ apr_size_t request_timeout;
};
/**
* Create UniRTSP signaling agent.
*/
-MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_unirtsp_client_agent_create(rtsp_client_config_t *config, apr_pool_t *pool);
+MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_unirtsp_client_agent_create(const char *id, rtsp_client_config_t *config, apr_pool_t *pool);
/**
* Allocate UniRTSP config.
*/
MRCP_DECLARE(rtsp_client_config_t*) mrcp_unirtsp_client_config_alloc(apr_pool_t *pool);
+
APT_END_EXTERN_C
-#endif /*__MRCP_UNIRTSP_CLIENT_AGENT_H__*/
+#endif /* MRCP_UNIRTSP_CLIENT_AGENT_H */
diff --git a/libs/unimrcp/modules/mrcp-unirtsp/include/mrcp_unirtsp_sdp.h b/libs/unimrcp/modules/mrcp-unirtsp/include/mrcp_unirtsp_sdp.h
index 58d35347d0..74de717a48 100644
--- a/libs/unimrcp/modules/mrcp-unirtsp/include/mrcp_unirtsp_sdp.h
+++ b/libs/unimrcp/modules/mrcp-unirtsp/include/mrcp_unirtsp_sdp.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_unirtsp_sdp.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __MRCP_UNIRTSP_SDP_H__
-#define __MRCP_UNIRTSP_SDP_H__
+#ifndef MRCP_UNIRTSP_SDP_H
+#define MRCP_UNIRTSP_SDP_H
/**
* @file mrcp_unirtsp_sdp.h
@@ -84,4 +86,4 @@ MRCP_DECLARE(const char*) rtsp_name_get_by_mrcp_name(const apr_table_t *resource
APT_END_EXTERN_C
-#endif /*__MRCP_UNIRTSP_SDP_H__*/
+#endif /* MRCP_UNIRTSP_SDP_H */
diff --git a/libs/unimrcp/modules/mrcp-unirtsp/include/mrcp_unirtsp_server_agent.h b/libs/unimrcp/modules/mrcp-unirtsp/include/mrcp_unirtsp_server_agent.h
index e117f2a672..e93f692c5b 100644
--- a/libs/unimrcp/modules/mrcp-unirtsp/include/mrcp_unirtsp_server_agent.h
+++ b/libs/unimrcp/modules/mrcp-unirtsp/include/mrcp_unirtsp_server_agent.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_unirtsp_server_agent.h 1700 2010-05-21 18:56:06Z achaloyan $
*/
-#ifndef __MRCP_UNIRTSP_SERVER_AGENT_H__
-#define __MRCP_UNIRTSP_SERVER_AGENT_H__
+#ifndef MRCP_UNIRTSP_SERVER_AGENT_H
+#define MRCP_UNIRTSP_SERVER_AGENT_H
/**
* @file mrcp_unirtsp_server_agent.h
@@ -56,7 +58,7 @@ struct rtsp_server_config_t {
/**
* Create UniRTSP signaling agent.
*/
-MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_unirtsp_server_agent_create(rtsp_server_config_t *config, apr_pool_t *pool);
+MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_unirtsp_server_agent_create(const char *id, rtsp_server_config_t *config, apr_pool_t *pool);
/**
* Allocate UniRTSP config.
@@ -65,4 +67,4 @@ MRCP_DECLARE(rtsp_server_config_t*) mrcp_unirtsp_server_config_alloc(apr_pool_t
APT_END_EXTERN_C
-#endif /*__MRCP_UNIRTSP_SERVER_AGENT_H__*/
+#endif /* MRCP_UNIRTSP_SERVER_AGENT_H */
diff --git a/libs/unimrcp/modules/mrcp-unirtsp/mrcpunirtsp.2008.vcproj b/libs/unimrcp/modules/mrcp-unirtsp/mrcpunirtsp.2008.vcproj
deleted file mode 100644
index d0d90c646d..0000000000
--- a/libs/unimrcp/modules/mrcp-unirtsp/mrcpunirtsp.2008.vcproj
+++ /dev/null
@@ -1,293 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/modules/mrcp-unirtsp/mrcpunirtsp.2010.vcxproj b/libs/unimrcp/modules/mrcp-unirtsp/mrcpunirtsp.2010.vcxproj
deleted file mode 100644
index f8a573d857..0000000000
--- a/libs/unimrcp/modules/mrcp-unirtsp/mrcpunirtsp.2010.vcxproj
+++ /dev/null
@@ -1,133 +0,0 @@
-
-
-
-
- Debug
- Win32
-
-
- Debug
- x64
-
-
- Release
- Win32
-
-
- Release
- x64
-
-
-
- mrcpunirtsp
- {DEB01ACB-D65F-4A62-AED9-58C1054499E9}
- mrcpunirtsp
- Win32Proj
-
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
- StaticLibrary
- Unicode
- true
-
-
- StaticLibrary
- Unicode
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- <_ProjectFileVersion>10.0.30319.1
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
- $(PlatformName)\$(Configuration)\
-
-
-
- include;%(AdditionalIncludeDirectories)
- APT_STATIC_LIB;RTSP_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;LIBSOFIA_SIP_UA_STATIC;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- include;%(AdditionalIncludeDirectories)
- APT_STATIC_LIB;RTSP_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;LIBSOFIA_SIP_UA_STATIC;%(PreprocessorDefinitions)
- ProgramDatabase
-
-
-
-
- include;%(AdditionalIncludeDirectories)
- APT_STATIC_LIB;RTSP_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;LIBSOFIA_SIP_UA_STATIC;%(PreprocessorDefinitions)
-
-
-
-
- X64
-
-
- include;%(AdditionalIncludeDirectories)
- APT_STATIC_LIB;RTSP_STATIC_LIB;MPF_STATIC_LIB;MRCP_STATIC_LIB;LIBSOFIA_SIP_UA_STATIC;%(PreprocessorDefinitions)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/modules/mrcp-unirtsp/mrcpunirtsp.2010.vcxproj.filters b/libs/unimrcp/modules/mrcp-unirtsp/mrcpunirtsp.2010.vcxproj.filters
deleted file mode 100644
index a990550f29..0000000000
--- a/libs/unimrcp/modules/mrcp-unirtsp/mrcpunirtsp.2010.vcxproj.filters
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
- {93995380-89BD-4b04-88EB-625FBE52EBFB}
- h;hpp;hxx;hm;inl;inc;xsd
-
-
- {f87f8ada-12d1-412b-bd14-7e62df3f92a0}
- cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
-
-
-
-
- include
-
-
- include
-
-
- include
-
-
-
-
- src
-
-
- src
-
-
- src
-
-
-
\ No newline at end of file
diff --git a/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_client_agent.c b/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_client_agent.c
index 0b0840b1d7..6997c47004 100644
--- a/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_client_agent.c
+++ b/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_client_agent.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_unirtsp_client_agent.c 1700 2010-05-21 18:56:06Z achaloyan $
*/
#include
@@ -28,7 +30,6 @@
#include "apt_consumer_task.h"
#include "apt_log.h"
-#define UNIRTSP_TASK_NAME "UniRTSP Agent"
typedef struct mrcp_unirtsp_agent_t mrcp_unirtsp_agent_t;
typedef struct mrcp_unirtsp_session_t mrcp_unirtsp_session_t;
@@ -41,10 +42,11 @@ struct mrcp_unirtsp_agent_t {
};
struct mrcp_unirtsp_session_t {
- mrcp_message_t *mrcp_message;
- mrcp_session_t *mrcp_session;
- rtsp_client_session_t *rtsp_session;
- su_home_t *home;
+ mrcp_message_t *mrcp_message;
+ mrcp_session_t *mrcp_session;
+ rtsp_client_session_t *rtsp_session;
+ mrcp_sig_settings_t *rtsp_settings;
+ su_home_t *home;
};
@@ -72,18 +74,18 @@ static const rtsp_client_vtable_t session_response_vtable = {
mrcp_unirtsp_on_session_event
};
-static apt_bool_t mrcp_unirtsp_session_create(mrcp_session_t *session);
+static apt_bool_t mrcp_unirtsp_session_create(mrcp_session_t *session, mrcp_sig_settings_t *settings);
static apt_bool_t rtsp_config_validate(mrcp_unirtsp_agent_t *agent, rtsp_client_config_t *config, apr_pool_t *pool);
static apt_bool_t mrcp_unirtsp_on_resource_discover(mrcp_unirtsp_agent_t *agent, mrcp_unirtsp_session_t *session, rtsp_message_t *request, rtsp_message_t *response);
/** Create UniRTSP Signaling Agent */
-MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_unirtsp_client_agent_create(rtsp_client_config_t *config, apr_pool_t *pool)
+MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_unirtsp_client_agent_create(const char *id, rtsp_client_config_t *config, apr_pool_t *pool)
{
apt_task_t *task;
mrcp_unirtsp_agent_t *agent;
agent = apr_palloc(pool,sizeof(mrcp_unirtsp_agent_t));
- agent->sig_agent = mrcp_signaling_agent_create(agent,MRCP_VERSION_1,pool);
+ agent->sig_agent = mrcp_signaling_agent_create(id,agent,MRCP_VERSION_1,pool);
agent->sig_agent->create_client_session = mrcp_unirtsp_session_create;
agent->config = config;
@@ -91,20 +93,22 @@ MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_unirtsp_client_agent_create(rtsp_client_con
return NULL;
}
- agent->rtsp_client = rtsp_client_create(config->max_connection_count,
- agent,&session_response_vtable,pool);
+ agent->rtsp_client = rtsp_client_create(
+ config->max_connection_count,
+ config->request_timeout,
+ agent,
+ &session_response_vtable,
+ pool);
if(!agent->rtsp_client) {
return NULL;
}
task = rtsp_client_task_get(agent->rtsp_client);
- apt_task_name_set(task,UNIRTSP_TASK_NAME);
+ apt_task_name_set(task,id);
agent->sig_agent->task = task;
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create "UNIRTSP_TASK_NAME" %s:%hu [%"APR_SIZE_T_FMT"]",
- config->server_ip,
- config->server_port,
- config->max_connection_count);
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create UniRTSP Agent [%s] [%"APR_SIZE_T_FMT"]",
+ id,config->max_connection_count);
return agent->sig_agent;
}
@@ -112,22 +116,14 @@ MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_unirtsp_client_agent_create(rtsp_client_con
MRCP_DECLARE(rtsp_client_config_t*) mrcp_unirtsp_client_config_alloc(apr_pool_t *pool)
{
rtsp_client_config_t *config = apr_palloc(pool,sizeof(rtsp_client_config_t));
- config->server_ip = NULL;
- config->server_port = 0;
- config->resource_location = NULL;
config->origin = NULL;
- config->resource_map = apr_table_make(pool,2);
config->max_connection_count = 100;
- config->force_destination = FALSE;
+ config->request_timeout = 0;
return config;
}
-
static apt_bool_t rtsp_config_validate(mrcp_unirtsp_agent_t *agent, rtsp_client_config_t *config, apr_pool_t *pool)
{
- if(!config->server_ip) {
- return FALSE;
- }
agent->config = config;
return TRUE;
}
@@ -139,7 +135,7 @@ static APR_INLINE mrcp_unirtsp_agent_t* client_agent_get(apt_task_t *task)
return agent;
}
-static apt_bool_t mrcp_unirtsp_session_create(mrcp_session_t *mrcp_session)
+static apt_bool_t mrcp_unirtsp_session_create(mrcp_session_t *mrcp_session, mrcp_sig_settings_t *settings)
{
mrcp_unirtsp_agent_t *agent = mrcp_session->signaling_agent->obj;
mrcp_unirtsp_session_t *session;
@@ -147,15 +143,16 @@ static apt_bool_t mrcp_unirtsp_session_create(mrcp_session_t *mrcp_session)
session = apr_palloc(mrcp_session->pool,sizeof(mrcp_unirtsp_session_t));
session->home = su_home_new(sizeof(*session->home));
+ session->rtsp_settings = settings;
session->mrcp_message = NULL;
session->mrcp_session = mrcp_session;
mrcp_session->obj = session;
session->rtsp_session = rtsp_client_session_create(
agent->rtsp_client,
- agent->config->server_ip,
- agent->config->server_port,
- agent->config->resource_location);
+ session->rtsp_settings->server_ip,
+ session->rtsp_settings->server_port,
+ session->rtsp_settings->resource_location);
if(!session->rtsp_session) {
su_home_unref(session->home);
return FALSE;
@@ -198,9 +195,9 @@ static apt_bool_t mrcp_unirtsp_on_announce_response(mrcp_unirtsp_agent_t *agent,
return FALSE;
}
- if(rtsp_header_property_check(&message->header.property_set,RTSP_HEADER_FIELD_CONTENT_TYPE) == TRUE &&
+ if(rtsp_header_property_check(&message->header,RTSP_HEADER_FIELD_CONTENT_TYPE) == TRUE &&
message->header.content_type == RTSP_CONTENT_TYPE_MRCP &&
- rtsp_header_property_check(&message->header.property_set,RTSP_HEADER_FIELD_CONTENT_LENGTH) == TRUE &&
+ rtsp_header_property_check(&message->header,RTSP_HEADER_FIELD_CONTENT_LENGTH) == TRUE &&
message->header.content_length > 0) {
apt_text_stream_t text_stream;
@@ -212,9 +209,8 @@ static apt_bool_t mrcp_unirtsp_on_announce_response(mrcp_unirtsp_agent_t *agent,
apt_string_set(&resource_name_str,resource_name);
parser = mrcp_parser_create(agent->sig_agent->resource_factory,session->mrcp_session->pool);
- mrcp_parser_resource_name_set(parser,&resource_name_str);
- if(mrcp_parser_run(parser,&text_stream) == MRCP_STREAM_STATUS_COMPLETE) {
- mrcp_message = mrcp_parser_message_get(parser);
+ mrcp_parser_resource_set(parser,&resource_name_str);
+ if(mrcp_parser_run(parser,&text_stream,&mrcp_message) == APT_MESSAGE_STATUS_COMPLETE) {
mrcp_message->channel_id.session_id = message->header.session_id;
}
else {
@@ -255,15 +251,15 @@ static apt_bool_t mrcp_unirtsp_on_session_response(rtsp_client_t *rtsp_client, r
const char *force_destination_ip = NULL;
mrcp_session_descriptor_t *descriptor;
- if(agent->config->force_destination == TRUE) {
- force_destination_ip = agent->config->server_ip;
+ if(session->rtsp_settings->force_destination == TRUE) {
+ force_destination_ip = session->rtsp_settings->server_ip;
}
descriptor = mrcp_descriptor_generate_by_rtsp_response(
request,
response,
force_destination_ip,
- agent->config->resource_map,
+ session->rtsp_settings->resource_map,
session->mrcp_session->pool,
session->home);
if(!descriptor) {
@@ -286,7 +282,7 @@ static apt_bool_t mrcp_unirtsp_on_session_response(rtsp_client_t *rtsp_client, r
request,
response,
NULL,
- agent->config->resource_map,
+ session->rtsp_settings->resource_map,
session->mrcp_session->pool,
session->home);
if(!descriptor) {
@@ -299,7 +295,7 @@ static apt_bool_t mrcp_unirtsp_on_session_response(rtsp_client_t *rtsp_client, r
{
mrcp_unirtsp_agent_t *agent = rtsp_client_object_get(rtsp_client);
const char *resource_name = mrcp_name_get_by_rtsp_name(
- agent->config->resource_map,
+ session->rtsp_settings->resource_map,
request->start_line.common.request_line.resource_name);
mrcp_unirtsp_on_announce_response(agent,session,response,resource_name);
break;
@@ -322,7 +318,7 @@ static apt_bool_t mrcp_unirtsp_on_session_event(rtsp_client_t *rtsp_client, rtsp
mrcp_unirtsp_agent_t *agent = rtsp_client_object_get(rtsp_client);
mrcp_unirtsp_session_t *session = rtsp_client_session_object_get(rtsp_session);
const char *resource_name = mrcp_name_get_by_rtsp_name(
- agent->config->resource_map,
+ session->rtsp_settings->resource_map,
message->start_line.common.request_line.resource_name);
if(!session || !resource_name) {
return FALSE;
@@ -342,7 +338,7 @@ static apt_bool_t mrcp_unirtsp_session_offer(mrcp_session_t *mrcp_session, mrcp_
apt_string_set(&descriptor->origin,agent->config->origin);
}
- request = rtsp_request_generate_by_mrcp_descriptor(descriptor,agent->config->resource_map,mrcp_session->pool);
+ request = rtsp_request_generate_by_mrcp_descriptor(descriptor,session->rtsp_settings->resource_map,mrcp_session->pool);
return rtsp_client_session_request(agent->rtsp_client,session->rtsp_session,request);
}
@@ -375,7 +371,7 @@ static apt_bool_t mrcp_unirtsp_session_control(mrcp_session_t *mrcp_session, mrc
rtsp_message = rtsp_request_create(mrcp_session->pool);
rtsp_message->start_line.common.request_line.resource_name = rtsp_name_get_by_mrcp_name(
- agent->config->resource_map,
+ session->rtsp_settings->resource_map,
mrcp_message->channel_id.resource_name.buf);
rtsp_message->start_line.common.request_line.method_id = RTSP_METHOD_ANNOUNCE;
@@ -389,9 +385,9 @@ static apt_bool_t mrcp_unirtsp_session_control(mrcp_session_t *mrcp_session, mrc
body->buf[body->length] = '\0';
rtsp_message->header.content_type = RTSP_CONTENT_TYPE_MRCP;
- rtsp_header_property_add(&rtsp_message->header.property_set,RTSP_HEADER_FIELD_CONTENT_TYPE);
+ rtsp_header_property_add(&rtsp_message->header,RTSP_HEADER_FIELD_CONTENT_TYPE,rtsp_message->pool);
rtsp_message->header.content_length = body->length;
- rtsp_header_property_add(&rtsp_message->header.property_set,RTSP_HEADER_FIELD_CONTENT_LENGTH);
+ rtsp_header_property_add(&rtsp_message->header,RTSP_HEADER_FIELD_CONTENT_LENGTH,rtsp_message->pool);
session->mrcp_message = mrcp_message;
rtsp_client_session_request(agent->rtsp_client,session->rtsp_session,rtsp_message);
@@ -409,7 +405,7 @@ static apt_bool_t mrcp_unirtsp_resource_discover(mrcp_session_t *mrcp_session, m
}
request = rtsp_resource_discovery_request_generate(
descriptor->resource_name.buf,
- agent->config->resource_map,
+ session->rtsp_settings->resource_map,
mrcp_session->pool);
if(request) {
rtsp_client_session_request(agent->rtsp_client,session->rtsp_session,request);
@@ -427,7 +423,7 @@ static apt_bool_t mrcp_unirtsp_on_resource_discover(mrcp_unirtsp_agent_t *agent,
descriptor = mrcp_resource_discovery_response_generate(
request,
response,
- agent->config->resource_map,
+ session->rtsp_settings->resource_map,
session->mrcp_session->pool,
session->home);
if(descriptor) {
diff --git a/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_sdp.c b/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_sdp.c
index e35055fdc9..ebb31fa007 100644
--- a/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_sdp.c
+++ b/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_sdp.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_unirtsp_sdp.c 1752 2010-08-09 19:05:23Z achaloyan $
*/
#include
@@ -190,8 +192,8 @@ MRCP_DECLARE(mrcp_session_descriptor_t*) mrcp_descriptor_generate_by_rtsp_reques
}
if(request->start_line.common.request_line.method_id == RTSP_METHOD_SETUP) {
- if(rtsp_header_property_check(&request->header.property_set,RTSP_HEADER_FIELD_CONTENT_TYPE) == TRUE &&
- rtsp_header_property_check(&request->header.property_set,RTSP_HEADER_FIELD_CONTENT_LENGTH) == TRUE &&
+ if(rtsp_header_property_check(&request->header,RTSP_HEADER_FIELD_CONTENT_TYPE) == TRUE &&
+ rtsp_header_property_check(&request->header,RTSP_HEADER_FIELD_CONTENT_LENGTH) == TRUE &&
request->body.buf) {
sdp_parser_t *parser;
@@ -216,7 +218,7 @@ MRCP_DECLARE(mrcp_session_descriptor_t*) mrcp_descriptor_generate_by_rtsp_reques
mpf_rtp_media_descriptor_init(media);
media->state = MPF_MEDIA_ENABLED;
media->id = mrcp_session_audio_media_add(descriptor,media);
- if(rtsp_header_property_check(&request->header.property_set,RTSP_HEADER_FIELD_TRANSPORT) == TRUE) {
+ if(rtsp_header_property_check(&request->header,RTSP_HEADER_FIELD_TRANSPORT) == TRUE) {
media->port = request->header.transport.client_port_range.min;
media->ip = request->header.transport.destination;
}
@@ -253,8 +255,8 @@ MRCP_DECLARE(mrcp_session_descriptor_t*) mrcp_descriptor_generate_by_rtsp_respon
}
if(request->start_line.common.request_line.method_id == RTSP_METHOD_SETUP) {
- if(rtsp_header_property_check(&response->header.property_set,RTSP_HEADER_FIELD_CONTENT_TYPE) == TRUE &&
- rtsp_header_property_check(&response->header.property_set,RTSP_HEADER_FIELD_CONTENT_LENGTH) == TRUE &&
+ if(rtsp_header_property_check(&response->header,RTSP_HEADER_FIELD_CONTENT_TYPE) == TRUE &&
+ rtsp_header_property_check(&response->header,RTSP_HEADER_FIELD_CONTENT_LENGTH) == TRUE &&
response->body.buf) {
sdp_parser_t *parser;
@@ -348,14 +350,14 @@ MRCP_DECLARE(rtsp_message_t*) rtsp_request_generate_by_mrcp_descriptor(const mrc
request->header.transport.protocol = RTSP_TRANSPORT_RTP;
request->header.transport.profile = RTSP_PROFILE_AVP;
request->header.transport.delivery = RTSP_DELIVERY_UNICAST;
- rtsp_header_property_add(&request->header.property_set,RTSP_HEADER_FIELD_TRANSPORT);
+ rtsp_header_property_add(&request->header,RTSP_HEADER_FIELD_TRANSPORT,request->pool);
if(offset) {
apt_string_assign_n(&request->body,buffer,offset,pool);
request->header.content_type = RTSP_CONTENT_TYPE_SDP;
- rtsp_header_property_add(&request->header.property_set,RTSP_HEADER_FIELD_CONTENT_TYPE);
+ rtsp_header_property_add(&request->header,RTSP_HEADER_FIELD_CONTENT_TYPE,request->pool);
request->header.content_length = offset;
- rtsp_header_property_add(&request->header.property_set,RTSP_HEADER_FIELD_CONTENT_LENGTH);
+ rtsp_header_property_add(&request->header,RTSP_HEADER_FIELD_CONTENT_LENGTH,request->pool);
}
return request;
}
@@ -434,14 +436,14 @@ MRCP_DECLARE(rtsp_message_t*) rtsp_response_generate_by_mrcp_descriptor(const rt
response->header.transport.protocol = RTSP_TRANSPORT_RTP;
response->header.transport.profile = RTSP_PROFILE_AVP;
response->header.transport.delivery = RTSP_DELIVERY_UNICAST;
- rtsp_header_property_add(&response->header.property_set,RTSP_HEADER_FIELD_TRANSPORT);
+ rtsp_header_property_add(&response->header,RTSP_HEADER_FIELD_TRANSPORT,response->pool);
if(offset) {
apt_string_assign_n(&response->body,buffer,offset,pool);
response->header.content_type = RTSP_CONTENT_TYPE_SDP;
- rtsp_header_property_add(&response->header.property_set,RTSP_HEADER_FIELD_CONTENT_TYPE);
+ rtsp_header_property_add(&response->header,RTSP_HEADER_FIELD_CONTENT_TYPE,response->pool);
response->header.content_length = offset;
- rtsp_header_property_add(&response->header.property_set,RTSP_HEADER_FIELD_CONTENT_LENGTH);
+ rtsp_header_property_add(&response->header,RTSP_HEADER_FIELD_CONTENT_LENGTH,response->pool);
}
}
return response;
@@ -481,8 +483,8 @@ MRCP_DECLARE(mrcp_session_descriptor_t*) mrcp_resource_discovery_response_genera
descriptor = mrcp_session_descriptor_create(pool);
apt_string_assign(&descriptor->resource_name,resource_name,pool);
- if(rtsp_header_property_check(&response->header.property_set,RTSP_HEADER_FIELD_CONTENT_TYPE) == TRUE &&
- rtsp_header_property_check(&response->header.property_set,RTSP_HEADER_FIELD_CONTENT_LENGTH) == TRUE &&
+ if(rtsp_header_property_check(&response->header,RTSP_HEADER_FIELD_CONTENT_TYPE) == TRUE &&
+ rtsp_header_property_check(&response->header,RTSP_HEADER_FIELD_CONTENT_LENGTH) == TRUE &&
response->body.buf) {
sdp_parser_t *parser;
@@ -546,9 +548,9 @@ MRCP_DECLARE(rtsp_message_t*) rtsp_resource_discovery_response_generate(
if(offset) {
apt_string_assign_n(&response->body,buffer,offset,pool);
response->header.content_type = RTSP_CONTENT_TYPE_SDP;
- rtsp_header_property_add(&response->header.property_set,RTSP_HEADER_FIELD_CONTENT_TYPE);
+ rtsp_header_property_add(&response->header,RTSP_HEADER_FIELD_CONTENT_TYPE,response->pool);
response->header.content_length = offset;
- rtsp_header_property_add(&response->header.property_set,RTSP_HEADER_FIELD_CONTENT_LENGTH);
+ rtsp_header_property_add(&response->header,RTSP_HEADER_FIELD_CONTENT_LENGTH,response->pool);
}
}
@@ -558,18 +560,20 @@ MRCP_DECLARE(rtsp_message_t*) rtsp_resource_discovery_response_generate(
/** Get MRCP resource name by RTSP resource name */
MRCP_DECLARE(const char*) mrcp_name_get_by_rtsp_name(const apr_table_t *resource_map, const char *rtsp_name)
{
- const apr_array_header_t *header = apr_table_elts(resource_map);
- apr_table_entry_t *entry = (apr_table_entry_t *)header->elts;
- int i;
-
- for(i=0; inelts; i++) {
- if(entry[i].val && rtsp_name) {
- if(apr_strnatcasecmp(entry[i].val,rtsp_name) == 0) {
+ if(rtsp_name) {
+ const apr_array_header_t *header = apr_table_elts(resource_map);
+ apr_table_entry_t *entry = (apr_table_entry_t *)header->elts;
+ int i;
+ for(i=0; inelts; i++) {
+ if(!entry[i].val) continue;
+
+ if(strcasecmp(entry[i].val,rtsp_name) == 0) {
return entry[i].key;
}
}
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown RTSP Resource Name [%s]", rtsp_name);
}
- return rtsp_name;
+ return "unknown";
}
/** Get RTSP resource name by MRCP resource name */
diff --git a/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_server_agent.c b/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_server_agent.c
index 1ef05e193e..873b3d216d 100644
--- a/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_server_agent.c
+++ b/libs/unimrcp/modules/mrcp-unirtsp/src/mrcp_unirtsp_server_agent.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_unirtsp_server_agent.c 1700 2010-05-21 18:56:06Z achaloyan $
*/
#include
@@ -28,8 +30,6 @@
#include "apt_consumer_task.h"
#include "apt_log.h"
-#define UNIRTSP_TASK_NAME "UniRTSP Agent"
-
typedef struct mrcp_unirtsp_agent_t mrcp_unirtsp_agent_t;
typedef struct mrcp_unirtsp_session_t mrcp_unirtsp_session_t;
@@ -72,12 +72,12 @@ static apt_bool_t rtsp_config_validate(mrcp_unirtsp_agent_t *agent, rtsp_server_
/** Create UniRTSP Signaling Agent */
-MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_unirtsp_server_agent_create(rtsp_server_config_t *config, apr_pool_t *pool)
+MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_unirtsp_server_agent_create(const char *id, rtsp_server_config_t *config, apr_pool_t *pool)
{
apt_task_t *task;
mrcp_unirtsp_agent_t *agent;
agent = apr_palloc(pool,sizeof(mrcp_unirtsp_agent_t));
- agent->sig_agent = mrcp_signaling_agent_create(agent,MRCP_VERSION_1,pool);
+ agent->sig_agent = mrcp_signaling_agent_create(id,agent,MRCP_VERSION_1,pool);
agent->config = config;
if(rtsp_config_validate(agent,config,pool) == FALSE) {
@@ -96,13 +96,14 @@ MRCP_DECLARE(mrcp_sig_agent_t*) mrcp_unirtsp_server_agent_create(rtsp_server_con
}
task = rtsp_server_task_get(agent->rtsp_server);
- apt_task_name_set(task,UNIRTSP_TASK_NAME);
+ apt_task_name_set(task,id);
agent->sig_agent->task = task;
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create "UNIRTSP_TASK_NAME" %s:%hu [%"APR_SIZE_T_FMT"]",
- config->local_ip,
- config->local_port,
- config->max_connection_count);
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create UniRTSP Agent [%s] %s:%hu [%"APR_SIZE_T_FMT"]",
+ id,
+ config->local_ip,
+ config->local_port,
+ config->max_connection_count);
return agent->sig_agent;
}
@@ -192,23 +193,23 @@ static apt_bool_t mrcp_unirtsp_session_announce(mrcp_unirtsp_agent_t *agent, mrc
apt_bool_t status = TRUE;
if(session && resource_name &&
- rtsp_header_property_check(&message->header.property_set,RTSP_HEADER_FIELD_CONTENT_TYPE) == TRUE &&
+ rtsp_header_property_check(&message->header,RTSP_HEADER_FIELD_CONTENT_TYPE) == TRUE &&
message->header.content_type == RTSP_CONTENT_TYPE_MRCP &&
- rtsp_header_property_check(&message->header.property_set,RTSP_HEADER_FIELD_CONTENT_LENGTH) == TRUE &&
+ rtsp_header_property_check(&message->header,RTSP_HEADER_FIELD_CONTENT_LENGTH) == TRUE &&
message->header.content_length > 0) {
apt_text_stream_t text_stream;
mrcp_parser_t *parser;
apt_str_t resource_name_str;
+ mrcp_message_t *mrcp_message;
text_stream.text = message->body;
apt_text_stream_reset(&text_stream);
apt_string_set(&resource_name_str,resource_name);
parser = mrcp_parser_create(agent->sig_agent->resource_factory,session->mrcp_session->pool);
- mrcp_parser_resource_name_set(parser,&resource_name_str);
- if(mrcp_parser_run(parser,&text_stream) == MRCP_STREAM_STATUS_COMPLETE) {
- mrcp_message_t *mrcp_message = mrcp_parser_message_get(parser);
+ mrcp_parser_resource_set(parser,&resource_name_str);
+ if(mrcp_parser_run(parser,&text_stream,&mrcp_message) == APT_MESSAGE_STATUS_COMPLETE) {
mrcp_message->channel_id.session_id = message->header.session_id;
status = mrcp_session_control_request(session->mrcp_session,mrcp_message);
}
@@ -375,9 +376,9 @@ static apt_bool_t mrcp_unirtsp_on_session_control(mrcp_session_t *mrcp_session,
body->buf[body->length] = '\0';
rtsp_message->header.content_type = RTSP_CONTENT_TYPE_MRCP;
- rtsp_header_property_add(&rtsp_message->header.property_set,RTSP_HEADER_FIELD_CONTENT_TYPE);
+ rtsp_header_property_add(&rtsp_message->header,RTSP_HEADER_FIELD_CONTENT_TYPE,rtsp_message->pool);
rtsp_message->header.content_length = body->length;
- rtsp_header_property_add(&rtsp_message->header.property_set,RTSP_HEADER_FIELD_CONTENT_LENGTH);
+ rtsp_header_property_add(&rtsp_message->header,RTSP_HEADER_FIELD_CONTENT_LENGTH,rtsp_message->pool);
rtsp_server_session_respond(agent->rtsp_server,session->rtsp_session,rtsp_message);
return TRUE;
diff --git a/libs/unimrcp/packages/inno-setup/setup.iss b/libs/unimrcp/packages/inno-setup/setup.iss
deleted file mode 100644
index 98677b46c9..0000000000
--- a/libs/unimrcp/packages/inno-setup/setup.iss
+++ /dev/null
@@ -1,14 +0,0 @@
-#define uni_version "0.8.0"
-
-AppName=UniMRCP
-AppVerName=UniMRCP-{#= uni_version}
-AppPublisher=UniMRCP
-AppPublisherURL=http://www.unimrcp.org/
-AppSupportURL=http://groups.google.com/group/unimrcp
-AppUpdatesURL=http://code.google.com/p/unimrcp/downloads/list
-DefaultDirName={pf}\UniMRCP
-DefaultGroupName=UniMRCP
-Compression=lzma
-InternalCompressLevel=max
-SolidCompression=true
-
diff --git a/libs/unimrcp/packages/inno-setup/setup.txt b/libs/unimrcp/packages/inno-setup/setup.txt
index 6dd7582ded..45d6489f83 100644
--- a/libs/unimrcp/packages/inno-setup/setup.txt
+++ b/libs/unimrcp/packages/inno-setup/setup.txt
@@ -1,4 +1,4 @@
-#define uni_version "0.9.0"
+#define uni_version "1.0.0"
#define uni_src "..\.."
AppName=UniMRCP
diff --git a/libs/unimrcp/packages/inno-setup/unimrcp.iss b/libs/unimrcp/packages/inno-setup/unimrcp.iss
index 0f17729874..9e65059430 100644
--- a/libs/unimrcp/packages/inno-setup/unimrcp.iss
+++ b/libs/unimrcp/packages/inno-setup/unimrcp.iss
@@ -31,6 +31,7 @@ Source: {#= uni_outdir}\plugin\demosynth.dll; DestDir: {app}\plugin; Components:
Source: {#= uni_outdir}\plugin\demorecog.dll; DestDir: {app}\plugin; Components: server/demorecog
Source: {#= uni_outdir}\conf\unimrcpserver.xml; DestDir: {app}\conf; Components: server
Source: {#= uni_outdir}\conf\unimrcpclient.xml; DestDir: {app}\conf; Components: client
+Source: {#= uni_outdir}\conf\client-profiles\*.xml; DestDir: {app}\conf\client-profiles; Components: client
Source: {#= uni_outdir}\conf\umcscenarios.xml; DestDir: {app}\conf; Components: client
Source: {#= uni_outdir}\data\*.pcm; DestDir: {app}\data; Components: server client
Source: {#= uni_outdir}\data\*.xml; DestDir: {app}\data; Components: server client
diff --git a/libs/unimrcp/platforms/asr-client/src/main.c b/libs/unimrcp/platforms/asr-client/src/main.c
index 0861bf4200..8a3a1d06de 100644
--- a/libs/unimrcp/platforms/asr-client/src/main.c
+++ b/libs/unimrcp/platforms/asr-client/src/main.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: main.c 1541 2010-02-22 20:20:10Z achaloyan $
*/
#include
@@ -44,7 +46,7 @@ static void* APR_THREAD_FUNC asr_session_run(apr_thread_t *thread, void *data)
asr_params_t *params = data;
asr_session_t *session = asr_session_create(params->engine,params->profile);
if(session) {
- const char *result = asr_session_recognize(session,params->grammar_file,params->input_file);
+ const char *result = asr_session_file_recognize(session,params->grammar_file,params->input_file);
if(result) {
printf("Recog Result [%s]",result);
}
@@ -87,7 +89,7 @@ static apt_bool_t asr_session_launch(asr_engine_t *engine, const char *grammar_f
params->profile = apr_pstrdup(pool,profile);
}
else {
- params->profile = "MRCPv2-Default";
+ params->profile = "uni2";
}
/* Launch a thread to run demo ASR session in */
@@ -126,11 +128,11 @@ static apt_bool_t cmdline_process(asr_engine_t *engine, char *cmdline)
"\n- run [grammar_file] [audio_input_file] [profile_name] (run demo asr client)\n"
" grammar_file is the name of grammar file, (path is relative to data dir)\n"
" audio_input_file is the name of audio file, (path is relative to data dir)\n"
- " profile_name is one of 'MRCPv2-Default', 'MRCPv1-Default', ...\n"
+ " profile_name is one of 'uni2', 'uni1', ...\n"
"\n examples: \n"
" run\n"
" run grammar.xml one.pcm\n"
- " run grammar.xml one.pcm MRCPv1-Default\n"
+ " run grammar.xml one.pcm uni1\n"
"\n- loglevel [level] (set loglevel, one of 0,1...7)\n"
"\n- quit, exit\n");
}
diff --git a/libs/unimrcp/platforms/libasr-client/include/asr_engine.h b/libs/unimrcp/platforms/libasr-client/include/asr_engine.h
index 6a9e62fbe5..065e7f83f9 100644
--- a/libs/unimrcp/platforms/libasr-client/include/asr_engine.h
+++ b/libs/unimrcp/platforms/libasr-client/include/asr_engine.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Arsen Chaloyan
+ * Copyright 2009-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: asr_engine.h 1566 2010-03-06 16:45:05Z achaloyan $
*/
-#ifndef __ASR_ENGINE_H__
-#define __ASR_ENGINE_H__
+#ifndef ASR_ENGINE_H
+#define ASR_ENGINE_H
/**
* @file asr_engine.h
@@ -75,13 +77,42 @@ ASR_CLIENT_DECLARE(apt_bool_t) asr_engine_destroy(asr_engine_t *engine);
ASR_CLIENT_DECLARE(asr_session_t*) asr_session_create(asr_engine_t *engine, const char *profile);
/**
- * Initiate recognition.
+ * Initiate recognition based on specified grammar and input file.
* @param session the session to run recognition in the scope of
* @param grammar_file the name of the grammar file to use (path is relative to data dir)
* @param input_file the name of the audio input file to use (path is relative to data dir)
* @return the recognition result (input element of NLSML content)
*/
-ASR_CLIENT_DECLARE(const char*) asr_session_recognize(asr_session_t *session, const char *grammar_file, const char *input_file);
+ASR_CLIENT_DECLARE(const char*) asr_session_file_recognize(
+ asr_session_t *session,
+ const char *grammar_file,
+ const char *input_file);
+
+/**
+ * Initiate recognition based on specified grammar and input stream.
+ * @param session the session to run recognition in the scope of
+ * @param grammar_file the name of the grammar file to use (path is relative to data dir)
+ * @param callback the callback to be called to get input media frames
+ * @param obj the object to pass to the callback
+ * @return the recognition result (input element of NLSML content)
+ *
+ * @remark Audio data should be streamed through
+ * asr_session_stream_write() function calls.
+ */
+ASR_CLIENT_DECLARE(const char*) asr_session_stream_recognize(
+ asr_session_t *session,
+ const char *grammar_file);
+
+/**
+ * Write audio data to recognize.
+ * @param session the session to write audio data for
+ * @param data the audio data
+ * @param size the size of data
+ */
+ASR_CLIENT_DECLARE(apt_bool_t) asr_session_stream_write(
+ asr_session_t *session,
+ char *data,
+ int size);
/**
* Destroy ASR session.
@@ -99,4 +130,4 @@ ASR_CLIENT_DECLARE(apt_bool_t) asr_engine_log_priority_set(apt_log_priority_e lo
APT_END_EXTERN_C
-#endif /*__ASR_ENGINE_H__*/
+#endif /* ASR_ENGINE_H */
diff --git a/libs/unimrcp/platforms/libasr-client/src/asr_engine.c b/libs/unimrcp/platforms/libasr-client/src/asr_engine.c
index 0879f4fe98..4048347a05 100644
--- a/libs/unimrcp/platforms/libasr-client/src/asr_engine.c
+++ b/libs/unimrcp/platforms/libasr-client/src/asr_engine.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Arsen Chaloyan
+ * Copyright 2009-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: asr_engine.c 1785 2010-09-22 06:14:29Z achaloyan $
*/
#include
@@ -20,14 +22,16 @@
#include
#include
-/* common includes */
+/* Common includes */
#include "unimrcp_client.h"
#include "mrcp_application.h"
#include "mrcp_message.h"
#include "mrcp_generic_header.h"
-/* recognizer includes */
+/* Recognizer includes */
#include "mrcp_recog_header.h"
#include "mrcp_recog_resource.h"
+/* MPF includes */
+#include
/* APT includes */
#include "apt_nlsml_doc.h"
#include "apt_log.h"
@@ -35,6 +39,11 @@
#include "asr_engine.h"
+typedef enum {
+ INPUT_MODE_NONE,
+ INPUT_MODE_FILE,
+ INPUT_MODE_STREAM
+} input_mode_e;
/** ASR engine on top of UniMRCP client stack */
struct asr_engine_t {
@@ -50,23 +59,27 @@ struct asr_engine_t {
/** ASR session on top of UniMRCP session/channel */
struct asr_session_t {
/** Back pointer to engine */
- asr_engine_t *engine;
+ asr_engine_t *engine;
/** MRCP session */
- mrcp_session_t *mrcp_session;
+ mrcp_session_t *mrcp_session;
/** MRCP channel */
- mrcp_channel_t *mrcp_channel;
+ mrcp_channel_t *mrcp_channel;
/** RECOGNITION-COMPLETE message */
- mrcp_message_t *recog_complete;
+ mrcp_message_t *recog_complete;
- /** File to read audio stream from */
- FILE *audio_in;
+ /** Input mode (either file or stream) */
+ input_mode_e input_mode;
+ /** File to read media frames from */
+ FILE *audio_in;
+ /* Buffer of media frames */
+ mpf_frame_buffer_t *media_buffer;
/** Streaming is in-progress */
- apt_bool_t streaming;
+ apt_bool_t streaming;
/** Conditional wait object */
- apr_thread_cond_t *wait_object;
+ apr_thread_cond_t *wait_object;
/** Mutex of the wait object */
- apr_thread_mutex_t *mutex;
+ apr_thread_mutex_t *mutex;
/** Message sent from client stack */
const mrcp_app_message_t *app_message;
@@ -114,7 +127,7 @@ ASR_CLIENT_DECLARE(asr_engine_t*) asr_engine_create(
if((log_output & APT_LOG_OUTPUT_FILE) == APT_LOG_OUTPUT_FILE) {
/* open the log file */
- apt_log_file_open(dir_layout->log_dir_path,"unimrcpclient",MAX_LOG_FILE_SIZE,MAX_LOG_FILE_COUNT,pool);
+ apt_log_file_open(dir_layout->log_dir_path,"unimrcpclient",MAX_LOG_FILE_SIZE,MAX_LOG_FILE_COUNT,FALSE,pool);
}
engine = apr_palloc(pool,sizeof(asr_engine_t));
@@ -204,12 +217,12 @@ static apt_bool_t asr_session_destroy_ex(asr_session_t *asr_session, apt_bool_t
apr_thread_cond_destroy(asr_session->wait_object);
asr_session->wait_object = NULL;
}
- if(asr_session->mrcp_session) {
- mrcp_application_session_destroy(asr_session->mrcp_session);
- asr_session->mrcp_session = NULL;
+ if(asr_session->media_buffer) {
+ mpf_frame_buffer_destroy(asr_session->media_buffer);
+ asr_session->media_buffer = NULL;
}
- free(asr_session);
- return TRUE;
+
+ return mrcp_application_session_destroy(asr_session->mrcp_session);
}
/** Open audio input file */
@@ -241,14 +254,21 @@ static apt_bool_t asr_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame
{
asr_session_t *asr_session = stream->obj;
if(asr_session && asr_session->streaming == TRUE) {
- if(asr_session->audio_in) {
- if(fread(frame->codec_frame.buffer,1,frame->codec_frame.size,asr_session->audio_in) == frame->codec_frame.size) {
- /* normal read */
- frame->type |= MEDIA_FRAME_TYPE_AUDIO;
+ if(asr_session->input_mode == INPUT_MODE_FILE) {
+ if(asr_session->audio_in) {
+ if(fread(frame->codec_frame.buffer,1,frame->codec_frame.size,asr_session->audio_in) == frame->codec_frame.size) {
+ /* normal read */
+ frame->type |= MEDIA_FRAME_TYPE_AUDIO;
+ }
+ else {
+ /* file is over */
+ asr_session->streaming = FALSE;
+ }
}
- else {
- /* file is over */
- asr_session->streaming = FALSE;
+ }
+ if(asr_session->input_mode == INPUT_MODE_STREAM) {
+ if(asr_session->media_buffer) {
+ mpf_frame_buffer_read(asr_session->media_buffer,frame);
}
}
}
@@ -415,6 +435,11 @@ static apt_bool_t mrcp_response_check(const mrcp_app_message_t *app_message, mrc
if(!mrcp_message || mrcp_message->start_line.message_type != MRCP_MESSAGE_TYPE_RESPONSE ) {
return FALSE;
}
+
+ if(mrcp_message->start_line.status_code != MRCP_STATUS_CODE_SUCCESS &&
+ mrcp_message->start_line.status_code != MRCP_STATUS_CODE_SUCCESS_WITH_IGNORE) {
+ return FALSE;
+ }
return (mrcp_message->start_line.request_state == state) ? TRUE : FALSE;
}
@@ -440,23 +465,33 @@ ASR_CLIENT_DECLARE(asr_session_t*) asr_session_create(asr_engine_t *engine, cons
mrcp_session_t *session;
const mrcp_app_message_t *app_message;
apr_pool_t *pool;
-
- asr_session_t *asr_session = malloc(sizeof(asr_session_t));
+ asr_session_t *asr_session;
+ mpf_stream_capabilities_t *capabilities;
/* create session */
- session = mrcp_application_session_create(engine->mrcp_app,profile,asr_session);
+ session = mrcp_application_session_create(engine->mrcp_app,profile,NULL);
if(!session) {
- free(asr_session);
return NULL;
}
pool = mrcp_application_session_pool_get(session);
+
+ asr_session = apr_palloc(pool,sizeof(asr_session_t));
+ mrcp_application_session_object_set(session,asr_session);
- termination = mrcp_application_source_termination_create(
+ /* create source stream capabilities */
+ capabilities = mpf_source_stream_capabilities_create(pool);
+ /* add codec capabilities (Linear PCM) */
+ mpf_codec_capabilities_add(
+ &capabilities->codecs,
+ MPF_SAMPLE_RATE_8000,
+ "LPCM");
+
+ termination = mrcp_application_audio_termination_create(
session, /* session, termination belongs to */
&audio_stream_vtable, /* virtual methods table of audio stream */
- NULL, /* codec descriptor of audio stream (NULL by default) */
- asr_session); /* object to associate */
-
+ capabilities, /* capabilities of audio stream */
+ asr_session); /* object to associate */
+
channel = mrcp_application_channel_create(
session, /* session, channel belongs to */
MRCP_RECOGNIZER_RESOURCE, /* MRCP resource identifier */
@@ -466,7 +501,6 @@ ASR_CLIENT_DECLARE(asr_session_t*) asr_session_create(asr_engine_t *engine, cons
if(!channel) {
mrcp_application_session_destroy(session);
- free(asr_session);
return NULL;
}
@@ -474,8 +508,10 @@ ASR_CLIENT_DECLARE(asr_session_t*) asr_session_create(asr_engine_t *engine, cons
asr_session->mrcp_session = session;
asr_session->mrcp_channel = channel;
asr_session->recog_complete = NULL;
+ asr_session->input_mode = INPUT_MODE_NONE;
asr_session->streaming = FALSE;
asr_session->audio_in = NULL;
+ asr_session->media_buffer = NULL;
asr_session->mutex = NULL;
asr_session->wait_object = NULL;
asr_session->app_message = NULL;
@@ -484,6 +520,9 @@ ASR_CLIENT_DECLARE(asr_session_t*) asr_session_create(asr_engine_t *engine, cons
apr_thread_mutex_create(&asr_session->mutex,APR_THREAD_MUTEX_DEFAULT,pool);
apr_thread_cond_create(&asr_session->wait_object,pool);
+ /* Create media buffer */
+ asr_session->media_buffer = mpf_frame_buffer_create(160,20,pool);
+
/* Send add channel request and wait for the response */
apr_thread_mutex_lock(asr_session->mutex);
app_message = NULL;
@@ -501,8 +540,11 @@ ASR_CLIENT_DECLARE(asr_session_t*) asr_session_create(asr_engine_t *engine, cons
return asr_session;
}
-/** Initiate recognition */
-ASR_CLIENT_DECLARE(const char*) asr_session_recognize(asr_session_t *asr_session, const char *grammar_file, const char *input_file)
+/** Initiate recognition based on specified grammar and input file */
+ASR_CLIENT_DECLARE(const char*) asr_session_file_recognize(
+ asr_session_t *asr_session,
+ const char *grammar_file,
+ const char *input_file)
{
const mrcp_app_message_t *app_message;
mrcp_message_t *mrcp_message;
@@ -551,6 +593,7 @@ ASR_CLIENT_DECLARE(const char*) asr_session_recognize(asr_session_t *asr_session
}
/* Open input file and start streaming */
+ asr_session->input_mode = INPUT_MODE_FILE;
if(asr_input_file_open(asr_session,input_file) == FALSE) {
return NULL;
}
@@ -579,6 +622,106 @@ ASR_CLIENT_DECLARE(const char*) asr_session_recognize(asr_session_t *asr_session
return nlsml_input_get(asr_session->recog_complete);
}
+/** Initiate recognition based on specified grammar and input stream */
+ASR_CLIENT_DECLARE(const char*) asr_session_stream_recognize(
+ asr_session_t *asr_session,
+ const char *grammar_file)
+{
+ const mrcp_app_message_t *app_message;
+ mrcp_message_t *mrcp_message;
+
+ app_message = NULL;
+ mrcp_message = define_grammar_message_create(asr_session,grammar_file);
+ if(!mrcp_message) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create DEFINE-GRAMMAR Request");
+ return NULL;
+ }
+
+ /* Send DEFINE-GRAMMAR request and wait for the response */
+ apr_thread_mutex_lock(asr_session->mutex);
+ if(mrcp_application_message_send(asr_session->mrcp_session,asr_session->mrcp_channel,mrcp_message) == TRUE) {
+ apr_thread_cond_wait(asr_session->wait_object,asr_session->mutex);
+ app_message = asr_session->app_message;
+ asr_session->app_message = NULL;
+ }
+ apr_thread_mutex_unlock(asr_session->mutex);
+
+ if(mrcp_response_check(app_message,MRCP_REQUEST_STATE_COMPLETE) == FALSE) {
+ return NULL;
+ }
+
+ /* Reset prev recog result (if any) */
+ asr_session->recog_complete = NULL;
+
+ app_message = NULL;
+ mrcp_message = recognize_message_create(asr_session);
+ if(!mrcp_message) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create RECOGNIZE Request");
+ return NULL;
+ }
+
+ /* Send RECOGNIZE request and wait for the response */
+ apr_thread_mutex_lock(asr_session->mutex);
+ if(mrcp_application_message_send(asr_session->mrcp_session,asr_session->mrcp_channel,mrcp_message) == TRUE) {
+ apr_thread_cond_wait(asr_session->wait_object,asr_session->mutex);
+ app_message = asr_session->app_message;
+ asr_session->app_message = NULL;
+ }
+ apr_thread_mutex_unlock(asr_session->mutex);
+
+ if(mrcp_response_check(app_message,MRCP_REQUEST_STATE_INPROGRESS) == FALSE) {
+ return NULL;
+ }
+
+ /* Reset media buffer */
+ mpf_frame_buffer_restart(asr_session->media_buffer);
+
+ /* Set input mode and start streaming */
+ asr_session->input_mode = INPUT_MODE_STREAM;
+ asr_session->streaming = TRUE;
+
+ /* Wait for events either START-OF-INPUT or RECOGNITION-COMPLETE */
+ do {
+ apr_thread_mutex_lock(asr_session->mutex);
+ app_message = NULL;
+ if(apr_thread_cond_timedwait(asr_session->wait_object,asr_session->mutex, 60 * 1000000) != APR_SUCCESS) {
+ apr_thread_mutex_unlock(asr_session->mutex);
+ return NULL;
+ }
+ app_message = asr_session->app_message;
+ asr_session->app_message = NULL;
+ apr_thread_mutex_unlock(asr_session->mutex);
+
+ mrcp_message = mrcp_event_get(app_message);
+ if(mrcp_message && mrcp_message->start_line.method_id == RECOGNIZER_RECOGNITION_COMPLETE) {
+ asr_session->recog_complete = mrcp_message;
+ }
+ }
+ while(!asr_session->recog_complete);
+
+ /* Get results */
+ return nlsml_input_get(asr_session->recog_complete);
+}
+
+/** Write audio frame to recognize */
+ASR_CLIENT_DECLARE(apt_bool_t) asr_session_stream_write(
+ asr_session_t *asr_session,
+ char *data,
+ int size)
+{
+ mpf_frame_t frame;
+ frame.type = MEDIA_FRAME_TYPE_AUDIO;
+ frame.marker = MPF_MARKER_NONE;
+ frame.codec_frame.buffer = data;
+ frame.codec_frame.size = size;
+
+ if(mpf_frame_buffer_write(asr_session->media_buffer,&frame) != TRUE) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Write Audio [%d]",size);
+ return FALSE;
+ }
+ return TRUE;
+}
+
/** Destroy ASR session */
ASR_CLIENT_DECLARE(apt_bool_t) asr_session_destroy(asr_session_t *asr_session)
{
diff --git a/libs/unimrcp/platforms/libunimrcp-client/include/unimrcp_client.h b/libs/unimrcp/platforms/libunimrcp-client/include/unimrcp_client.h
index 152f856374..2efff488c4 100644
--- a/libs/unimrcp/platforms/libunimrcp-client/include/unimrcp_client.h
+++ b/libs/unimrcp/platforms/libunimrcp-client/include/unimrcp_client.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: unimrcp_client.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __UNIMRCP_CLIENT_H__
-#define __UNIMRCP_CLIENT_H__
+#ifndef UNIMRCP_CLIENT_H
+#define UNIMRCP_CLIENT_H
/**
* @file unimrcp_client.h
@@ -35,4 +37,4 @@ MRCP_DECLARE(mrcp_client_t*) unimrcp_client_create(apt_dir_layout_t *dir_layout)
APT_END_EXTERN_C
-#endif /*__UNIMRCP_CLIENT_H__*/
+#endif /* UNIMRCP_CLIENT_H */
diff --git a/libs/unimrcp/platforms/libunimrcp-client/libunimrcpclient.2008.vcproj b/libs/unimrcp/platforms/libunimrcp-client/libunimrcpclient.2008.vcproj
deleted file mode 100644
index cee4d73515..0000000000
--- a/libs/unimrcp/platforms/libunimrcp-client/libunimrcpclient.2008.vcproj
+++ /dev/null
@@ -1,156 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/platforms/libunimrcp-client/libunimrcpclient.vcproj b/libs/unimrcp/platforms/libunimrcp-client/libunimrcpclient.vcproj
index 1d78a98519..170941bc41 100644
--- a/libs/unimrcp/platforms/libunimrcp-client/libunimrcpclient.vcproj
+++ b/libs/unimrcp/platforms/libunimrcp-client/libunimrcpclient.vcproj
@@ -244,6 +244,10 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
+
+
diff --git a/libs/unimrcp/platforms/libunimrcp-client/src/unimrcp_client.c b/libs/unimrcp/platforms/libunimrcp-client/src/unimrcp_client.c
index b8eda6546d..3ef85f3329 100644
--- a/libs/unimrcp/platforms/libunimrcp-client/src/unimrcp_client.c
+++ b/libs/unimrcp/platforms/libunimrcp-client/src/unimrcp_client.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,12 +12,16 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: unimrcp_client.c 1750 2010-07-23 19:33:34Z achaloyan $
*/
#include
#include
-#include "unimrcp_client.h"
+#include
+#include
#include "uni_version.h"
+#include "unimrcp_client.h"
#include "mrcp_resource_loader.h"
#include "mpf_engine.h"
#include "mpf_codec_manager.h"
@@ -31,10 +35,8 @@
#define CONF_FILE_NAME "unimrcpclient.xml"
#define DEFAULT_CONF_DIR_PATH "../conf"
-#define DEFAULT_LOCAL_IP_ADDRESS "127.0.0.1"
-#define DEFAULT_REMOTE_IP_ADDRESS "127.0.0.1"
-#define DEFAULT_SIP_LOCAL_PORT 8062
-#define DEFAULT_SIP_REMOTE_PORT 8060
+#define DEFAULT_IP_ADDRESS "127.0.0.1"
+#define DEFAULT_SIP_PORT 8062
#define DEFAULT_RTP_PORT_MIN 4000
#define DEFAULT_RTP_PORT_MAX 5000
@@ -42,17 +44,40 @@
#define DEFAULT_SDP_ORIGIN "UniMRCPClient"
#define DEFAULT_RESOURCE_LOCATION "media"
-#define XML_FILE_BUFFER_LENGTH 2000
+#define XML_FILE_BUFFER_LENGTH 16000
-static apr_xml_doc* unimrcp_client_config_parse(const char *path, apr_pool_t *pool);
-static apt_bool_t unimrcp_client_config_load(mrcp_client_t *client, const apr_xml_doc *doc, apr_pool_t *pool);
+/** UniMRCP client loader */
+typedef struct unimrcp_client_loader_t unimrcp_client_loader_t;
-/** Start UniMRCP client */
+/** UniMRCP client loader */
+struct unimrcp_client_loader_t {
+ /** MRCP client */
+ mrcp_client_t *client;
+ /** XML document */
+ apr_xml_doc *doc;
+ /** Pool to allocate memory from */
+ apr_pool_t *pool;
+
+ /** Default ip address (named property) */
+ const char *ip;
+ /** Default external (NAT) ip address (named property) */
+ const char *ext_ip;
+ /** Default server ip address (named property) */
+ const char *server_ip;
+
+ /** Implicitly detected, cached ip address */
+ const char *auto_ip;
+};
+
+static apt_bool_t unimrcp_client_load(unimrcp_client_loader_t *loader, const char *dir_path, const char *file_name, apr_pool_t *pool);
+
+/** Create and load UniMRCP client */
MRCP_DECLARE(mrcp_client_t*) unimrcp_client_create(apt_dir_layout_t *dir_layout)
{
apr_pool_t *pool;
- apr_xml_doc *doc;
mrcp_client_t *client;
+ const char *dir_path;
+ unimrcp_client_loader_t *loader;
if(!dir_layout) {
return NULL;
@@ -69,51 +94,94 @@ MRCP_DECLARE(mrcp_client_t*) unimrcp_client_create(apt_dir_layout_t *dir_layout)
return NULL;
}
- doc = unimrcp_client_config_parse(dir_layout->conf_dir_path,pool);
- if(doc) {
- unimrcp_client_config_load(client,doc,pool);
+ loader = apr_palloc(pool,sizeof(unimrcp_client_loader_t));
+ loader->doc = NULL;
+ loader->client = client;
+ loader->pool = pool;
+ loader->ip = NULL;
+ loader->ext_ip = NULL;
+ loader->server_ip = NULL;
+ loader->auto_ip = NULL;
+
+ dir_path = dir_layout->conf_dir_path;
+ if(!dir_path) {
+ dir_path = DEFAULT_CONF_DIR_PATH;
+ }
+
+ if(unimrcp_client_load(loader,dir_path,CONF_FILE_NAME,pool) == FALSE) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Load UniMRCP Client Document");
}
return client;
}
-/** Parse config file */
-static apr_xml_doc* unimrcp_client_config_parse(const char *dir_path, apr_pool_t *pool)
+/** Check whether specified attribute is valid */
+static APR_INLINE apt_bool_t is_attr_valid(const apr_xml_attr *attr)
{
- apr_xml_parser *parser = NULL;
- apr_xml_doc *doc = NULL;
- apr_file_t *fd = NULL;
- apr_status_t rv;
- const char *file_path;
-
- if(!dir_path) {
- dir_path = DEFAULT_CONF_DIR_PATH;
- }
- if(*dir_path == '\0') {
- file_path = CONF_FILE_NAME;
- }
- else {
- file_path = apr_psprintf(pool,"%s/%s",dir_path,CONF_FILE_NAME);
- }
-
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Open Config File [%s]",file_path);
- rv = apr_file_open(&fd,file_path,APR_READ|APR_BINARY,0,pool);
- if(rv != APR_SUCCESS) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open Config File [%s]",file_path);
- return NULL;
- }
-
- rv = apr_xml_parse_file(pool,&parser,&doc,fd,XML_FILE_BUFFER_LENGTH);
- if(rv != APR_SUCCESS) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Parse Config File [%s]",file_path);
- doc = NULL;
- }
-
- apr_file_close(fd);
- return doc;
+ return (attr && attr->value && attr->value != '\0');
}
-static apt_bool_t param_name_value_get(const apr_xml_elem *elem, const apr_xml_attr **name, const apr_xml_attr **value)
+/** Check whether specified attribute is enabled (true) */
+static APR_INLINE apt_bool_t is_attr_enabled(const apr_xml_attr *attr)
+{
+ if(attr && strcasecmp(attr->value,"false") == 0) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/** Check whether cdata is valid */
+static APR_INLINE apt_bool_t is_cdata_valid(const apr_xml_elem *elem)
+{
+ return (elem->first_cdata.first && elem->first_cdata.first->text);
+}
+
+/** Get text cdata */
+static APR_INLINE const char* cdata_text_get(const apr_xml_elem *elem)
+{
+ return elem->first_cdata.first->text;
+}
+
+/** Get boolean cdata */
+static APR_INLINE apt_bool_t cdata_bool_get(const apr_xml_elem *elem)
+{
+ return (strcasecmp(elem->first_cdata.first->text,"true") == 0) ? TRUE : FALSE;
+}
+
+/** Copy cdata */
+static APR_INLINE char* cdata_copy(const apr_xml_elem *elem, apr_pool_t *pool)
+{
+ return apr_pstrdup(pool,elem->first_cdata.first->text);
+}
+
+/** Get generic "id" and "enable" attributes */
+static apt_bool_t header_attribs_get(const apr_xml_elem *elem, const apr_xml_attr **id, const apr_xml_attr **enable)
+{
+ const apr_xml_attr *attr;
+ if(!id || !enable) {
+ return FALSE;
+ }
+
+ *id = NULL;
+ *enable = NULL;
+ for(attr = elem->attr; attr; attr = attr->next) {
+ if(strcasecmp(attr->name,"id") == 0) {
+ *id = attr;
+ }
+ else if(strcasecmp(attr->name,"enable") == 0) {
+ *enable = attr;
+ }
+ }
+
+ if(is_attr_valid(*id) == FALSE) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Missing Required Attribute in Element <%s>",elem->name);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/** Get generic "name" and "value" attributes */
+static apt_bool_t name_value_attribs_get(const apr_xml_elem *elem, const apr_xml_attr **name, const apr_xml_attr **value)
{
const apr_xml_attr *attr;
if(!name || !value) {
@@ -133,397 +201,63 @@ static apt_bool_t param_name_value_get(const apr_xml_elem *elem, const apr_xml_a
return (*name && *value) ? TRUE : FALSE;
}
-static char* ip_addr_get(const char *value, apr_pool_t *pool)
+static char* unimrcp_client_ip_address_get(unimrcp_client_loader_t *loader, const apr_xml_elem *elem, const char *default_ip)
{
- if(!value || strcasecmp(value,"auto") == 0) {
- char *addr = DEFAULT_LOCAL_IP_ADDRESS;
- apt_ip_get(&addr,pool);
- return addr;
- }
- return apr_pstrdup(pool,value);
-}
-
-/** Load map of MRCP resource names */
-static apt_bool_t resource_map_load(apr_table_t *resource_map, const apr_xml_elem *root, apr_pool_t *pool)
-{
- const apr_xml_attr *attr_name;
- const apr_xml_attr *attr_value;
- const apr_xml_elem *elem;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Resource Map");
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"param") == 0) {
- if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
- apr_table_set(resource_map,attr_name->value,attr_value->value);
- }
+ const apr_xml_attr *attr = NULL;
+ for(attr = elem->attr; attr; attr = attr->next) {
+ if(strcasecmp(attr->name,"type") == 0) {
+ break;
}
- }
- return TRUE;
-}
-
-/** Load SofiaSIP signaling agent */
-static mrcp_sig_agent_t* unimrcp_client_sofiasip_agent_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
-{
- const apr_xml_elem *elem;
- mrcp_sofia_client_config_t *config = mrcp_sofiasip_client_config_alloc(pool);
- config->local_ip = DEFAULT_LOCAL_IP_ADDRESS;
- config->local_port = DEFAULT_SIP_LOCAL_PORT;
- config->remote_ip = DEFAULT_REMOTE_IP_ADDRESS;
- config->remote_port = DEFAULT_SIP_REMOTE_PORT;
- config->ext_ip = NULL;
- config->user_agent_name = DEFAULT_SOFIASIP_UA_NAME;
- config->origin = DEFAULT_SDP_ORIGIN;
-
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading SofiaSIP Agent");
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"param") == 0) {
- const apr_xml_attr *attr_name;
- const apr_xml_attr *attr_value;
- if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
- if(strcasecmp(attr_name->value,"client-ip") == 0) {
- config->local_ip = ip_addr_get(attr_value->value,pool);
- }
- else if(strcasecmp(attr_name->value,"client-ext-ip") == 0) {
- config->ext_ip = ip_addr_get(attr_value->value,pool);
- }
- else if(strcasecmp(attr_name->value,"client-port") == 0) {
- config->local_port = (apr_port_t)atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"server-ip") == 0) {
- config->remote_ip = ip_addr_get(attr_value->value,pool);
- }
- else if(strcasecmp(attr_name->value,"server-port") == 0) {
- config->remote_port = (apr_port_t)atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"server-username") == 0) {
- config->remote_user_name = apr_pstrdup(pool,attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"force-destination") == 0) {
- config->force_destination = atoi(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"sip-transport") == 0) {
- config->transport = apr_pstrdup(pool,attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"ua-name") == 0) {
- config->user_agent_name = apr_pstrdup(pool,attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"sdp-origin") == 0) {
- config->origin = apr_pstrdup(pool,attr_value->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
- }
- }
- }
- }
- return mrcp_sofiasip_client_agent_create(config,pool);
-}
-
-/** Load UniRTSP signaling agent */
-static mrcp_sig_agent_t* unimrcp_client_rtsp_agent_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
-{
- const apr_xml_elem *elem;
- rtsp_client_config_t *config = mrcp_unirtsp_client_config_alloc(pool);
- config->origin = DEFAULT_SDP_ORIGIN;
- config->resource_location = DEFAULT_RESOURCE_LOCATION;
-
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading UniRTSP Agent");
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"param") == 0) {
- const apr_xml_attr *attr_name;
- const apr_xml_attr *attr_value;
- if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
- if(strcasecmp(attr_name->value,"server-ip") == 0) {
- config->server_ip = ip_addr_get(attr_value->value,pool);
- }
- else if(strcasecmp(attr_name->value,"server-port") == 0) {
- config->server_port = (apr_port_t)atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"resource-location") == 0) {
- config->resource_location = apr_pstrdup(pool,attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"sdp-origin") == 0) {
- config->origin = apr_pstrdup(pool,attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"max-connection-count") == 0) {
- config->max_connection_count = atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"force-destination") == 0) {
- config->force_destination = atoi(attr_value->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
- }
- }
- }
- else if(strcasecmp(elem->name,"resourcemap") == 0) {
- resource_map_load(config->resource_map,elem,pool);
- }
- }
- return mrcp_unirtsp_client_agent_create(config,pool);
-}
-
-/** Load signaling agents */
-static apt_bool_t unimrcp_client_signaling_agents_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
-{
- const apr_xml_elem *elem;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Signaling Agents");
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"agent") == 0) {
- mrcp_sig_agent_t *sig_agent = NULL;
- const char *name = NULL;
- const apr_xml_attr *attr;
- for(attr = elem->attr; attr; attr = attr->next) {
- if(strcasecmp(attr->name,"name") == 0) {
- name = apr_pstrdup(pool,attr->value);
- }
- else if(strcasecmp(attr->name,"class") == 0) {
- if(strcasecmp(attr->value,"SofiaSIP") == 0) {
- sig_agent = unimrcp_client_sofiasip_agent_load(client,elem,pool);
- }
- else if(strcasecmp(attr->value,"UniRTSP") == 0) {
- sig_agent = unimrcp_client_rtsp_agent_load(client,elem,pool);
- }
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
- }
- }
- if(sig_agent) {
- mrcp_client_signaling_agent_register(client,sig_agent,name);
- }
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
- }
- }
- return TRUE;
-}
-
-/** Load MRCPv2 connection agent */
-static mrcp_connection_agent_t* unimrcp_client_connection_agent_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
-{
- const apr_xml_elem *elem;
- apr_size_t max_connection_count = 100;
- apt_bool_t offer_new_connection = FALSE;
-
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading MRCPv2 Agent");
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"param") == 0) {
- const apr_xml_attr *attr_name;
- const apr_xml_attr *attr_value;
- if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
- if(strcasecmp(attr_name->value,"max-connection-count") == 0) {
- max_connection_count = atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"offer-new-connection") == 0) {
- offer_new_connection = atoi(attr_value->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
- }
- }
- }
- }
- return mrcp_client_connection_agent_create(max_connection_count,offer_new_connection,pool);
-}
-
-/** Load MRCPv2 conection agents */
-static apt_bool_t unimrcp_client_connection_agents_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
-{
- const apr_xml_elem *elem;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Connection Agents");
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"agent") == 0) {
- mrcp_connection_agent_t *connection_agent;
- const char *name = NULL;
- const apr_xml_attr *attr;
- for(attr = elem->attr; attr; attr = attr->next) {
- if(strcasecmp(attr->name,"name") == 0) {
- name = apr_pstrdup(pool,attr->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
- }
- }
- connection_agent = unimrcp_client_connection_agent_load(client,elem,pool);
- if(connection_agent) {
- mrcp_client_connection_agent_register(client,connection_agent,name);
- }
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
- }
- }
- return TRUE;
-}
-
-/** Load RTP termination factory */
-static mpf_termination_factory_t* unimrcp_client_rtp_factory_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
-{
- const apr_xml_elem *elem;
- char *rtp_ip = DEFAULT_LOCAL_IP_ADDRESS;
- char *rtp_ext_ip = NULL;
- mpf_rtp_config_t *rtp_config = mpf_rtp_config_create(pool);
- rtp_config->rtp_port_min = DEFAULT_RTP_PORT_MIN;
- rtp_config->rtp_port_max = DEFAULT_RTP_PORT_MAX;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading RTP Termination Factory");
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"param") == 0) {
- const apr_xml_attr *attr_name;
- const apr_xml_attr *attr_value;
- if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
- if(strcasecmp(attr_name->value,"rtp-ip") == 0) {
- rtp_ip = ip_addr_get(attr_value->value,pool);
- }
- else if(strcasecmp(attr_name->value,"rtp-ext-ip") == 0) {
- rtp_ext_ip = ip_addr_get(attr_value->value,pool);
- }
- else if(strcasecmp(attr_name->value,"rtp-port-min") == 0) {
- rtp_config->rtp_port_min = (apr_port_t)atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"rtp-port-max") == 0) {
- rtp_config->rtp_port_max = (apr_port_t)atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"playout-delay") == 0) {
- rtp_config->jb_config.initial_playout_delay = atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"min-playout-delay") == 0) {
- rtp_config->jb_config.min_playout_delay = atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"max-playout-delay") == 0) {
- rtp_config->jb_config.max_playout_delay = atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"codecs") == 0) {
- const mpf_codec_manager_t *codec_manager = mrcp_client_codec_manager_get(client);
- if(codec_manager) {
- mpf_codec_manager_codec_list_load(codec_manager,&rtp_config->codec_list,attr_value->value,pool);
- }
- }
- else if(strcasecmp(attr_name->value,"ptime") == 0) {
- rtp_config->ptime = (apr_uint16_t)atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"rtcp") == 0) {
- rtp_config->rtcp = atoi(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"rtcp-bye") == 0) {
- rtp_config->rtcp_bye_policy = atoi(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"rtcp-tx-interval") == 0) {
- rtp_config->rtcp_tx_interval = (apr_uint16_t)atoi(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"rtcp-rx-resolution") == 0) {
- rtp_config->rtcp_rx_resolution = (apr_uint16_t)atol(attr_value->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
- }
- }
- }
- }
- apt_string_set(&rtp_config->ip,rtp_ip);
- if(rtp_ext_ip) {
- apt_string_set(&rtp_config->ext_ip,rtp_ext_ip);
- }
- return mpf_rtp_termination_factory_create(rtp_config,pool);
-}
-
-/** Load media engines */
-static apt_bool_t unimrcp_client_media_engines_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
-{
- const apr_xml_elem *elem;
-
- /* create codec manager first */
- mpf_codec_manager_t *codec_manager = mpf_engine_codec_manager_create(pool);
- if(codec_manager) {
- mrcp_client_codec_manager_register(client,codec_manager);
}
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Media Engines");
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"engine") == 0) {
- mpf_engine_t *media_engine;
- unsigned long realtime_rate = 1;
- const char *name = NULL;
- const apr_xml_attr *attr;
- for(attr = elem->attr; attr; attr = attr->next) {
- if(strcasecmp(attr->name,"name") == 0) {
- name = apr_pstrdup(pool,attr->value);
- }
- else if(strcasecmp(attr->name,"realtime-rate") == 0) {
- realtime_rate = atol(attr->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
- }
- }
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Media Engine");
- media_engine = mpf_engine_create(pool);
- if(media_engine) {
- mpf_engine_scheduler_rate_set(media_engine,realtime_rate);
- mrcp_client_media_engine_register(client,media_engine,name);
- }
+ if(attr && strcasecmp(attr->value,"auto") == 0) {
+ /* implicitly detect ip address, if not already detected */
+ if(!loader->auto_ip) {
+ char *auto_addr = DEFAULT_IP_ADDRESS;
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Detecting IP Address");
+ apt_ip_get(&auto_addr,loader->pool);
+ loader->auto_ip = auto_addr;
}
- else if(strcasecmp(elem->name,"rtp") == 0) {
- mpf_termination_factory_t *rtp_factory;
- const char *name = NULL;
- const apr_xml_attr *attr;
- for(attr = elem->attr; attr; attr = attr->next) {
- if(strcasecmp(attr->name,"name") == 0) {
- name = apr_pstrdup(pool,attr->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
- }
- }
- rtp_factory = unimrcp_client_rtp_factory_load(client,elem,pool);
- if(rtp_factory) {
- mrcp_client_rtp_factory_register(client,rtp_factory,name);
- }
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
- }
- }
- return TRUE;
+ return apr_pstrdup(loader->pool,loader->auto_ip);
+ }
+
+ if(is_cdata_valid(elem)) {
+ /* use specified ip address */
+ return cdata_copy(elem,loader->pool);
+ }
+
+ /* use default ip address */
+ return apr_pstrdup(loader->pool,loader->ip);
}
+
+
/** Load resource */
-static apt_bool_t unimrcp_client_resource_load(mrcp_client_t *client, mrcp_resource_loader_t *resource_loader, const apr_xml_elem *root, apr_pool_t *pool)
+static apt_bool_t unimrcp_client_resource_load(mrcp_resource_loader_t *resource_loader, const apr_xml_elem *root, apr_pool_t *pool)
{
apt_str_t resource_class;
- apt_bool_t resource_enabled = TRUE;
- const apr_xml_attr *attr;
+ const apr_xml_attr *id_attr;
+ const apr_xml_attr *enable_attr;
apt_string_reset(&resource_class);
- for(attr = root->attr; attr; attr = attr->next) {
- if(strcasecmp(attr->name,"class") == 0) {
- apt_string_set(&resource_class,attr->value);
- }
- else if(strcasecmp(attr->name,"enable") == 0) {
- resource_enabled = atoi(attr->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
- }
- }
- if(!resource_class.buf || !resource_enabled) {
+ if(header_attribs_get(root,&id_attr,&enable_attr) == FALSE) {
return FALSE;
}
+
+ if(is_attr_enabled(enable_attr) == FALSE) {
+ return TRUE;
+ }
+ apt_string_set(&resource_class,id_attr->value);
return mrcp_resource_load(resource_loader,&resource_class);
}
-/** Load resources */
-static apt_bool_t unimrcp_client_resources_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
+/** Load resource factory */
+static apt_bool_t unimrcp_client_resource_factory_load(unimrcp_client_loader_t *loader, const apr_xml_elem *root)
{
const apr_xml_elem *elem;
mrcp_resource_factory_t *resource_factory;
- mrcp_resource_loader_t *resource_loader = mrcp_resource_loader_create(FALSE,pool);
+ mrcp_resource_loader_t *resource_loader = mrcp_resource_loader_create(FALSE,loader->pool);
if(!resource_loader) {
return FALSE;
}
@@ -531,32 +265,664 @@ static apt_bool_t unimrcp_client_resources_load(mrcp_client_t *client, const apr
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Resources");
for(elem = root->first_child; elem; elem = elem->next) {
if(strcasecmp(elem->name,"resource") == 0) {
- unimrcp_client_resource_load(client,resource_loader,elem,pool);
+ unimrcp_client_resource_load(resource_loader,elem,loader->pool);
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ resource_factory = mrcp_resource_factory_get(resource_loader);
+ return mrcp_client_resource_factory_register(loader->client,resource_factory);
+}
+
+/** Load SofiaSIP signaling agent */
+static apt_bool_t unimrcp_client_sip_uac_load(unimrcp_client_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ mrcp_sig_agent_t *agent;
+ mrcp_sofia_client_config_t *config;
+
+ config = mrcp_sofiasip_client_config_alloc(loader->pool);
+ config->local_port = DEFAULT_SIP_PORT;
+ config->user_agent_name = DEFAULT_SOFIASIP_UA_NAME;
+ config->origin = DEFAULT_SDP_ORIGIN;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading SofiaSIP Agent <%s>",id);
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"sip-ip") == 0) {
+ config->local_ip = unimrcp_client_ip_address_get(loader,elem,loader->ip);
+ }
+ else if(strcasecmp(elem->name,"sip-ext-ip") == 0) {
+ config->ext_ip = unimrcp_client_ip_address_get(loader,elem,loader->ext_ip);
+ }
+ else if(strcasecmp(elem->name,"sip-port") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->local_port = (apr_port_t)atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"sip-transport") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->transport = cdata_copy(elem,loader->pool);
+ }
+ }
+ else if(strcasecmp(elem->name,"ua-name") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->user_agent_name = cdata_copy(elem,loader->pool);
+ }
+ }
+ else if(strcasecmp(elem->name,"sdp-origin") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->origin = cdata_copy(elem,loader->pool);
+ }
+ }
+ else if(strcasecmp(elem->name,"sip-t1") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->sip_t1 = atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"sip-t2") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->sip_t2 = atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"sip-t4") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->sip_t4 = atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"sip-t1x64") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->sip_t1x64 = atol(cdata_text_get(elem));
+ }
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ if(!config->local_ip) {
+ /* use default ip address if not specified */
+ config->local_ip = apr_pstrdup(loader->pool,loader->ip);
+ }
+ if(!config->ext_ip && loader->ext_ip) {
+ /* use default ext ip address if not specified */
+ config->ext_ip = apr_pstrdup(loader->pool,loader->ext_ip);
+ }
+
+ agent = mrcp_sofiasip_client_agent_create(id,config,loader->pool);
+ return mrcp_client_signaling_agent_register(loader->client,agent);
+}
+
+/** Load UniRTSP signaling agent */
+static apt_bool_t unimrcp_client_rtsp_uac_load(unimrcp_client_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ mrcp_sig_agent_t *agent;
+ rtsp_client_config_t *config;
+
+ config = mrcp_unirtsp_client_config_alloc(loader->pool);
+ config->origin = DEFAULT_SDP_ORIGIN;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading UniRTSP Agent <%s>",id);
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"sdp-origin") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->origin = cdata_copy(elem,loader->pool);
+ }
+ }
+ else if(strcasecmp(elem->name,"max-connection-count") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->max_connection_count = atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"request-timeout") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->request_timeout = atol(cdata_text_get(elem));
+ }
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ agent = mrcp_unirtsp_client_agent_create(id,config,loader->pool);
+ return mrcp_client_signaling_agent_register(loader->client,agent);
+}
+
+/** Load MRCPv2 connection agent */
+static apt_bool_t unimrcp_client_mrcpv2_uac_load(unimrcp_client_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ mrcp_connection_agent_t *agent;
+ apr_size_t max_connection_count = 100;
+ apt_bool_t offer_new_connection = FALSE;
+ const char *rx_buffer_size = NULL;
+ const char *tx_buffer_size = NULL;
+ const char *request_timeout = NULL;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading MRCPv2 Agent <%s>",id);
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"max-connection-count") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ max_connection_count = atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"offer-new-connection") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ offer_new_connection = atoi(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"rx-buffer-size") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ rx_buffer_size = cdata_text_get(elem);
+ }
+ }
+ else if(strcasecmp(elem->name,"tx-buffer-size") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ tx_buffer_size = cdata_text_get(elem);
+ }
+ }
+ else if(strcasecmp(elem->name,"request-timeout") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ request_timeout = cdata_text_get(elem);
+ }
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ agent = mrcp_client_connection_agent_create(id,max_connection_count,offer_new_connection,loader->pool);
+ if(agent) {
+ if(rx_buffer_size) {
+ mrcp_client_connection_rx_size_set(agent,atol(rx_buffer_size));
+ }
+ if(tx_buffer_size) {
+ mrcp_client_connection_tx_size_set(agent,atol(tx_buffer_size));
+ }
+ if(request_timeout) {
+ mrcp_client_connection_timeout_set(agent,atol(request_timeout));
+ }
+ }
+ return mrcp_client_connection_agent_register(loader->client,agent);
+}
+
+/** Load media engine */
+static apt_bool_t unimrcp_client_media_engine_load(unimrcp_client_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ mpf_engine_t *media_engine;
+ unsigned long realtime_rate = 1;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Media Engine <%s>",id);
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"realtime-rate") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ realtime_rate = atol(cdata_text_get(elem));
+ }
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ media_engine = mpf_engine_create(id,loader->pool);
+ if(media_engine) {
+ mpf_engine_scheduler_rate_set(media_engine,realtime_rate);
+ }
+ return mrcp_client_media_engine_register(loader->client,media_engine);
+}
+
+/** Load RTP factory */
+static apt_bool_t unimrcp_client_rtp_factory_load(unimrcp_client_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ char *rtp_ip = NULL;
+ char *rtp_ext_ip = NULL;
+ mpf_termination_factory_t *rtp_factory;
+ mpf_rtp_config_t *rtp_config;
+
+ rtp_config = mpf_rtp_config_alloc(loader->pool);
+ rtp_config->rtp_port_min = DEFAULT_RTP_PORT_MIN;
+ rtp_config->rtp_port_max = DEFAULT_RTP_PORT_MAX;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading RTP Factory <%s>",id);
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"rtp-ip") == 0) {
+ rtp_ip = unimrcp_client_ip_address_get(loader,elem,loader->ip);
+ }
+ else if(strcasecmp(elem->name,"rtp-ext-ip") == 0) {
+ rtp_ext_ip = unimrcp_client_ip_address_get(loader,elem,loader->ext_ip);
+ }
+ else if(strcasecmp(elem->name,"rtp-port-min") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ rtp_config->rtp_port_min = (apr_port_t)atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"rtp-port-max") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ rtp_config->rtp_port_max = (apr_port_t)atol(cdata_text_get(elem));
+ }
}
else {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
}
}
- resource_factory = mrcp_resource_factory_get(resource_loader);
- mrcp_client_resource_factory_register(client,resource_factory);
+ if(rtp_ip) {
+ apt_string_set(&rtp_config->ip,rtp_ip);
+ }
+ else {
+ apt_string_set(&rtp_config->ip,loader->ip);
+ }
+ if(rtp_ext_ip) {
+ apt_string_set(&rtp_config->ext_ip,rtp_ext_ip);
+ }
+ else if(loader->ext_ip){
+ apt_string_set(&rtp_config->ext_ip,loader->ext_ip);
+ }
+
+ rtp_factory = mpf_rtp_termination_factory_create(rtp_config,loader->pool);
+ return mrcp_client_rtp_factory_register(loader->client,rtp_factory,id);
+}
+
+
+/** Load SIP settings */
+static apt_bool_t unimrcp_client_sip_settings_load(unimrcp_client_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ mrcp_sig_settings_t *settings = mrcp_signaling_settings_alloc(loader->pool);
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading SIP Settings <%s>",id);
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"server-ip") == 0) {
+ settings->server_ip = unimrcp_client_ip_address_get(loader,elem,loader->server_ip);
+ }
+ else if(strcasecmp(elem->name,"server-port") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ settings->server_port = (apr_port_t)atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"server-username") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ settings->user_name = cdata_copy(elem,loader->pool);
+ }
+ }
+ else if(strcasecmp(elem->name,"force-destination") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ settings->force_destination = cdata_bool_get(elem);
+ }
+ }
+ else if(strcasecmp(elem->name,"feature-tags") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ settings->feature_tags = cdata_copy(elem,loader->pool);
+ }
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ if(!settings->server_ip) {
+ settings->server_ip = apr_pstrdup(loader->pool,loader->server_ip);
+ }
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Create SIP Settings %s:%hu",settings->server_ip,settings->server_port);
+ return mrcp_client_signaling_settings_register(loader->client,settings,id);
+}
+
+/** Load RTSP settings */
+static apt_bool_t unimrcp_client_rtsp_settings_load(unimrcp_client_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ mrcp_sig_settings_t *settings = mrcp_signaling_settings_alloc(loader->pool);
+ settings->resource_location = DEFAULT_RESOURCE_LOCATION;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading RTSP Settings <%s>",id);
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"server-ip") == 0) {
+ settings->server_ip = unimrcp_client_ip_address_get(loader,elem,loader->server_ip);
+ }
+ else if(strcasecmp(elem->name,"server-port") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ settings->server_port = (apr_port_t)atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"force-destination") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ settings->force_destination = cdata_bool_get(elem);
+ }
+ }
+ else if(strcasecmp(elem->name,"resource-location") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ settings->resource_location = cdata_copy(elem,loader->pool);
+ }
+ else {
+ settings->resource_location = "";
+ }
+ }
+ else if(strcasecmp(elem->name,"resource-map") == 0) {
+ const apr_xml_attr *name_attr;
+ const apr_xml_attr *value_attr;
+ const apr_xml_elem *child_elem;
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Resource Map");
+ for(child_elem = elem->first_child; child_elem; child_elem = child_elem->next) {
+ if(name_value_attribs_get(child_elem,&name_attr,&value_attr) == TRUE) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",name_attr->value,value_attr->value);
+ apr_table_set(settings->resource_map,name_attr->value,value_attr->value);
+ }
+ }
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ if(!settings->server_ip) {
+ settings->server_ip = apr_pstrdup(loader->pool,loader->server_ip);
+ }
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Create RTSP Settings %s:%hu",settings->server_ip,settings->server_port);
+ return mrcp_client_signaling_settings_register(loader->client,settings,id);
+}
+
+/** Load jitter buffer settings */
+static apt_bool_t unimrcp_client_jb_settings_load(unimrcp_client_loader_t *loader, mpf_jb_config_t *jb, const apr_xml_elem *root)
+{
+ const apr_xml_elem *elem;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Jitter Buffer Settings");
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"playout-delay") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ jb->initial_playout_delay = atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"min-playout-delay") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ jb->min_playout_delay = atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"max-playout-delay") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ jb->max_playout_delay = atol(cdata_text_get(elem));
+ }
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
return TRUE;
}
-/** Load settings */
-static apt_bool_t unimrcp_client_settings_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
+/** Load RTCP settings */
+static apt_bool_t unimrcp_client_rtcp_settings_load(unimrcp_client_loader_t *loader, mpf_rtp_settings_t *rtcp_settings, const apr_xml_elem *root)
{
const apr_xml_elem *elem;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Settings");
+ const apr_xml_attr *attr = NULL;
+ for(attr = root->attr; attr; attr = attr->next) {
+ if(strcasecmp(attr->name,"enable") == 0) {
+ break;
+ }
+ }
+
+ if(is_attr_enabled(attr) == FALSE) {
+ /* RTCP is disabled, skip the rest */
+ return TRUE;
+ }
+
+ rtcp_settings->rtcp = TRUE;
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading RTCP Settings");
for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"signaling") == 0) {
- unimrcp_client_signaling_agents_load(client,elem,pool);
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"rtcp-bye") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ rtcp_settings->rtcp_bye_policy = atoi(cdata_text_get(elem));
+ }
}
- else if(strcasecmp(elem->name,"connection") == 0) {
- unimrcp_client_connection_agents_load(client,elem,pool);
+ else if(strcasecmp(elem->name,"tx-interval") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ rtcp_settings->rtcp_tx_interval = (apr_uint16_t)atoi(cdata_text_get(elem));
+ }
}
- else if(strcasecmp(elem->name,"media") == 0) {
- unimrcp_client_media_engines_load(client,elem,pool);
+ else if(strcasecmp(elem->name,"rx-resolution") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ rtcp_settings->rtcp_rx_resolution = (apr_uint16_t)atol(cdata_text_get(elem));
+ }
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+ return TRUE;
+}
+
+/** Load RTP settings */
+static apt_bool_t unimrcp_client_rtp_settings_load(unimrcp_client_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ mpf_rtp_settings_t *rtp_settings = mpf_rtp_settings_alloc(loader->pool);
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading RTP Settings <%s>",id);
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"jitter-buffer") == 0) {
+ unimrcp_client_jb_settings_load(loader,&rtp_settings->jb_config,elem);
+ }
+ else if(strcasecmp(elem->name,"ptime") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ rtp_settings->ptime = (apr_uint16_t)atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"codecs") == 0) {
+ const mpf_codec_manager_t *codec_manager = mrcp_client_codec_manager_get(loader->client);
+ if(is_cdata_valid(elem) == TRUE && codec_manager) {
+ mpf_codec_manager_codec_list_load(
+ codec_manager,
+ &rtp_settings->codec_list,
+ cdata_text_get(elem),
+ loader->pool);
+ }
+ }
+ else if(strcasecmp(elem->name,"rtcp") == 0) {
+ unimrcp_client_rtcp_settings_load(loader,rtp_settings,elem);
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ return mrcp_client_rtp_settings_register(loader->client,rtp_settings,id);
+}
+
+/** Load MRCPv2 profile */
+static apt_bool_t unimrcp_client_mrcpv2_profile_load(unimrcp_client_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ mrcp_profile_t *profile;
+ mrcp_sig_agent_t *sip_agent = NULL;
+ mrcp_connection_agent_t *mrcpv2_agent = NULL;
+ mpf_engine_t *media_engine = NULL;
+ mpf_termination_factory_t *rtp_factory = NULL;
+ mpf_rtp_settings_t *rtp_settings = NULL;
+ mrcp_sig_settings_t *sip_settings = NULL;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading MRCPv2 Profile <%s>",id);
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+
+ if(is_cdata_valid(elem) == FALSE) {
+ continue;
+ }
+
+ if(strcasecmp(elem->name,"sip-uac") == 0) {
+ sip_agent = mrcp_client_signaling_agent_get(loader->client,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"mrcpv2-uac") == 0) {
+ mrcpv2_agent = mrcp_client_connection_agent_get(loader->client,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"media-engine") == 0) {
+ media_engine = mrcp_client_media_engine_get(loader->client,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"rtp-factory") == 0) {
+ rtp_factory = mrcp_client_rtp_factory_get(loader->client,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"sip-settings") == 0) {
+ sip_settings = mrcp_client_signaling_settings_get(loader->client,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"rtp-settings") == 0) {
+ rtp_settings = mrcp_client_rtp_settings_get(loader->client,cdata_text_get(elem));
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create MRCPv2 Profile [%s]",id);
+ profile = mrcp_client_profile_create(
+ NULL,sip_agent,mrcpv2_agent,
+ media_engine,rtp_factory,
+ rtp_settings,sip_settings,
+ loader->pool);
+ return mrcp_client_profile_register(loader->client,profile,id);
+}
+
+/** Load MRCPv1 profile */
+static apt_bool_t unimrcp_client_mrcpv1_profile_load(unimrcp_client_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ mrcp_profile_t *profile;
+ mrcp_sig_agent_t *rtsp_agent = NULL;
+ mpf_engine_t *media_engine = NULL;
+ mpf_termination_factory_t *rtp_factory = NULL;
+ mpf_rtp_settings_t *rtp_settings = NULL;
+ mrcp_sig_settings_t *rtsp_settings = NULL;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading MRCPv1 Profile <%s>",id);
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+
+ if(is_cdata_valid(elem) == FALSE) {
+ continue;
+ }
+
+ if(strcasecmp(elem->name,"rtsp-uac") == 0) {
+ rtsp_agent = mrcp_client_signaling_agent_get(loader->client,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"media-engine") == 0) {
+ media_engine = mrcp_client_media_engine_get(loader->client,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"rtp-factory") == 0) {
+ rtp_factory = mrcp_client_rtp_factory_get(loader->client,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"rtsp-settings") == 0) {
+ rtsp_settings = mrcp_client_signaling_settings_get(loader->client,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"rtp-settings") == 0) {
+ rtp_settings = mrcp_client_rtp_settings_get(loader->client,cdata_text_get(elem));
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create MRCPv1 Profile [%s]",id);
+ profile = mrcp_client_profile_create(
+ NULL,rtsp_agent,NULL,
+ media_engine,rtp_factory,
+ rtp_settings,rtsp_settings,
+ loader->pool);
+ return mrcp_client_profile_register(loader->client,profile,id);
+}
+
+
+/** Load properties */
+static apt_bool_t unimrcp_client_properties_load(unimrcp_client_loader_t *loader, const apr_xml_elem *root)
+{
+ const apr_xml_elem *elem;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Properties");
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"ip") == 0) {
+ loader->ip = unimrcp_client_ip_address_get(loader,elem,DEFAULT_IP_ADDRESS);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Set Property ip:%s",loader->ip);
+ }
+ else if(strcasecmp(elem->name,"ext-ip") == 0) {
+ loader->ext_ip = unimrcp_client_ip_address_get(loader,elem,DEFAULT_IP_ADDRESS);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Set Property ext-ip:%s",loader->ext_ip);
+ }
+ else if(strcasecmp(elem->name,"server-ip") == 0) {
+ loader->server_ip = unimrcp_client_ip_address_get(loader,elem,DEFAULT_IP_ADDRESS);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Set Property server-ip:%s",loader->server_ip);
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ if(!loader->ip) {
+ loader->ip = DEFAULT_IP_ADDRESS;
+ }
+ if(!loader->server_ip) {
+ loader->server_ip = loader->ip;
+ }
+ return TRUE;
+}
+
+/** Load components */
+static apt_bool_t unimrcp_client_components_load(unimrcp_client_loader_t *loader, const apr_xml_elem *root)
+{
+ const apr_xml_elem *elem;
+ const apr_xml_attr *id_attr;
+ const apr_xml_attr *enable_attr;
+ const char *id;
+
+ /* Create codec manager first (probably it should be loaded from config either) */
+ mpf_codec_manager_t *codec_manager = mpf_engine_codec_manager_create(loader->pool);
+ if(codec_manager) {
+ mrcp_client_codec_manager_register(loader->client,codec_manager);
+ }
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Components");
+ for(elem = root->first_child; elem; elem = elem->next) {
+ if(strcasecmp(elem->name,"resource-factory") == 0) {
+ unimrcp_client_resource_factory_load(loader,elem);
+ continue;
+ }
+
+ /* get common "id" and "enable" attributes */
+ if(header_attribs_get(elem,&id_attr,&enable_attr) == FALSE) {
+ /* invalid id */
+ continue;
+ }
+ if(is_attr_enabled(enable_attr) == FALSE) {
+ /* disabled element, just skip it */
+ continue;
+ }
+ id = apr_pstrdup(loader->pool,id_attr->value);
+
+ if(strcasecmp(elem->name,"sip-uac") == 0) {
+ unimrcp_client_sip_uac_load(loader,elem,id);
+ }
+ else if(strcasecmp(elem->name,"rtsp-uac") == 0) {
+ unimrcp_client_rtsp_uac_load(loader,elem,id);
+ }
+ else if(strcasecmp(elem->name,"mrcpv2-uac") == 0) {
+ unimrcp_client_mrcpv2_uac_load(loader,elem,id);
+ }
+ else if(strcasecmp(elem->name,"media-engine") == 0) {
+ unimrcp_client_media_engine_load(loader,elem,id);
+ }
+ else if(strcasecmp(elem->name,"rtp-factory") == 0) {
+ unimrcp_client_rtp_factory_load(loader,elem,id);
}
else {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
@@ -565,99 +931,195 @@ static apt_bool_t unimrcp_client_settings_load(mrcp_client_t *client, const apr_
return TRUE;
}
-/** Load profile */
-static apt_bool_t unimrcp_client_profile_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
+/** Load settings */
+static apt_bool_t unimrcp_client_settings_load(unimrcp_client_loader_t *loader, const apr_xml_elem *root)
{
- const char *name = NULL;
- mrcp_profile_t *profile;
- mrcp_sig_agent_t *sig_agent = NULL;
- mrcp_connection_agent_t *cnt_agent = NULL;
- mpf_engine_t *media_engine = NULL;
- mpf_termination_factory_t *rtp_factory = NULL;
const apr_xml_elem *elem;
- const apr_xml_attr *attr;
- for(attr = root->attr; attr; attr = attr->next) {
- if(strcasecmp(attr->name,"name") == 0) {
- name = apr_pstrdup(pool,attr->value);
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Profile [%s]",name);
+ const apr_xml_attr *id_attr;
+ const apr_xml_attr *enable_attr;
+ const char *id;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Settings");
+ for(elem = root->first_child; elem; elem = elem->next) {
+ /* get common "id" and "enable" attributes */
+ if(header_attribs_get(elem,&id_attr,&enable_attr) == FALSE) {
+ /* invalid id */
+ continue;
+ }
+ if(is_attr_enabled(enable_attr) == FALSE) {
+ /* disabled element, just skip it */
+ continue;
+ }
+ id = apr_pstrdup(loader->pool,id_attr->value);
+
+ if(strcasecmp(elem->name,"sip-settings") == 0) {
+ unimrcp_client_sip_settings_load(loader,elem,id);
+ }
+ else if(strcasecmp(elem->name,"rtsp-settings") == 0) {
+ unimrcp_client_rtsp_settings_load(loader,elem,id);
+ }
+ else if(strcasecmp(elem->name,"rtp-settings") == 0) {
+ unimrcp_client_rtp_settings_load(loader,elem,id);
}
else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
}
- }
- if(!name) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Load Profile: no profile name specified");
- return FALSE;
- }
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"param") == 0) {
- const apr_xml_attr *attr_name;
- const apr_xml_attr *attr_value;
- if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Loading Profile %s [%s]",attr_name->value,attr_value->value);
- if(strcasecmp(attr_name->value,"signaling-agent") == 0) {
- sig_agent = mrcp_client_signaling_agent_get(client,attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"connection-agent") == 0) {
- cnt_agent = mrcp_client_connection_agent_get(client,attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"media-engine") == 0) {
- media_engine = mrcp_client_media_engine_get(client,attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"rtp-factory") == 0) {
- rtp_factory = mrcp_client_rtp_factory_get(client,attr_value->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
- }
- }
- }
- }
-
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create Profile [%s]",name);
- profile = mrcp_client_profile_create(NULL,sig_agent,cnt_agent,media_engine,rtp_factory,pool);
- return mrcp_client_profile_register(client,profile,name);
+ }
+ return TRUE;
}
/** Load profiles */
-static apt_bool_t unimrcp_client_profiles_load(mrcp_client_t *client, const apr_xml_elem *root, apr_pool_t *pool)
+static apt_bool_t unimrcp_client_profiles_load(unimrcp_client_loader_t *loader, const apr_xml_elem *root)
{
const apr_xml_elem *elem;
+ const apr_xml_attr *id_attr;
+ const apr_xml_attr *enable_attr;
+ const char *id;
+
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Profiles");
for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"profile") == 0) {
- unimrcp_client_profile_load(client,elem,pool);
+ /* get common "id" and "enable" attributes */
+ if(header_attribs_get(elem,&id_attr,&enable_attr) == FALSE) {
+ /* invalid id */
+ continue;
}
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ if(is_attr_enabled(enable_attr) == FALSE) {
+ /* disabled element, just skip it */
+ continue;
}
- }
- return TRUE;
-}
+ id = apr_pstrdup(loader->pool,id_attr->value);
-/** Load configuration (settings and profiles) */
-static apt_bool_t unimrcp_client_config_load(mrcp_client_t *client, const apr_xml_doc *doc, apr_pool_t *pool)
-{
- const apr_xml_elem *elem;
- const apr_xml_elem *root = doc->root;
- if(!root || strcasecmp(root->name,"unimrcpclient") != 0) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Document");
- return FALSE;
- }
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"resources") == 0) {
- unimrcp_client_resources_load(client,elem,pool);
+ if(strcasecmp(elem->name,"mrcpv2-profile") == 0) {
+ unimrcp_client_mrcpv2_profile_load(loader,elem,id);
}
- else if(strcasecmp(elem->name,"settings") == 0) {
- unimrcp_client_settings_load(client,elem,pool);
- }
- else if(strcasecmp(elem->name,"profiles") == 0) {
- unimrcp_client_profiles_load(client,elem,pool);
+ else if(strcasecmp(elem->name,"mrcpv1-profile") == 0) {
+ unimrcp_client_mrcpv1_profile_load(loader,elem,id);
}
else {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
}
- }
-
+ }
+ return TRUE;
+}
+
+/** Parse XML document */
+static apr_xml_doc* unimrcp_client_doc_parse(const char *file_path, apr_pool_t *pool)
+{
+ apr_xml_parser *parser = NULL;
+ apr_xml_doc *xml_doc = NULL;
+ apr_file_t *fd = NULL;
+ apr_status_t rv;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Open Config File [%s]",file_path);
+ rv = apr_file_open(&fd,file_path,APR_READ|APR_BINARY,0,pool);
+ if(rv != APR_SUCCESS) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open Config File [%s]",file_path);
+ return NULL;
+ }
+
+ rv = apr_xml_parse_file(pool,&parser,&xml_doc,fd,XML_FILE_BUFFER_LENGTH);
+ if(rv != APR_SUCCESS) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Parse Config File [%s]",file_path);
+ xml_doc = NULL;
+ }
+
+ apr_file_close(fd);
+ return xml_doc;
+}
+
+/** Load UniMRCP client */
+static apt_bool_t unimrcp_client_load(unimrcp_client_loader_t *loader, const char *dir_path, const char *file_name, apr_pool_t *pool)
+{
+ apr_xml_doc *doc;
+ const apr_xml_elem *elem;
+ const apr_xml_elem *root;
+ const apr_xml_attr *attr;
+ const char *file_path;
+ const char *version = NULL;
+ const char *subfolder = NULL;
+
+ if(!dir_path || !file_name) {
+ return FALSE;
+ }
+
+ if(*dir_path == '\0') {
+ file_path = file_name;
+ }
+ else {
+ file_path = apr_psprintf(pool,"%s/%s",dir_path,file_name);
+ }
+
+ /* Parse XML document */
+ doc = unimrcp_client_doc_parse(file_path,pool);
+ if(!doc) {
+ return FALSE;
+ }
+
+ root = doc->root;
+
+ /* Match document name */
+ if(!root || strcasecmp(root->name,"unimrcpclient") != 0) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Document <%s>",root->name);
+ return FALSE;
+ }
+
+ /* Read attributes */
+ for(attr = root->attr; attr; attr = attr->next) {
+ if(strcasecmp(attr->name,"version") == 0) {
+ version = attr->value;
+ }
+ else if(strcasecmp(attr->name,"subfolder") == 0) {
+ subfolder = attr->value;
+ }
+ }
+
+ /* Check version number first */
+ if(!version) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Version");
+ return FALSE;
+ }
+
+ loader->doc = doc;
+
+ /* Navigate through document */
+ for(elem = root->first_child; elem; elem = elem->next) {
+ if(strcasecmp(elem->name,"properties") == 0) {
+ unimrcp_client_properties_load(loader,elem);
+ }
+ else if(strcasecmp(elem->name,"components") == 0) {
+ unimrcp_client_components_load(loader,elem);
+ }
+ else if(strcasecmp(elem->name,"settings") == 0) {
+ unimrcp_client_settings_load(loader,elem);
+ }
+ else if(strcasecmp(elem->name,"profiles") == 0) {
+ unimrcp_client_profiles_load(loader,elem);
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ if(subfolder && subfolder != '\0') {
+ apr_dir_t *dir;
+ apr_finfo_t finfo;
+ apr_status_t rv;
+
+ dir_path = apr_psprintf(pool,"%s/%s",dir_path,subfolder);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Enter Directory [%s]",dir_path);
+ rv = apr_dir_open(&dir,dir_path,pool);
+ if(rv == APR_SUCCESS) {
+ while(apr_dir_read(&finfo, APR_FINFO_NAME, dir) == APR_SUCCESS) {
+ if(apr_fnmatch("*.xml", finfo.name, 0) == APR_SUCCESS) {
+ unimrcp_client_load(loader,dir_path,finfo.name,pool);
+ }
+ }
+ apr_dir_close(dir);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Leave Directory [%s]",dir_path);
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No Such Directory %s",dir_path);
+ }
+ }
return TRUE;
}
diff --git a/libs/unimrcp/platforms/libunimrcp-server/include/unimrcp_server.h b/libs/unimrcp/platforms/libunimrcp-server/include/unimrcp_server.h
index 39f3813048..c66fb74e56 100644
--- a/libs/unimrcp/platforms/libunimrcp-server/include/unimrcp_server.h
+++ b/libs/unimrcp/platforms/libunimrcp-server/include/unimrcp_server.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: unimrcp_server.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __UNIMRCP_SERVER_H__
-#define __UNIMRCP_SERVER_H__
+#ifndef UNIMRCP_SERVER_H
+#define UNIMRCP_SERVER_H
/**
* @file unimrcp_server.h
@@ -40,4 +42,4 @@ MRCP_DECLARE(apt_bool_t) unimrcp_server_shutdown(mrcp_server_t *server);
APT_END_EXTERN_C
-#endif /*__UNIMRCP_SERVER_H__*/
+#endif /* UNIMRCP_SERVER_H */
diff --git a/libs/unimrcp/platforms/libunimrcp-server/libunimrcpserver.2008.vcproj b/libs/unimrcp/platforms/libunimrcp-server/libunimrcpserver.2008.vcproj
deleted file mode 100644
index d1b51c7929..0000000000
--- a/libs/unimrcp/platforms/libunimrcp-server/libunimrcpserver.2008.vcproj
+++ /dev/null
@@ -1,156 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/platforms/libunimrcp-server/libunimrcpserver.vcproj b/libs/unimrcp/platforms/libunimrcp-server/libunimrcpserver.vcproj
index 877610a9a3..0f5b68f4e9 100644
--- a/libs/unimrcp/platforms/libunimrcp-server/libunimrcpserver.vcproj
+++ b/libs/unimrcp/platforms/libunimrcp-server/libunimrcpserver.vcproj
@@ -244,6 +244,10 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
+
+
diff --git a/libs/unimrcp/platforms/libunimrcp-server/src/unimrcp_server.c b/libs/unimrcp/platforms/libunimrcp-server/src/unimrcp_server.c
index d2532c6ebf..d7b23865c2 100644
--- a/libs/unimrcp/platforms/libunimrcp-server/src/unimrcp_server.c
+++ b/libs/unimrcp/platforms/libunimrcp-server/src/unimrcp_server.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,12 +12,15 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: unimrcp_server.c 1711 2010-05-25 17:54:02Z achaloyan $
*/
#include
#include
-#include "unimrcp_server.h"
+#include
#include "uni_version.h"
+#include "unimrcp_server.h"
#include "mrcp_resource_loader.h"
#include "mpf_engine.h"
#include "mpf_codec_manager.h"
@@ -29,7 +32,6 @@
#include "apt_log.h"
#define CONF_FILE_NAME "unimrcpserver.xml"
-#define DEFAULT_CONF_DIR_PATH "../conf"
#define DEFAULT_PLUGIN_DIR_PATH "../plugin"
#ifdef WIN32
#define DEFAULT_PLUGIN_EXT "dll"
@@ -47,16 +49,37 @@
#define DEFAULT_SOFIASIP_UA_NAME "UniMRCP SofiaSIP"
#define DEFAULT_SDP_ORIGIN "UniMRCPServer"
-#define XML_FILE_BUFFER_LENGTH 2000
+#define XML_FILE_BUFFER_LENGTH 16000
-static apr_xml_doc* unimrcp_server_config_parse(const char *path, apr_pool_t *pool);
-static apt_bool_t unimrcp_server_config_load(mrcp_server_t *server, const char *plugin_dir_path, const apr_xml_doc *doc, apr_pool_t *pool);
+/** UniMRCP server loader */
+typedef struct unimrcp_server_loader_t unimrcp_server_loader_t;
+
+/** UniMRCP server loader */
+struct unimrcp_server_loader_t {
+ /** MRCP server */
+ mrcp_server_t *server;
+ /** Directory layout */
+ apt_dir_layout_t *dir_layout;
+ /** XML document */
+ apr_xml_doc *doc;
+ /** Pool to allocate memory from */
+ apr_pool_t *pool;
+
+ /** Default ip address (named property) */
+ const char *ip;
+ /** Default external (NAT) ip address (named property) */
+ const char *ext_ip;
+
+ /** Implicitly detected, cached ip address */
+ const char *auto_ip;
+};
+
+static apt_bool_t unimrcp_server_load(mrcp_server_t *mrcp_server, apt_dir_layout_t *dir_layout, apr_pool_t *pool);
/** Start UniMRCP server */
MRCP_DECLARE(mrcp_server_t*) unimrcp_server_start(apt_dir_layout_t *dir_layout)
{
apr_pool_t *pool;
- apr_xml_doc *doc;
mrcp_server_t *server;
if(!dir_layout) {
@@ -74,9 +97,8 @@ MRCP_DECLARE(mrcp_server_t*) unimrcp_server_start(apt_dir_layout_t *dir_layout)
return NULL;
}
- doc = unimrcp_server_config_parse(dir_layout->conf_dir_path,pool);
- if(doc) {
- unimrcp_server_config_load(server,dir_layout->plugin_dir_path,doc,pool);
+ if(unimrcp_server_load(server,dir_layout,pool) == FALSE) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Load UniMRCP Server Document");
}
mrcp_server_start(server);
@@ -93,43 +115,73 @@ MRCP_DECLARE(apt_bool_t) unimrcp_server_shutdown(mrcp_server_t *server)
}
-/** Parse config file */
-static apr_xml_doc* unimrcp_server_config_parse(const char *dir_path, apr_pool_t *pool)
+/** Check whether specified attribute is valid */
+static APR_INLINE apt_bool_t is_attr_valid(const apr_xml_attr *attr)
{
- apr_xml_parser *parser = NULL;
- apr_xml_doc *doc = NULL;
- apr_file_t *fd = NULL;
- apr_status_t rv;
- const char *file_path;
-
- if(!dir_path) {
- dir_path = DEFAULT_CONF_DIR_PATH;
- }
- if(*dir_path == '\0') {
- file_path = CONF_FILE_NAME;
- }
- else {
- file_path = apr_psprintf(pool,"%s/%s",dir_path,CONF_FILE_NAME);
- }
-
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Open Config File [%s]",file_path);
- rv = apr_file_open(&fd,file_path,APR_READ|APR_BINARY,0,pool);
- if(rv != APR_SUCCESS) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open Config File [%s]",file_path);
- return NULL;
- }
-
- rv = apr_xml_parse_file(pool,&parser,&doc,fd,XML_FILE_BUFFER_LENGTH);
- if(rv != APR_SUCCESS) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Parse Config File [%s]",file_path);
- doc = NULL;
- }
-
- apr_file_close(fd);
- return doc;
+ return (attr && attr->value && attr->value != '\0');
}
-static apt_bool_t param_name_value_get(const apr_xml_elem *elem, const apr_xml_attr **name, const apr_xml_attr **value)
+/** Check whether specified attribute is enabled (true) */
+static APR_INLINE apt_bool_t is_attr_enabled(const apr_xml_attr *attr)
+{
+ if(attr && strcasecmp(attr->value,"false") == 0) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/** Check whether cdata is valid */
+static APR_INLINE apt_bool_t is_cdata_valid(const apr_xml_elem *elem)
+{
+ return (elem->first_cdata.first && elem->first_cdata.first->text);
+}
+
+/** Get text cdata */
+static APR_INLINE const char* cdata_text_get(const apr_xml_elem *elem)
+{
+ return elem->first_cdata.first->text;
+}
+
+/** Get boolean cdata */
+static APR_INLINE apt_bool_t cdata_bool_get(const apr_xml_elem *elem)
+{
+ return (strcasecmp(elem->first_cdata.first->text,"true") == 0) ? TRUE : FALSE;
+}
+
+/** Copy cdata */
+static APR_INLINE char* cdata_copy(const apr_xml_elem *elem, apr_pool_t *pool)
+{
+ return apr_pstrdup(pool,elem->first_cdata.first->text);
+}
+
+/** Get generic "id" and "enable" attributes */
+static apt_bool_t header_attribs_get(const apr_xml_elem *elem, const apr_xml_attr **id, const apr_xml_attr **enable)
+{
+ const apr_xml_attr *attr;
+ if(!id || !enable) {
+ return FALSE;
+ }
+
+ *id = NULL;
+ *enable = NULL;
+ for(attr = elem->attr; attr; attr = attr->next) {
+ if(strcasecmp(attr->name,"id") == 0) {
+ *id = attr;
+ }
+ else if(strcasecmp(attr->name,"enable") == 0) {
+ *enable = attr;
+ }
+ }
+
+ if(is_attr_valid(*id) == FALSE) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Missing Required Attribute in Element <%s>",elem->name);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/** Get generic "name" and "value" attributes */
+static apt_bool_t name_value_attribs_get(const apr_xml_elem *elem, const apr_xml_attr **name, const apr_xml_attr **value)
{
const apr_xml_attr *attr;
if(!name || !value) {
@@ -149,414 +201,61 @@ static apt_bool_t param_name_value_get(const apr_xml_elem *elem, const apr_xml_a
return (*name && *value) ? TRUE : FALSE;
}
-static char* ip_addr_get(const char *value, apr_pool_t *pool)
+static char* unimrcp_server_ip_address_get(unimrcp_server_loader_t *loader, const apr_xml_elem *elem)
{
- if(!value || strcasecmp(value,"auto") == 0) {
- char *addr = DEFAULT_IP_ADDRESS;
- apt_ip_get(&addr,pool);
- return addr;
- }
- return apr_pstrdup(pool,value);
-}
-
-/** Load map of MRCP resource names */
-static apt_bool_t resource_map_load(apr_table_t *resource_map, const apr_xml_elem *root, apr_pool_t *pool)
-{
- const apr_xml_attr *attr_name;
- const apr_xml_attr *attr_value;
- const apr_xml_elem *elem;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Resource Map");
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"param") == 0) {
- if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
- apr_table_set(resource_map,attr_name->value,attr_value->value);
- }
- }
- }
- return TRUE;
-}
-
-/** Load map of plugins */
-static apt_bool_t plugin_map_load(apr_table_t *plugin_map, const apr_xml_elem *root, apr_pool_t *pool)
-{
- const apr_xml_attr *attr_name;
- const apr_xml_attr *attr_value;
- const apr_xml_elem *elem;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Plugin Map");
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"param") == 0) {
- if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
- apr_table_set(plugin_map,attr_name->value,attr_value->value);
- }
- }
- }
- return TRUE;
-}
-
-/** Load SofiaSIP signaling agent */
-static mrcp_sig_agent_t* unimrcp_server_sofiasip_agent_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
-{
- const apr_xml_elem *elem;
- mrcp_sofia_server_config_t *config = mrcp_sofiasip_server_config_alloc(pool);
- config->local_ip = DEFAULT_IP_ADDRESS;
- config->local_port = DEFAULT_SIP_PORT;
- config->ext_ip = NULL;
- config->user_agent_name = DEFAULT_SOFIASIP_UA_NAME;
- config->origin = DEFAULT_SDP_ORIGIN;
-
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading SofiaSIP Agent");
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"param") == 0) {
- const apr_xml_attr *attr_name;
- const apr_xml_attr *attr_value;
- if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
- if(strcasecmp(attr_name->value,"sip-ip") == 0) {
- config->local_ip = ip_addr_get(attr_value->value,pool);
- }
- else if(strcasecmp(attr_name->value,"sip-ext-ip") == 0) {
- config->ext_ip = ip_addr_get(attr_value->value,pool);
- }
- else if(strcasecmp(attr_name->value,"sip-port") == 0) {
- config->local_port = (apr_port_t)atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"sip-transport") == 0) {
- config->transport = apr_pstrdup(pool,attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"ua-name") == 0) {
- config->user_agent_name = apr_pstrdup(pool,attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"sdp-origin") == 0) {
- config->origin = apr_pstrdup(pool,attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"force-destination") == 0) {
- config->force_destination = atoi(attr_value->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
- }
- }
- }
- }
- return mrcp_sofiasip_server_agent_create(config,pool);
-}
-
-/** Load UniRTSP signaling agent */
-static mrcp_sig_agent_t* unimrcp_server_rtsp_agent_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
-{
- const apr_xml_elem *elem;
- rtsp_server_config_t *config = mrcp_unirtsp_server_config_alloc(pool);
- config->local_ip = DEFAULT_IP_ADDRESS;
- config->local_port = DEFAULT_RTSP_PORT;
- config->origin = DEFAULT_SDP_ORIGIN;
-
-
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading UniRTSP Agent");
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"param") == 0) {
- const apr_xml_attr *attr_name;
- const apr_xml_attr *attr_value;
- if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
- if(strcasecmp(attr_name->value,"rtsp-ip") == 0) {
- config->local_ip = ip_addr_get(attr_value->value,pool);
- }
- else if(strcasecmp(attr_name->value,"rtsp-port") == 0) {
- config->local_port = (apr_port_t)atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"sdp-origin") == 0) {
- config->origin = apr_pstrdup(pool,attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"max-connection-count") == 0) {
- config->max_connection_count = atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"force-destination") == 0) {
- config->force_destination = atoi(attr_value->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
- }
- }
- }
- else if(strcasecmp(elem->name,"resourcemap") == 0) {
- resource_map_load(config->resource_map,elem,pool);
+ const apr_xml_attr *attr = NULL;
+ for(attr = elem->attr; attr; attr = attr->next) {
+ if(strcasecmp(attr->name,"type") == 0) {
+ break;
}
}
- return mrcp_unirtsp_server_agent_create(config,pool);
-}
-/** Load signaling agents */
-static apt_bool_t unimrcp_server_signaling_agents_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
-{
- const apr_xml_elem *elem;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Signaling Agents");
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"agent") == 0) {
- mrcp_sig_agent_t *sig_agent = NULL;
- const char *name = NULL;
- const apr_xml_attr *attr;
- for(attr = elem->attr; attr; attr = attr->next) {
- if(strcasecmp(attr->name,"name") == 0) {
- name = apr_pstrdup(pool,attr->value);
- }
- else if(strcasecmp(attr->name,"class") == 0) {
- if(strcasecmp(attr->value,"SofiaSIP") == 0) {
- sig_agent = unimrcp_server_sofiasip_agent_load(server,elem,pool);
- }
- else if(strcasecmp(attr->value,"UniRTSP") == 0) {
- sig_agent = unimrcp_server_rtsp_agent_load(server,elem,pool);
- }
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
- }
- }
- if(sig_agent) {
- mrcp_server_signaling_agent_register(server,sig_agent,name);
- }
+ if(attr && strcasecmp(attr->value,"auto") == 0) {
+ /* implicitly detect ip address, if not already detected */
+ if(!loader->auto_ip) {
+ char *auto_addr = DEFAULT_IP_ADDRESS;
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Detecting IP Address");
+ apt_ip_get(&auto_addr,loader->pool);
+ loader->auto_ip = auto_addr;
}
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
- }
- }
- return TRUE;
-}
-
-/** Load MRCPv2 connection agent */
-static mrcp_connection_agent_t* unimrcp_server_connection_agent_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
-{
- const apr_xml_elem *elem;
- char *mrcp_ip = DEFAULT_IP_ADDRESS;
- apr_port_t mrcp_port = DEFAULT_MRCP_PORT;
- apr_size_t max_connection_count = 100;
- apt_bool_t force_new_connection = FALSE;
-
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading MRCPv2 Agent");
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"param") == 0) {
- const apr_xml_attr *attr_name;
- const apr_xml_attr *attr_value;
- if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
- if(strcasecmp(attr_name->value,"mrcp-ip") == 0) {
- mrcp_ip = ip_addr_get(attr_value->value,pool);
- }
- else if(strcasecmp(attr_name->value,"mrcp-port") == 0) {
- mrcp_port = (apr_port_t)atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"max-connection-count") == 0) {
- max_connection_count = atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"force-new-connection") == 0) {
- force_new_connection = atoi(attr_value->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
- }
- }
- }
- }
- return mrcp_server_connection_agent_create(mrcp_ip,mrcp_port,max_connection_count,force_new_connection,pool);
-}
-
-/** Load MRCPv2 conection agents */
-static apt_bool_t unimrcp_server_connection_agents_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
-{
- const apr_xml_elem *elem;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Connection Agents");
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"agent") == 0) {
- mrcp_connection_agent_t *connection_agent;
- const char *name = NULL;
- const apr_xml_attr *attr;
- for(attr = elem->attr; attr; attr = attr->next) {
- if(strcasecmp(attr->name,"name") == 0) {
- name = apr_pstrdup(pool,attr->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
- }
- }
- connection_agent = unimrcp_server_connection_agent_load(server,elem,pool);
- if(connection_agent) {
- mrcp_server_connection_agent_register(server,connection_agent,name);
- }
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
- }
- }
- return TRUE;
-}
-
-/** Load RTP termination factory */
-static mpf_termination_factory_t* unimrcp_server_rtp_factory_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
-{
- const apr_xml_elem *elem;
- char *rtp_ip = DEFAULT_IP_ADDRESS;
- char *rtp_ext_ip = NULL;
- mpf_rtp_config_t *rtp_config = mpf_rtp_config_create(pool);
- rtp_config->rtp_port_min = DEFAULT_RTP_PORT_MIN;
- rtp_config->rtp_port_max = DEFAULT_RTP_PORT_MAX;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading RTP Termination Factory");
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"param") == 0) {
- const apr_xml_attr *attr_name;
- const apr_xml_attr *attr_value;
- if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
- if(strcasecmp(attr_name->value,"rtp-ip") == 0) {
- rtp_ip = ip_addr_get(attr_value->value,pool);
- }
- else if(strcasecmp(attr_name->value,"rtp-ext-ip") == 0) {
- rtp_ext_ip = ip_addr_get(attr_value->value,pool);
- }
- else if(strcasecmp(attr_name->value,"rtp-port-min") == 0) {
- rtp_config->rtp_port_min = (apr_port_t)atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"rtp-port-max") == 0) {
- rtp_config->rtp_port_max = (apr_port_t)atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"playout-delay") == 0) {
- rtp_config->jb_config.initial_playout_delay = atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"min-playout-delay") == 0) {
- rtp_config->jb_config.min_playout_delay = atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"max-playout-delay") == 0) {
- rtp_config->jb_config.max_playout_delay = atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"codecs") == 0) {
- const mpf_codec_manager_t *codec_manager = mrcp_server_codec_manager_get(server);
- if(codec_manager) {
- mpf_codec_manager_codec_list_load(codec_manager,&rtp_config->codec_list,attr_value->value,pool);
- }
- }
- else if(strcasecmp(attr_name->value,"ptime") == 0) {
- rtp_config->ptime = (apr_uint16_t)atol(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"own-preference") == 0) {
- rtp_config->own_preferrence = atoi(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"rtcp") == 0) {
- rtp_config->rtcp = atoi(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"rtcp-bye") == 0) {
- rtp_config->rtcp_bye_policy = atoi(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"rtcp-tx-interval") == 0) {
- rtp_config->rtcp_tx_interval = (apr_uint16_t)atoi(attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"rtcp-rx-resolution") == 0) {
- rtp_config->rtcp_rx_resolution = (apr_uint16_t)atol(attr_value->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
- }
- }
- }
- }
- apt_string_set(&rtp_config->ip,rtp_ip);
- if(rtp_ext_ip) {
- apt_string_set(&rtp_config->ext_ip,rtp_ext_ip);
- }
- return mpf_rtp_termination_factory_create(rtp_config,pool);
-}
-
-/** Load media engines */
-static apt_bool_t unimrcp_server_media_engines_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
-{
- const apr_xml_elem *elem;
-
- /* create codec manager first */
- mpf_codec_manager_t *codec_manager = mpf_engine_codec_manager_create(pool);
- if(codec_manager) {
- mrcp_server_codec_manager_register(server,codec_manager);
+ return apr_pstrdup(loader->pool,loader->auto_ip);
}
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Media Engines");
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"engine") == 0) {
- mpf_engine_t *media_engine;
- unsigned long realtime_rate = 1;
- const char *name = NULL;
- const apr_xml_attr *attr;
- for(attr = elem->attr; attr; attr = attr->next) {
- if(strcasecmp(attr->name,"name") == 0) {
- name = apr_pstrdup(pool,attr->value);
- }
- else if(strcasecmp(attr->name,"realtime-rate") == 0) {
- realtime_rate = atol(attr->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
- }
- }
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Media Engine");
- media_engine = mpf_engine_create(pool);
- if(media_engine) {
- mpf_engine_scheduler_rate_set(media_engine,realtime_rate);
- mrcp_server_media_engine_register(server,media_engine,name);
- }
- }
- else if(strcasecmp(elem->name,"rtp") == 0) {
- mpf_termination_factory_t *rtp_factory;
- const char *name = NULL;
- const apr_xml_attr *attr;
- for(attr = elem->attr; attr; attr = attr->next) {
- if(strcasecmp(attr->name,"name") == 0) {
- name = apr_pstrdup(pool,attr->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
- }
- }
- rtp_factory = unimrcp_server_rtp_factory_load(server,elem,pool);
- if(rtp_factory) {
- mrcp_server_rtp_factory_register(server,rtp_factory,name);
- }
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
- }
- }
- return TRUE;
+ if(is_cdata_valid(elem)) {
+ /* use provided ip address */
+ return cdata_copy(elem,loader->pool);
+ }
+
+ /* use default ip address */
+ return apr_pstrdup(loader->pool,loader->ip);
}
/** Load resource */
-static apt_bool_t unimrcp_server_resource_load(mrcp_server_t *server, mrcp_resource_loader_t *resource_loader, const apr_xml_elem *root, apr_pool_t *pool)
+static apt_bool_t unimrcp_server_resource_load(mrcp_resource_loader_t *resource_loader, const apr_xml_elem *root, apr_pool_t *pool)
{
apt_str_t resource_class;
- apt_bool_t resource_enabled = TRUE;
- const apr_xml_attr *attr;
+ const apr_xml_attr *id_attr;
+ const apr_xml_attr *enable_attr;
apt_string_reset(&resource_class);
- for(attr = root->attr; attr; attr = attr->next) {
- if(strcasecmp(attr->name,"class") == 0) {
- apt_string_set(&resource_class,attr->value);
- }
- else if(strcasecmp(attr->name,"enable") == 0) {
- resource_enabled = atoi(attr->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
- }
- }
- if(!resource_class.buf || !resource_enabled) {
+ if(header_attribs_get(root,&id_attr,&enable_attr) == FALSE) {
return FALSE;
}
+
+ if(is_attr_enabled(enable_attr) == FALSE) {
+ return TRUE;
+ }
+ apt_string_set(&resource_class,id_attr->value);
return mrcp_resource_load(resource_loader,&resource_class);
}
-/** Load resources */
-static apt_bool_t unimrcp_server_resources_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
+/** Load resource factory */
+static apt_bool_t unimrcp_server_resource_factory_load(unimrcp_server_loader_t *loader, const apr_xml_elem *root)
{
const apr_xml_elem *elem;
mrcp_resource_factory_t *resource_factory;
- mrcp_resource_loader_t *resource_loader = mrcp_resource_loader_create(FALSE,pool);
+ mrcp_resource_loader_t *resource_loader = mrcp_resource_loader_create(FALSE,loader->pool);
if(!resource_loader) {
return FALSE;
}
@@ -564,76 +263,378 @@ static apt_bool_t unimrcp_server_resources_load(mrcp_server_t *server, const apr
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Resources");
for(elem = root->first_child; elem; elem = elem->next) {
if(strcasecmp(elem->name,"resource") == 0) {
- unimrcp_server_resource_load(server,resource_loader,elem,pool);
+ unimrcp_server_resource_load(resource_loader,elem,loader->pool);
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ resource_factory = mrcp_resource_factory_get(resource_loader);
+ return mrcp_server_resource_factory_register(loader->server,resource_factory);
+}
+
+/** Load SofiaSIP signaling agent */
+static apt_bool_t unimrcp_server_sip_uas_load(unimrcp_server_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ mrcp_sig_agent_t *agent;
+ mrcp_sofia_server_config_t *config;
+
+ config = mrcp_sofiasip_server_config_alloc(loader->pool);
+ config->local_port = DEFAULT_SIP_PORT;
+ config->user_agent_name = DEFAULT_SOFIASIP_UA_NAME;
+ config->origin = DEFAULT_SDP_ORIGIN;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading SofiaSIP Agent <%s>",id);
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"sip-ip") == 0) {
+ config->local_ip = unimrcp_server_ip_address_get(loader,elem);
+ }
+ else if(strcasecmp(elem->name,"sip-ext-ip") == 0) {
+ config->ext_ip = unimrcp_server_ip_address_get(loader,elem);
+ }
+ else if(strcasecmp(elem->name,"sip-port") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->local_port = (apr_port_t)atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"sip-transport") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->transport = cdata_copy(elem,loader->pool);
+ }
+ }
+ else if(strcasecmp(elem->name,"ua-name") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->user_agent_name = cdata_copy(elem,loader->pool);
+ }
+ }
+ else if(strcasecmp(elem->name,"sdp-origin") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->origin = cdata_copy(elem,loader->pool);
+ }
+ }
+ else if(strcasecmp(elem->name,"force-destination") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->force_destination = cdata_bool_get(elem);
+ }
+ }
+ else if(strcasecmp(elem->name,"sip-t1") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->sip_t1 = atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"sip-t2") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->sip_t2 = atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"sip-t4") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->sip_t4 = atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"sip-t1x64") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->sip_t1x64 = atol(cdata_text_get(elem));
+ }
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ if(!config->local_ip) {
+ /* use default ip address if not specified */
+ config->local_ip = apr_pstrdup(loader->pool,loader->ip);
+ }
+ if(!config->ext_ip && loader->ext_ip) {
+ /* use default ext ip address if not specified */
+ config->ext_ip = apr_pstrdup(loader->pool,loader->ext_ip);
+ }
+
+ agent = mrcp_sofiasip_server_agent_create(id,config,loader->pool);
+ return mrcp_server_signaling_agent_register(loader->server,agent);
+}
+
+/** Load UniRTSP signaling agent */
+static apt_bool_t unimrcp_server_rtsp_uas_load(unimrcp_server_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ mrcp_sig_agent_t *agent;
+ rtsp_server_config_t *config;
+
+ config = mrcp_unirtsp_server_config_alloc(loader->pool);
+ config->origin = DEFAULT_SDP_ORIGIN;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading UniRTSP Agent <%s>",id);
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"rtsp-ip") == 0) {
+ config->local_ip = unimrcp_server_ip_address_get(loader,elem);
+ }
+ else if(strcasecmp(elem->name,"rtsp-port") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->local_port = (apr_port_t)atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"sdp-origin") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->origin = cdata_copy(elem,loader->pool);
+ }
+ }
+ else if(strcasecmp(elem->name,"max-connection-count") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->max_connection_count = atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"force-destination") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->force_destination = cdata_bool_get(elem);
+ }
+ }
+ else if(strcasecmp(elem->name,"resource-map") == 0) {
+ const apr_xml_attr *name_attr;
+ const apr_xml_attr *value_attr;
+ const apr_xml_elem *child_elem;
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Resource Map");
+ for(child_elem = elem->first_child; child_elem; child_elem = child_elem->next) {
+ if(name_value_attribs_get(child_elem,&name_attr,&value_attr) == TRUE) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",name_attr->value,value_attr->value);
+ apr_table_set(config->resource_map,name_attr->value,value_attr->value);
+ }
+ }
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ if(!config->local_ip) {
+ /* use default ip address if not specified */
+ config->local_ip = apr_pstrdup(loader->pool,loader->ip);
+ }
+
+ agent = mrcp_unirtsp_server_agent_create(id,config,loader->pool);
+ return mrcp_server_signaling_agent_register(loader->server,agent);
+}
+
+/** Load MRCPv2 connection agent */
+static apt_bool_t unimrcp_server_mrcpv2_uas_load(unimrcp_server_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ mrcp_connection_agent_t *agent;
+ char *mrcp_ip = NULL;
+ apr_port_t mrcp_port = DEFAULT_MRCP_PORT;
+ apr_size_t max_connection_count = 100;
+ apt_bool_t force_new_connection = FALSE;
+ apr_size_t rx_buffer_size = 0;
+ apr_size_t tx_buffer_size = 0;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading MRCPv2 Agent <%s>",id);
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"mrcp-ip") == 0) {
+ mrcp_ip = unimrcp_server_ip_address_get(loader,elem);
+ }
+ else if(strcasecmp(elem->name,"mrcp-port") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ mrcp_port = (apr_port_t)atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"max-connection-count") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ max_connection_count = atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"force-new-connection") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ force_new_connection = cdata_bool_get(elem);
+ }
+ }
+ else if(strcasecmp(elem->name,"rx-buffer-size") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ rx_buffer_size = atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"tx-buffer-size") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ tx_buffer_size = atol(cdata_text_get(elem));
+ }
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ if(!mrcp_ip) {
+ /* use default ip address if not specified */
+ mrcp_ip = apr_pstrdup(loader->pool,loader->ip);
+ }
+
+ agent = mrcp_server_connection_agent_create(id,mrcp_ip,mrcp_port,max_connection_count,force_new_connection,loader->pool);
+ if(agent) {
+ if(rx_buffer_size) {
+ mrcp_server_connection_rx_size_set(agent,rx_buffer_size);
+ }
+ if(tx_buffer_size) {
+ mrcp_server_connection_tx_size_set(agent,tx_buffer_size);
+ }
+ }
+ return mrcp_server_connection_agent_register(loader->server,agent);
+}
+
+/** Load media engine */
+static apt_bool_t unimrcp_server_media_engine_load(unimrcp_server_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ mpf_engine_t *media_engine;
+ unsigned long realtime_rate = 1;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Media Engine <%s>",id);
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"realtime-rate") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ realtime_rate = atol(cdata_text_get(elem));
+ }
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ media_engine = mpf_engine_create(id,loader->pool);
+ if(media_engine) {
+ mpf_engine_scheduler_rate_set(media_engine,realtime_rate);
+ }
+ return mrcp_server_media_engine_register(loader->server,media_engine);
+}
+
+/** Load RTP factory */
+static apt_bool_t unimrcp_server_rtp_factory_load(unimrcp_server_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ char *rtp_ip = NULL;
+ char *rtp_ext_ip = NULL;
+ mpf_termination_factory_t *rtp_factory;
+ mpf_rtp_config_t *rtp_config;
+
+ rtp_config = mpf_rtp_config_alloc(loader->pool);
+ rtp_config->rtp_port_min = DEFAULT_RTP_PORT_MIN;
+ rtp_config->rtp_port_max = DEFAULT_RTP_PORT_MAX;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading RTP Factory <%s>",id);
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"rtp-ip") == 0) {
+ rtp_ip = unimrcp_server_ip_address_get(loader,elem);
+ }
+ else if(strcasecmp(elem->name,"rtp-ext-ip") == 0) {
+ rtp_ext_ip = unimrcp_server_ip_address_get(loader,elem);
+ }
+ else if(strcasecmp(elem->name,"rtp-port-min") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ rtp_config->rtp_port_min = (apr_port_t)atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"rtp-port-max") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ rtp_config->rtp_port_max = (apr_port_t)atol(cdata_text_get(elem));
+ }
}
else {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
}
}
- resource_factory = mrcp_resource_factory_get(resource_loader);
- mrcp_server_resource_factory_register(server,resource_factory);
- return TRUE;
+ if(rtp_ip) {
+ apt_string_set(&rtp_config->ip,rtp_ip);
+ }
+ else {
+ apt_string_set(&rtp_config->ip,loader->ip);
+ }
+ if(rtp_ext_ip) {
+ apt_string_set(&rtp_config->ext_ip,rtp_ext_ip);
+ }
+ else if(loader->ext_ip){
+ apt_string_set(&rtp_config->ext_ip,loader->ext_ip);
+ }
+
+ rtp_factory = mpf_rtp_termination_factory_create(rtp_config,loader->pool);
+ return mrcp_server_rtp_factory_register(loader->server,rtp_factory,id);
}
/** Load plugin */
-static apt_bool_t unimrcp_server_plugin_load(mrcp_server_t *server, const char *plugin_dir_path, const apr_xml_elem *root, apr_pool_t *pool)
+static apt_bool_t unimrcp_server_plugin_load(unimrcp_server_loader_t *loader, const apr_xml_elem *root)
{
+ mrcp_engine_t *engine;
mrcp_engine_config_t *config;
- const char *plugin_class = NULL;
+ const char *plugin_id = NULL;
+ const char *plugin_name = NULL;
const char *plugin_ext = NULL;
const char *plugin_path = NULL;
apt_bool_t plugin_enabled = TRUE;
const apr_xml_attr *attr;
- config = mrcp_engine_config_alloc(pool);
for(attr = root->attr; attr; attr = attr->next) {
- if(strcasecmp(attr->name,"name") == 0) {
- config->name = apr_pstrdup(pool,attr->value);
+ if(strcasecmp(attr->name,"id") == 0) {
+ plugin_id = apr_pstrdup(loader->pool,attr->value);
}
- else if(strcasecmp(attr->name,"class") == 0) {
- plugin_class = attr->value;
+ else if(strcasecmp(attr->name,"name") == 0) {
+ plugin_name = attr->value;
}
else if(strcasecmp(attr->name,"ext") == 0) {
plugin_ext = attr->value;
}
else if(strcasecmp(attr->name,"enable") == 0) {
- plugin_enabled = atoi(attr->value);
- }
- else if(strcasecmp(attr->name,"max-channel-count") == 0) {
- config->max_channel_count = atol(attr->value);
+ plugin_enabled = is_attr_enabled(attr);
}
else {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
}
}
- if(!plugin_class || !plugin_enabled) {
+ if(!plugin_id || !plugin_name) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Missing plugin id or name");
return FALSE;
}
- if(!plugin_dir_path) {
- plugin_dir_path = DEFAULT_PLUGIN_DIR_PATH;
+
+ if(!plugin_enabled) {
+ /* disabled plugin, just skip it */
+ return TRUE;
}
+
if(!plugin_ext) {
plugin_ext = DEFAULT_PLUGIN_EXT;
}
- if(*plugin_dir_path == '\0') {
- plugin_path = apr_psprintf(pool,"%s.%s",plugin_class,plugin_ext);
+ if(*loader->dir_layout->plugin_dir_path == '\0') {
+ plugin_path = apr_psprintf(loader->pool,"%s.%s",
+ plugin_name,plugin_ext);
}
else {
- plugin_path = apr_psprintf(pool,"%s/%s.%s",plugin_dir_path,plugin_class,plugin_ext);
+ plugin_path = apr_psprintf(loader->pool,"%s/%s.%s",
+ loader->dir_layout->plugin_dir_path,plugin_name,plugin_ext);
}
- /* load optional name/value params */
+ config = mrcp_engine_config_alloc(loader->pool);
+
+ /* load optional named and generic name/value params */
if(root->first_child){
const apr_xml_attr *attr_name;
const apr_xml_attr *attr_value;
const apr_xml_elem *elem;
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Engine Params");
- config->params = apr_table_make(pool,1);
+ config->params = apr_table_make(loader->pool,1);
for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"param") == 0) {
- if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
+ if(strcasecmp(elem->name,"max-channel-count") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ config->max_channel_count = atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"param") == 0) {
+ if(name_value_attribs_get(elem,&attr_name,&attr_value) == TRUE) {
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
apr_table_set(config->params,attr_name->value,attr_value->value);
}
@@ -641,149 +642,520 @@ static apt_bool_t unimrcp_server_plugin_load(mrcp_server_t *server, const char *
}
}
- return mrcp_server_plugin_register(server,plugin_path,config);
+ engine = mrcp_server_engine_load(loader->server,plugin_id,plugin_path,config);
+ return mrcp_server_engine_register(loader->server,engine);
}
-/** Load plugins */
-static apt_bool_t unimrcp_server_plugins_load(mrcp_server_t *server, const char *plugin_dir_path, const apr_xml_elem *root, apr_pool_t *pool)
+/** Load plugin (engine) factory */
+static apt_bool_t unimrcp_server_plugin_factory_load(unimrcp_server_loader_t *loader, const apr_xml_elem *root)
{
const apr_xml_elem *elem;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Engine Plugins");
+
+ if(!loader->dir_layout->plugin_dir_path) {
+ loader->dir_layout->plugin_dir_path = DEFAULT_PLUGIN_DIR_PATH;
+ }
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Plugin Factory");
for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
if(strcasecmp(elem->name,"engine") == 0) {
- unimrcp_server_plugin_load(server,plugin_dir_path,elem,pool);
+ unimrcp_server_plugin_load(loader,elem);
}
else {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
}
- }
+ }
return TRUE;
}
-
-/** Load settings */
-static apt_bool_t unimrcp_server_settings_load(mrcp_server_t *server, const char *plugin_dir_path, const apr_xml_elem *root, apr_pool_t *pool)
+/** Load jitter buffer settings */
+static apt_bool_t unimrcp_server_jb_settings_load(unimrcp_server_loader_t *loader, mpf_jb_config_t *jb, const apr_xml_elem *root)
{
const apr_xml_elem *elem;
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Settings");
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Jitter Buffer Settings");
for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"signaling") == 0) {
- unimrcp_server_signaling_agents_load(server,elem,pool);
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"playout-delay") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ jb->initial_playout_delay = atol(cdata_text_get(elem));
+ }
}
- else if(strcasecmp(elem->name,"connection") == 0) {
- unimrcp_server_connection_agents_load(server,elem,pool);
+ else if(strcasecmp(elem->name,"min-playout-delay") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ jb->min_playout_delay = atol(cdata_text_get(elem));
+ }
}
- else if(strcasecmp(elem->name,"media") == 0) {
- unimrcp_server_media_engines_load(server,elem,pool);
- }
- else if(strcasecmp(elem->name,"plugin") == 0) {
- unimrcp_server_plugins_load(server,plugin_dir_path,elem,pool);
+ else if(strcasecmp(elem->name,"max-playout-delay") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ jb->max_playout_delay = atol(cdata_text_get(elem));
+ }
}
else {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
}
- }
+ }
return TRUE;
}
-/** Load profile */
-static apt_bool_t unimrcp_server_profile_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
+/** Load RTCP settings */
+static apt_bool_t unimrcp_server_rtcp_settings_load(unimrcp_server_loader_t *loader, mpf_rtp_settings_t *rtcp_settings, const apr_xml_elem *root)
{
- const char *name = NULL;
- mrcp_profile_t *profile;
- mrcp_sig_agent_t *sig_agent = NULL;
- mrcp_connection_agent_t *cnt_agent = NULL;
- mpf_engine_t *media_engine = NULL;
- mpf_termination_factory_t *rtp_factory = NULL;
- apr_table_t *plugin_map = NULL;
const apr_xml_elem *elem;
- const apr_xml_attr *attr;
+ const apr_xml_attr *attr = NULL;
for(attr = root->attr; attr; attr = attr->next) {
- if(strcasecmp(attr->name,"name") == 0) {
- name = apr_pstrdup(pool,attr->value);
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Profile [%s]",name);
+ if(strcasecmp(attr->name,"enable") == 0) {
+ break;
+ }
+ }
+
+ if(is_attr_enabled(attr) == FALSE) {
+ /* RTCP is disabled, skip the rest */
+ return TRUE;
+ }
+
+ rtcp_settings->rtcp = TRUE;
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading RTCP Settings");
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"rtcp-bye") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ rtcp_settings->rtcp_bye_policy = atoi(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"tx-interval") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ rtcp_settings->rtcp_tx_interval = (apr_uint16_t)atoi(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"rx-resolution") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ rtcp_settings->rtcp_rx_resolution = (apr_uint16_t)atol(cdata_text_get(elem));
+ }
}
else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr->name);
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
}
}
- if(!name) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Load Profile: no profile name specified");
- return FALSE;
- }
+ return TRUE;
+}
+
+/** Load RTP settings */
+static apt_bool_t unimrcp_server_rtp_settings_load(unimrcp_server_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ mpf_rtp_settings_t *rtp_settings = mpf_rtp_settings_alloc(loader->pool);
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading RTP Settings <%s>",id);
for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"param") == 0) {
- const apr_xml_attr *attr_name;
- const apr_xml_attr *attr_value;
- if(param_name_value_get(elem,&attr_name,&attr_value) == TRUE) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Loading Profile %s [%s]",attr_name->value,attr_value->value);
- if(strcasecmp(attr_name->value,"signaling-agent") == 0) {
- sig_agent = mrcp_server_signaling_agent_get(server,attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"connection-agent") == 0) {
- cnt_agent = mrcp_server_connection_agent_get(server,attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"media-engine") == 0) {
- media_engine = mrcp_server_media_engine_get(server,attr_value->value);
- }
- else if(strcasecmp(attr_name->value,"rtp-factory") == 0) {
- rtp_factory = mrcp_server_rtp_factory_get(server,attr_value->value);
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Attribute <%s>",attr_name->value);
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"jitter-buffer") == 0) {
+ unimrcp_server_jb_settings_load(loader,&rtp_settings->jb_config,elem);
+ }
+ else if(strcasecmp(elem->name,"ptime") == 0) {
+ if(is_cdata_valid(elem) == TRUE) {
+ rtp_settings->ptime = (apr_uint16_t)atol(cdata_text_get(elem));
+ }
+ }
+ else if(strcasecmp(elem->name,"codecs") == 0) {
+ const apr_xml_attr *attr;
+ const mpf_codec_manager_t *codec_manager = mrcp_server_codec_manager_get(loader->server);
+ if(is_cdata_valid(elem) == TRUE && codec_manager) {
+ mpf_codec_manager_codec_list_load(
+ codec_manager,
+ &rtp_settings->codec_list,
+ cdata_text_get(elem),
+ loader->pool);
+ }
+ for(attr = elem->attr; attr; attr = attr->next) {
+ if(strcasecmp(attr->name,"own-preference") == 0) {
+ rtp_settings->own_preferrence = is_attr_enabled(attr);
+ break;
}
}
}
- else if(strcasecmp(elem->name,"pluginmap") == 0) {
- plugin_map = apr_table_make(pool,2);
- plugin_map_load(plugin_map,elem,pool);
+ else if(strcasecmp(elem->name,"rtcp") == 0) {
+ unimrcp_server_rtcp_settings_load(loader,rtp_settings,elem);
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ return mrcp_server_rtp_settings_register(loader->server,rtp_settings,id);
+}
+
+/** Load map of resources and engines */
+static apr_table_t* resource_engine_map_load(const apr_xml_elem *root, apr_pool_t *pool)
+{
+ const apr_xml_attr *attr_name;
+ const apr_xml_attr *attr_value;
+ const apr_xml_elem *elem;
+ apr_table_t *plugin_map = apr_table_make(pool,2);
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Plugin Map");
+ for(elem = root->first_child; elem; elem = elem->next) {
+ if(strcasecmp(elem->name,"param") == 0) {
+ if(name_value_attribs_get(elem,&attr_name,&attr_value) == TRUE) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Param %s:%s",attr_name->value,attr_value->value);
+ apr_table_set(plugin_map,attr_name->value,attr_value->value);
+ }
+ }
+ }
+ return plugin_map;
+}
+
+/** Load MRCPv2 profile */
+static apt_bool_t unimrcp_server_mrcpv2_profile_load(unimrcp_server_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ mrcp_profile_t *profile;
+ mrcp_sig_agent_t *sip_agent = NULL;
+ mrcp_connection_agent_t *mrcpv2_agent = NULL;
+ mpf_engine_t *media_engine = NULL;
+ mpf_termination_factory_t *rtp_factory = NULL;
+ mpf_rtp_settings_t *rtp_settings = NULL;
+ apr_table_t *resource_engine_map = NULL;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading MRCPv2 Profile <%s>",id);
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+
+ if(is_cdata_valid(elem) == FALSE) {
+ continue;
+ }
+
+ if(strcasecmp(elem->name,"sip-uas") == 0) {
+ sip_agent = mrcp_server_signaling_agent_get(loader->server,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"mrcpv2-uas") == 0) {
+ mrcpv2_agent = mrcp_server_connection_agent_get(loader->server,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"media-engine") == 0) {
+ media_engine = mrcp_server_media_engine_get(loader->server,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"rtp-factory") == 0) {
+ rtp_factory = mrcp_server_rtp_factory_get(loader->server,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"rtp-settings") == 0) {
+ rtp_settings = mrcp_server_rtp_settings_get(loader->server,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"resource-engine-map") == 0) {
+ resource_engine_map = resource_engine_map_load(elem,loader->pool);
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
}
}
- apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create Profile [%s]",name);
- profile = mrcp_server_profile_create(NULL,sig_agent,cnt_agent,media_engine,rtp_factory,pool);
- return mrcp_server_profile_register(server,profile,plugin_map,name);
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create MRCPv2 Profile [%s]",id);
+ profile = mrcp_server_profile_create(
+ id,
+ NULL,
+ sip_agent,
+ mrcpv2_agent,
+ media_engine,
+ rtp_factory,
+ rtp_settings,
+ loader->pool);
+ return mrcp_server_profile_register(loader->server,profile,resource_engine_map);
+}
+
+/** Load MRCPv1 profile */
+static apt_bool_t unimrcp_server_mrcpv1_profile_load(unimrcp_server_loader_t *loader, const apr_xml_elem *root, const char *id)
+{
+ const apr_xml_elem *elem;
+ mrcp_profile_t *profile;
+ mrcp_sig_agent_t *rtsp_agent = NULL;
+ mpf_engine_t *media_engine = NULL;
+ mpf_termination_factory_t *rtp_factory = NULL;
+ mpf_rtp_settings_t *rtp_settings = NULL;
+ apr_table_t *resource_engine_map = NULL;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading MRCPv1 Profile <%s>",id);
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+
+ if(is_cdata_valid(elem) == FALSE) {
+ continue;
+ }
+
+ if(strcasecmp(elem->name,"rtsp-uas") == 0) {
+ rtsp_agent = mrcp_server_signaling_agent_get(loader->server,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"media-engine") == 0) {
+ media_engine = mrcp_server_media_engine_get(loader->server,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"rtp-factory") == 0) {
+ rtp_factory = mrcp_server_rtp_factory_get(loader->server,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"rtp-settings") == 0) {
+ rtp_settings = mrcp_server_rtp_settings_get(loader->server,cdata_text_get(elem));
+ }
+ else if(strcasecmp(elem->name,"resource-engine-map") == 0) {
+ resource_engine_map = resource_engine_map_load(elem,loader->pool);
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create MRCPv1 Profile [%s]",id);
+ profile = mrcp_server_profile_create(
+ id,
+ NULL,
+ rtsp_agent,
+ NULL,
+ media_engine,
+ rtp_factory,
+ rtp_settings,
+ loader->pool);
+ return mrcp_server_profile_register(loader->server,profile,resource_engine_map);
+}
+
+
+/** Load properties */
+static apt_bool_t unimrcp_server_properties_load(unimrcp_server_loader_t *loader, const apr_xml_elem *root)
+{
+ const apr_xml_elem *elem;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Properties");
+ for(elem = root->first_child; elem; elem = elem->next) {
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Element <%s>",elem->name);
+ if(strcasecmp(elem->name,"ip") == 0) {
+ loader->ip = unimrcp_server_ip_address_get(loader,elem);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Set Property ip:%s",loader->ip);
+ }
+ else if(strcasecmp(elem->name,"ext-ip") == 0) {
+ loader->ext_ip = unimrcp_server_ip_address_get(loader,elem);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Set Property ext-ip:%s",loader->ext_ip);
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+ return TRUE;
+}
+
+/** Load components */
+static apt_bool_t unimrcp_server_components_load(unimrcp_server_loader_t *loader, const apr_xml_elem *root)
+{
+ const apr_xml_elem *elem;
+ const apr_xml_attr *id_attr;
+ const apr_xml_attr *enable_attr;
+ const char *id;
+
+ /* Create codec manager first (probably it should be loaded from config either) */
+ mpf_codec_manager_t *codec_manager = mpf_engine_codec_manager_create(loader->pool);
+ if(codec_manager) {
+ mrcp_server_codec_manager_register(loader->server,codec_manager);
+ }
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Components");
+ for(elem = root->first_child; elem; elem = elem->next) {
+ if(strcasecmp(elem->name,"resource-factory") == 0) {
+ unimrcp_server_resource_factory_load(loader,elem);
+ continue;
+ }
+ if(strcasecmp(elem->name,"plugin-factory") == 0) {
+ unimrcp_server_plugin_factory_load(loader,elem);
+ continue;
+ }
+
+ /* get common "id" and "enable" attributes */
+ if(header_attribs_get(elem,&id_attr,&enable_attr) == FALSE) {
+ /* invalid id */
+ continue;
+ }
+ if(is_attr_enabled(enable_attr) == FALSE) {
+ /* disabled element, just skip it */
+ continue;
+ }
+ id = apr_pstrdup(loader->pool,id_attr->value);
+
+ if(strcasecmp(elem->name,"sip-uas") == 0) {
+ unimrcp_server_sip_uas_load(loader,elem,id);
+ }
+ else if(strcasecmp(elem->name,"rtsp-uas") == 0) {
+ unimrcp_server_rtsp_uas_load(loader,elem,id);
+ }
+ else if(strcasecmp(elem->name,"mrcpv2-uas") == 0) {
+ unimrcp_server_mrcpv2_uas_load(loader,elem,id);
+ }
+ else if(strcasecmp(elem->name,"media-engine") == 0) {
+ unimrcp_server_media_engine_load(loader,elem,id);
+ }
+ else if(strcasecmp(elem->name,"rtp-factory") == 0) {
+ unimrcp_server_rtp_factory_load(loader,elem,id);
+ }
+ else if(strcasecmp(elem->name,"plugin-factory") == 0) {
+ unimrcp_server_plugin_factory_load(loader,elem);
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+ return TRUE;
+}
+
+/** Load settings */
+static apt_bool_t unimrcp_server_settings_load(unimrcp_server_loader_t *loader, const apr_xml_elem *root)
+{
+ const apr_xml_elem *elem;
+ const apr_xml_attr *id_attr;
+ const apr_xml_attr *enable_attr;
+ const char *id;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Settings");
+ for(elem = root->first_child; elem; elem = elem->next) {
+ /* get common "id" and "enable" attributes */
+ if(header_attribs_get(elem,&id_attr,&enable_attr) == FALSE) {
+ /* invalid id */
+ continue;
+ }
+ if(is_attr_enabled(enable_attr) == FALSE) {
+ /* disabled element, just skip it */
+ continue;
+ }
+ id = apr_pstrdup(loader->pool,id_attr->value);
+
+ if(strcasecmp(elem->name,"rtp-settings") == 0) {
+ unimrcp_server_rtp_settings_load(loader,elem,id);
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
+ return TRUE;
}
/** Load profiles */
-static apt_bool_t unimrcp_server_profiles_load(mrcp_server_t *server, const apr_xml_elem *root, apr_pool_t *pool)
+static apt_bool_t unimrcp_server_profiles_load(unimrcp_server_loader_t *loader, const apr_xml_elem *root)
{
const apr_xml_elem *elem;
+ const apr_xml_attr *id_attr;
+ const apr_xml_attr *enable_attr;
+ const char *id;
+
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Loading Profiles");
for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"profile") == 0) {
- unimrcp_server_profile_load(server,elem,pool);
+ /* get common "id" and "enable" attributes */
+ if(header_attribs_get(elem,&id_attr,&enable_attr) == FALSE) {
+ /* invalid id */
+ continue;
}
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ if(is_attr_enabled(enable_attr) == FALSE) {
+ /* disabled element, just skip it */
+ continue;
}
- }
- return TRUE;
-}
+ id = apr_pstrdup(loader->pool,id_attr->value);
-/** Load configuration (settings and profiles) */
-static apt_bool_t unimrcp_server_config_load(mrcp_server_t *server, const char *plugin_dir_path, const apr_xml_doc *doc, apr_pool_t *pool)
-{
- const apr_xml_elem *elem;
- const apr_xml_elem *root = doc->root;
- if(!root || strcasecmp(root->name,"unimrcpserver") != 0) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Document");
- return FALSE;
- }
- for(elem = root->first_child; elem; elem = elem->next) {
- if(strcasecmp(elem->name,"resources") == 0) {
- unimrcp_server_resources_load(server,elem,pool);
+ if(strcasecmp(elem->name,"mrcpv2-profile") == 0) {
+ unimrcp_server_mrcpv2_profile_load(loader,elem,id);
}
- else if(strcasecmp(elem->name,"settings") == 0) {
- unimrcp_server_settings_load(server,plugin_dir_path,elem,pool);
- }
- else if(strcasecmp(elem->name,"profiles") == 0) {
- unimrcp_server_profiles_load(server,elem,pool);
+ else if(strcasecmp(elem->name,"mrcpv1-profile") == 0) {
+ unimrcp_server_mrcpv1_profile_load(loader,elem,id);
}
else {
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
}
- }
-
+ }
+ return TRUE;
+}
+
+/** Parse XML document */
+static apr_xml_doc* unimrcp_server_doc_parse(const char *file_path, apr_pool_t *pool)
+{
+ apr_xml_parser *parser = NULL;
+ apr_xml_doc *xml_doc = NULL;
+ apr_file_t *fd = NULL;
+ apr_status_t rv;
+
+ apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Open Config File [%s]",file_path);
+ rv = apr_file_open(&fd,file_path,APR_READ|APR_BINARY,0,pool);
+ if(rv != APR_SUCCESS) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open Config File [%s]",file_path);
+ return NULL;
+ }
+
+ rv = apr_xml_parse_file(pool,&parser,&xml_doc,fd,XML_FILE_BUFFER_LENGTH);
+ if(rv != APR_SUCCESS) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Parse Config File [%s]",file_path);
+ xml_doc = NULL;
+ }
+
+ apr_file_close(fd);
+ return xml_doc;
+}
+
+static apt_bool_t unimrcp_server_load(mrcp_server_t *mrcp_server, apt_dir_layout_t *dir_layout, apr_pool_t *pool)
+{
+ const char *file_path;
+ apr_xml_doc *doc;
+ const apr_xml_elem *elem;
+ const apr_xml_elem *root;
+ const apr_xml_attr *attr;
+ unimrcp_server_loader_t *loader;
+ const char *version = NULL;
+
+ file_path = apt_confdir_filepath_get(dir_layout,CONF_FILE_NAME,pool);
+ if(!file_path) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Get Path to Conf File [%s]",CONF_FILE_NAME);
+ return FALSE;
+ }
+
+ /* Parse XML document */
+ doc = unimrcp_server_doc_parse(file_path,pool);
+ if(!doc) {
+ return FALSE;
+ }
+
+ root = doc->root;
+
+ /* Match document name */
+ if(!root || strcasecmp(root->name,"unimrcpserver") != 0) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Document <%s>",root->name);
+ return FALSE;
+ }
+
+ /* Read attributes */
+ for(attr = root->attr; attr; attr = attr->next) {
+ if(strcasecmp(attr->name,"version") == 0) {
+ version = attr->value;
+ }
+ }
+
+ /* Check version number first */
+ if(!version) {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Version");
+ return FALSE;
+ }
+
+ loader = apr_palloc(pool,sizeof(unimrcp_server_loader_t));
+ loader->doc = doc;
+ loader->server = mrcp_server;
+ loader->dir_layout = dir_layout;
+ loader->pool = pool;
+ loader->ip = DEFAULT_IP_ADDRESS;
+ loader->ext_ip = NULL;
+ loader->auto_ip = NULL;
+
+ /* Navigate through document */
+ for(elem = root->first_child; elem; elem = elem->next) {
+ if(strcasecmp(elem->name,"properties") == 0) {
+ unimrcp_server_properties_load(loader,elem);
+ }
+ else if(strcasecmp(elem->name,"components") == 0) {
+ unimrcp_server_components_load(loader,elem);
+ }
+ else if(strcasecmp(elem->name,"settings") == 0) {
+ unimrcp_server_settings_load(loader,elem);
+ }
+ else if(strcasecmp(elem->name,"profiles") == 0) {
+ unimrcp_server_profiles_load(loader,elem);
+ }
+ else {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Unknown Element <%s>",elem->name);
+ }
+ }
return TRUE;
}
diff --git a/libs/unimrcp/platforms/umc/Makefile.am b/libs/unimrcp/platforms/umc/Makefile.am
index 9e450119c8..a33ddfdd0f 100644
--- a/libs/unimrcp/platforms/umc/Makefile.am
+++ b/libs/unimrcp/platforms/umc/Makefile.am
@@ -28,7 +28,10 @@ umc_SOURCES = src/main.cpp \
src/dtmfscenario.cpp \
src/dtmfsession.cpp \
src/setparamscenario.cpp \
- src/setparamsession.cpp
+ src/setparamsession.cpp \
+ src/verifierscenario.cpp \
+ src/verifiersession.cpp
+
umc_LDADD = $(top_builddir)/platforms/libunimrcp-client/libunimrcpclient.la
if ISMAC
diff --git a/libs/unimrcp/platforms/umc/include/dtmfscenario.h b/libs/unimrcp/platforms/umc/include/dtmfscenario.h
index 63aab623c4..45a5430cf7 100644
--- a/libs/unimrcp/platforms/umc/include/dtmfscenario.h
+++ b/libs/unimrcp/platforms/umc/include/dtmfscenario.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: dtmfscenario.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __DTMF_SCENARIO_H__
-#define __DTMF_SCENARIO_H__
+#ifndef DTMF_SCENARIO_H
+#define DTMF_SCENARIO_H
/**
* @file dtmfscenario.h
@@ -72,4 +74,4 @@ inline const char* DtmfScenario::GetDigits() const
}
-#endif /*__DTMF_SCENARIO_H__*/
+#endif /* DTMF_SCENARIO_H */
diff --git a/libs/unimrcp/platforms/umc/include/dtmfsession.h b/libs/unimrcp/platforms/umc/include/dtmfsession.h
index 2bf21bc50c..e0a3f7ccd0 100644
--- a/libs/unimrcp/platforms/umc/include/dtmfsession.h
+++ b/libs/unimrcp/platforms/umc/include/dtmfsession.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: dtmfsession.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __DTMF_SESSION_H__
-#define __DTMF_SESSION_H__
+#ifndef DTMF_SESSION_H
+#define DTMF_SESSION_H
/**
* @file dtmfsession.h
@@ -65,4 +67,4 @@ inline const DtmfScenario* DtmfSession::GetScenario() const
return (DtmfScenario*)m_pScenario;
}
-#endif /*__DTMF_SESSION_H__*/
+#endif /* DTMF_SESSION_H */
diff --git a/libs/unimrcp/platforms/umc/include/recogscenario.h b/libs/unimrcp/platforms/umc/include/recogscenario.h
index 1be4d739a9..fc20c10757 100644
--- a/libs/unimrcp/platforms/umc/include/recogscenario.h
+++ b/libs/unimrcp/platforms/umc/include/recogscenario.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: recogscenario.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __RECOG_SCENARIO_H__
-#define __RECOG_SCENARIO_H__
+#ifndef RECOG_SCENARIO_H
+#define RECOG_SCENARIO_H
/**
* @file recogscenario.h
@@ -85,4 +87,4 @@ inline bool RecogScenario::IsRecognizeEnabled() const
return m_Recognize;
}
-#endif /*__RECOG_SCENARIO_H__*/
+#endif /* RECOG_SCENARIO_H */
diff --git a/libs/unimrcp/platforms/umc/include/recogsession.h b/libs/unimrcp/platforms/umc/include/recogsession.h
index bca9f553e9..5cc44404e0 100644
--- a/libs/unimrcp/platforms/umc/include/recogsession.h
+++ b/libs/unimrcp/platforms/umc/include/recogsession.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: recogsession.h 1587 2010-03-12 19:40:02Z achaloyan $
*/
-#ifndef __RECOG_SESSION_H__
-#define __RECOG_SESSION_H__
+#ifndef RECOG_SESSION_H
+#define RECOG_SESSION_H
/**
* @file recogsession.h
@@ -37,6 +39,7 @@ public:
protected:
/* ============================ MANIPULATORS =============================== */
virtual bool Start();
+ virtual bool Stop();
RecogChannel* CreateRecogChannel();
bool StartRecognition(mrcp_channel_t* pMrcpChannel);
@@ -69,4 +72,4 @@ inline const RecogScenario* RecogSession::GetScenario() const
return (RecogScenario*)m_pScenario;
}
-#endif /*__RECOG_SESSION_H__*/
+#endif /* RECOG_SESSION_H */
diff --git a/libs/unimrcp/platforms/umc/include/recorderscenario.h b/libs/unimrcp/platforms/umc/include/recorderscenario.h
index 9648fd3f2b..cc27b0a1e7 100644
--- a/libs/unimrcp/platforms/umc/include/recorderscenario.h
+++ b/libs/unimrcp/platforms/umc/include/recorderscenario.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: recorderscenario.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __RECORDER_SCENARIO_H__
-#define __RECORDER_SCENARIO_H__
+#ifndef RECORDER_SCENARIO_H
+#define RECORDER_SCENARIO_H
/**
* @file recorderscenario.h
@@ -63,4 +65,4 @@ inline bool RecorderScenario::IsRecordEnabled() const
return m_Record;
}
-#endif /*__RECORDER_SCENARIO_H__*/
+#endif /* RECORDER_SCENARIO_H */
diff --git a/libs/unimrcp/platforms/umc/include/recordersession.h b/libs/unimrcp/platforms/umc/include/recordersession.h
index d2497cd3e1..4f4200ef1c 100644
--- a/libs/unimrcp/platforms/umc/include/recordersession.h
+++ b/libs/unimrcp/platforms/umc/include/recordersession.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: recordersession.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __RECORDER_SESSION_H__
-#define __RECORDER_SESSION_H__
+#ifndef RECORDER_SESSION_H
+#define RECORDER_SESSION_H
/**
* @file recordersession.h
@@ -65,4 +67,4 @@ inline const RecorderScenario* RecorderSession::GetScenario() const
return (RecorderScenario*)m_pScenario;
}
-#endif /*__RECORDER_SESSION_H__*/
+#endif /* RECORDER_SESSION_H */
diff --git a/libs/unimrcp/platforms/umc/include/setparamscenario.h b/libs/unimrcp/platforms/umc/include/setparamscenario.h
index 3cbdf6a43f..75df62c6b2 100644
--- a/libs/unimrcp/platforms/umc/include/setparamscenario.h
+++ b/libs/unimrcp/platforms/umc/include/setparamscenario.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: setparamscenario.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __SETPARAM_SCENARIO_H__
-#define __SETPARAM_SCENARIO_H__
+#ifndef SETPARAM_SCENARIO_H
+#define SETPARAM_SCENARIO_H
/**
* @file setaparamscenario.h
@@ -44,4 +46,4 @@ protected:
/* ============================ INLINE METHODS ============================= */
-#endif /*__SETPARAM_SCENARIO_H__*/
+#endif /* SETPARAM_SCENARIO_H */
diff --git a/libs/unimrcp/platforms/umc/include/setparamsession.h b/libs/unimrcp/platforms/umc/include/setparamsession.h
index e7fb24bb33..916a86ee40 100644
--- a/libs/unimrcp/platforms/umc/include/setparamsession.h
+++ b/libs/unimrcp/platforms/umc/include/setparamsession.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: setparamsession.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __SETPARAM_SESSION_H__
-#define __SETPARAM_SESSION_H__
+#ifndef SETPARAM_SESSION_H
+#define SETPARAM_SESSION_H
/**
* @file setparamsession.h
@@ -73,4 +75,4 @@ inline const SetParamScenario* SetParamSession::GetScenario() const
return (SetParamScenario*)m_pScenario;
}
-#endif /*__SETPARAM_SESSION_H__*/
+#endif /* SETPARAM_SESSION_H */
diff --git a/libs/unimrcp/platforms/umc/include/synthscenario.h b/libs/unimrcp/platforms/umc/include/synthscenario.h
index fd5aa9557e..921a857905 100644
--- a/libs/unimrcp/platforms/umc/include/synthscenario.h
+++ b/libs/unimrcp/platforms/umc/include/synthscenario.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: synthscenario.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __SYNTH_SCENARIO_H__
-#define __SYNTH_SCENARIO_H__
+#ifndef SYNTH_SCENARIO_H
+#define SYNTH_SCENARIO_H
/**
* @file synthscenario.h
@@ -71,4 +73,4 @@ inline bool SynthScenario::IsSpeakEnabled() const
return m_Speak;
}
-#endif /*__SYNTH_SCENARIO_H__*/
+#endif /* SYNTH_SCENARIO_H */
diff --git a/libs/unimrcp/platforms/umc/include/synthsession.h b/libs/unimrcp/platforms/umc/include/synthsession.h
index 59f88711c6..94a592c86d 100644
--- a/libs/unimrcp/platforms/umc/include/synthsession.h
+++ b/libs/unimrcp/platforms/umc/include/synthsession.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: synthsession.h 1586 2010-03-12 19:39:02Z achaloyan $
*/
-#ifndef __SYNTH_SESSION_H__
-#define __SYNTH_SESSION_H__
+#ifndef SYNTH_SESSION_H
+#define SYNTH_SESSION_H
/**
* @file synthsession.h
@@ -37,6 +39,7 @@ public:
protected:
/* ============================ MANIPULATORS =============================== */
virtual bool Start();
+ virtual bool Stop();
SynthChannel* CreateSynthChannel();
@@ -50,7 +53,7 @@ protected:
/* ============================ ACCESSORS ================================== */
const SynthScenario* GetScenario() const;
-
+
private:
/* ============================ DATA ======================================= */
SynthChannel* m_pSynthChannel;
@@ -63,4 +66,4 @@ inline const SynthScenario* SynthSession::GetScenario() const
return (SynthScenario*)m_pScenario;
}
-#endif /*__SYNTH_SESSION_H__*/
+#endif /* SYNTH_SESSION_H */
diff --git a/libs/unimrcp/platforms/umc/include/umcconsole.h b/libs/unimrcp/platforms/umc/include/umcconsole.h
index c8bd7c6d64..23bf6b1882 100644
--- a/libs/unimrcp/platforms/umc/include/umcconsole.h
+++ b/libs/unimrcp/platforms/umc/include/umcconsole.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: umcconsole.h 1525 2010-02-16 14:58:56Z achaloyan $
*/
-#ifndef __UMC_CONSOLE_H__
-#define __UMC_CONSOLE_H__
+#ifndef UMC_CONSOLE_H
+#define UMC_CONSOLE_H
/**
* @file umcconsole.h
@@ -47,12 +49,12 @@ private:
struct UmcOptions
{
const char* m_RootDirPath;
- apt_log_priority_e m_LogPriority;
- apt_log_output_e m_LogOutput;
+ const char* m_LogPriority;
+ const char* m_LogOutput;
};
UmcOptions m_Options;
UmcFramework* m_pFramework;
};
-#endif /*__UMC_CONSOLE_H__*/
+#endif /* UMC_CONSOLE_H */
diff --git a/libs/unimrcp/platforms/umc/include/umcframework.h b/libs/unimrcp/platforms/umc/include/umcframework.h
index 34b3dcc933..ef803cb184 100644
--- a/libs/unimrcp/platforms/umc/include/umcframework.h
+++ b/libs/unimrcp/platforms/umc/include/umcframework.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: umcframework.h 1585 2010-03-12 19:12:05Z achaloyan $
*/
-#ifndef __UMC_FRAMEWORK_H__
-#define __UMC_FRAMEWORK_H__
+#ifndef UMC_FRAMEWORK_H
+#define UMC_FRAMEWORK_H
/**
* @file umcframework.h
@@ -42,6 +44,7 @@ public:
void Destroy();
void RunSession(const char* pScenarioName, const char* pProfileName);
+ void StopSession(const char* id);
void KillSession(const char* id);
void ShowScenarios();
@@ -61,6 +64,7 @@ protected:
void DestroyScenarios();
bool ProcessRunRequest(const char* pScenarioName, const char* pProfileName);
+ void ProcessStopRequest(const char* id);
void ProcessKillRequest(const char* id);
void ProcessShowScenarios();
void ProcessShowSessions();
@@ -89,4 +93,4 @@ private:
apr_hash_t* m_pSessionTable;
};
-#endif /*__UMC_FRAMEWORK_H__*/
+#endif /* UMC_FRAMEWORK_H */
diff --git a/libs/unimrcp/platforms/umc/include/umcscenario.h b/libs/unimrcp/platforms/umc/include/umcscenario.h
index 712eb666cc..2425fc968e 100644
--- a/libs/unimrcp/platforms/umc/include/umcscenario.h
+++ b/libs/unimrcp/platforms/umc/include/umcscenario.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: umcscenario.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __UMC_SCENARIO_H__
-#define __UMC_SCENARIO_H__
+#ifndef UMC_SCENARIO_H
+#define UMC_SCENARIO_H
/**
* @file umcscenario.h
@@ -117,4 +119,4 @@ inline bool UmcScenario::IsDiscoveryEnabled() const
}
-#endif /*__UMC_SCENARIO_H__*/
+#endif /* UMC_SCENARIO_H */
diff --git a/libs/unimrcp/platforms/umc/include/umcsession.h b/libs/unimrcp/platforms/umc/include/umcsession.h
index 2c2f729aec..308e1704ff 100644
--- a/libs/unimrcp/platforms/umc/include/umcsession.h
+++ b/libs/unimrcp/platforms/umc/include/umcsession.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: umcsession.h 1585 2010-03-12 19:12:05Z achaloyan $
*/
-#ifndef __UMC_SESSION_H__
-#define __UMC_SESSION_H__
+#ifndef UMC_SESSION_H
+#define UMC_SESSION_H
/**
* @file umcsession.h
@@ -35,6 +37,7 @@ public:
/* ============================ MANIPULATORS =============================== */
virtual bool Run();
+ virtual bool Stop();
virtual bool Terminate();
void SetMrcpProfile(const char* pMrcpProfile);
@@ -82,6 +85,7 @@ protected:
/* ============================ ACCESSORS ================================== */
apr_pool_t* GetSessionPool() const;
const char* GetMrcpSessionId() const;
+ mrcp_message_t* GetMrcpMessage() const;
/* ============================ DATA ======================================= */
const UmcScenario* m_pScenario;
@@ -92,6 +96,7 @@ private:
/* ============================ DATA ======================================= */
mrcp_application_t* m_pMrcpApplication;
mrcp_session_t* m_pMrcpSession;
+ mrcp_message_t* m_pMrcpMessage; /* last message sent */
bool m_Running;
bool m_Terminating;
};
@@ -118,4 +123,9 @@ inline void UmcSession::SetMrcpProfile(const char* pMrcpProfile)
m_pMrcpProfile = pMrcpProfile;
}
-#endif /*__UMC_SESSION_H__*/
+inline mrcp_message_t* UmcSession::GetMrcpMessage() const
+{
+ return m_pMrcpMessage;
+}
+
+#endif /* UMC_SESSION_H */
diff --git a/libs/unimrcp/platforms/umc/include/verifierscenario.h b/libs/unimrcp/platforms/umc/include/verifierscenario.h
new file mode 100644
index 0000000000..52856b077a
--- /dev/null
+++ b/libs/unimrcp/platforms/umc/include/verifierscenario.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: verifierscenario.h 1775 2010-08-26 18:23:38Z achaloyan $
+ */
+
+#ifndef VERIFIER_SCENARIO_H
+#define VERIFIER_SCENARIO_H
+
+/**
+ * @file verifierscenario.h
+ * @brief Verifier Scenario
+ */
+
+#include "umcscenario.h"
+
+class VerifierScenario : public UmcScenario
+{
+public:
+/* ============================ CREATORS =================================== */
+ VerifierScenario();
+ virtual ~VerifierScenario();
+
+/* ============================ MANIPULATORS =============================== */
+ virtual void Destroy();
+
+ virtual UmcSession* CreateSession();
+
+/* ============================ ACCESSORS ================================== */
+ const char* GetRepositoryURI() const;
+ const char* GetVerificationMode() const;
+ const char* GetVoiceprintIdentifier() const;
+
+/* ============================ INQUIRIES ================================== */
+protected:
+/* ============================ MANIPULATORS =============================== */
+ virtual bool LoadElement(const apr_xml_elem* pElem, apr_pool_t* pool);
+
+ bool LoadVerify(const apr_xml_elem* pElem, apr_pool_t* pool);
+
+/* ============================ DATA ======================================= */
+ const char* m_RepositoryURI;
+ const char* m_VerificationMode;
+ const char* m_VoiceprintIdentifier;
+};
+
+/* ============================ INLINE METHODS ============================= */
+inline const char* VerifierScenario::GetRepositoryURI() const
+{
+ return m_RepositoryURI;
+}
+
+inline const char* VerifierScenario::GetVerificationMode() const
+{
+ return m_VerificationMode;
+}
+
+inline const char* VerifierScenario::GetVoiceprintIdentifier() const
+{
+ return m_VoiceprintIdentifier;
+}
+
+#endif /* VERIFIER_SCENARIO_H */
diff --git a/libs/unimrcp/platforms/umc/include/verifiersession.h b/libs/unimrcp/platforms/umc/include/verifiersession.h
new file mode 100644
index 0000000000..856a889f91
--- /dev/null
+++ b/libs/unimrcp/platforms/umc/include/verifiersession.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: verifiersession.h 1776 2010-08-27 16:36:38Z achaloyan $
+ */
+
+#ifndef VERIFIER_SESSION_H
+#define VERIFIER_SESSION_H
+
+/**
+ * @file verifiersession.h
+ * @brief Verifier Session
+ */
+
+#include "umcsession.h"
+
+class VerifierScenario;
+struct VerifierChannel;
+
+class VerifierSession : public UmcSession
+{
+public:
+/* ============================ CREATORS =================================== */
+ VerifierSession(const VerifierScenario* pScenario);
+ virtual ~VerifierSession();
+
+protected:
+/* ============================ MANIPULATORS =============================== */
+ virtual bool Start();
+ virtual bool Stop();
+
+ VerifierChannel* CreateVerifierChannel();
+ bool StartVerification(mrcp_channel_t* pMrcpChannel);
+
+ mrcp_message_t* CreateStartSessionRequest(mrcp_channel_t* pMrcpChannel);
+ mrcp_message_t* CreateEndSessionRequest(mrcp_channel_t* pMrcpChannel);
+ mrcp_message_t* CreateVerificationRequest(mrcp_channel_t* pMrcpChannel);
+
+ FILE* GetAudioIn(const mpf_codec_descriptor_t* pDescriptor, apr_pool_t* pool) const;
+
+/* ============================ HANDLERS =================================== */
+ virtual bool OnSessionTerminate(mrcp_sig_status_code_e status);
+ virtual bool OnChannelAdd(mrcp_channel_t* channel, mrcp_sig_status_code_e status);
+ virtual bool OnMessageReceive(mrcp_channel_t* channel, mrcp_message_t* message);
+
+/* ============================ ACCESSORS ================================== */
+ const VerifierScenario* GetScenario() const;
+
+private:
+/* ============================ DATA ======================================= */
+ VerifierChannel* m_pVerifierChannel;
+ const char* m_ContentId;
+};
+
+
+/* ============================ INLINE METHODS ============================= */
+inline const VerifierScenario* VerifierSession::GetScenario() const
+{
+ return (VerifierScenario*)m_pScenario;
+}
+
+#endif /* VERIFIER_SESSION_H */
diff --git a/libs/unimrcp/platforms/umc/src/dtmfscenario.cpp b/libs/unimrcp/platforms/umc/src/dtmfscenario.cpp
index ca644b382c..d61b528071 100644
--- a/libs/unimrcp/platforms/umc/src/dtmfscenario.cpp
+++ b/libs/unimrcp/platforms/umc/src/dtmfscenario.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: dtmfscenario.cpp 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include
diff --git a/libs/unimrcp/platforms/umc/src/dtmfsession.cpp b/libs/unimrcp/platforms/umc/src/dtmfsession.cpp
index 83a2ee5ec2..8ce8f9767f 100644
--- a/libs/unimrcp/platforms/umc/src/dtmfsession.cpp
+++ b/libs/unimrcp/platforms/umc/src/dtmfsession.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: dtmfsession.cpp 1780 2010-09-01 05:59:32Z achaloyan $
*/
#include "dtmfsession.h"
@@ -30,8 +32,6 @@ struct RecogChannel
mrcp_channel_t* m_pMrcpChannel;
/** DTMF generator */
mpf_dtmf_generator_t* m_pDtmfGenerator;
- /** Audio stream */
- mpf_audio_stream_t* m_pStream;
/** Streaming is in-progress */
bool m_Streaming;
};
@@ -79,13 +79,6 @@ bool DtmfSession::OnSessionTerminate(mrcp_sig_status_code_e status)
return UmcSession::OnSessionTerminate(status);
}
-static apt_bool_t OpenStream(mpf_audio_stream_t* pStream, mpf_codec_t *codec)
-{
- RecogChannel* pRecogChannel = (RecogChannel*) pStream->obj;
- pRecogChannel->m_pStream = pStream;
- return TRUE;
-}
-
static apt_bool_t ReadStream(mpf_audio_stream_t* pStream, mpf_frame_t* pFrame)
{
RecogChannel* pRecogChannel = (RecogChannel*) pStream->obj;
@@ -110,7 +103,6 @@ RecogChannel* DtmfSession::CreateRecogChannel()
RecogChannel *pRecogChannel = new RecogChannel;
pRecogChannel->m_pMrcpChannel = NULL;
pRecogChannel->m_pDtmfGenerator = NULL;
- pRecogChannel->m_pStream = NULL;
pRecogChannel->m_Streaming = false;
/* create source stream capabilities */
@@ -120,7 +112,7 @@ RecogChannel* DtmfSession::CreateRecogChannel()
static const mpf_audio_stream_vtable_t audio_stream_vtable =
{
NULL,
- OpenStream,
+ NULL,
NULL,
ReadStream,
NULL,
@@ -162,7 +154,11 @@ bool DtmfSession::OnChannelAdd(mrcp_channel_t* pMrcpChannel, mrcp_sig_status_cod
RecogChannel* pRecogChannel = (RecogChannel*) mrcp_application_channel_object_get(pMrcpChannel);
if(pRecogChannel)
{
- pRecogChannel->m_pDtmfGenerator = mpf_dtmf_generator_create(pRecogChannel->m_pStream,GetSessionPool());
+ const mpf_audio_stream_t* pStream = mrcp_application_audio_stream_get(pMrcpChannel);
+ if(pStream)
+ {
+ pRecogChannel->m_pDtmfGenerator = mpf_dtmf_generator_create(pStream,GetSessionPool());
+ }
}
return StartRecognition(pMrcpChannel);
diff --git a/libs/unimrcp/platforms/umc/src/main.cpp b/libs/unimrcp/platforms/umc/src/main.cpp
index 089dee3cd5..08983a20ae 100644
--- a/libs/unimrcp/platforms/umc/src/main.cpp
+++ b/libs/unimrcp/platforms/umc/src/main.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: main.cpp 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "umcconsole.h"
diff --git a/libs/unimrcp/platforms/umc/src/recogscenario.cpp b/libs/unimrcp/platforms/umc/src/recogscenario.cpp
index c7cfbcbc26..eb13a9a81d 100644
--- a/libs/unimrcp/platforms/umc/src/recogscenario.cpp
+++ b/libs/unimrcp/platforms/umc/src/recogscenario.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: recogscenario.cpp 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include
diff --git a/libs/unimrcp/platforms/umc/src/recogsession.cpp b/libs/unimrcp/platforms/umc/src/recogsession.cpp
index 6fd6adbe1d..c9a418d923 100644
--- a/libs/unimrcp/platforms/umc/src/recogsession.cpp
+++ b/libs/unimrcp/platforms/umc/src/recogsession.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: recogsession.cpp 1587 2010-03-12 19:40:02Z achaloyan $
*/
#include "recogsession.h"
@@ -27,12 +29,21 @@ struct RecogChannel
{
/** MRCP control channel */
mrcp_channel_t* m_pMrcpChannel;
+ /** IN-PROGRESS RECOGNIZE request */
+ mrcp_message_t* m_pRecogRequest;
/** Streaming is in-progress */
bool m_Streaming;
/** File to read audio stream from */
FILE* m_pAudioIn;
/** Estimated time to complete (used if no audio_in available) */
apr_size_t m_TimeToComplete;
+
+ RecogChannel() :
+ m_pMrcpChannel(NULL),
+ m_pRecogRequest(NULL),
+ m_Streaming(false),
+ m_pAudioIn(NULL),
+ m_TimeToComplete(0) {}
};
RecogSession::RecogSession(const RecogScenario* pScenario) :
@@ -67,6 +78,37 @@ bool RecogSession::Start()
return true;
}
+bool RecogSession::Stop()
+{
+ if(!UmcSession::Stop())
+ return false;
+
+ if(!m_pRecogChannel)
+ return false;
+
+ mrcp_message_t* pStopMessage = CreateMrcpMessage(m_pRecogChannel->m_pMrcpChannel,RECOGNIZER_STOP);
+ if(!pStopMessage)
+ return false;
+
+ if(m_pRecogChannel->m_pRecogRequest)
+ {
+ mrcp_generic_header_t* pGenericHeader;
+ /* get/allocate generic header */
+ pGenericHeader = (mrcp_generic_header_t*) mrcp_generic_header_prepare(pStopMessage);
+ if(pGenericHeader)
+ {
+ pGenericHeader->active_request_id_list.count = 1;
+ pGenericHeader->active_request_id_list.ids[0] =
+ m_pRecogChannel->m_pRecogRequest->start_line.request_id;
+ mrcp_generic_header_property_add(pStopMessage,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
+ }
+
+ m_pRecogChannel->m_pRecogRequest = NULL;
+ }
+
+ return SendMrcpRequest(m_pRecogChannel->m_pMrcpChannel,pStopMessage);
+}
+
bool RecogSession::OnSessionTerminate(mrcp_sig_status_code_e status)
{
if(m_pRecogChannel)
@@ -128,11 +170,7 @@ RecogChannel* RecogSession::CreateRecogChannel()
apr_pool_t* pool = GetSessionPool();
/* create channel */
- RecogChannel *pRecogChannel = new RecogChannel;
- pRecogChannel->m_pMrcpChannel = NULL;
- pRecogChannel->m_Streaming = false;
- pRecogChannel->m_pAudioIn = NULL;
- pRecogChannel->m_TimeToComplete = 0;
+ RecogChannel* pRecogChannel = new RecogChannel;
/* create source stream capabilities */
pCapabilities = mpf_source_stream_capabilities_create(pool);
@@ -218,11 +256,13 @@ bool RecogSession::OnMessageReceive(mrcp_channel_t* pMrcpChannel, mrcp_message_t
/* received the response to RECOGNIZE request */
if(pMrcpMessage->start_line.request_state == MRCP_REQUEST_STATE_INPROGRESS)
{
+ RecogChannel* pRecogChannel = (RecogChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+ if(pRecogChannel)
+ pRecogChannel->m_pRecogRequest = GetMrcpMessage();
+
/* start to stream the speech to recognize */
if(pRecogChannel)
- {
pRecogChannel->m_Streaming = true;
- }
}
else
{
@@ -241,9 +281,12 @@ bool RecogSession::OnMessageReceive(mrcp_channel_t* pMrcpChannel, mrcp_message_t
{
ParseNLSMLResult(pMrcpMessage);
if(pRecogChannel)
- {
pRecogChannel->m_Streaming = false;
- }
+
+ RecogChannel* pRecogChannel = (RecogChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+ if(pRecogChannel)
+ pRecogChannel->m_pRecogRequest = NULL;
+
Terminate();
}
else if(pMrcpMessage->start_line.method_id == RECOGNIZER_START_OF_INPUT)
diff --git a/libs/unimrcp/platforms/umc/src/recorderscenario.cpp b/libs/unimrcp/platforms/umc/src/recorderscenario.cpp
index 398fc57c56..dd0ee2b1a9 100644
--- a/libs/unimrcp/platforms/umc/src/recorderscenario.cpp
+++ b/libs/unimrcp/platforms/umc/src/recorderscenario.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: recorderscenario.cpp 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include
diff --git a/libs/unimrcp/platforms/umc/src/recordersession.cpp b/libs/unimrcp/platforms/umc/src/recordersession.cpp
index 28a7138e80..e10369eeb5 100644
--- a/libs/unimrcp/platforms/umc/src/recordersession.cpp
+++ b/libs/unimrcp/platforms/umc/src/recordersession.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: recordersession.cpp 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "recordersession.h"
diff --git a/libs/unimrcp/platforms/umc/src/setparamscenario.cpp b/libs/unimrcp/platforms/umc/src/setparamscenario.cpp
index 60e889297d..c2b62b1934 100644
--- a/libs/unimrcp/platforms/umc/src/setparamscenario.cpp
+++ b/libs/unimrcp/platforms/umc/src/setparamscenario.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: setparamscenario.cpp 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "setparamscenario.h"
diff --git a/libs/unimrcp/platforms/umc/src/setparamsession.cpp b/libs/unimrcp/platforms/umc/src/setparamsession.cpp
index 403629bfb4..cc60a020a7 100644
--- a/libs/unimrcp/platforms/umc/src/setparamsession.cpp
+++ b/libs/unimrcp/platforms/umc/src/setparamsession.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: setparamsession.cpp 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "setparamsession.h"
diff --git a/libs/unimrcp/platforms/umc/src/synthscenario.cpp b/libs/unimrcp/platforms/umc/src/synthscenario.cpp
index 37c9d66f30..b104ef20a6 100644
--- a/libs/unimrcp/platforms/umc/src/synthscenario.cpp
+++ b/libs/unimrcp/platforms/umc/src/synthscenario.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: synthscenario.cpp 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include
diff --git a/libs/unimrcp/platforms/umc/src/synthsession.cpp b/libs/unimrcp/platforms/umc/src/synthsession.cpp
index a0cb5082a5..003d2f6b62 100644
--- a/libs/unimrcp/platforms/umc/src/synthsession.cpp
+++ b/libs/unimrcp/platforms/umc/src/synthsession.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: synthsession.cpp 1586 2010-03-12 19:39:02Z achaloyan $
*/
#include "synthsession.h"
@@ -23,9 +25,14 @@
struct SynthChannel
{
+ /** MRCP channel */
mrcp_channel_t* m_pMrcpChannel;
+ /** IN-PROGRESS SPEAK request */
+ mrcp_message_t* m_pSpeakRequest;
/** File to write audio stream to */
FILE* m_pAudioOut;
+
+ SynthChannel() : m_pMrcpChannel(NULL), m_pSpeakRequest(NULL), m_pAudioOut(NULL) {}
};
SynthSession::SynthSession(const SynthScenario* pScenario) :
@@ -58,6 +65,37 @@ bool SynthSession::Start()
return true;
}
+bool SynthSession::Stop()
+{
+ if(!UmcSession::Stop())
+ return false;
+
+ if(!m_pSynthChannel)
+ return false;
+
+ mrcp_message_t* pStopMessage = CreateMrcpMessage(m_pSynthChannel->m_pMrcpChannel,SYNTHESIZER_STOP);
+ if(!pStopMessage)
+ return false;
+
+ if(m_pSynthChannel->m_pSpeakRequest)
+ {
+ mrcp_generic_header_t* pGenericHeader;
+ /* get/allocate generic header */
+ pGenericHeader = (mrcp_generic_header_t*) mrcp_generic_header_prepare(pStopMessage);
+ if(pGenericHeader)
+ {
+ pGenericHeader->active_request_id_list.count = 1;
+ pGenericHeader->active_request_id_list.ids[0] =
+ m_pSynthChannel->m_pSpeakRequest->start_line.request_id;
+ mrcp_generic_header_property_add(pStopMessage,GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST);
+ }
+
+ m_pSynthChannel->m_pSpeakRequest = NULL;
+ }
+
+ return SendMrcpRequest(m_pSynthChannel->m_pMrcpChannel,pStopMessage);
+}
+
bool SynthSession::OnSessionTerminate(mrcp_sig_status_code_e status)
{
if(m_pSynthChannel)
@@ -93,8 +131,7 @@ SynthChannel* SynthSession::CreateSynthChannel()
apr_pool_t* pool = GetSessionPool();
/* create channel */
- SynthChannel *pSynthChannel = new SynthChannel;
- pSynthChannel->m_pMrcpChannel = NULL;
+ SynthChannel* pSynthChannel = new SynthChannel;
/* create sink stream capabilities */
pCapabilities = mpf_sink_stream_capabilities_create(pool);
@@ -128,7 +165,6 @@ SynthChannel* SynthSession::CreateSynthChannel()
}
pSynthChannel->m_pMrcpChannel = pChannel;
- pSynthChannel->m_pAudioOut = NULL;
return pSynthChannel;
}
@@ -169,6 +205,10 @@ bool SynthSession::OnMessageReceive(mrcp_channel_t* pMrcpChannel, mrcp_message_t
/* received the response to SPEAK request */
if(pMrcpMessage->start_line.request_state == MRCP_REQUEST_STATE_INPROGRESS)
{
+ SynthChannel* pSynthChannel = (SynthChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+ if(pSynthChannel)
+ pSynthChannel->m_pSpeakRequest = GetMrcpMessage();
+
/* waiting for SPEAK-COMPLETE event */
}
else
@@ -187,6 +227,9 @@ bool SynthSession::OnMessageReceive(mrcp_channel_t* pMrcpChannel, mrcp_message_t
/* received MRCP event */
if(pMrcpMessage->start_line.method_id == SYNTHESIZER_SPEAK_COMPLETE)
{
+ SynthChannel* pSynthChannel = (SynthChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+ if(pSynthChannel)
+ pSynthChannel->m_pSpeakRequest = NULL;
/* received SPEAK-COMPLETE event, terminate the session */
Terminate();
}
diff --git a/libs/unimrcp/platforms/umc/src/umcconsole.cpp b/libs/unimrcp/platforms/umc/src/umcconsole.cpp
index 203bc442ef..feff85c6b2 100644
--- a/libs/unimrcp/platforms/umc/src/umcconsole.cpp
+++ b/libs/unimrcp/platforms/umc/src/umcconsole.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: umcconsole.cpp 1785 2010-09-22 06:14:29Z achaloyan $
*/
#include
@@ -37,6 +39,7 @@ bool UmcConsole::Run(int argc, const char * const *argv)
{
apr_pool_t* pool = NULL;
apt_dir_layout_t* pDirLayout = NULL;
+ const char *logConfPath;
/* APR global initialization */
if(apr_initialize() != APR_SUCCESS)
@@ -63,13 +66,27 @@ bool UmcConsole::Run(int argc, const char * const *argv)
/* create the structure of default directories layout */
pDirLayout = apt_default_dir_layout_create(m_Options.m_RootDirPath,pool);
- /* create singleton logger */
- apt_log_instance_create(m_Options.m_LogOutput,m_Options.m_LogPriority,pool);
- if((m_Options.m_LogOutput & APT_LOG_OUTPUT_FILE) == APT_LOG_OUTPUT_FILE)
+ /* get path to logger configuration file */
+ logConfPath = apt_confdir_filepath_get(pDirLayout,"logger.xml",pool);
+ /* create and load singleton logger */
+ apt_log_instance_load(logConfPath,pool);
+
+ if(m_Options.m_LogPriority)
+ {
+ /* override the log priority, if specified in command line */
+ apt_log_priority_set((apt_log_priority_e)atoi(m_Options.m_LogPriority));
+ }
+ if(m_Options.m_LogOutput)
+ {
+ /* override the log output mode, if specified in command line */
+ apt_log_output_mode_set((apt_log_output_e)atoi(m_Options.m_LogOutput));
+ }
+
+ if(apt_log_output_mode_check(APT_LOG_OUTPUT_FILE) == TRUE)
{
/* open the log file */
- apt_log_file_open(pDirLayout->log_dir_path,"unimrcpclient",MAX_LOG_FILE_SIZE,MAX_LOG_FILE_COUNT,pool);
+ apt_log_file_open(pDirLayout->log_dir_path,"unimrcpclient",MAX_LOG_FILE_SIZE,MAX_LOG_FILE_COUNT,FALSE,pool);
}
/* create demo framework */
@@ -105,7 +122,7 @@ bool UmcConsole::ProcessCmdLine(char* pCmdLine)
const char* pProfileName = apr_strtok(NULL, " ", &last);
if(!pProfileName)
{
- pProfileName = "MRCPv2-Default";
+ pProfileName = "uni2";
}
m_pFramework->RunSession(pScenarioName,pProfileName);
}
@@ -118,6 +135,14 @@ bool UmcConsole::ProcessCmdLine(char* pCmdLine)
m_pFramework->KillSession(pID);
}
}
+ else if(strcasecmp(name,"stop") == 0)
+ {
+ char* pID = apr_strtok(NULL, " ", &last);
+ if(pID)
+ {
+ m_pFramework->StopSession(pID);
+ }
+ }
else if(strcasecmp(name,"show") == 0)
{
char* pWhat = apr_strtok(NULL, " ", &last);
@@ -146,12 +171,12 @@ bool UmcConsole::ProcessCmdLine(char* pCmdLine)
printf("usage:\n"
"\n- run [scenario] [profile] (run new session)\n"
" scenario is one of 'synth', 'recog', ... (use 'show scenarios')\n"
- " profile is one of 'MRCPv2-Default', 'MRCPv1-Default', ... (see unimrcpclient.xml)\n"
+ " profile is one of 'uni2', 'uni1', ... (see unimrcpclient.xml)\n"
"\n examples: \n"
" run synth\n"
" run recog\n"
- " run synth MRCPv1-Default\n"
- " run recog MRCPv1-Default\n"
+ " run synth uni1\n"
+ " run recog uni1\n"
"\n- kill [id] (kill session)\n"
" id is a session identifier: 1, 2, ... (use 'show sessions')\n"
"\n example: \n"
@@ -238,8 +263,8 @@ bool UmcConsole::LoadOptions(int argc, const char * const *argv, apr_pool_t *poo
/* set the default options */
m_Options.m_RootDirPath = "../";
- m_Options.m_LogPriority = APT_PRIO_INFO;
- m_Options.m_LogOutput = APT_LOG_OUTPUT_CONSOLE;
+ m_Options.m_LogPriority = NULL;
+ m_Options.m_LogOutput = NULL;
rv = apr_getopt_init(&opt, pool , argc, argv);
if(rv != APR_SUCCESS)
@@ -254,15 +279,11 @@ bool UmcConsole::LoadOptions(int argc, const char * const *argv, apr_pool_t *poo
break;
case 'l':
if(optarg)
- {
- m_Options.m_LogPriority = (apt_log_priority_e) atoi(optarg);
- }
+ m_Options.m_LogPriority = optarg;
break;
case 'o':
if(optarg)
- {
- m_Options.m_LogOutput = (apt_log_output_e) atoi(optarg);
- }
+ m_Options.m_LogOutput = optarg;
break;
case 'h':
Usage();
diff --git a/libs/unimrcp/platforms/umc/src/umcframework.cpp b/libs/unimrcp/platforms/umc/src/umcframework.cpp
index a4620bbf8b..9c06064919 100644
--- a/libs/unimrcp/platforms/umc/src/umcframework.cpp
+++ b/libs/unimrcp/platforms/umc/src/umcframework.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: umcframework.cpp 1767 2010-08-23 19:10:22Z achaloyan $
*/
#include "umcframework.h"
@@ -21,6 +23,7 @@
#include "recorderscenario.h"
#include "dtmfscenario.h"
#include "setparamscenario.h"
+#include "verifierscenario.h"
#include "unimrcp_client.h"
#include "apt_log.h"
@@ -36,6 +39,7 @@ enum UmcTaskMsgType
{
UMC_TASK_CLIENT_MSG,
UMC_TASK_RUN_SESSION_MSG,
+ UMC_TASK_STOP_SESSION_MSG,
UMC_TASK_KILL_SESSION_MSG,
UMC_TASK_SHOW_SCENARIOS_MSG,
UMC_TASK_SHOW_SESSIONS_MSG
@@ -134,7 +138,7 @@ bool UmcFramework::CreateTask()
return false;
pTask = apt_consumer_task_base_get(m_pTask);
- apt_task_name_set(pTask,"Framework Task");
+ apt_task_name_set(pTask,"Framework Agent");
pVtable = apt_consumer_task_vtable_get(m_pTask);
if(pVtable)
{
@@ -175,6 +179,8 @@ UmcScenario* UmcFramework::CreateScenario(const char* pType)
return new DtmfScenario();
else if(strcasecmp(pType,"Params") == 0)
return new SetParamScenario();
+ else if(strcasecmp(pType,"Verifier") == 0)
+ return new VerifierScenario();
}
return NULL;
}
@@ -335,6 +341,24 @@ bool UmcFramework::ProcessRunRequest(const char* pScenarioName, const char* pPro
return true;
}
+void UmcFramework::ProcessStopRequest(const char* id)
+{
+ UmcSession* pSession;
+ void* pVal;
+ apr_hash_index_t* it = apr_hash_first(m_pPool,m_pSessionTable);
+ for(; it; it = apr_hash_next(it))
+ {
+ apr_hash_this(it,NULL,NULL,&pVal);
+ pSession = (UmcSession*) pVal;
+ if(pSession && strcasecmp(pSession->GetId(),id) == 0)
+ {
+ /* stop in-progress request */
+ pSession->Stop();
+ return;
+ }
+ }
+}
+
void UmcFramework::ProcessKillRequest(const char* id)
{
UmcSession* pSession;
@@ -346,7 +370,7 @@ void UmcFramework::ProcessKillRequest(const char* id)
pSession = (UmcSession*) pVal;
if(pSession && strcasecmp(pSession->GetId(),id) == 0)
{
- /* first, terminate session */
+ /* terminate session */
pSession->Terminate();
return;
}
@@ -403,6 +427,22 @@ void UmcFramework::RunSession(const char* pScenarioName, const char* pProfileNam
apt_task_msg_signal(pTask,pTaskMsg);
}
+void UmcFramework::StopSession(const char* id)
+{
+ apt_task_t* pTask = apt_consumer_task_base_get(m_pTask);
+ apt_task_msg_t* pTaskMsg = apt_task_msg_get(pTask);
+ if(!pTaskMsg)
+ return;
+
+ pTaskMsg->type = TASK_MSG_USER;
+ pTaskMsg->sub_type = UMC_TASK_STOP_SESSION_MSG;
+
+ UmcTaskMsg* pUmcMsg = (UmcTaskMsg*) pTaskMsg->data;
+ strncpy(pUmcMsg->m_SessionId,id,sizeof(pUmcMsg->m_SessionId)-1);
+ pUmcMsg->m_pAppMessage = NULL;
+ apt_task_msg_signal(pTask,pTaskMsg);
+}
+
void UmcFramework::KillSession(const char* id)
{
apt_task_t* pTask = apt_consumer_task_base_get(m_pTask);
@@ -562,6 +602,11 @@ apt_bool_t UmcProcessMsg(apt_task_t *pTask, apt_task_msg_t *pMsg)
pFramework->ProcessRunRequest(pUmcMsg->m_ScenarioName,pUmcMsg->m_ProfileName);
break;
}
+ case UMC_TASK_STOP_SESSION_MSG:
+ {
+ pFramework->ProcessStopRequest(pUmcMsg->m_SessionId);
+ break;
+ }
case UMC_TASK_KILL_SESSION_MSG:
{
pFramework->ProcessKillRequest(pUmcMsg->m_SessionId);
diff --git a/libs/unimrcp/platforms/umc/src/umcscenario.cpp b/libs/unimrcp/platforms/umc/src/umcscenario.cpp
index e93c53a1b6..f48bea74c9 100644
--- a/libs/unimrcp/platforms/umc/src/umcscenario.cpp
+++ b/libs/unimrcp/platforms/umc/src/umcscenario.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,14 +12,17 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: umcscenario.cpp 1571 2010-03-07 20:33:39Z achaloyan $
*/
#include
#include "umcscenario.h"
+#include "apt_log.h"
UmcScenario::UmcScenario() :
m_pName(NULL),
- m_pMrcpProfile("MRCPv2-Default"),
+ m_pMrcpProfile("uni2"),
m_pDirLayout(NULL),
m_ResourceDiscovery(false),
m_pCapabilities(NULL),
@@ -200,14 +203,31 @@ const char* UmcScenario::LoadFileContent(const char* pFileName, apr_pool_t* pool
if(!pFilePath)
return NULL;
- FILE* pFile = fopen(pFilePath,"r");
- if(!pFile)
+ apr_file_t *pFile;
+ if(apr_file_open(&pFile,pFilePath,APR_FOPEN_READ|APR_FOPEN_BINARY,0,pool) != APR_SUCCESS)
+ {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open File %s",pFilePath);
return NULL;
+ }
- char text[1024];
- apr_size_t size;
- size = fread(text,1,sizeof(text)-1,pFile);
- text[size] = '\0';
- fclose(pFile);
- return apr_pstrdup(pool,text);
+ apr_finfo_t finfo;
+ if(apr_file_info_get(&finfo,APR_FINFO_SIZE,pFile) != APR_SUCCESS)
+ {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Get File Info %s",pFilePath);
+ apr_file_close(pFile);
+ return NULL;
+ }
+
+ apr_size_t size = (apr_size_t)finfo.size;
+ char* pContent = (char*) apr_palloc(pool,size+1);
+ apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Load File Content size [%"APR_SIZE_T_FMT" bytes] %s",size,pFilePath);
+ if(apr_file_read(pFile,pContent,&size) != APR_SUCCESS)
+ {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Read Content %s",pFilePath);
+ apr_file_close(pFile);
+ return NULL;
+ }
+ pContent[size] = '\0';
+ apr_file_close(pFile);
+ return pContent;
}
diff --git a/libs/unimrcp/platforms/umc/src/umcsession.cpp b/libs/unimrcp/platforms/umc/src/umcsession.cpp
index d19be46466..d619893cac 100644
--- a/libs/unimrcp/platforms/umc/src/umcsession.cpp
+++ b/libs/unimrcp/platforms/umc/src/umcsession.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,16 +12,20 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: umcsession.cpp 1695 2010-05-19 18:56:15Z achaloyan $
*/
#include "umcsession.h"
#include "umcscenario.h"
+#include "mrcp_message.h"
UmcSession::UmcSession(const UmcScenario* pScenario) :
m_pScenario(pScenario),
m_pMrcpProfile(NULL),
m_pMrcpApplication(NULL),
m_pMrcpSession(NULL),
+ m_pMrcpMessage(NULL),
m_Running(false),
m_Terminating(false)
{
@@ -69,6 +73,14 @@ bool UmcSession::Run()
return ret;
}
+bool UmcSession::Stop()
+{
+ if(m_Terminating)
+ return false;
+
+ return true;
+}
+
bool UmcSession::Terminate()
{
if(m_Terminating)
@@ -105,7 +117,17 @@ bool UmcSession::OnChannelRemove(mrcp_channel_t *channel, mrcp_sig_status_code_e
bool UmcSession::OnMessageReceive(mrcp_channel_t *channel, mrcp_message_t *message)
{
- return m_Running;
+ if(!m_Running)
+ return false;
+
+ if(!m_pMrcpMessage)
+ return false;
+
+ /* match request identifiers */
+ if(m_pMrcpMessage->start_line.request_id != message->start_line.request_id)
+ return false;
+
+ return true;
}
bool UmcSession::OnTerminateEvent(mrcp_channel_t *channel)
@@ -129,6 +151,9 @@ bool UmcSession::OnResourceDiscover(mrcp_session_descriptor_t* descriptor, mrcp_
bool UmcSession::CreateMrcpSession(const char* pProfileName)
{
m_pMrcpSession = mrcp_application_session_create(m_pMrcpApplication,pProfileName,this);
+ char name[32];
+ apr_snprintf(name,sizeof(name),"umc-%s",m_Id);
+ mrcp_application_session_name_set(m_pMrcpSession,name);
return (m_pMrcpSession != NULL);
}
@@ -163,6 +188,7 @@ bool UmcSession::SendMrcpRequest(mrcp_channel_t* pMrcpChannel, mrcp_message_t* p
if(!m_Running)
return false;
+ m_pMrcpMessage = pMrcpMessage;
return (mrcp_application_message_send(m_pMrcpSession,pMrcpChannel,pMrcpMessage) == TRUE);
}
diff --git a/libs/unimrcp/platforms/umc/src/verifierscenario.cpp b/libs/unimrcp/platforms/umc/src/verifierscenario.cpp
new file mode 100644
index 0000000000..23ee362803
--- /dev/null
+++ b/libs/unimrcp/platforms/umc/src/verifierscenario.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: verifierscenario.cpp 1775 2010-08-26 18:23:38Z achaloyan $
+ */
+
+#include
+#include "verifierscenario.h"
+#include "verifiersession.h"
+#include "mrcp_message.h"
+#include "mrcp_generic_header.h"
+#include "mrcp_recog_header.h"
+#include "mrcp_recog_resource.h"
+#include "apt_log.h"
+
+VerifierScenario::VerifierScenario() :
+ m_RepositoryURI(NULL),
+ m_VerificationMode(NULL),
+ m_VoiceprintIdentifier(NULL)
+{
+}
+
+VerifierScenario::~VerifierScenario()
+{
+}
+
+void VerifierScenario::Destroy()
+{
+}
+
+bool VerifierScenario::LoadElement(const apr_xml_elem* pElem, apr_pool_t* pool)
+{
+ if(UmcScenario::LoadElement(pElem,pool))
+ return true;
+
+ if(strcasecmp(pElem->name,"verify") == 0)
+ {
+ LoadVerify(pElem,pool);
+ return true;
+ }
+ return false;
+}
+
+bool VerifierScenario::LoadVerify(const apr_xml_elem* pElem, apr_pool_t* pool)
+{
+ const apr_xml_attr* pAttr;
+ for(pAttr = pElem->attr; pAttr; pAttr = pAttr->next)
+ {
+ if(strcasecmp(pAttr->name,"repository-uri") == 0)
+ {
+ m_RepositoryURI = pAttr->value;
+ }
+ else if(strcasecmp(pAttr->name,"verification-mode") == 0)
+ {
+ m_VerificationMode = pAttr->value;
+ }
+ else if(strcasecmp(pAttr->name,"voiceprint-identifier") == 0)
+ {
+ m_VoiceprintIdentifier = pAttr->value;
+ }
+ }
+
+ return true;
+}
+
+
+UmcSession* VerifierScenario::CreateSession()
+{
+ return new VerifierSession(this);
+}
diff --git a/libs/unimrcp/platforms/umc/src/verifiersession.cpp b/libs/unimrcp/platforms/umc/src/verifiersession.cpp
new file mode 100644
index 0000000000..c44530e006
--- /dev/null
+++ b/libs/unimrcp/platforms/umc/src/verifiersession.cpp
@@ -0,0 +1,389 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: verifiersession.cpp 1778 2010-08-27 17:34:52Z achaloyan $
+ */
+
+#include "verifiersession.h"
+#include "verifierscenario.h"
+#include "mrcp_message.h"
+#include "mrcp_generic_header.h"
+#include "mrcp_verifier_header.h"
+#include "mrcp_verifier_resource.h"
+#include "apt_nlsml_doc.h"
+#include "apt_log.h"
+
+struct VerifierChannel
+{
+ /** MRCP control channel */
+ mrcp_channel_t* m_pMrcpChannel;
+ /** IN-PROGRESS VERIFY request */
+ mrcp_message_t* m_pVerificationRequest;
+ /** Streaming is in-progress */
+ bool m_Streaming;
+ /** File to read audio stream from */
+ FILE* m_pAudioIn;
+ /** Estimated time to complete (used if no audio_in available) */
+ apr_size_t m_TimeToComplete;
+
+ VerifierChannel() :
+ m_pMrcpChannel(NULL),
+ m_pVerificationRequest(NULL),
+ m_Streaming(false),
+ m_pAudioIn(NULL),
+ m_TimeToComplete(0) {}
+};
+
+VerifierSession::VerifierSession(const VerifierScenario* pScenario) :
+ UmcSession(pScenario),
+ m_pVerifierChannel(NULL),
+ m_ContentId("request1@form-level")
+{
+}
+
+VerifierSession::~VerifierSession()
+{
+}
+
+bool VerifierSession::Start()
+{
+ /* create channel and associate all the required data */
+ m_pVerifierChannel = CreateVerifierChannel();
+ if(!m_pVerifierChannel)
+ return false;
+
+ /* add channel to session (send asynchronous request) */
+ if(!AddMrcpChannel(m_pVerifierChannel->m_pMrcpChannel))
+ {
+ delete m_pVerifierChannel;
+ m_pVerifierChannel = NULL;
+ return false;
+ }
+ return true;
+}
+
+bool VerifierSession::Stop()
+{
+ if(!UmcSession::Stop())
+ return false;
+
+ if(!m_pVerifierChannel)
+ return false;
+
+ mrcp_message_t* pStopMessage = CreateMrcpMessage(m_pVerifierChannel->m_pMrcpChannel,VERIFIER_STOP);
+ if(!pStopMessage)
+ return false;
+
+ return SendMrcpRequest(m_pVerifierChannel->m_pMrcpChannel,pStopMessage);
+}
+
+bool VerifierSession::OnSessionTerminate(mrcp_sig_status_code_e status)
+{
+ if(m_pVerifierChannel)
+ {
+ FILE* pAudioIn = m_pVerifierChannel->m_pAudioIn;
+ if(pAudioIn)
+ {
+ m_pVerifierChannel->m_pAudioIn = NULL;
+ fclose(pAudioIn);
+ }
+
+ delete m_pVerifierChannel;
+ m_pVerifierChannel = NULL;
+ }
+ return UmcSession::OnSessionTerminate(status);
+}
+
+static apt_bool_t ReadStream(mpf_audio_stream_t* pStream, mpf_frame_t* pFrame)
+{
+ VerifierChannel* pVerifierChannel = (VerifierChannel*) pStream->obj;
+ if(pVerifierChannel && pVerifierChannel->m_Streaming)
+ {
+ if(pVerifierChannel->m_pAudioIn)
+ {
+ if(fread(pFrame->codec_frame.buffer,1,pFrame->codec_frame.size,pVerifierChannel->m_pAudioIn) == pFrame->codec_frame.size)
+ {
+ /* normal read */
+ pFrame->type |= MEDIA_FRAME_TYPE_AUDIO;
+ }
+ else
+ {
+ /* file is over */
+ pVerifierChannel->m_Streaming = false;
+ }
+ }
+ else
+ {
+ /* fill with silence in case no file available */
+ if(pVerifierChannel->m_TimeToComplete >= CODEC_FRAME_TIME_BASE)
+ {
+ pFrame->type |= MEDIA_FRAME_TYPE_AUDIO;
+ memset(pFrame->codec_frame.buffer,0,pFrame->codec_frame.size);
+ pVerifierChannel->m_TimeToComplete -= CODEC_FRAME_TIME_BASE;
+ }
+ else
+ {
+ pVerifierChannel->m_Streaming = false;
+ }
+ }
+ }
+ return TRUE;
+}
+
+VerifierChannel* VerifierSession::CreateVerifierChannel()
+{
+ mrcp_channel_t* pChannel;
+ mpf_termination_t* pTermination;
+ mpf_stream_capabilities_t* pCapabilities;
+ apr_pool_t* pool = GetSessionPool();
+
+ /* create channel */
+ VerifierChannel* pVerifierChannel = new VerifierChannel;
+
+ /* create source stream capabilities */
+ pCapabilities = mpf_source_stream_capabilities_create(pool);
+ GetScenario()->InitCapabilities(pCapabilities);
+
+ static const mpf_audio_stream_vtable_t audio_stream_vtable =
+ {
+ NULL,
+ NULL,
+ NULL,
+ ReadStream,
+ NULL,
+ NULL,
+ NULL
+ };
+
+ pTermination = CreateAudioTermination(
+ &audio_stream_vtable, /* virtual methods table of audio stream */
+ pCapabilities, /* capabilities of audio stream */
+ pVerifierChannel); /* object to associate */
+
+ pChannel = CreateMrcpChannel(
+ MRCP_VERIFIER_RESOURCE, /* MRCP resource identifier */
+ pTermination, /* media termination, used to terminate audio stream */
+ NULL, /* RTP descriptor, used to create RTP termination (NULL by default) */
+ pVerifierChannel); /* object to associate */
+ if(!pChannel)
+ {
+ delete pVerifierChannel;
+ return NULL;
+ }
+
+ pVerifierChannel->m_pMrcpChannel = pChannel;
+ return pVerifierChannel;
+}
+
+bool VerifierSession::OnChannelAdd(mrcp_channel_t* pMrcpChannel, mrcp_sig_status_code_e status)
+{
+ if(!UmcSession::OnChannelAdd(pMrcpChannel,status))
+ return false;
+
+ if(status != MRCP_SIG_STATUS_CODE_SUCCESS)
+ {
+ /* error case, just terminate the demo */
+ return Terminate();
+ }
+
+ return StartVerification(pMrcpChannel);
+}
+
+bool VerifierSession::OnMessageReceive(mrcp_channel_t* pMrcpChannel, mrcp_message_t* pMrcpMessage)
+{
+ if(!UmcSession::OnMessageReceive(pMrcpChannel,pMrcpMessage))
+ return false;
+
+ VerifierChannel* pVerifierChannel = (VerifierChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+ if(pMrcpMessage->start_line.message_type == MRCP_MESSAGE_TYPE_RESPONSE)
+ {
+ /* received MRCP response */
+ if(pMrcpMessage->start_line.method_id == VERIFIER_START_SESSION)
+ {
+ /* received the response to START-SESSION request */
+ /* create and send VERIFY request */
+ mrcp_message_t* pMrcpMessage = CreateVerificationRequest(pMrcpChannel);
+ if(pMrcpMessage)
+ {
+ SendMrcpRequest(pVerifierChannel->m_pMrcpChannel,pMrcpMessage);
+ }
+ }
+ else if(pMrcpMessage->start_line.method_id == VERIFIER_END_SESSION)
+ {
+ /* received the response to END-SESSION request */
+ Terminate();
+ }
+ else if(pMrcpMessage->start_line.method_id == VERIFIER_VERIFY)
+ {
+ /* received the response to VERIFY request */
+ if(pMrcpMessage->start_line.request_state == MRCP_REQUEST_STATE_INPROGRESS)
+ {
+ VerifierChannel* pVerifierChannel = (VerifierChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+ if(pVerifierChannel)
+ pVerifierChannel->m_pVerificationRequest = GetMrcpMessage();
+
+ /* start to stream the speech to Verify */
+ if(pVerifierChannel)
+ pVerifierChannel->m_Streaming = true;
+ }
+ else
+ {
+ /* create and send END-SESSION request */
+ mrcp_message_t* pMrcpMessage = CreateEndSessionRequest(pMrcpChannel);
+ if(pMrcpMessage)
+ {
+ SendMrcpRequest(pVerifierChannel->m_pMrcpChannel,pMrcpMessage);
+ }
+ }
+ }
+ else
+ {
+ /* received unexpected response */
+ }
+ }
+ else if(pMrcpMessage->start_line.message_type == MRCP_MESSAGE_TYPE_EVENT)
+ {
+ if(pMrcpMessage->start_line.method_id == VERIFIER_VERIFICATION_COMPLETE)
+ {
+ if(pVerifierChannel)
+ pVerifierChannel->m_Streaming = false;
+
+ VerifierChannel* pVerifierChannel = (VerifierChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+ if(pVerifierChannel)
+ pVerifierChannel->m_pVerificationRequest = NULL;
+
+ /* create and send END-SESSION request */
+ mrcp_message_t* pMrcpMessage = CreateEndSessionRequest(pMrcpChannel);
+ if(pMrcpMessage)
+ {
+ SendMrcpRequest(pVerifierChannel->m_pMrcpChannel,pMrcpMessage);
+ }
+ }
+ else if(pMrcpMessage->start_line.method_id == VERIFIER_START_OF_INPUT)
+ {
+ /* received start-of-input, do whatever you need here */
+ }
+ }
+ return true;
+}
+
+bool VerifierSession::StartVerification(mrcp_channel_t* pMrcpChannel)
+{
+ VerifierChannel* pVerifierChannel = (VerifierChannel*) mrcp_application_channel_object_get(pMrcpChannel);
+ /* create and send Verification request */
+ mrcp_message_t* pMrcpMessage = CreateStartSessionRequest(pMrcpChannel);
+ if(pMrcpMessage)
+ {
+ SendMrcpRequest(pVerifierChannel->m_pMrcpChannel,pMrcpMessage);
+ }
+
+ const mpf_codec_descriptor_t* pDescriptor = mrcp_application_source_descriptor_get(pMrcpChannel);
+ pVerifierChannel->m_pAudioIn = GetAudioIn(pDescriptor,GetSessionPool());
+ if(!pVerifierChannel->m_pAudioIn)
+ {
+ /* no audio input availble, set some estimated time to complete instead */
+ pVerifierChannel->m_TimeToComplete = 5000; // 5 sec
+ }
+ return true;
+}
+
+mrcp_message_t* VerifierSession::CreateStartSessionRequest(mrcp_channel_t* pMrcpChannel)
+{
+ mrcp_message_t* pMrcpMessage = CreateMrcpMessage(pMrcpChannel,VERIFIER_START_SESSION);
+ if(!pMrcpMessage)
+ return NULL;
+
+ mrcp_verifier_header_t* pVerifierHeader;
+
+ /* get/allocate verifier header */
+ pVerifierHeader = (mrcp_verifier_header_t*) mrcp_resource_header_prepare(pMrcpMessage);
+ if(pVerifierHeader)
+ {
+ const VerifierScenario* pScenario = GetScenario();
+ const char* pRepositoryURI = pScenario->GetRepositoryURI();
+ if(pRepositoryURI)
+ {
+ apt_string_set(&pVerifierHeader->repository_uri,pRepositoryURI);
+ mrcp_resource_header_property_add(pMrcpMessage,VERIFIER_HEADER_REPOSITORY_URI);
+ }
+ const char* pVoiceprintIdentifier = pScenario->GetVoiceprintIdentifier();
+ if(pVoiceprintIdentifier)
+ {
+ apt_string_set(&pVerifierHeader->voiceprint_identifier,pVoiceprintIdentifier);
+ mrcp_resource_header_property_add(pMrcpMessage,VERIFIER_HEADER_VOICEPRINT_IDENTIFIER);
+ }
+ const char* pVerificationMode = pScenario->GetVerificationMode();
+ if(pVerificationMode)
+ {
+ apt_string_set(&pVerifierHeader->verification_mode,pVerificationMode);
+ mrcp_resource_header_property_add(pMrcpMessage,VERIFIER_HEADER_VERIFICATION_MODE);
+ }
+ }
+ return pMrcpMessage;
+}
+
+mrcp_message_t* VerifierSession::CreateEndSessionRequest(mrcp_channel_t* pMrcpChannel)
+{
+ return CreateMrcpMessage(pMrcpChannel,VERIFIER_END_SESSION);
+}
+
+mrcp_message_t* VerifierSession::CreateVerificationRequest(mrcp_channel_t* pMrcpChannel)
+{
+ mrcp_message_t* pMrcpMessage = CreateMrcpMessage(pMrcpChannel,VERIFIER_VERIFY);
+ if(!pMrcpMessage)
+ return NULL;
+
+ mrcp_verifier_header_t* pVerifierHeader;
+
+ /* get/allocate verifier header */
+ pVerifierHeader = (mrcp_verifier_header_t*) mrcp_resource_header_prepare(pMrcpMessage);
+ if(pVerifierHeader)
+ {
+ pVerifierHeader->no_input_timeout = 5000;
+ mrcp_resource_header_property_add(pMrcpMessage,VERIFIER_HEADER_NO_INPUT_TIMEOUT);
+ pVerifierHeader->start_input_timers = TRUE;
+ mrcp_resource_header_property_add(pMrcpMessage,VERIFIER_HEADER_START_INPUT_TIMERS);
+ }
+ return pMrcpMessage;
+}
+
+FILE* VerifierSession::GetAudioIn(const mpf_codec_descriptor_t* pDescriptor, apr_pool_t* pool) const
+{
+ const VerifierScenario* pScenario = GetScenario();
+ const char* pVoiceprintIdentifier = pScenario->GetVoiceprintIdentifier();
+ if(!pVoiceprintIdentifier)
+ {
+ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No Voiceprint Specified");
+ return NULL;
+ }
+
+ const char* pFileName = apr_psprintf(pool,"%s-%dkHz.pcm",
+ pVoiceprintIdentifier,
+ pDescriptor ? pDescriptor->sampling_rate/1000 : 8);
+ apt_dir_layout_t* pDirLayout = pScenario->GetDirLayout();
+ const char* pFilePath = apt_datadir_filepath_get(pDirLayout,pFileName,pool);
+ if(!pFilePath)
+ return NULL;
+
+ FILE* pFile = fopen(pFilePath,"rb");
+ if(!pFile)
+ {
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Cannot Find [%s]",pFilePath);
+ return NULL;
+ }
+
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Set [%s] as Speech Source",pFilePath);
+ return pFile;
+}
diff --git a/libs/unimrcp/platforms/umc/umc.rc b/libs/unimrcp/platforms/umc/umc.rc
new file mode 100644
index 0000000000..511efb81b6
--- /dev/null
+++ b/libs/unimrcp/platforms/umc/umc.rc
@@ -0,0 +1,39 @@
+#include "uni_version.h"
+
+1 VERSIONINFO
+ FILEVERSION UNI_VERSION_STRING_CSV,0
+ PRODUCTVERSION UNI_VERSION_STRING_CSV,0
+ FILEFLAGSMASK 0x3fL
+#if defined(_DEBUG)
+ FILEFLAGS 0x01L
+#else
+ FILEFLAGS 0x00L
+#endif
+#if defined(WINNT) || defined(WIN64)
+ FILEOS 0x40004L
+#else
+ FILEOS 0x4L
+#endif
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Comments", UNI_LICENSE "\0"
+ VALUE "CompanyName", "UniMRCP\0"
+ VALUE "FileDescription", "UniMRCP Client Application\0"
+ VALUE "FileVersion", UNI_VERSION_STRING "\0"
+ VALUE "InternalName", "umc" "\0"
+ VALUE "LegalCopyright", UNI_COPYRIGHT "\0"
+ VALUE "OriginalFilename", "umc.exe" "\0"
+ VALUE "ProductName", "UniMRCP Project\0"
+ VALUE "ProductVersion", UNI_VERSION_STRING "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/libs/unimrcp/platforms/umc/umc.vcproj b/libs/unimrcp/platforms/umc/umc.vcproj
index 5862942a50..d003362f18 100644
--- a/libs/unimrcp/platforms/umc/umc.vcproj
+++ b/libs/unimrcp/platforms/umc/umc.vcproj
@@ -339,6 +339,14 @@
RelativePath=".\src\umcsession.cpp"
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/unimrcp/platforms/unimrcp-client/include/demo_application.h b/libs/unimrcp/platforms/unimrcp-client/include/demo_application.h
index 608d996f98..305858b642 100644
--- a/libs/unimrcp/platforms/unimrcp-client/include/demo_application.h
+++ b/libs/unimrcp/platforms/unimrcp-client/include/demo_application.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: demo_application.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __DEMO_APPLICATION_H__
-#define __DEMO_APPLICATION_H__
+#ifndef DEMO_APPLICATION_H
+#define DEMO_APPLICATION_H
/**
* @file demo_application.h
@@ -58,4 +60,4 @@ demo_application_t* demo_discover_application_create(apr_pool_t *pool);
APT_END_EXTERN_C
-#endif /*__DEMO_APPLICATION_H__*/
+#endif /* DEMO_APPLICATION_H */
diff --git a/libs/unimrcp/platforms/unimrcp-client/include/demo_framework.h b/libs/unimrcp/platforms/unimrcp-client/include/demo_framework.h
index 5cef92305d..ef173ef7de 100644
--- a/libs/unimrcp/platforms/unimrcp-client/include/demo_framework.h
+++ b/libs/unimrcp/platforms/unimrcp-client/include/demo_framework.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: demo_framework.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __DEMO_FRAMEWORK_H__
-#define __DEMO_FRAMEWORK_H__
+#ifndef DEMO_FRAMEWORK_H
+#define DEMO_FRAMEWORK_H
/**
* @file demo_framework.h
@@ -50,4 +52,4 @@ apt_bool_t demo_framework_destroy(demo_framework_t *framework);
APT_END_EXTERN_C
-#endif /*__DEMO_FRAMEWORK_H__*/
+#endif /* DEMO_FRAMEWORK_H */
diff --git a/libs/unimrcp/platforms/unimrcp-client/include/demo_util.h b/libs/unimrcp/platforms/unimrcp-client/include/demo_util.h
index c3d6e793d9..82b1d5ada5 100644
--- a/libs/unimrcp/platforms/unimrcp-client/include/demo_util.h
+++ b/libs/unimrcp/platforms/unimrcp-client/include/demo_util.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: demo_util.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __DEMO_UTIL_H__
-#define __DEMO_UTIL_H__
+#ifndef DEMO_UTIL_H
+#define DEMO_UTIL_H
/**
* @file demo_util.h
@@ -42,4 +44,4 @@ mpf_rtp_termination_descriptor_t* demo_rtp_descriptor_create(apr_pool_t *pool);
APT_END_EXTERN_C
-#endif /*__DEMO_UTIL_H__*/
+#endif /* DEMO_UTIL_H */
diff --git a/libs/unimrcp/platforms/unimrcp-client/src/demo_bypass_application.c b/libs/unimrcp/platforms/unimrcp-client/src/demo_bypass_application.c
index 6a9b660bce..5780a87ae5 100644
--- a/libs/unimrcp/platforms/unimrcp-client/src/demo_bypass_application.c
+++ b/libs/unimrcp/platforms/unimrcp-client/src/demo_bypass_application.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: demo_bypass_application.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
/*
diff --git a/libs/unimrcp/platforms/unimrcp-client/src/demo_discover_application.c b/libs/unimrcp/platforms/unimrcp-client/src/demo_discover_application.c
index a31b96873c..652fc72a07 100644
--- a/libs/unimrcp/platforms/unimrcp-client/src/demo_discover_application.c
+++ b/libs/unimrcp/platforms/unimrcp-client/src/demo_discover_application.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: demo_discover_application.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
/*
diff --git a/libs/unimrcp/platforms/unimrcp-client/src/demo_framework.c b/libs/unimrcp/platforms/unimrcp-client/src/demo_framework.c
index 9d65750fbd..69ac8b1a60 100644
--- a/libs/unimrcp/platforms/unimrcp-client/src/demo_framework.c
+++ b/libs/unimrcp/platforms/unimrcp-client/src/demo_framework.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: demo_framework.c 1571 2010-03-07 20:33:39Z achaloyan $
*/
#include
@@ -21,7 +23,7 @@
#include "apt_consumer_task.h"
#include "apt_log.h"
-#define FRAMEWORK_TASK_NAME "Framework Task"
+#define FRAMEWORK_TASK_NAME "Framework Agent"
#define MAX_APP_NAME_LENGTH 16
#define MAX_PROFILE_NAME_LENGTH 16
diff --git a/libs/unimrcp/platforms/unimrcp-client/src/demo_recog_application.c b/libs/unimrcp/platforms/unimrcp-client/src/demo_recog_application.c
index 3235b2ad86..a4b4845741 100644
--- a/libs/unimrcp/platforms/unimrcp-client/src/demo_recog_application.c
+++ b/libs/unimrcp/platforms/unimrcp-client/src/demo_recog_application.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: demo_recog_application.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
/*
diff --git a/libs/unimrcp/platforms/unimrcp-client/src/demo_synth_application.c b/libs/unimrcp/platforms/unimrcp-client/src/demo_synth_application.c
index 4ad6a7d0d5..d010bb3883 100644
--- a/libs/unimrcp/platforms/unimrcp-client/src/demo_synth_application.c
+++ b/libs/unimrcp/platforms/unimrcp-client/src/demo_synth_application.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: demo_synth_application.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
/*
diff --git a/libs/unimrcp/platforms/unimrcp-client/src/demo_util.c b/libs/unimrcp/platforms/unimrcp-client/src/demo_util.c
index db873f288e..ebbc0a5c67 100644
--- a/libs/unimrcp/platforms/unimrcp-client/src/demo_util.c
+++ b/libs/unimrcp/platforms/unimrcp-client/src/demo_util.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: demo_util.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "demo_util.h"
diff --git a/libs/unimrcp/platforms/unimrcp-client/src/main.c b/libs/unimrcp/platforms/unimrcp-client/src/main.c
index 6a242ca4cd..5da982b533 100644
--- a/libs/unimrcp/platforms/unimrcp-client/src/main.c
+++ b/libs/unimrcp/platforms/unimrcp-client/src/main.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: main.c 1785 2010-09-22 06:14:29Z achaloyan $
*/
#include
@@ -23,9 +25,9 @@
#include "apt_log.h"
typedef struct {
- const char *root_dir_path;
- apt_log_priority_e log_priority;
- apt_log_output_e log_output;
+ const char *root_dir_path;
+ const char *log_priority;
+ const char *log_output;
} client_options_t;
static apt_bool_t demo_framework_cmdline_process(demo_framework_t *framework, char *cmdline)
@@ -40,7 +42,7 @@ static apt_bool_t demo_framework_cmdline_process(demo_framework_t *framework, ch
if(app_name) {
char *profile_name = apr_strtok(NULL, " ", &last);
if(!profile_name) {
- profile_name = "MRCPv2-Default";
+ profile_name = "uni2";
}
demo_framework_app_run(framework,app_name,profile_name);
}
@@ -58,12 +60,12 @@ static apt_bool_t demo_framework_cmdline_process(demo_framework_t *framework, ch
printf("usage:\n"
"\n- run [app_name] [profile_name] (run demo application)\n"
" app_name is one of 'synth', 'recog', 'bypass', 'discover'\n"
- " profile_name is one of 'MRCPv2-Default', 'MRCPv1-Default', ...\n"
+ " profile_name is one of 'uni2', 'uni1', ...\n"
"\n examples: \n"
" run synth\n"
" run recog\n"
- " run synth MRCPv1-Default\n"
- " run recog MRCPv1-Default\n"
+ " run synth uni1\n"
+ " run recog uni1\n"
"\n- loglevel [level] (set loglevel, one of 0,1...7)\n"
"\n- quit, exit\n");
}
@@ -145,14 +147,10 @@ static apt_bool_t demo_framework_options_load(client_options_t *options, int arg
options->root_dir_path = optarg;
break;
case 'l':
- if(optarg) {
- options->log_priority = atoi(optarg);
- }
+ options->log_priority = optarg;
break;
case 'o':
- if(optarg) {
- options->log_output = atoi(optarg);
- }
+ options->log_output = optarg;
break;
case 'h':
usage();
@@ -173,6 +171,7 @@ int main(int argc, const char * const *argv)
apr_pool_t *pool = NULL;
client_options_t options;
apt_dir_layout_t *dir_layout;
+ const char *log_conf_path;
demo_framework_t *framework;
/* APR global initialization */
@@ -190,8 +189,8 @@ int main(int argc, const char * const *argv)
/* set the default options */
options.root_dir_path = "../";
- options.log_priority = APT_PRIO_INFO;
- options.log_output = APT_LOG_OUTPUT_CONSOLE;
+ options.log_priority = NULL;
+ options.log_output = NULL;
/* load options */
if(demo_framework_options_load(&options,argc,argv,pool) != TRUE) {
@@ -202,12 +201,24 @@ int main(int argc, const char * const *argv)
/* create the structure of default directories layout */
dir_layout = apt_default_dir_layout_create(options.root_dir_path,pool);
- /* create singleton logger */
- apt_log_instance_create(options.log_output,options.log_priority,pool);
- if((options.log_output & APT_LOG_OUTPUT_FILE) == APT_LOG_OUTPUT_FILE) {
+ /* get path to logger configuration file */
+ log_conf_path = apt_confdir_filepath_get(dir_layout,"logger.xml",pool);
+ /* create and load singleton logger */
+ apt_log_instance_load(log_conf_path,pool);
+
+ if(options.log_priority) {
+ /* override the log priority, if specified in command line */
+ apt_log_priority_set(atoi(options.log_priority));
+ }
+ if(options.log_output) {
+ /* override the log output mode, if specified in command line */
+ apt_log_output_mode_set(atoi(options.log_output));
+ }
+
+ if(apt_log_output_mode_check(APT_LOG_OUTPUT_FILE) == TRUE) {
/* open the log file */
- apt_log_file_open(dir_layout->log_dir_path,"unimrcpclient",MAX_LOG_FILE_SIZE,MAX_LOG_FILE_COUNT,pool);
+ apt_log_file_open(dir_layout->log_dir_path,"unimrcpclient",MAX_LOG_FILE_SIZE,MAX_LOG_FILE_COUNT,FALSE,pool);
}
/* create demo framework */
diff --git a/libs/unimrcp/platforms/unimrcp-client/unimrcpclient.2008.vcproj b/libs/unimrcp/platforms/unimrcp-client/unimrcpclient.2008.vcproj
deleted file mode 100644
index 46cd13ccaa..0000000000
--- a/libs/unimrcp/platforms/unimrcp-client/unimrcpclient.2008.vcproj
+++ /dev/null
@@ -1,200 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/platforms/unimrcp-client/unimrcpclient.rc b/libs/unimrcp/platforms/unimrcp-client/unimrcpclient.rc
new file mode 100644
index 0000000000..b7d34091c4
--- /dev/null
+++ b/libs/unimrcp/platforms/unimrcp-client/unimrcpclient.rc
@@ -0,0 +1,39 @@
+#include "uni_version.h"
+
+1 VERSIONINFO
+ FILEVERSION UNI_VERSION_STRING_CSV,0
+ PRODUCTVERSION UNI_VERSION_STRING_CSV,0
+ FILEFLAGSMASK 0x3fL
+#if defined(_DEBUG)
+ FILEFLAGS 0x01L
+#else
+ FILEFLAGS 0x00L
+#endif
+#if defined(WINNT) || defined(WIN64)
+ FILEOS 0x40004L
+#else
+ FILEOS 0x4L
+#endif
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Comments", UNI_LICENSE "\0"
+ VALUE "CompanyName", "UniMRCP\0"
+ VALUE "FileDescription", "UniMRCP Client Application\0"
+ VALUE "FileVersion", UNI_VERSION_STRING "\0"
+ VALUE "InternalName", "unimrcpclient" "\0"
+ VALUE "LegalCopyright", UNI_COPYRIGHT "\0"
+ VALUE "OriginalFilename", "unimrcpclient.exe" "\0"
+ VALUE "ProductName", "UniMRCP Project\0"
+ VALUE "ProductVersion", UNI_VERSION_STRING "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/libs/unimrcp/platforms/unimrcp-client/unimrcpclient.vcproj b/libs/unimrcp/platforms/unimrcp-client/unimrcpclient.vcproj
index 36b3bf1072..706498e4a4 100644
--- a/libs/unimrcp/platforms/unimrcp-client/unimrcpclient.vcproj
+++ b/libs/unimrcp/platforms/unimrcp-client/unimrcpclient.vcproj
@@ -326,6 +326,42 @@
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/unimrcp/platforms/unimrcp-server/src/main.c b/libs/unimrcp/platforms/unimrcp-server/src/main.c
index eb283f957c..3d2c75e78b 100644
--- a/libs/unimrcp/platforms/unimrcp-server/src/main.c
+++ b/libs/unimrcp/platforms/unimrcp-server/src/main.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: main.c 1785 2010-09-22 06:14:29Z achaloyan $
*/
#include
@@ -22,10 +24,10 @@
#include "apt_log.h"
typedef struct {
- const char *root_dir_path;
- apt_bool_t foreground;
- apt_log_priority_e log_priority;
- apt_log_output_e log_output;
+ const char *root_dir_path;
+ apt_bool_t foreground;
+ const char *log_priority;
+ const char *log_output;
} server_options_t;
#ifdef WIN32
@@ -98,14 +100,10 @@ static apt_bool_t options_load(server_options_t *options, int argc, const char *
options->root_dir_path = optarg;
break;
case 'l':
- if(optarg) {
- options->log_priority = atoi(optarg);
- }
+ options->log_priority = optarg;
break;
case 'o':
- if(optarg) {
- options->log_output = atoi(optarg);
- }
+ options->log_output = optarg;
break;
#ifdef WIN32
case 's':
@@ -135,6 +133,7 @@ int main(int argc, const char * const *argv)
apr_pool_t *pool = NULL;
server_options_t options;
apt_dir_layout_t *dir_layout;
+ const char *log_conf_path;
/* APR global initialization */
if(apr_initialize() != APR_SUCCESS) {
@@ -152,8 +151,8 @@ int main(int argc, const char * const *argv)
/* set the default options */
options.root_dir_path = "../";
options.foreground = TRUE;
- options.log_priority = APT_PRIO_INFO;
- options.log_output = APT_LOG_OUTPUT_CONSOLE;
+ options.log_priority = NULL;
+ options.log_output = NULL;
/* load options */
if(options_load(&options,argc,argv,pool) != TRUE) {
@@ -164,12 +163,24 @@ int main(int argc, const char * const *argv)
/* create the structure of default directories layout */
dir_layout = apt_default_dir_layout_create(options.root_dir_path,pool);
- /* create singleton logger */
- apt_log_instance_create(options.log_output,options.log_priority,pool);
+
+ /* get path to logger configuration file */
+ log_conf_path = apt_confdir_filepath_get(dir_layout,"logger.xml",pool);
+ /* create and load singleton logger */
+ apt_log_instance_load(log_conf_path,pool);
- if((options.log_output & APT_LOG_OUTPUT_FILE) == APT_LOG_OUTPUT_FILE) {
+ if(options.log_priority) {
+ /* override the log priority, if specified in command line */
+ apt_log_priority_set(atoi(options.log_priority));
+ }
+ if(options.log_output) {
+ /* override the log output mode, if specified in command line */
+ apt_log_output_mode_set(atoi(options.log_output));
+ }
+
+ if(apt_log_output_mode_check(APT_LOG_OUTPUT_FILE) == TRUE) {
/* open the log file */
- apt_log_file_open(dir_layout->log_dir_path,"unimrcpserver",MAX_LOG_FILE_SIZE,MAX_LOG_FILE_COUNT,pool);
+ apt_log_file_open(dir_layout->log_dir_path,"unimrcpserver",MAX_LOG_FILE_SIZE,MAX_LOG_FILE_COUNT,TRUE,pool);
}
if(options.foreground == TRUE) {
diff --git a/libs/unimrcp/platforms/unimrcp-server/src/uni_cmdline.c b/libs/unimrcp/platforms/unimrcp-server/src/uni_cmdline.c
index bac1d6685e..36db7f6412 100644
--- a/libs/unimrcp/platforms/unimrcp-server/src/uni_cmdline.c
+++ b/libs/unimrcp/platforms/unimrcp-server/src/uni_cmdline.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: uni_cmdline.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include
diff --git a/libs/unimrcp/platforms/unimrcp-server/src/uni_daemon.c b/libs/unimrcp/platforms/unimrcp-server/src/uni_daemon.c
index ee7287009b..76c1b00a87 100644
--- a/libs/unimrcp/platforms/unimrcp-server/src/uni_daemon.c
+++ b/libs/unimrcp/platforms/unimrcp-server/src/uni_daemon.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: uni_daemon.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include
diff --git a/libs/unimrcp/platforms/unimrcp-server/src/uni_service.c b/libs/unimrcp/platforms/unimrcp-server/src/uni_service.c
index 9b597d88d9..b179b90e7b 100644
--- a/libs/unimrcp/platforms/unimrcp-server/src/uni_service.c
+++ b/libs/unimrcp/platforms/unimrcp-server/src/uni_service.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: uni_service.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include
diff --git a/libs/unimrcp/platforms/unimrcp-server/unimrcpserver.2008.vcproj b/libs/unimrcp/platforms/unimrcp-server/unimrcpserver.2008.vcproj
deleted file mode 100644
index 147b8dccde..0000000000
--- a/libs/unimrcp/platforms/unimrcp-server/unimrcpserver.2008.vcproj
+++ /dev/null
@@ -1,174 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/platforms/unimrcp-server/unimrcpserver.rc b/libs/unimrcp/platforms/unimrcp-server/unimrcpserver.rc
new file mode 100644
index 0000000000..7c562afc96
--- /dev/null
+++ b/libs/unimrcp/platforms/unimrcp-server/unimrcpserver.rc
@@ -0,0 +1,39 @@
+#include "uni_version.h"
+
+1 VERSIONINFO
+ FILEVERSION UNI_VERSION_STRING_CSV,0
+ PRODUCTVERSION UNI_VERSION_STRING_CSV,0
+ FILEFLAGSMASK 0x3fL
+#if defined(_DEBUG)
+ FILEFLAGS 0x01L
+#else
+ FILEFLAGS 0x00L
+#endif
+#if defined(WINNT) || defined(WIN64)
+ FILEOS 0x40004L
+#else
+ FILEOS 0x4L
+#endif
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Comments", UNI_LICENSE "\0"
+ VALUE "CompanyName", "UniMRCP\0"
+ VALUE "FileDescription", "UniMRCP Server Application\0"
+ VALUE "FileVersion", UNI_VERSION_STRING "\0"
+ VALUE "InternalName", "unimrcpserver" "\0"
+ VALUE "LegalCopyright", UNI_COPYRIGHT "\0"
+ VALUE "OriginalFilename", "unimrcpserver.exe" "\0"
+ VALUE "ProductName", "UniMRCP Project\0"
+ VALUE "ProductVersion", UNI_VERSION_STRING "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x409, 1200
+ END
+END
diff --git a/libs/unimrcp/platforms/unimrcp-server/unimrcpserver.vcproj b/libs/unimrcp/platforms/unimrcp-server/unimrcpserver.vcproj
index c2b6f6c3f7..46e57dab5a 100644
--- a/libs/unimrcp/platforms/unimrcp-server/unimrcpserver.vcproj
+++ b/libs/unimrcp/platforms/unimrcp-server/unimrcpserver.vcproj
@@ -298,6 +298,42 @@
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libs/unimrcp/plugins/Makefile.am b/libs/unimrcp/plugins/Makefile.am
index 9bc7eb75c8..9d8b7b5964 100644
--- a/libs/unimrcp/plugins/Makefile.am
+++ b/libs/unimrcp/plugins/Makefile.am
@@ -10,12 +10,12 @@ if DEMORECOG_PLUGIN
SUBDIRS += demo-recog
endif
-if RECORDER_PLUGIN
-SUBDIRS += mrcp-recorder
+if DEMOVERIFIER_PLUGIN
+SUBDIRS += demo-verifier
endif
-if CEPSTRAL_PLUGIN
-SUBDIRS += mrcp-cepstral
+if RECORDER_PLUGIN
+SUBDIRS += mrcp-recorder
endif
if POCKETSPHINX_PLUGIN
diff --git a/libs/unimrcp/plugins/demo-recog/demorecog.2008.vcproj b/libs/unimrcp/plugins/demo-recog/demorecog.2008.vcproj
deleted file mode 100644
index ff23c031b4..0000000000
--- a/libs/unimrcp/plugins/demo-recog/demorecog.2008.vcproj
+++ /dev/null
@@ -1,164 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/plugins/demo-recog/src/demo_recog_engine.c b/libs/unimrcp/plugins/demo-recog/src/demo_recog_engine.c
index 5c1e66f38b..95681c8c84 100644
--- a/libs/unimrcp/plugins/demo-recog/src/demo_recog_engine.c
+++ b/libs/unimrcp/plugins/demo-recog/src/demo_recog_engine.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: demo_recog_engine.c 1706 2010-05-23 14:11:11Z achaloyan $
*/
/*
@@ -175,7 +177,7 @@ static apt_bool_t demo_recog_engine_open(mrcp_engine_t *engine)
apt_task_t *task = apt_consumer_task_base_get(demo_engine->task);
apt_task_start(task);
}
- return TRUE;
+ return mrcp_engine_open_respond(engine,TRUE);
}
/** Close recognizer engine */
@@ -186,7 +188,7 @@ static apt_bool_t demo_recog_engine_close(mrcp_engine_t *engine)
apt_task_t *task = apt_consumer_task_base_get(demo_engine->task);
apt_task_terminate(task,TRUE);
}
- return TRUE;
+ return mrcp_engine_close_respond(engine);
}
static mrcp_engine_channel_t* demo_recog_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool)
@@ -459,15 +461,18 @@ static apt_bool_t demo_recog_stream_write(mpf_audio_stream_t *stream, const mpf_
mpf_detector_event_e det_event = mpf_activity_detector_process(recog_channel->detector,frame);
switch(det_event) {
case MPF_DETECTOR_EVENT_ACTIVITY:
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected Voice Activity");
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected Voice Activity "APT_SIDRES_FMT,
+ MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
demo_recog_start_of_input(recog_channel);
break;
case MPF_DETECTOR_EVENT_INACTIVITY:
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected Voice Inactivity");
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected Voice Inactivity "APT_SIDRES_FMT,
+ MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
demo_recog_recognition_complete(recog_channel,RECOGNIZER_COMPLETION_CAUSE_SUCCESS);
break;
case MPF_DETECTOR_EVENT_NOINPUT:
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected Noinput");
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected Noinput "APT_SIDRES_FMT,
+ MRCP_MESSAGE_SIDRES(recog_channel->recog_request));
if(recog_channel->timers_started == TRUE) {
demo_recog_recognition_complete(recog_channel,RECOGNIZER_COMPLETION_CAUSE_NO_INPUT_TIMEOUT);
}
@@ -478,11 +483,13 @@ static apt_bool_t demo_recog_stream_write(mpf_audio_stream_t *stream, const mpf_
if((frame->type & MEDIA_FRAME_TYPE_EVENT) == MEDIA_FRAME_TYPE_EVENT) {
if(frame->marker == MPF_MARKER_START_OF_EVENT) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected Start of Event: id [%d]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected Start of Event "APT_SIDRES_FMT" id:%d",
+ MRCP_MESSAGE_SIDRES(recog_channel->recog_request),
frame->event_frame.event_id);
}
else if(frame->marker == MPF_MARKER_END_OF_EVENT) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected End of Event: id [%d] duration [%d ts]",
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected End of Event "APT_SIDRES_FMT" id:%d duration:%d ts",
+ MRCP_MESSAGE_SIDRES(recog_channel->recog_request),
frame->event_frame.event_id,
frame->event_frame.duration);
}
diff --git a/libs/unimrcp/plugins/demo-synth/demosynth.2008.vcproj b/libs/unimrcp/plugins/demo-synth/demosynth.2008.vcproj
deleted file mode 100644
index 3c5897e6ee..0000000000
--- a/libs/unimrcp/plugins/demo-synth/demosynth.2008.vcproj
+++ /dev/null
@@ -1,164 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/plugins/demo-synth/src/demo_synth_engine.c b/libs/unimrcp/plugins/demo-synth/src/demo_synth_engine.c
index 5374fdc75a..9daa99f5e3 100644
--- a/libs/unimrcp/plugins/demo-synth/src/demo_synth_engine.c
+++ b/libs/unimrcp/plugins/demo-synth/src/demo_synth_engine.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: demo_synth_engine.c 1706 2010-05-23 14:11:11Z achaloyan $
*/
/*
@@ -177,7 +179,7 @@ static apt_bool_t demo_synth_engine_open(mrcp_engine_t *engine)
apt_task_t *task = apt_consumer_task_base_get(demo_engine->task);
apt_task_start(task);
}
- return TRUE;
+ return mrcp_engine_open_respond(engine,TRUE);
}
/** Close synthesizer engine */
@@ -188,7 +190,7 @@ static apt_bool_t demo_synth_engine_close(mrcp_engine_t *engine)
apt_task_t *task = apt_consumer_task_base_get(demo_engine->task);
apt_task_terminate(task,TRUE);
}
- return TRUE;
+ return mrcp_engine_close_respond(engine);
}
/** Create demo synthesizer channel derived from engine channel base */
@@ -270,10 +272,14 @@ static apt_bool_t demo_synth_channel_speak(mrcp_engine_channel_t *channel, mrcp_
if(file_path) {
synth_channel->audio_file = fopen(file_path,"rb");
if(synth_channel->audio_file) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Set [%s] as Speech Source",file_path);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Set [%s] as Speech Source "APT_SIDRES_FMT,
+ file_path,
+ MRCP_MESSAGE_SIDRES(request));
}
else {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"No Speech Source [%s] Found",file_path);
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"No Speech Source [%s] Found "APT_SIDRES_FMT,
+ file_path,
+ MRCP_MESSAGE_SIDRES(request));
/* calculate estimated time to complete */
if(mrcp_generic_header_property_check(request,GENERIC_HEADER_CONTENT_LENGTH) == TRUE) {
mrcp_generic_header_t *generic_header = mrcp_generic_header_get(request);
diff --git a/libs/unimrcp/plugins/mrcp-cepstral/Makefile.am b/libs/unimrcp/plugins/demo-verifier/Makefile.am
similarity index 70%
rename from libs/unimrcp/plugins/mrcp-cepstral/Makefile.am
rename to libs/unimrcp/plugins/demo-verifier/Makefile.am
index 38b9bab308..175950a055 100644
--- a/libs/unimrcp/plugins/mrcp-cepstral/Makefile.am
+++ b/libs/unimrcp/plugins/demo-verifier/Makefile.am
@@ -8,10 +8,9 @@ INCLUDES = -Iinclude \
-I$(top_srcdir)/libs/mrcp/resources/include \
-I$(top_srcdir)/libs/mpf/include \
-I$(top_srcdir)/libs/apr-toolkit/include \
- $(UNIMRCP_APR_INCLUDES) $(UNIMRCP_APU_INCLUDES) $(UNIMRCP_SWIFT_INCLUDES)
+ $(UNIMRCP_APR_INCLUDES) $(UNIMRCP_APU_INCLUDES)
-plugin_LTLIBRARIES = mrcpcepstral.la
+plugin_LTLIBRARIES = demoverifier.la
-mrcpcepstral_la_SOURCES = src/mrcp_swift.c
-mrcpcepstral_la_LDFLAGS = -module $(PLUGIN_LT_VERSION) $(UNIMRCP_SWIFT_LDFLAGS)
-mrcpcepstral_la_LIBADD = $(UNIMRCP_SWIFT_LIBS)
+demoverifier_la_SOURCES = src/demo_verifier_engine.c
+demoverifier_la_LDFLAGS = -module $(PLUGIN_LT_VERSION)
diff --git a/libs/unimrcp/plugins/mrcp-cepstral/mrcpcepstral.vcproj b/libs/unimrcp/plugins/demo-verifier/demoverifier.vcproj
similarity index 93%
rename from libs/unimrcp/plugins/mrcp-cepstral/mrcpcepstral.vcproj
rename to libs/unimrcp/plugins/demo-verifier/demoverifier.vcproj
index e5a57dea79..efe5f79423 100644
--- a/libs/unimrcp/plugins/mrcp-cepstral/mrcpcepstral.vcproj
+++ b/libs/unimrcp/plugins/demo-verifier/demoverifier.vcproj
@@ -2,9 +2,9 @@
@@ -21,7 +21,7 @@
@@ -146,7 +146,7 @@
@@ -286,7 +286,7 @@
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
>
diff --git a/libs/unimrcp/plugins/demo-verifier/src/demo_verifier_engine.c b/libs/unimrcp/plugins/demo-verifier/src/demo_verifier_engine.c
new file mode 100644
index 0000000000..8918bedcbf
--- /dev/null
+++ b/libs/unimrcp/plugins/demo-verifier/src/demo_verifier_engine.c
@@ -0,0 +1,577 @@
+/*
+ * Copyright 2008-2010 Arsen Chaloyan
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * $Id: demo_verifier_engine.c 1776 2010-08-27 16:36:38Z achaloyan $
+ */
+
+/*
+ * Mandatory rules concerning plugin implementation.
+ * 1. Each plugin MUST implement a plugin/engine creator function
+ * with the exact signature and name (the main entry point)
+ * MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
+ * 2. Each plugin MUST declare its version number
+ * MRCP_PLUGIN_VERSION_DECLARE
+ * 3. One and only one response MUST be sent back to the received request.
+ * 4. Methods (callbacks) of the MRCP engine channel MUST not block.
+ * (asynchronous response can be sent from the context of other thread)
+ * 5. Methods (callbacks) of the MPF engine stream MUST not block.
+ */
+
+#include "mrcp_verifier_engine.h"
+#include "mpf_activity_detector.h"
+#include "apt_consumer_task.h"
+#include "apt_log.h"
+
+#define VERIFIER_ENGINE_TASK_NAME "Demo Verifier Engine"
+
+typedef struct demo_verifier_engine_t demo_verifier_engine_t;
+typedef struct demo_verifier_channel_t demo_verifier_channel_t;
+typedef struct demo_verifier_msg_t demo_verifier_msg_t;
+
+/** Declaration of verification engine methods */
+static apt_bool_t demo_verifier_engine_destroy(mrcp_engine_t *engine);
+static apt_bool_t demo_verifier_engine_open(mrcp_engine_t *engine);
+static apt_bool_t demo_verifier_engine_close(mrcp_engine_t *engine);
+static mrcp_engine_channel_t* demo_verifier_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool);
+
+static const struct mrcp_engine_method_vtable_t engine_vtable = {
+ demo_verifier_engine_destroy,
+ demo_verifier_engine_open,
+ demo_verifier_engine_close,
+ demo_verifier_engine_channel_create
+};
+
+
+/** Declaration of verification channel methods */
+static apt_bool_t demo_verifier_channel_destroy(mrcp_engine_channel_t *channel);
+static apt_bool_t demo_verifier_channel_open(mrcp_engine_channel_t *channel);
+static apt_bool_t demo_verifier_channel_close(mrcp_engine_channel_t *channel);
+static apt_bool_t demo_verifier_channel_request_process(mrcp_engine_channel_t *channel, mrcp_message_t *request);
+
+static const struct mrcp_engine_channel_method_vtable_t channel_vtable = {
+ demo_verifier_channel_destroy,
+ demo_verifier_channel_open,
+ demo_verifier_channel_close,
+ demo_verifier_channel_request_process
+};
+
+/** Declaration of verification audio stream methods */
+static apt_bool_t demo_verifier_stream_destroy(mpf_audio_stream_t *stream);
+static apt_bool_t demo_verifier_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec);
+static apt_bool_t demo_verifier_stream_close(mpf_audio_stream_t *stream);
+static apt_bool_t demo_verifier_stream_write(mpf_audio_stream_t *stream, const mpf_frame_t *frame);
+
+static const mpf_audio_stream_vtable_t audio_stream_vtable = {
+ demo_verifier_stream_destroy,
+ NULL,
+ NULL,
+ NULL,
+ demo_verifier_stream_open,
+ demo_verifier_stream_close,
+ demo_verifier_stream_write
+};
+
+/** Declaration of demo verification engine */
+struct demo_verifier_engine_t {
+ apt_consumer_task_t *task;
+};
+
+/** Declaration of demo verification channel */
+struct demo_verifier_channel_t {
+ /** Back pointer to engine */
+ demo_verifier_engine_t *demo_engine;
+ /** Engine channel base */
+ mrcp_engine_channel_t *channel;
+
+ /** Active (in-progress) verification request */
+ mrcp_message_t *verifier_request;
+ /** Pending stop response */
+ mrcp_message_t *stop_response;
+ /** Indicates whether input timers are started */
+ apt_bool_t timers_started;
+ /** Voice activity detector */
+ mpf_activity_detector_t *detector;
+ /** File to write voiceprint to */
+ FILE *audio_out;
+};
+
+typedef enum {
+ DEMO_VERIF_MSG_OPEN_CHANNEL,
+ DEMO_VERIF_MSG_CLOSE_CHANNEL,
+ DEMO_VERIF_MSG_REQUEST_PROCESS
+} demo_verifier_msg_type_e;
+
+/** Declaration of demo verification task message */
+struct demo_verifier_msg_t {
+ demo_verifier_msg_type_e type;
+ mrcp_engine_channel_t *channel;
+ mrcp_message_t *request;
+};
+
+static apt_bool_t demo_verifier_msg_signal(demo_verifier_msg_type_e type, mrcp_engine_channel_t *channel, mrcp_message_t *request);
+static apt_bool_t demo_verifier_msg_process(apt_task_t *task, apt_task_msg_t *msg);
+
+static apt_bool_t demo_verifier_result_load(demo_verifier_channel_t *verifier_channel, mrcp_message_t *message);
+
+/** Declare this macro to set plugin version */
+MRCP_PLUGIN_VERSION_DECLARE
+
+/** Declare this macro to use log routine of the server, plugin is loaded from */
+MRCP_PLUGIN_LOGGER_IMPLEMENT
+
+/** Create demo verification engine */
+MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
+{
+ demo_verifier_engine_t *demo_engine = apr_palloc(pool,sizeof(demo_verifier_engine_t));
+ apt_task_t *task;
+ apt_task_vtable_t *vtable;
+ apt_task_msg_pool_t *msg_pool;
+
+ msg_pool = apt_task_msg_pool_create_dynamic(sizeof(demo_verifier_msg_t),pool);
+ demo_engine->task = apt_consumer_task_create(demo_engine,msg_pool,pool);
+ if(!demo_engine->task) {
+ return NULL;
+ }
+ task = apt_consumer_task_base_get(demo_engine->task);
+ apt_task_name_set(task,VERIFIER_ENGINE_TASK_NAME);
+ vtable = apt_task_vtable_get(task);
+ if(vtable) {
+ vtable->process_msg = demo_verifier_msg_process;
+ }
+
+ /* create engine base */
+ return mrcp_engine_create(
+ MRCP_VERIFIER_RESOURCE, /* MRCP resource identifier */
+ demo_engine, /* object to associate */
+ &engine_vtable, /* virtual methods table of engine */
+ pool); /* pool to allocate memory from */
+}
+
+/** Destroy verification engine */
+static apt_bool_t demo_verifier_engine_destroy(mrcp_engine_t *engine)
+{
+ demo_verifier_engine_t *demo_engine = engine->obj;
+ if(demo_engine->task) {
+ apt_task_t *task = apt_consumer_task_base_get(demo_engine->task);
+ apt_task_destroy(task);
+ demo_engine->task = NULL;
+ }
+ return TRUE;
+}
+
+/** Open verification engine */
+static apt_bool_t demo_verifier_engine_open(mrcp_engine_t *engine)
+{
+ demo_verifier_engine_t *demo_engine = engine->obj;
+ if(demo_engine->task) {
+ apt_task_t *task = apt_consumer_task_base_get(demo_engine->task);
+ apt_task_start(task);
+ }
+ return mrcp_engine_open_respond(engine,TRUE);
+}
+
+/** Close verification engine */
+static apt_bool_t demo_verifier_engine_close(mrcp_engine_t *engine)
+{
+ demo_verifier_engine_t *demo_engine = engine->obj;
+ if(demo_engine->task) {
+ apt_task_t *task = apt_consumer_task_base_get(demo_engine->task);
+ apt_task_terminate(task,TRUE);
+ }
+ return mrcp_engine_close_respond(engine);
+}
+
+static mrcp_engine_channel_t* demo_verifier_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool)
+{
+ mpf_stream_capabilities_t *capabilities;
+ mpf_termination_t *termination;
+
+ /* create demo verification channel */
+ demo_verifier_channel_t *verifier_channel = apr_palloc(pool,sizeof(demo_verifier_channel_t));
+ verifier_channel->demo_engine = engine->obj;
+ verifier_channel->verifier_request = NULL;
+ verifier_channel->stop_response = NULL;
+ verifier_channel->detector = mpf_activity_detector_create(pool);
+ verifier_channel->audio_out = NULL;
+
+ capabilities = mpf_sink_stream_capabilities_create(pool);
+ mpf_codec_capabilities_add(
+ &capabilities->codecs,
+ MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000,
+ "LPCM");
+
+ /* create media termination */
+ termination = mrcp_engine_audio_termination_create(
+ verifier_channel, /* object to associate */
+ &audio_stream_vtable, /* virtual methods table of audio stream */
+ capabilities, /* stream capabilities */
+ pool); /* pool to allocate memory from */
+
+ /* create engine channel base */
+ verifier_channel->channel = mrcp_engine_channel_create(
+ engine, /* engine */
+ &channel_vtable, /* virtual methods table of engine channel */
+ verifier_channel, /* object to associate */
+ termination, /* associated media termination */
+ pool); /* pool to allocate memory from */
+
+ return verifier_channel->channel;
+}
+
+/** Destroy engine channel */
+static apt_bool_t demo_verifier_channel_destroy(mrcp_engine_channel_t *channel)
+{
+ /* nothing to destrtoy */
+ return TRUE;
+}
+
+/** Open engine channel (asynchronous response MUST be sent)*/
+static apt_bool_t demo_verifier_channel_open(mrcp_engine_channel_t *channel)
+{
+ return demo_verifier_msg_signal(DEMO_VERIF_MSG_OPEN_CHANNEL,channel,NULL);
+}
+
+/** Close engine channel (asynchronous response MUST be sent)*/
+static apt_bool_t demo_verifier_channel_close(mrcp_engine_channel_t *channel)
+{
+ return demo_verifier_msg_signal(DEMO_VERIF_MSG_CLOSE_CHANNEL,channel,NULL);
+}
+
+/** Process MRCP channel request (asynchronous response MUST be sent)*/
+static apt_bool_t demo_verifier_channel_request_process(mrcp_engine_channel_t *channel, mrcp_message_t *request)
+{
+ return demo_verifier_msg_signal(DEMO_VERIF_MSG_REQUEST_PROCESS,channel,request);
+}
+
+/** Process VERIFY request */
+static apt_bool_t demo_verifier_channel_verify(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
+{
+ /* process verify request */
+ mrcp_verifier_header_t *verifier_header;
+ demo_verifier_channel_t *verifier_channel = channel->method_obj;
+ verifier_channel->timers_started = TRUE;
+
+ /* get verifier header */
+ verifier_header = mrcp_resource_header_get(request);
+ if(verifier_header) {
+ if(mrcp_resource_header_property_check(request,VERIFIER_HEADER_START_INPUT_TIMERS) == TRUE) {
+ verifier_channel->timers_started = verifier_header->start_input_timers;
+ }
+ if(mrcp_resource_header_property_check(request,VERIFIER_HEADER_NO_INPUT_TIMEOUT) == TRUE) {
+ mpf_activity_detector_noinput_timeout_set(verifier_channel->detector,verifier_header->no_input_timeout);
+ }
+ if(mrcp_resource_header_property_check(request,VERIFIER_HEADER_SPEECH_COMPLETE_TIMEOUT) == TRUE) {
+ mpf_activity_detector_silence_timeout_set(verifier_channel->detector,verifier_header->speech_complete_timeout);
+ }
+ }
+
+ if(!verifier_channel->audio_out) {
+ const apt_dir_layout_t *dir_layout = channel->engine->dir_layout;
+ const mpf_codec_descriptor_t *descriptor = mrcp_engine_sink_stream_codec_get(channel);
+ char *file_name = apr_psprintf(channel->pool,"voiceprint-%dkHz-%s.pcm",
+ descriptor ? descriptor->sampling_rate/1000 : 8,
+ request->channel_id.session_id.buf);
+ char *file_path = apt_datadir_filepath_get(dir_layout,file_name,channel->pool);
+ if(file_path) {
+ verifier_channel->audio_out = fopen(file_path,"wb");
+ }
+ }
+
+ response->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
+ /* send asynchronous response */
+ mrcp_engine_channel_message_send(channel,response);
+ verifier_channel->verifier_request = request;
+ return TRUE;
+}
+
+/** Process STOP request */
+static apt_bool_t demo_verifier_channel_stop(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
+{
+ /* process STOP request */
+ demo_verifier_channel_t *verifier_channel = channel->method_obj;
+ /* store STOP request, make sure there is no more activity and only then send the response */
+ verifier_channel->stop_response = response;
+ return TRUE;
+}
+
+/** Process START-INPUT-TIMERS request */
+static apt_bool_t demo_verifier_channel_timers_start(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
+{
+ demo_verifier_channel_t *verifier_channel = channel->method_obj;
+ verifier_channel->timers_started = TRUE;
+ return mrcp_engine_channel_message_send(channel,response);
+}
+
+/** Process GET-INTERMEDIATE-RESULT request */
+static apt_bool_t demo_verifier_channel_get_result(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
+{
+ demo_verifier_channel_t *verifier_channel = channel->method_obj;
+ demo_verifier_result_load(verifier_channel,response);
+ return mrcp_engine_channel_message_send(channel,response);
+}
+
+
+/** Dispatch MRCP request */
+static apt_bool_t demo_verifier_channel_request_dispatch(mrcp_engine_channel_t *channel, mrcp_message_t *request)
+{
+ apt_bool_t processed = FALSE;
+ mrcp_message_t *response = mrcp_response_create(request,request->pool);
+ switch(request->start_line.method_id) {
+ case VERIFIER_SET_PARAMS:
+ break;
+ case VERIFIER_GET_PARAMS:
+ break;
+ case VERIFIER_START_SESSION:
+ break;
+ case VERIFIER_END_SESSION:
+ break;
+ case VERIFIER_QUERY_VOICEPRINT:
+ break;
+ case VERIFIER_DELETE_VOICEPRINT:
+ break;
+ case VERIFIER_VERIFY:
+ processed = demo_verifier_channel_verify(channel,request,response);
+ break;
+ case VERIFIER_VERIFY_FROM_BUFFER:
+ break;
+ case VERIFIER_VERIFY_ROLLBACK:
+ break;
+ case VERIFIER_STOP:
+ processed = demo_verifier_channel_stop(channel,request,response);
+ break;
+ case VERIFIER_CLEAR_BUFFER:
+ break;
+ case VERIFIER_START_INPUT_TIMERS:
+ processed = demo_verifier_channel_timers_start(channel,request,response);
+ break;
+ case VERIFIER_GET_INTERMIDIATE_RESULT:
+ processed = demo_verifier_channel_get_result(channel,request,response);
+ break;
+
+ default:
+ break;
+ }
+ if(processed == FALSE) {
+ /* send asynchronous response for not handled request */
+ mrcp_engine_channel_message_send(channel,response);
+ }
+ return TRUE;
+}
+
+/** Callback is called from MPF engine context to destroy any additional data associated with audio stream */
+static apt_bool_t demo_verifier_stream_destroy(mpf_audio_stream_t *stream)
+{
+ return TRUE;
+}
+
+/** Callback is called from MPF engine context to perform any action before open */
+static apt_bool_t demo_verifier_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
+{
+ return TRUE;
+}
+
+/** Callback is called from MPF engine context to perform any action after close */
+static apt_bool_t demo_verifier_stream_close(mpf_audio_stream_t *stream)
+{
+ return TRUE;
+}
+
+/* Raise demo START-OF-INPUT event */
+static apt_bool_t demo_verifier_start_of_input(demo_verifier_channel_t *verifier_channel)
+{
+ /* create START-OF-INPUT event */
+ mrcp_message_t *message = mrcp_event_create(
+ verifier_channel->verifier_request,
+ VERIFIER_START_OF_INPUT,
+ verifier_channel->verifier_request->pool);
+ if(!message) {
+ return FALSE;
+ }
+
+ /* set request state */
+ message->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
+ /* send asynch event */
+ return mrcp_engine_channel_message_send(verifier_channel->channel,message);
+}
+
+/* Load demo verification result */
+static apt_bool_t demo_verifier_result_load(demo_verifier_channel_t *verifier_channel, mrcp_message_t *message)
+{
+ FILE *file;
+ mrcp_engine_channel_t *channel = verifier_channel->channel;
+ const apt_dir_layout_t *dir_layout = channel->engine->dir_layout;
+ char *file_path = apt_datadir_filepath_get(dir_layout,"result-verification.xml",message->pool);
+ if(!file_path) {
+ return FALSE;
+ }
+
+ /* read the demo result from file */
+ file = fopen(file_path,"r");
+ if(file) {
+ mrcp_generic_header_t *generic_header;
+ char text[1024];
+ apr_size_t size;
+ size = fread(text,1,sizeof(text),file);
+ apt_string_assign_n(&message->body,text,size,message->pool);
+ fclose(file);
+
+ /* get/allocate generic header */
+ generic_header = mrcp_generic_header_prepare(message);
+ if(generic_header) {
+ /* set content types */
+ apt_string_assign(&generic_header->content_type,"application/nlsml+xml",message->pool);
+ mrcp_generic_header_property_add(message,GENERIC_HEADER_CONTENT_TYPE);
+ }
+ }
+ return TRUE;
+}
+
+/* Raise demo VERIFICATION-COMPLETE event */
+static apt_bool_t demo_verifier_verification_complete(demo_verifier_channel_t *verifier_channel, mrcp_verifier_completion_cause_e cause)
+{
+ mrcp_verifier_header_t *verifier_header;
+ /* create VERIFICATION-COMPLETE event */
+ mrcp_message_t *message = mrcp_event_create(
+ verifier_channel->verifier_request,
+ VERIFIER_VERIFICATION_COMPLETE,
+ verifier_channel->verifier_request->pool);
+ if(!message) {
+ return FALSE;
+ }
+
+ /* get/allocate verifier header */
+ verifier_header = mrcp_resource_header_prepare(message);
+ if(verifier_header) {
+ /* set completion cause */
+ verifier_header->completion_cause = cause;
+ mrcp_resource_header_property_add(message,VERIFIER_HEADER_COMPLETION_CAUSE);
+ }
+ /* set request state */
+ message->start_line.request_state = MRCP_REQUEST_STATE_COMPLETE;
+
+ if(cause == VERIFIER_COMPLETION_CAUSE_SUCCESS) {
+ demo_verifier_result_load(verifier_channel,message);
+ }
+
+ verifier_channel->verifier_request = NULL;
+ /* send asynch event */
+ return mrcp_engine_channel_message_send(verifier_channel->channel,message);
+}
+
+/** Callback is called from MPF engine context to write/send new frame */
+static apt_bool_t demo_verifier_stream_write(mpf_audio_stream_t *stream, const mpf_frame_t *frame)
+{
+ demo_verifier_channel_t *verifier_channel = stream->obj;
+ if(verifier_channel->stop_response) {
+ /* send asynchronous response to STOP request */
+ mrcp_engine_channel_message_send(verifier_channel->channel,verifier_channel->stop_response);
+ verifier_channel->stop_response = NULL;
+ verifier_channel->verifier_request = NULL;
+ return TRUE;
+ }
+
+ if(verifier_channel->verifier_request) {
+ mpf_detector_event_e det_event = mpf_activity_detector_process(verifier_channel->detector,frame);
+ switch(det_event) {
+ case MPF_DETECTOR_EVENT_ACTIVITY:
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected Voice Activity "APT_SIDRES_FMT,
+ MRCP_MESSAGE_SIDRES(verifier_channel->verifier_request));
+ demo_verifier_start_of_input(verifier_channel);
+ break;
+ case MPF_DETECTOR_EVENT_INACTIVITY:
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected Voice Inactivity "APT_SIDRES_FMT,
+ MRCP_MESSAGE_SIDRES(verifier_channel->verifier_request));
+ demo_verifier_verification_complete(verifier_channel,VERIFIER_COMPLETION_CAUSE_SUCCESS);
+ break;
+ case MPF_DETECTOR_EVENT_NOINPUT:
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected Noinput "APT_SIDRES_FMT,
+ MRCP_MESSAGE_SIDRES(verifier_channel->verifier_request));
+ if(verifier_channel->timers_started == TRUE) {
+ demo_verifier_verification_complete(verifier_channel,VERIFIER_COMPLETION_CAUSE_NO_INPUT_TIMEOUT);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if((frame->type & MEDIA_FRAME_TYPE_EVENT) == MEDIA_FRAME_TYPE_EVENT) {
+ if(frame->marker == MPF_MARKER_START_OF_EVENT) {
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected Start of Event "APT_SIDRES_FMT" id:%d",
+ MRCP_MESSAGE_SIDRES(verifier_channel->verifier_request),
+ frame->event_frame.event_id);
+ }
+ else if(frame->marker == MPF_MARKER_END_OF_EVENT) {
+ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Detected End of Event "APT_SIDRES_FMT" id:%d duration:%d ts",
+ MRCP_MESSAGE_SIDRES(verifier_channel->verifier_request),
+ frame->event_frame.event_id,
+ frame->event_frame.duration);
+ }
+ }
+
+ if(verifier_channel->audio_out) {
+ fwrite(frame->codec_frame.buffer,1,frame->codec_frame.size,verifier_channel->audio_out);
+ }
+ }
+ return TRUE;
+}
+
+static apt_bool_t demo_verifier_msg_signal(demo_verifier_msg_type_e type, mrcp_engine_channel_t *channel, mrcp_message_t *request)
+{
+ apt_bool_t status = FALSE;
+ demo_verifier_channel_t *demo_channel = channel->method_obj;
+ demo_verifier_engine_t *demo_engine = demo_channel->demo_engine;
+ apt_task_t *task = apt_consumer_task_base_get(demo_engine->task);
+ apt_task_msg_t *msg = apt_task_msg_get(task);
+ if(msg) {
+ demo_verifier_msg_t *demo_msg;
+ msg->type = TASK_MSG_USER;
+ demo_msg = (demo_verifier_msg_t*) msg->data;
+
+ demo_msg->type = type;
+ demo_msg->channel = channel;
+ demo_msg->request = request;
+ status = apt_task_msg_signal(task,msg);
+ }
+ return status;
+}
+
+static apt_bool_t demo_verifier_msg_process(apt_task_t *task, apt_task_msg_t *msg)
+{
+ demo_verifier_msg_t *demo_msg = (demo_verifier_msg_t*)msg->data;
+ switch(demo_msg->type) {
+ case DEMO_VERIF_MSG_OPEN_CHANNEL:
+ /* open channel and send asynch response */
+ mrcp_engine_channel_open_respond(demo_msg->channel,TRUE);
+ break;
+ case DEMO_VERIF_MSG_CLOSE_CHANNEL:
+ {
+ /* close channel, make sure there is no activity and send asynch response */
+ demo_verifier_channel_t *verifier_channel = demo_msg->channel->method_obj;
+ if(verifier_channel->audio_out) {
+ fclose(verifier_channel->audio_out);
+ verifier_channel->audio_out = NULL;
+ }
+
+ mrcp_engine_channel_close_respond(demo_msg->channel);
+ break;
+ }
+ case DEMO_VERIF_MSG_REQUEST_PROCESS:
+ demo_verifier_channel_request_dispatch(demo_msg->channel,demo_msg->request);
+ break;
+ default:
+ break;
+ }
+ return TRUE;
+}
diff --git a/libs/unimrcp/plugins/mrcp-cepstral/mrcpcepstral.2008.vcproj b/libs/unimrcp/plugins/mrcp-cepstral/mrcpcepstral.2008.vcproj
deleted file mode 100644
index abdb4cec4c..0000000000
--- a/libs/unimrcp/plugins/mrcp-cepstral/mrcpcepstral.2008.vcproj
+++ /dev/null
@@ -1,164 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/plugins/mrcp-cepstral/src/mrcp_swift.c b/libs/unimrcp/plugins/mrcp-cepstral/src/mrcp_swift.c
deleted file mode 100644
index 037939b8dd..0000000000
--- a/libs/unimrcp/plugins/mrcp-cepstral/src/mrcp_swift.c
+++ /dev/null
@@ -1,774 +0,0 @@
-/*
- * Copyright 2008 Arsen Chaloyan
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Mandatory rules concerning plugin implementation.
- * 1. Each plugin MUST implement a plugin/engine creator function
- * with the exact signature and name (the main entry point)
- * MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
- * 2. Each plugin MUST declare its version number
- * MRCP_PLUGIN_VERSION_DECLARE
- * 3. One and only one response MUST be sent back to the received request.
- * 4. Methods (callbacks) of the MRCP engine channel MUST not block.
- * (asynchronous response can be sent from the context of other thread)
- * 5. Methods (callbacks) of the MPF engine stream MUST not block.
- */
-
-#include
-#include
-#include "mrcp_synth_engine.h"
-#include "mpf_buffer.h"
-#include "apt_log.h"
-
-/** Declaration of synthesizer engine methods */
-static apt_bool_t mrcp_swift_engine_destroy(mrcp_engine_t *engine);
-static apt_bool_t mrcp_swift_engine_open(mrcp_engine_t *engine);
-static apt_bool_t mrcp_swift_engine_close(mrcp_engine_t *engine);
-static mrcp_engine_channel_t* mrcp_swift_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool);
-
-static const struct mrcp_engine_method_vtable_t engine_vtable = {
- mrcp_swift_engine_destroy,
- mrcp_swift_engine_open,
- mrcp_swift_engine_close,
- mrcp_swift_engine_channel_create
-};
-
-
-/** Declaration of synthesizer channel methods */
-static apt_bool_t mrcp_swift_channel_destroy(mrcp_engine_channel_t *channel);
-static apt_bool_t mrcp_swift_channel_open(mrcp_engine_channel_t *channel);
-static apt_bool_t mrcp_swift_channel_close(mrcp_engine_channel_t *channel);
-static apt_bool_t mrcp_swift_channel_request_process(mrcp_engine_channel_t *channel, mrcp_message_t *request);
-
-static const struct mrcp_engine_channel_method_vtable_t channel_vtable = {
- mrcp_swift_channel_destroy,
- mrcp_swift_channel_open,
- mrcp_swift_channel_close,
- mrcp_swift_channel_request_process
-};
-
-/** Declaration of synthesizer audio stream methods */
-static apt_bool_t synth_stream_destroy(mpf_audio_stream_t *stream);
-static apt_bool_t synth_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec);
-static apt_bool_t synth_stream_close(mpf_audio_stream_t *stream);
-static apt_bool_t synth_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame);
-
-static const mpf_audio_stream_vtable_t audio_stream_vtable = {
- synth_stream_destroy,
- synth_stream_open,
- synth_stream_close,
- synth_stream_read,
- NULL,
- NULL,
- NULL
-};
-
-typedef struct mrcp_swift_engine_t mrcp_swift_engine_t;
-/** Declaration of Swift synthesizer engine */
-struct mrcp_swift_engine_t {
- /** Swift synthesizer engine */
- swift_engine *swift;
- /** Speech language mapping */
- apr_table_t *language_table;
- /** Sampling rates (bitmask of mpf_sample_rates_e)
- installed voices support */
- int sample_rates;
-};
-
-typedef struct mrcp_swift_channel_t mrcp_swift_channel_t;
-/** Declaration of Swift synthesizer channel */
-struct mrcp_swift_channel_t {
- /** Swift port */
- swift_port *port;
- swift_background_t tts_stream;
-
- /** Audio buffer */
- mpf_buffer_t *audio_buffer;
-
- /** Engine channel base */
- mrcp_engine_channel_t *channel;
-
- /** Active (in-progress) speak request */
- mrcp_message_t *speak_request;
- /** Pending stop response */
- mrcp_message_t *stop_response;
- /** Is paused */
- apt_bool_t paused;
-};
-
-/** Table of prosody volumes for Swift engine */
-static const int swift_prosody_volume_table[PROSODY_VOLUME_COUNT] = {
- 25, /* PROSODY_VOLUME_SILENT */
- 50, /* PROSODY_VOLUME_XSOFT */
- 75, /* PROSODY_VOLUME_SOFT */
- 100, /* PROSODY_VOLUME_MEDIUM */
- 125, /* PROSODY_VOLUME_LOUD */
- 150, /* PROSODY_VOLUME_XLOUD */
- 100 /* PROSODY_VOLUME_DEFAULT */
-};
-
-/** Table of prosody rates for Swift engine */
-static const int swift_prosody_rate_table[PROSODY_RATE_COUNT] = {
- 85, /* PROSODY_RATE_XSLOW */
- 113, /* PROSODY_RATE_SLOW */
- 170, /* PROSODY_RATE_MEDIUM */
- 225, /* PROSODY_RATE_FAST */
- 340, /* PROSODY_RATE_XFAST */
- 170 /* PROSODY_RATE_DEFAULT */
-};
-
-
-static apr_table_t* mrcp_swift_language_table_create(apr_pool_t *pool);
-static apt_bool_t mrcp_swift_voices_scan(mrcp_swift_engine_t *engine);
-static swift_result_t mrcp_swift_write_audio(swift_event *event, swift_event_t type, void *udata);
-static apt_bool_t mrcp_swift_channel_voice_set(mrcp_swift_channel_t *synth_channel, mrcp_message_t *message);
-static apt_bool_t mrcp_swift_channel_params_set(mrcp_swift_channel_t *synth_channel, mrcp_message_t *message);
-
-/** Declare this macro to set plugin version */
-MRCP_PLUGIN_VERSION_DECLARE
-
-/** Declare this macro to use log routine of the server, plugin is loaded from */
-MRCP_PLUGIN_LOGGER_IMPLEMENT
-
-/** Create Swift synthesizer engine */
-MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
-{
- mrcp_swift_engine_t *synth_engine = apr_palloc(pool,sizeof(mrcp_swift_engine_t));
- synth_engine->swift = NULL;
- synth_engine->language_table = mrcp_swift_language_table_create(pool);
- synth_engine->sample_rates = MPF_SAMPLE_RATE_NONE;
-
- /* create engine base */
- return mrcp_engine_create(
- MRCP_SYNTHESIZER_RESOURCE, /* MRCP resource identifier */
- synth_engine, /* object to associate */
- &engine_vtable, /* virtual methods table of engine */
- pool); /* pool to allocate memory from */
-}
-
-/** Destroy synthesizer engine */
-static apt_bool_t mrcp_swift_engine_destroy(mrcp_engine_t *engine)
-{
- /* nothing to destroy */
- return TRUE;
-}
-
-/** Open synthesizer engine */
-static apt_bool_t mrcp_swift_engine_open(mrcp_engine_t *engine)
-{
- mrcp_swift_engine_t *synth_engine = engine->obj;
-
- /* open swift engine */
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Open Swift Engine [%s]",swift_version);
- if((synth_engine->swift = swift_engine_open(NULL)) == NULL) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open Swift Engine");
- return FALSE;
- }
-
- if(mrcp_swift_voices_scan(synth_engine) == FALSE) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Scan Swift Voices");
- swift_engine_close(synth_engine->swift);
- synth_engine->swift = NULL;
- return FALSE;
- }
- return TRUE;
-}
-
-/** Close synthesizer engine */
-static apt_bool_t mrcp_swift_engine_close(mrcp_engine_t *engine)
-{
- mrcp_swift_engine_t *synth_engine = engine->obj;
-
- /* close swift engine */
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Close Swift Engine");
- if(synth_engine->swift) {
- swift_engine_close(synth_engine->swift);
- synth_engine->swift = NULL;
- }
- return TRUE;
-}
-
-/** Create demo synthesizer channel derived from engine channel base */
-static mrcp_engine_channel_t* mrcp_swift_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool)
-{
- mrcp_swift_engine_t *synth_engine = engine->obj;
-
- mpf_stream_capabilities_t *capabilities;
- mpf_termination_t *termination;
- mrcp_engine_channel_t *channel;
-
- /* create swift synth channel */
- mrcp_swift_channel_t *synth_channel = apr_palloc(pool,sizeof(mrcp_swift_channel_t));
- synth_channel->port = NULL;
- synth_channel->tts_stream = 0;
- synth_channel->channel = NULL;
- synth_channel->audio_buffer = NULL;
- synth_channel->speak_request = NULL;
- synth_channel->stop_response = NULL;
- synth_channel->paused = FALSE;
-
- capabilities = mpf_source_stream_capabilities_create(pool);
- mpf_codec_capabilities_add(
- &capabilities->codecs,
- synth_engine->sample_rates,
- "LPCM");
-
- /* create media termination */
- termination = mrcp_engine_audio_termination_create(
- synth_channel, /* object to associate */
- &audio_stream_vtable, /* virtual methods table of audio stream */
- capabilities, /* stream capabilities */
- pool); /* pool to allocate memory from */
-
- /* create engine channel base */
- channel = mrcp_engine_channel_create(
- engine, /* engine */
- &channel_vtable, /* virtual methods table of engine channel */
- synth_channel, /* object to associate */
- termination, /* associated media termination */
- pool); /* pool to allocate memory from */
-
- if(channel) {
- synth_channel->audio_buffer = mpf_buffer_create(pool);
- }
- synth_channel->channel = channel;
- return channel;
-}
-
-/** Destroy engine channel */
-static apt_bool_t mrcp_swift_channel_destroy(mrcp_engine_channel_t *channel)
-{
- /* nothing to destroy */
- return TRUE;
-}
-
-/** Open engine channel (asynchronous response MUST be sent)*/
-static apt_bool_t mrcp_swift_channel_open(mrcp_engine_channel_t *channel)
-{
- /* open channel and send asynch response */
- apt_bool_t status = FALSE;
- mrcp_swift_channel_t *synth_channel = channel->method_obj;
- mrcp_swift_engine_t *synth_engine = channel->engine->obj;
- const mpf_codec_descriptor_t *descriptor = mrcp_engine_source_stream_codec_get(synth_channel->channel);
- if(descriptor) {
- swift_params *params;
- swift_port *port;
-
- params = swift_params_new(NULL);
- swift_params_set_string(params, "audio/encoding", "pcm16");
- swift_params_set_int(params, "audio/sampling-rate", descriptor->sampling_rate);
- /* open swift port */
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Open Swift Port");
- port = swift_port_open(synth_engine->swift,params);
- if(port) {
- /* set swift_write_audio as a callback, with the output file as its param */
- swift_port_set_callback(port, &mrcp_swift_write_audio, SWIFT_EVENT_AUDIO | SWIFT_EVENT_END, synth_channel);
- synth_channel->port = port;
- status = TRUE;
- }
- else {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open Swift Port");
- }
- }
-
- return mrcp_engine_channel_open_respond(channel,status);
-}
-
-/** Close engine channel (asynchronous response MUST be sent)*/
-static apt_bool_t mrcp_swift_channel_close(mrcp_engine_channel_t *channel)
-{
- /* close channel, make sure there is no activity and send asynch response */
- mrcp_swift_channel_t *synth_channel = channel->method_obj;
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Close Swift Port");
- if(synth_channel->port) {
- /* close swift port */
- swift_port_close(synth_channel->port);
- synth_channel->port = NULL;
- }
-
- return mrcp_engine_channel_close_respond(channel);
-}
-
-/** Process SPEAK request */
-static apt_bool_t mrcp_swift_channel_speak(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
-{
- mrcp_swift_channel_t *synth_channel = channel->method_obj;
-
- /* set voice */
- mrcp_swift_channel_voice_set(synth_channel,request);
- /* set params */
- mrcp_swift_channel_params_set(synth_channel,request);
- /* (re)start audio buffer */
- mpf_buffer_restart(synth_channel->audio_buffer);
- response->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
- /* start to synthesize */
- if(swift_port_speak_text(synth_channel->port,request->body.buf,0,NULL,&synth_channel->tts_stream,NULL) != SWIFT_SUCCESS) {
- response->start_line.request_state = MRCP_REQUEST_STATE_COMPLETE;
- response->start_line.status_code = MRCP_STATUS_CODE_METHOD_FAILED;
- }
- /* send asynchronous response */
- mrcp_engine_channel_message_send(channel,response);
- synth_channel->speak_request = request;
- return TRUE;
-}
-
-/** Process STOP request */
-static apt_bool_t mrcp_swift_channel_stop(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
-{
- mrcp_swift_channel_t *synth_channel = channel->method_obj;
- /* store the request, make sure there is no more activity and only then send the response */
- swift_port_stop(synth_channel->port,synth_channel->tts_stream,SWIFT_EVENT_NOW);
- synth_channel->stop_response = response;
- return TRUE;
-}
-
-/** Process PAUSE request */
-static apt_bool_t mrcp_swift_channel_pause(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
-{
- mrcp_swift_channel_t *synth_channel = channel->method_obj;
- synth_channel->paused = TRUE;
- /* send asynchronous response */
- mrcp_engine_channel_message_send(channel,response);
- return TRUE;
-}
-
-/** Process RESUME request */
-static apt_bool_t mrcp_swift_channel_resume(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
-{
- mrcp_swift_channel_t *synth_channel = channel->method_obj;
- synth_channel->paused = FALSE;
- /* send asynchronous response */
- mrcp_engine_channel_message_send(channel,response);
- return TRUE;
-}
-
-/** Process CONTROL request */
-static apt_bool_t mrcp_swift_channel_control(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
-{
- mrcp_swift_channel_t *synth_channel = channel->method_obj;
- /* set params */
- mrcp_swift_channel_params_set(synth_channel,request);
- /* send asynchronous response */
- mrcp_engine_channel_message_send(channel,response);
- return TRUE;
-}
-
-/** Process MRCP channel request (asynchronous response MUST be sent)*/
-static apt_bool_t mrcp_swift_channel_request_process(mrcp_engine_channel_t *channel, mrcp_message_t *request)
-{
- apt_bool_t processed = FALSE;
- mrcp_message_t *response = mrcp_response_create(request,request->pool);
- switch(request->start_line.method_id) {
- case SYNTHESIZER_SET_PARAMS:
- break;
- case SYNTHESIZER_GET_PARAMS:
- break;
- case SYNTHESIZER_SPEAK:
- processed = mrcp_swift_channel_speak(channel,request,response);
- break;
- case SYNTHESIZER_STOP:
- processed = mrcp_swift_channel_stop(channel,request,response);
- break;
- case SYNTHESIZER_PAUSE:
- processed = mrcp_swift_channel_pause(channel,request,response);
- break;
- case SYNTHESIZER_RESUME:
- processed = mrcp_swift_channel_resume(channel,request,response);
- break;
- case SYNTHESIZER_BARGE_IN_OCCURRED:
- processed = mrcp_swift_channel_stop(channel,request,response);
- break;
- case SYNTHESIZER_CONTROL:
- processed = mrcp_swift_channel_control(channel,request,response);
- break;
- case SYNTHESIZER_DEFINE_LEXICON:
- break;
- default:
- break;
- }
- if(processed == FALSE) {
- /* send asynchronous response for not handled request */
- mrcp_engine_channel_message_send(channel,response);
- }
- return TRUE;
-}
-
-
-
-/** Callback is called from MPF engine context to destroy any additional data associated with audio stream */
-static apt_bool_t synth_stream_destroy(mpf_audio_stream_t *stream)
-{
- return TRUE;
-}
-
-/** Callback is called from MPF engine context to perform any action before open */
-static apt_bool_t synth_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec)
-{
- return TRUE;
-}
-
-/** Callback is called from MPF engine context to perform any action after close */
-static apt_bool_t synth_stream_close(mpf_audio_stream_t *stream)
-{
- return TRUE;
-}
-
-/** Raise SPEAK-COMPLETE event */
-static apt_bool_t synth_speak_complete_raise(mrcp_swift_channel_t *synth_channel)
-{
- mrcp_message_t *message;
- mrcp_synth_header_t *synth_header;
- if(!synth_channel->speak_request) {
- return FALSE;
- }
- message = mrcp_event_create(
- synth_channel->speak_request,
- SYNTHESIZER_SPEAK_COMPLETE,
- synth_channel->speak_request->pool);
- if(!message) {
- return FALSE;
- }
-
- /* get/allocate synthesizer header */
- synth_header = mrcp_resource_header_prepare(message);
- if(synth_header) {
- /* set completion cause */
- synth_header->completion_cause = SYNTHESIZER_COMPLETION_CAUSE_NORMAL;
- mrcp_resource_header_property_add(message,SYNTHESIZER_HEADER_COMPLETION_CAUSE);
- }
- /* set request state */
- message->start_line.request_state = MRCP_REQUEST_STATE_COMPLETE;
-
- synth_channel->speak_request = NULL;
- /* send asynch event */
- return mrcp_engine_channel_message_send(synth_channel->channel,message);
-}
-
-/** Callback is called from MPF engine context to read/get new frame */
-static apt_bool_t synth_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame)
-{
- mrcp_swift_channel_t *synth_channel = stream->obj;
- /* check if STOP was requested */
- if(synth_channel->stop_response) {
- /* send asynchronous response to STOP request */
- mrcp_engine_channel_message_send(synth_channel->channel,synth_channel->stop_response);
- synth_channel->stop_response = NULL;
- synth_channel->speak_request = NULL;
- synth_channel->paused = FALSE;
- return TRUE;
- }
-
- /* check if there is active SPEAK request and it isn't in paused state */
- if(synth_channel->speak_request && synth_channel->paused == FALSE) {
- /* normal processing */
- mpf_buffer_frame_read(synth_channel->audio_buffer,frame);
-
- if((frame->type & MEDIA_FRAME_TYPE_EVENT) == MEDIA_FRAME_TYPE_EVENT) {
- synth_speak_complete_raise(synth_channel);
- }
- }
- return TRUE;
-}
-
-/** Swift engine callback */
-static swift_result_t mrcp_swift_write_audio(swift_event *event, swift_event_t type, void *udata)
-{
- void *buf;
- int len;
- mrcp_swift_channel_t *synth_channel = udata;
- swift_event_t rv = SWIFT_SUCCESS;
-
- if(type & SWIFT_EVENT_END) {
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Swift Engine: Write End-of-Speech Event");
- mpf_buffer_event_write(synth_channel->audio_buffer,MEDIA_FRAME_TYPE_EVENT);
- return rv;
- }
-
- rv = swift_event_get_audio(event, &buf, &len);
- if(!SWIFT_FAILED(rv)) {
-#if 0
- /* Get the event times */
- float time_start, time_len;
- swift_event_get_times(event, &time_start, &time_len);
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Swift Engine: Write Audio [%d | %0.4f | %0.4f]",len, time_start, time_len);
-#endif
- mpf_buffer_audio_write(synth_channel->audio_buffer,buf,len);
- }
-
- return rv;
-}
-
-/** Add delimiter (&) to search criteria */
-static APR_INLINE int search_criteria_delimiter_add(char *search_criteria, int size, apt_bool_t initial)
-{
- if(initial == FALSE && size >= 3) {
- search_criteria[0] = ' ';
- search_criteria[1] = '&';
- search_criteria[2] = ' ';
- return 3;
- }
- return 0;
-}
-
-/** Set voice matching specified criteria */
-static apt_bool_t mrcp_swift_channel_voice_set(mrcp_swift_channel_t *synth_channel, mrcp_message_t *message)
-{
- mrcp_synth_header_t *synth_header = mrcp_resource_header_get(message);
- char search_criteria[1024];
- int offset = 0;
- swift_voice *voice;
- swift_result_t res;
-
- if(!synth_header) {
- /* no params to set */
- return TRUE;
- }
-
- if(mrcp_resource_header_property_check(message,SYNTHESIZER_HEADER_VOICE_NAME) == TRUE) {
- offset += search_criteria_delimiter_add(search_criteria+offset,sizeof(search_criteria)-offset,(offset == 0));
- offset += apr_snprintf(search_criteria+offset,sizeof(search_criteria)-offset,"speaker/name=%s",synth_header->voice_param.name.buf);
- }
- if(mrcp_resource_header_property_check(message,SYNTHESIZER_HEADER_VOICE_GENDER) == TRUE) {
- switch(synth_header->voice_param.gender) {
- case VOICE_GENDER_MALE:
- offset += search_criteria_delimiter_add(search_criteria+offset,sizeof(search_criteria)-offset,offset == 0);
- offset += apr_snprintf(search_criteria+offset,sizeof(search_criteria)-offset,"speaker/gender=male");
- break;
- case VOICE_GENDER_FEMALE:
- offset += search_criteria_delimiter_add(search_criteria+offset,sizeof(search_criteria)-offset,offset == 0);
- offset += apr_snprintf(search_criteria+offset,sizeof(search_criteria)-offset,"speaker/gender=female");
- break;
- default:
- break;
- }
- }
- if(mrcp_resource_header_property_check(message,SYNTHESIZER_HEADER_VOICE_AGE) == TRUE) {
- offset += search_criteria_delimiter_add(search_criteria+offset,sizeof(search_criteria)-offset,offset == 0);
- offset += apr_snprintf(search_criteria+offset,sizeof(search_criteria)-offset,"speaker/age=%d",synth_header->voice_param.age);
- }
- if(mrcp_resource_header_property_check(message,SYNTHESIZER_HEADER_SPEECH_LANGUAGE) == TRUE) {
- const char *swift_lang_name = NULL;
- mrcp_engine_t *engine = synth_channel->channel->engine;
- mrcp_swift_engine_t *synth_engine = engine->obj;
- if(synth_engine && synth_engine->language_table) {
- swift_lang_name = apr_table_get(synth_engine->language_table,synth_header->speech_language.buf);
- }
- if(!swift_lang_name) {
- swift_lang_name = synth_header->speech_language.buf;
- }
- offset += search_criteria_delimiter_add(search_criteria+offset,sizeof(search_criteria)-offset,offset == 0);
- offset += apr_snprintf(search_criteria+offset,sizeof(search_criteria)-offset,"language/name=%s",swift_lang_name);
- }
-
- if(offset > 0) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Find Swift Voice Matching the Criteria [%s]", search_criteria);
- voice = swift_port_find_first_voice(synth_channel->port,search_criteria,NULL);
- if(!voice) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"No Swift Voice Available Matching the Criteria [%s]",search_criteria);
- /* find the first available one */
- voice = swift_port_find_first_voice(synth_channel->port,NULL,NULL);
- }
-
- if(voice) {
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Set Swift Voice [%s]",
- swift_voice_get_attribute(voice, "name"));
- if(SWIFT_FAILED(res = swift_port_set_voice(synth_channel->port,voice)) ) {
- const char *error_string = swift_strerror(res);
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,error_string);
- return FALSE;
- }
- }
- }
- return TRUE;
-}
-
-/** Get volume by prosody params */
-static apt_bool_t swift_prosody_volume_get(const mrcp_prosody_volume_t *prosody_volume, int *volume)
-{
- apt_bool_t res = FALSE;
- if(prosody_volume->type == PROSODY_VOLUME_TYPE_LABEL) {
- if(prosody_volume->value.label < PROSODY_VOLUME_COUNT) {
- *volume = swift_prosody_volume_table[prosody_volume->value.label];
- res = TRUE;
- }
- }
- else if(prosody_volume->type == PROSODY_VOLUME_TYPE_NUMERIC) {
- *volume = (int)prosody_volume->value.numeric;
- res = TRUE;
- }
- else if(prosody_volume->type == PROSODY_VOLUME_TYPE_RELATIVE_CHANGE) {
- int def = swift_prosody_volume_table[PROSODY_VOLUME_DEFAULT];
- *volume = (int)(prosody_volume->value.relative * def);
- res = TRUE;
- }
- return res;
-}
-
-/** Get rate by prosody params */
-static apt_bool_t swift_prosody_rate_get(const mrcp_prosody_rate_t *prosody_rate, int *rate)
-{
- apt_bool_t res = FALSE;
- if(prosody_rate->type == PROSODY_RATE_TYPE_LABEL) {
- if(prosody_rate->value.label < PROSODY_RATE_COUNT) {
- *rate = swift_prosody_rate_table[prosody_rate->value.label];
- res = TRUE;
- }
- }
- else if(prosody_rate->type == PROSODY_RATE_TYPE_RELATIVE_CHANGE) {
- int def = swift_prosody_rate_table[PROSODY_RATE_DEFAULT];
- *rate = (int)(prosody_rate->value.relative * def);
- res = TRUE;
- }
- return res;
-}
-
-
-/** Set Swift port param */
-static apt_bool_t mrcp_swift_channel_param_set(mrcp_swift_channel_t *synth_channel, const char *name, swift_val *val)
-{
- swift_result_t res;
- if(SWIFT_FAILED(res = swift_port_set_param(synth_channel->port,name,val,synth_channel->tts_stream)) ) {
- const char *error_string = swift_strerror(res);
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Swift Param %s: %s",name,error_string);
- return FALSE;
- }
- return TRUE;
-}
-
-/** Set Swift port params */
-static apt_bool_t mrcp_swift_channel_params_set(mrcp_swift_channel_t *synth_channel, mrcp_message_t *message)
-{
- const char *name;
- mrcp_synth_header_t *synth_header = mrcp_resource_header_get(message);
- mrcp_generic_header_t *generic_header = mrcp_generic_header_get(message);
-
- if(synth_header) {
- if(mrcp_resource_header_property_check(message,SYNTHESIZER_HEADER_PROSODY_VOLUME) == TRUE) {
- int volume = 0;
- if(swift_prosody_volume_get(&synth_header->prosody_param.volume,&volume) == TRUE) {
- name = "audio/volume";
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Swift Param %s=%d",name,volume);
- mrcp_swift_channel_param_set(synth_channel,name,swift_val_int(volume));
- }
- }
- if(mrcp_resource_header_property_check(message,SYNTHESIZER_HEADER_PROSODY_RATE) == TRUE) {
- int rate = 0;
- if(swift_prosody_rate_get(&synth_header->prosody_param.rate,&rate) == TRUE) {
- name = "speech/rate";
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Swift Param %s=%d",name,rate);
- mrcp_swift_channel_param_set(synth_channel,name,swift_val_int(rate));
- }
- }
- }
-
- if(generic_header) {
- if(mrcp_generic_header_property_check(message,GENERIC_HEADER_CONTENT_TYPE) == TRUE) {
- name = "tts/content-type";
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Swift Param %s=%s",name,generic_header->content_type);
- mrcp_swift_channel_param_set(synth_channel,name,swift_val_string(generic_header->content_type.buf));
- }
- if(mrcp_generic_header_property_check(message,GENERIC_HEADER_CONTENT_ENCODING) == TRUE) {
- name = "tts/text-encoding";
- apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Swift Param %s=%s",name,generic_header->content_encoding);
- mrcp_swift_channel_param_set(synth_channel,name,swift_val_string(generic_header->content_encoding.buf));
- }
- }
-
- return TRUE;
-}
-
-static void mrcp_swift_sample_rates_set(mrcp_swift_engine_t *engine, const char *str)
-{
- if(str) {
- int value = atoi(str);
- if(value == 8000) {
- engine->sample_rates |= MPF_SAMPLE_RATE_8000;
- }
- else if(value == 16000) {
- engine->sample_rates |= MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000;
- }
- }
-}
-
-/** Scan Swift available voices */
-static apt_bool_t mrcp_swift_voices_scan(mrcp_swift_engine_t *engine)
-{
- swift_port *port;
- swift_voice *voice;
- const char *license_status;
- const char *sample_rate;
-
- if(!engine->swift) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Invalid Swift Engine");
- return FALSE;
- }
-
- /* open swift port*/
- if((port = swift_port_open(engine->swift, NULL)) == NULL) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open Swift Port");
- return FALSE;
- }
-
- engine->sample_rates = MPF_SAMPLE_RATE_NONE;
-
- /* find the first voice on the system */
- if((voice = swift_port_find_first_voice(port, NULL, NULL)) == NULL) {
- apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"No Swift Voice Available");
- swift_port_close(port);
- return FALSE;
- }
- /* go through all of the voices on the system and print some info about each */
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Swift Available Voices:");
- for(; voice; voice = swift_port_find_next_voice(port)) {
- if(swift_voice_get_attribute(voice, "license/key")) {
- license_status = "licensed";
- }
- else {
- license_status = "unlicensed";
- }
- sample_rate = swift_voice_get_attribute(voice, "sample-rate");
- apt_log(APT_LOG_MARK,APT_PRIO_INFO,"%s: %s, age %s, %s, %sHz, %s, %s",
- swift_voice_get_attribute(voice, "name"),
- swift_voice_get_attribute(voice, "speaker/gender"),
- swift_voice_get_attribute(voice, "speaker/age"),
- swift_voice_get_attribute(voice, "language/name"),
- sample_rate,
- swift_voice_get_attribute(voice, "version"),
- license_status);
-
- mrcp_swift_sample_rates_set(engine,sample_rate);
- }
-
- swift_port_close(port);
- return TRUE;
-}
-
-/** Create speech language lookup table */
-static apr_table_t* mrcp_swift_language_table_create(apr_pool_t *pool)
-{
- apr_table_t *table = apr_table_make(pool,1);
- if(!table) {
- return NULL;
- }
-
- apr_table_setn(table,"en-US","US English");
- apr_table_setn(table,"en-UK","UK English");
- apr_table_setn(table,"fr-CA","Canadian French");
- apr_table_setn(table,"es-MX","Americas Spanish");
- apr_table_setn(table,"de-DE","German");
- apr_table_setn(table,"it-IT","Italian");
- return table;
-}
diff --git a/libs/unimrcp/plugins/mrcp-flite/include/flite_voices.h b/libs/unimrcp/plugins/mrcp-flite/include/flite_voices.h
index eb5a438368..59ebaf8b4d 100644
--- a/libs/unimrcp/plugins/mrcp-flite/include/flite_voices.h
+++ b/libs/unimrcp/plugins/mrcp-flite/include/flite_voices.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,10 +12,12 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: flite_voices.h 1474 2010-02-07 20:51:47Z achaloyan $
*/
-#ifndef __FLITE_VOICES_H__
-#define __FLITE_VOICES_H__
+#ifndef FLITE_VOICES_H
+#define FLITE_VOICES_H
/**
* @file flite_voices.h
@@ -42,4 +44,4 @@ cst_voice* flite_voices_best_match_get(flite_voices_t *voices, mrcp_message_t *m
APT_END_EXTERN_C
-#endif /*__FLITE_VOICES_H__*/
+#endif /* FLITE_VOICES_H */
diff --git a/libs/unimrcp/plugins/mrcp-flite/mrcpflite.2008.vcproj b/libs/unimrcp/plugins/mrcp-flite/mrcpflite.2008.vcproj
deleted file mode 100644
index 9767ed6e40..0000000000
--- a/libs/unimrcp/plugins/mrcp-flite/mrcpflite.2008.vcproj
+++ /dev/null
@@ -1,172 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/libs/unimrcp/plugins/mrcp-flite/src/flite_voices.c b/libs/unimrcp/plugins/mrcp-flite/src/flite_voices.c
index eb37963b32..d3bfe293ae 100644
--- a/libs/unimrcp/plugins/mrcp-flite/src/flite_voices.c
+++ b/libs/unimrcp/plugins/mrcp-flite/src/flite_voices.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: flite_voices.c 1474 2010-02-07 20:51:47Z achaloyan $
*/
#include "flite_voices.h"
diff --git a/libs/unimrcp/plugins/mrcp-flite/src/mrcp_flite.c b/libs/unimrcp/plugins/mrcp-flite/src/mrcp_flite.c
index 5d691aca80..b3b3f80130 100644
--- a/libs/unimrcp/plugins/mrcp-flite/src/mrcp_flite.c
+++ b/libs/unimrcp/plugins/mrcp-flite/src/mrcp_flite.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Arsen Chaloyan
+ * Copyright 2008-2010 Arsen Chaloyan
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -12,6 +12,8 @@
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
+ *
+ * $Id: mrcp_flite.c 1678 2010-05-01 18:54:07Z achaloyan $
*/
/*
@@ -158,7 +160,7 @@ static apt_bool_t flite_synth_engine_open(mrcp_engine_t *engine)
flite_engine->voices = flite_voices_load(engine->pool);
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite init success");
- return TRUE;
+ return mrcp_engine_open_respond(engine,TRUE);
}
/** Close synthesizer engine */
@@ -169,7 +171,7 @@ static apt_bool_t flite_synth_engine_close(mrcp_engine_t *engine)
flite_voices_unload(flite_engine->voices);
- return TRUE;
+ return mrcp_engine_close_respond(engine);
}
static apt_bool_t flite_synth_task_create(flite_synth_channel_t *synth_channel)
diff --git a/libs/unimrcp/plugins/mrcp-pocketsphinx/conf/pocketsphinx.xml b/libs/unimrcp/plugins/mrcp-pocketsphinx/conf/pocketsphinx.xml
index f9bbb6a6b3..6d7bfa1ef5 100644
--- a/libs/unimrcp/plugins/mrcp-pocketsphinx/conf/pocketsphinx.xml
+++ b/libs/unimrcp/plugins/mrcp-pocketsphinx/conf/pocketsphinx.xml
@@ -1,9 +1,10 @@
+
-
+
FreeSWITCH logging bridge */
-static apt_bool_t unimrcp_log(const char *file, int line, const char *id, apt_log_priority_e priority, const char *format, va_list arg_ptr);
+static apt_bool_t unimrcp_log(const char *file, int line, const char *obj, apt_log_priority_e priority, const char *format, va_list arg_ptr);
static apt_log_priority_e str_to_log_level(const char *level);
static int get_next_speech_channel_number(void);
@@ -1810,56 +1814,66 @@ static apt_bool_t speech_on_session_terminate(mrcp_application_t *application, m
* @return TRUE
*/
static apt_bool_t speech_on_channel_add(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel,
- mrcp_sig_status_code_e status)
+ mrcp_sig_status_code_e status)
{
switch_event_t *event = NULL;
speech_channel_t *schannel = (speech_channel_t *) mrcp_application_channel_object_get(channel);
+ char codec_name[60] = { 0 };
+ const mpf_codec_descriptor_t *descriptor;
/* check status */
- if (session && schannel && status == MRCP_SIG_STATUS_CODE_SUCCESS) {
- char codec_name[60] = { 0 };
- const mpf_codec_descriptor_t *descriptor;
- /* what sample rate did we negotiate? */
- if (schannel->type == SPEECH_CHANNEL_SYNTHESIZER) {
- descriptor = mrcp_application_sink_descriptor_get(channel);
- } else {
- descriptor = mrcp_application_source_descriptor_get(channel);
- }
- schannel->rate = descriptor->sampling_rate;
- if (descriptor->name.length) {
- strncpy(codec_name, descriptor->name.buf, sizeof(codec_name));
- }
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) %s channel is ready, codec = %s, sample rate = %d\n", schannel->name,
- speech_channel_type_to_string(schannel->type), codec_name, schannel->rate);
- speech_channel_set_state(schannel, SPEECH_CHANNEL_READY);
- /* notify of channel open */
- if (globals.enable_profile_events && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_PROFILE_OPEN) == SWITCH_STATUS_SUCCESS) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "MRCP-Profile", schannel->profile->name);
- if (schannel->type == SPEECH_CHANNEL_SYNTHESIZER) {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "MRCP-Resource-Type", "TTS");
- } else {
- switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "MRCP-Resource-Type", "ASR");
- }
- switch_event_fire(&event);
- }
- schannel->channel_opened = 1;
+ if (!session || !schannel || status != MRCP_SIG_STATUS_CODE_SUCCESS) {
+ goto error;
+ }
+
+ /* what sample rate did we negotiate? */
+ if (schannel->type == SPEECH_CHANNEL_SYNTHESIZER) {
+ descriptor = mrcp_application_sink_descriptor_get(channel);
} else {
- if (schannel) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "(%s) %s channel error!\n", schannel->name,
- speech_channel_type_to_string(schannel->type));
+ descriptor = mrcp_application_source_descriptor_get(channel);
+ }
+ if (!descriptor) {
+ goto error;
+ }
+ schannel->rate = descriptor->sampling_rate;
+ if (descriptor->name.length) {
+ strncpy(codec_name, descriptor->name.buf, sizeof(codec_name));
+ }
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "(%s) %s channel is ready, codec = %s, sample rate = %d\n", schannel->name,
+ speech_channel_type_to_string(schannel->type), codec_name, schannel->rate);
+ speech_channel_set_state(schannel, SPEECH_CHANNEL_READY);
+
+ /* notify of channel open */
+ if (globals.enable_profile_events && switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_PROFILE_OPEN) == SWITCH_STATUS_SUCCESS) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "MRCP-Profile", schannel->profile->name);
+ if (schannel->type == SPEECH_CHANNEL_SYNTHESIZER) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "MRCP-Resource-Type", "TTS");
} else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "(unknown) channel error!\n");
- }
- if (session) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Terminating MRCP session\n");
- speech_channel_set_state(schannel, SPEECH_CHANNEL_ERROR);
- mrcp_application_session_terminate(session);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "MRCP-Resource-Type", "ASR");
}
+ switch_event_fire(&event);
+ }
+ schannel->channel_opened = 1;
+
+ return TRUE;
+
+error:
+ if (schannel) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "(%s) %s channel error!\n", schannel->name,
+ speech_channel_type_to_string(schannel->type));
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "(unknown) channel error!\n");
+ }
+ if (session) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Terminating MRCP session\n");
+ speech_channel_set_state(schannel, SPEECH_CHANNEL_ERROR);
+ mrcp_application_session_terminate(session);
}
return TRUE;
}
+
/**
* Handle the UniMRCP responses sent to channel remove requests
*
@@ -3729,7 +3743,7 @@ static int process_profile_config(profile_t *profile, const char *param, const c
* @param pool memory pool to use
* @return true if this param belongs to RTP config
*/
-static int process_rtp_config(mrcp_client_t *client, mpf_rtp_config_t *rtp_config, const char *param, const char *val, apr_pool_t *pool)
+static int process_rtp_config(mrcp_client_t *client, mpf_rtp_config_t *rtp_config, mpf_rtp_settings_t *rtp_settings, const char *param, const char *val, apr_pool_t *pool)
{
int mine = 1;
if (strcasecmp(param, "rtp-ip") == 0) {
@@ -3741,26 +3755,26 @@ static int process_rtp_config(mrcp_client_t *client, mpf_rtp_config_t *rtp_confi
} else if (strcasecmp(param, "rtp-port-max") == 0) {
rtp_config->rtp_port_max = (apr_port_t) atol(val);
} else if (strcasecmp(param, "playout-delay") == 0) {
- rtp_config->jb_config.initial_playout_delay = atol(val);
+ rtp_settings->jb_config.initial_playout_delay = atol(val);
} else if (strcasecmp(param, "min-playout-delay") == 0) {
- rtp_config->jb_config.min_playout_delay = atol(val);
+ rtp_settings->jb_config.min_playout_delay = atol(val);
} else if (strcasecmp(param, "max-playout-delay") == 0) {
- rtp_config->jb_config.max_playout_delay = atol(val);
+ rtp_settings->jb_config.max_playout_delay = atol(val);
} else if (strcasecmp(param, "codecs") == 0) {
const mpf_codec_manager_t *codec_manager = mrcp_client_codec_manager_get(client);
if (codec_manager) {
- mpf_codec_manager_codec_list_load(codec_manager, &rtp_config->codec_list, val, pool);
+ mpf_codec_manager_codec_list_load(codec_manager, &rtp_settings->codec_list, val, pool);
}
} else if (strcasecmp(param, "ptime") == 0) {
- rtp_config->ptime = (apr_uint16_t) atol(val);
+ rtp_settings->ptime = (apr_uint16_t) atol(val);
} else if (strcasecmp(param, "rtcp") == 0) {
- rtp_config->rtcp = atoi(val);
+ rtp_settings->rtcp = atoi(val);
} else if (strcasecmp(param, "rtcp-bye") == 0) {
- rtp_config->rtcp_bye_policy = atoi(val);
+ rtp_settings->rtcp_bye_policy = atoi(val);
} else if (strcasecmp(param, "rtcp-tx-interval") == 0) {
- rtp_config->rtcp_tx_interval = (apr_uint16_t) atoi(val);
+ rtp_settings->rtcp_tx_interval = (apr_uint16_t) atoi(val);
} else if (strcasecmp(param, "rtcp-rx-resolution") == 0) {
- rtp_config->rtcp_rx_resolution = (apr_uint16_t) atol(val);
+ rtp_settings->rtcp_rx_resolution = (apr_uint16_t) atol(val);
} else {
mine = 0;
}
@@ -3771,28 +3785,29 @@ static int process_rtp_config(mrcp_client_t *client, mpf_rtp_config_t *rtp_confi
/**
* set RTSP client config struct with param, val pair
* @param config the config struct to set
+ * @param sig_settings the sig settings struct to set
* @param param the param name
* @param val the param value
* @param pool memory pool to use
* @return true if this param belongs to RTSP config
*/
-static int process_mrcpv1_config(rtsp_client_config_t *config, const char *param, const char *val, apr_pool_t *pool)
+static int process_mrcpv1_config(rtsp_client_config_t *config, mrcp_sig_settings_t *sig_settings, const char *param, const char *val, apr_pool_t *pool)
{
int mine = 1;
if (strcasecmp(param, "server-ip") == 0) {
- config->server_ip = ip_addr_get(val, pool);
+ sig_settings->server_ip = ip_addr_get(val, pool);
} else if (strcasecmp(param, "server-port") == 0) {
- config->server_port = (apr_port_t) atol(val);
+ sig_settings->server_port = (apr_port_t) atol(val);
} else if (strcasecmp(param, "resource-location") == 0) {
- config->resource_location = apr_pstrdup(pool, val);
+ sig_settings->resource_location = apr_pstrdup(pool, val);
} else if (strcasecmp(param, "sdp-origin") == 0) {
config->origin = apr_pstrdup(pool, val);
} else if (strcasecmp(param, "max-connection-count") == 0) {
config->max_connection_count = atol(val);
} else if (strcasecmp(param, "force-destination") == 0) {
- config->force_destination = atoi(val);
+ sig_settings->force_destination = atoi(val);
} else if (strcasecmp(param, "speechsynth") == 0 || strcasecmp(param, "speechrecog") == 0) {
- apr_table_set(config->resource_map, param, val);
+ apr_table_set(sig_settings->resource_map, param, val);
} else {
mine = 0;
}
@@ -3802,12 +3817,13 @@ static int process_mrcpv1_config(rtsp_client_config_t *config, const char *param
/**
* set SofiaSIP client config struct with param, val pair
* @param config the config struct to set
+ * @param sig_settings the sig settings struct to set
* @param param the param name
* @param val the param value
* @param pool memory pool to use
* @return true if this param belongs to SofiaSIP config
*/
-static int process_mrcpv2_config(mrcp_sofia_client_config_t *config, const char *param, const char *val, apr_pool_t *pool)
+static int process_mrcpv2_config(mrcp_sofia_client_config_t *config, mrcp_sig_settings_t *sig_settings, const char *param, const char *val, apr_pool_t *pool)
{
int mine = 1;
if (strcasecmp(param, "client-ip") == 0) {
@@ -3817,13 +3833,13 @@ static int process_mrcpv2_config(mrcp_sofia_client_config_t *config, const char
} else if (strcasecmp(param, "client-port") == 0) {
config->local_port = (apr_port_t) atol(val);
} else if (strcasecmp(param, "server-ip") == 0) {
- config->remote_ip = ip_addr_get(val, pool);
+ sig_settings->server_ip = ip_addr_get(val, pool);
} else if (strcasecmp(param, "server-port") == 0) {
- config->remote_port = (apr_port_t) atol(val);
+ sig_settings->server_port = (apr_port_t) atol(val);
} else if (strcasecmp(param, "server-username") == 0) {
- config->remote_user_name = apr_pstrdup(pool, val);
+ sig_settings->user_name = apr_pstrdup(pool, val);
} else if (strcasecmp(param, "force-destination") == 0) {
- config->force_destination = atoi(val);
+ sig_settings->force_destination = atoi(val);
} else if (strcasecmp(param, "sip-transport") == 0) {
config->transport = apr_pstrdup(pool, val);
} else if (strcasecmp(param, "ua-name") == 0) {
@@ -3905,15 +3921,21 @@ static mrcp_client_t *mod_unimrcp_client_create(switch_memory_pool_t *mod_pool)
if (!zstr(globals.unimrcp_offer_new_connection)) {
offer_new_connection = strcasecmp("true", globals.unimrcp_offer_new_connection);
}
- connection_agent = mrcp_client_connection_agent_create(max_connection_count, offer_new_connection, pool);
+ connection_agent = mrcp_client_connection_agent_create("MRCPv2ConnectionAgent", max_connection_count, offer_new_connection, pool);
if (connection_agent) {
- mrcp_client_connection_agent_register(client, connection_agent, "MRCPv2ConnectionAgent");
+ if (!zstr(globals.unimrcp_request_timeout)) {
+ apr_size_t request_timeout = (apr_size_t)atol(globals.unimrcp_request_timeout);
+ if (request_timeout > 0) {
+ mrcp_client_connection_timeout_set(connection_agent, request_timeout);
+ }
+ }
+ mrcp_client_connection_agent_register(client, connection_agent);
}
/* Set up the media engine that will be shared with all profiles */
- media_engine = mpf_engine_create(pool);
+ media_engine = mpf_engine_create("MediaEngine", pool);
if (media_engine) {
- mrcp_client_media_engine_register(client, media_engine, "MediaEngine");
+ mrcp_client_media_engine_register(client, media_engine);
}
/* configure the client profiles */
@@ -3929,6 +3951,8 @@ static mrcp_client_t *mod_unimrcp_client_create(switch_memory_pool_t *mod_pool)
mpf_termination_factory_t *termination_factory = NULL;
mrcp_profile_t *mprofile = NULL;
mpf_rtp_config_t *rtp_config = NULL;
+ mpf_rtp_settings_t *rtp_settings = mpf_rtp_settings_alloc(pool);
+ mrcp_sig_settings_t *sig_settings = mrcp_signaling_settings_alloc(pool);
profile_t *mod_profile = NULL;
switch_xml_t default_params = NULL;
@@ -3958,8 +3982,13 @@ static mrcp_client_t *mod_unimrcp_client_create(switch_memory_pool_t *mod_pool)
client = NULL;
goto done;
}
+ if (zstr(param_value)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing SPEAK param value\n");
+ client = NULL;
+ goto done;
+ }
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Loading SPEAK Param %s:%s\n", param_name, param_value);
- switch_core_hash_insert(mod_profile->default_synth_params, param_name, param_value);
+ switch_core_hash_insert(mod_profile->default_synth_params, switch_core_strdup(pool, param_name), switch_core_strdup(pool, param_value));
}
}
@@ -3976,24 +4005,35 @@ static mrcp_client_t *mod_unimrcp_client_create(switch_memory_pool_t *mod_pool)
client = NULL;
goto done;
}
+ if (zstr(param_value)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing RECOGNIZE param value\n");
+ client = NULL;
+ goto done;
+ }
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Loading RECOGNIZE Param %s:%s\n", param_name, param_value);
- switch_core_hash_insert(mod_profile->default_recog_params, param_name, param_value);
+ switch_core_hash_insert(mod_profile->default_recog_params, switch_core_strdup(pool, param_name), switch_core_strdup(pool, param_value));
}
}
/* create RTP config, common to MRCPv1 and MRCPv2 */
- rtp_config = mpf_rtp_config_create(pool);
+ rtp_config = mpf_rtp_config_alloc(pool);
rtp_config->rtp_port_min = DEFAULT_RTP_PORT_MIN;
rtp_config->rtp_port_max = DEFAULT_RTP_PORT_MAX;
apt_string_set(&rtp_config->ip, DEFAULT_LOCAL_IP_ADDRESS);
if (strcmp("1", version) == 0) {
/* MRCPv1 configuration */
- rtsp_client_config_t *config = mrcp_unirtsp_client_config_alloc(pool);
switch_xml_t param = NULL;
+ rtsp_client_config_t *config = mrcp_unirtsp_client_config_alloc(pool);
config->origin = DEFAULT_SDP_ORIGIN;
- config->resource_location = DEFAULT_RESOURCE_LOCATION;
+ sig_settings->resource_location = DEFAULT_RESOURCE_LOCATION;
+ if (!zstr(globals.unimrcp_request_timeout)) {
+ apr_size_t request_timeout = (apr_size_t)atol(globals.unimrcp_request_timeout);
+ if (request_timeout > 0) {
+ config->request_timeout = request_timeout;
+ }
+ }
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Loading MRCPv1 profile: %s\n", name);
for (param = switch_xml_child(profile, "param"); param; param = switch_xml_next(param)) {
const char *param_name = switch_xml_attr(param, "name");
@@ -4004,21 +4044,21 @@ static mrcp_client_t *mod_unimrcp_client_create(switch_memory_pool_t *mod_pool)
goto done;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Loading Param %s:%s\n", param_name, param_value);
- if (!process_mrcpv1_config(config, param_name, param_value, pool) &&
- !process_rtp_config(client, rtp_config, param_name, param_value, pool) &&
+ if (!process_mrcpv1_config(config, sig_settings, param_name, param_value, pool) &&
+ !process_rtp_config(client, rtp_config, rtp_settings, param_name, param_value, pool) &&
!process_profile_config(mod_profile, param_name, param_value, mod_pool)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown param %s\n", param_name);
}
}
- agent = mrcp_unirtsp_client_agent_create(config, pool);
+ agent = mrcp_unirtsp_client_agent_create(name, config, pool);
} else if (strcmp("2", version) == 0) {
/* MRCPv2 configuration */
mrcp_sofia_client_config_t *config = mrcp_sofiasip_client_config_alloc(pool);
switch_xml_t param = NULL;
config->local_ip = DEFAULT_LOCAL_IP_ADDRESS;
config->local_port = DEFAULT_SIP_LOCAL_PORT;
- config->remote_ip = DEFAULT_REMOTE_IP_ADDRESS;
- config->remote_port = DEFAULT_SIP_REMOTE_PORT;
+ sig_settings->server_ip = DEFAULT_REMOTE_IP_ADDRESS;
+ sig_settings->server_port = DEFAULT_SIP_REMOTE_PORT;
config->ext_ip = NULL;
config->user_agent_name = DEFAULT_SOFIASIP_UA_NAME;
config->origin = DEFAULT_SDP_ORIGIN;
@@ -4032,13 +4072,13 @@ static mrcp_client_t *mod_unimrcp_client_create(switch_memory_pool_t *mod_pool)
goto done;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Loading Param %s:%s\n", param_name, param_value);
- if (!process_mrcpv2_config(config, param_name, param_value, pool) &&
- !process_rtp_config(client, rtp_config, param_name, param_value, pool) &&
+ if (!process_mrcpv2_config(config, sig_settings, param_name, param_value, pool) &&
+ !process_rtp_config(client, rtp_config, rtp_settings, param_name, param_value, pool) &&
!process_profile_config(mod_profile, param_name, param_value, mod_pool)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unknown param %s\n", param_name);
}
}
- agent = mrcp_sofiasip_client_agent_create(config, pool);
+ agent = mrcp_sofiasip_client_agent_create(name, config, pool);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "version must be either \"1\" or \"2\"\n");
client = NULL;
@@ -4050,11 +4090,11 @@ static mrcp_client_t *mod_unimrcp_client_create(switch_memory_pool_t *mod_pool)
mrcp_client_rtp_factory_register(client, termination_factory, name);
}
if (agent) {
- mrcp_client_signaling_agent_register(client, agent, name);
+ mrcp_client_signaling_agent_register(client, agent);
}
/* create the profile and register it */
- mprofile = mrcp_client_profile_create(NULL, agent, connection_agent, media_engine, termination_factory, pool);
+ mprofile = mrcp_client_profile_create(NULL, agent, connection_agent, media_engine, termination_factory, rtp_settings, sig_settings, pool);
if (mprofile) {
mrcp_client_profile_register(client, mprofile, name);
}
@@ -4185,11 +4225,12 @@ static apt_log_priority_e str_to_log_level(const char *level)
* Connects UniMRCP logging to FreeSWITCH
* @return TRUE
*/
-static apt_bool_t unimrcp_log(const char *file, int line, const char *id, apt_log_priority_e priority, const char *format, va_list arg_ptr)
+static apt_bool_t unimrcp_log(const char *file, int line, const char *obj, apt_log_priority_e priority, const char *format, va_list arg_ptr)
{
switch_log_level_t level;
char log_message[4096] = { 0 }; /* same size as MAX_LOG_ENTRY_SIZE in UniMRCP apt_log.c */
size_t msglen;
+ const char *id = (obj == NULL) ? "" : ((speech_channel_t *)obj)->name;
if (zstr(format)) {
return TRUE;
@@ -4227,10 +4268,10 @@ static apt_bool_t unimrcp_log(const char *file, int line, const char *id, apt_lo
msglen = strlen(log_message);
if (msglen >= 2 && log_message[msglen - 2] == '\\' && log_message[msglen - 1] == 'n') {
/* log_message already ends in \n */
- switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "", line, id, level, "%s", log_message);
+ switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "", line, NULL, level, "(%s) %s", id, log_message);
} else if (msglen > 0) {
/* log message needs \n appended */
- switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "", line, id, level, "%s\n", log_message);
+ switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, "", line, NULL, level, "(%s) %s\n", id, log_message);
}
return TRUE;
diff --git a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c
index c2d6ae40b5..6971995f50 100644
--- a/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c
+++ b/src/mod/codecs/mod_sangoma_codec/mod_sangoma_codec.c
@@ -89,7 +89,7 @@ vocallo_codec_t g_codec_map[] =
{ SNGTC_CODEC_PCMA, IANA_PCMA_A_8000_1, "PCMA", "Sangoma PCMA", 40, 64000, 10000, 80, 160, 80, 8000, 8000, 1 },
{ SNGTC_CODEC_L16_1, IANA_L16_A_8000_1, "L16", "Sangoma L16", 40, 120000, 10000, 80, 160, 160, 8000, 8000, 0 },
{ SNGTC_CODEC_L16_2, IANA_L16_A_16000_1, "L16", "Sangoma L16 2", 40, 320000, 10000, 160, 320, 320, 16000, 16000, 0 },
- { SNGTC_CODEC_G729AB, IANA_G729_AB_8000_1, "G729", "Sangoma G729", 200, 8000, 10000, 80, 160, 10, 8000, 8000, 1 },
+ { SNGTC_CODEC_G729AB, IANA_G729_AB_8000_1, "G729", "Sangoma G729", 50, 8000, 10000, 80, 160, 10, 8000, 8000, 1 },
{ SNGTC_CODEC_G726_32, IANA_G726_32_8000_1, "G726-32", "Sangoma G.726 32k", 40, 32000, 10000, 80, 160, 40, 8000, 8000, 1 },
{ SNGTC_CODEC_G722, IANA_G722_A_8000_1, "G722", "Sangoma G722", 20, 64000, 10000, 80, 160, 80, 8000, 8000, 1 },
@@ -224,7 +224,7 @@ static int sangoma_create_rtp_port(void *usr_priv, uint32_t host_ip, uint32_t *p
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "New allocated port %d for IP %s/%d.%d.%d.%d\n", rtp_port, local_ip,
SNGTC_NIPV4(host_ip));
*p_rtp_port = rtp_port;
- *rtp_fd = (void *)(long)rtp_port;
+ *rtp_fd = NULL;
return 0;
}
@@ -259,6 +259,9 @@ static int sangoma_create_rtp(void *usr_priv, sngtc_codec_request_leg_t *codec_r
switch_port_t rtp_port;
struct sangoma_transcoding_session *sess = usr_priv;
+ rtp_port = codec_req_leg->host_udp_port;
+ *rtp_fd = NULL;
+
/*
* We *MUST* use a new pool
* Do not use the session pool since the session may go away while the RTP socket should linger around
@@ -271,10 +274,6 @@ static int sangoma_create_rtp(void *usr_priv, sngtc_codec_request_leg_t *codec_r
return -1;
}
- rtp_port = (switch_port_t)(long)*rtp_fd;
-
- codec_req_leg->host_udp_port = rtp_port;
-
local_ip_addr.s_addr = htonl(codec_req_leg->host_ip);
switch_inet_ntop(AF_INET, &local_ip_addr, local_ip, sizeof(local_ip));
sngtc_codec_ipv4_hex_to_str(codec_reply_leg->codec_ip, codec_ip);
@@ -307,6 +306,9 @@ static int sangoma_destroy_rtp(void *usr_priv, void *fd)
{
switch_memory_pool_t *sesspool;
switch_rtp_t *rtp = fd;
+ if (!rtp) {
+ return 0;
+ }
sesspool = switch_rtp_get_private(rtp);
switch_rtp_destroy(&rtp);
switch_core_destroy_memory_pool(&sesspool);
@@ -1267,10 +1269,10 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_sangoma_codec_load)
* At this point there is an empty shell codec interface registered, but not yet implementations */
SWITCH_ADD_CODEC(codec_interface, g_codec_map[c].fs_name);
- /* Now add as many codec implementations as needed, just up to 40ms for now */
+ /* Now add as many codec implementations as needed, just up to 200ms for now */
if (g_codec_map[c].autoinit) {
int ms = 0;
- for (i = 1; i <= 4; i++) {
+ for (i = 1; i <= 20; i++) {
ms = i * 10;
if (g_codec_map[c].maxms < ms) {
break;
diff --git a/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c b/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c
index 929372be1a..5f042fbf26 100644
--- a/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c
+++ b/src/mod/dialplans/mod_dialplan_xml/mod_dialplan_xml.c
@@ -222,6 +222,11 @@ static int parse_exten(switch_core_session_t *session, switch_caller_profile_t *
proceed = 1;
}
} else {
+ if (field && strchr(expression, '(')) {
+ switch_channel_set_variable(channel, "DP_MATCH", NULL);
+ switch_capture_regex(re, proceed, field_data, ovector, "DP_MATCH", switch_regex_set_var_callback, session);
+ }
+
for (xaction = switch_xml_child(xcond, "action"); xaction; xaction = xaction->next) {
char *application = (char *) switch_xml_attr_soft(xaction, "application");
const char *loop = switch_xml_attr(xaction, "loop");
diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c
index 2db3660ccd..59d76d110b 100644
--- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c
+++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c
@@ -30,7 +30,6 @@
*
*/
#include
-#include
#include
#include
@@ -1912,9 +1911,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dingaling_load)
SWITCH_ADD_API(api_interface, "dingaling", "DingaLing Menu", dingaling, DINGALING_SYNTAX);
SWITCH_ADD_CHAT(chat_interface, MDL_CHAT_PROTO, chat_send);
- switch_ssl_init_ssl_locks();
-
-
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
@@ -2012,8 +2008,6 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_dingaling_shutdown)
switch_safe_free(globals.codec_string);
switch_safe_free(globals.codec_rates_string);
- switch_ssl_destroy_ssl_locks();
-
return SWITCH_STATUS_SUCCESS;
}
diff --git a/src/mod/endpoints/mod_loopback/mod_loopback.c b/src/mod/endpoints/mod_loopback/mod_loopback.c
index 8fb8384e6b..97684b6f10 100644
--- a/src/mod/endpoints/mod_loopback/mod_loopback.c
+++ b/src/mod/endpoints/mod_loopback/mod_loopback.c
@@ -54,7 +54,8 @@ typedef enum {
TFLAG_BLEG = (1 << 6),
TFLAG_APP = (1 << 7),
TFLAG_RUNNING_APP = (1 << 8),
- TFLAG_BOWOUT_USED = (1 << 9)
+ TFLAG_BOWOUT_USED = (1 << 9),
+ TFLAG_CLEAR = (1 << 10)
} TFLAGS;
struct private_object {
@@ -105,6 +106,17 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
+
+static void clear_queue(private_t *tech_pvt)
+{
+ void *pop;
+
+ while (switch_queue_trypop(tech_pvt->frame_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
+ switch_frame_t *frame = (switch_frame_t *) pop;
+ switch_frame_free(&frame);
+ }
+}
+
static switch_status_t tech_init(private_t *tech_pvt, switch_core_session_t *session, switch_codec_t *codec)
{
const char *iananame = "L16";
@@ -566,6 +578,12 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
mutex = tech_pvt->mutex;
switch_mutex_lock(mutex);
+
+ if (switch_test_flag(tech_pvt, TFLAG_CLEAR)) {
+ clear_queue(tech_pvt);
+ switch_clear_flag(tech_pvt, TFLAG_CLEAR);
+ }
+
if (switch_queue_trypop(tech_pvt->frame_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
if (tech_pvt->write_frame) {
switch_frame_free(&tech_pvt->write_frame);
@@ -599,17 +617,6 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
return status;
}
-static void clear_queue(private_t *tech_pvt)
-{
- void *pop;
-
- while (switch_queue_trypop(tech_pvt->frame_queue, &pop) == SWITCH_STATUS_SUCCESS && pop) {
- switch_frame_t *frame = (switch_frame_t *) pop;
- switch_frame_free(&frame);
- }
-}
-
-
static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
{
switch_channel_t *channel = NULL;
@@ -750,9 +757,9 @@ static switch_status_t channel_receive_message(switch_core_session_t *session, s
{
done = 1;
+ switch_set_flag(tech_pvt, TFLAG_CLEAR);
+ switch_set_flag(tech_pvt->other_tech_pvt, TFLAG_CLEAR);
- clear_queue(tech_pvt);
- clear_queue(tech_pvt->other_tech_pvt);
switch_core_timer_sync(&tech_pvt->timer);
switch_core_timer_sync(&tech_pvt->other_tech_pvt->timer);
}
diff --git a/src/mod/endpoints/mod_portaudio/mod_portaudio.c b/src/mod/endpoints/mod_portaudio/mod_portaudio.c
index 8564a771e5..f84fdeee96 100644
--- a/src/mod/endpoints/mod_portaudio/mod_portaudio.c
+++ b/src/mod/endpoints/mod_portaudio/mod_portaudio.c
@@ -24,6 +24,7 @@
* Contributor(s):
*
* Anthony Minessale II
+ * Moises Silva (Multiple endpoints work sponsored by Comrex Corporation)
*
*
* mod_portaudio.c -- PortAudio Endpoint Module
@@ -45,6 +46,9 @@
#define MY_EVENT_ERROR_AUDIO_DEV "portaudio::audio_dev_error"
#define SWITCH_PA_CALL_ID_VARIABLE "pa_call_id"
+#define MIN_STREAM_SAMPLE_RATE 8000
+#define STREAM_SAMPLES_PER_PACKET(stream) ((stream->codec_ms * stream->sample_rate) / 1000)
+
SWITCH_MODULE_LOAD_FUNCTION(mod_portaudio_load);
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_portaudio_shutdown);
//SWITCH_MODULE_RUNTIME_FUNCTION(mod_portaudio_runtime);
@@ -79,6 +83,76 @@ typedef enum {
TFLAG_AUTO_ANSWER = (1 << 10)
} TFLAGS;
+struct audio_stream {
+ int indev;
+ int outdev;
+ PABLIO_Stream *stream;
+ switch_timer_t write_timer;
+ struct audio_stream *next;
+};
+typedef struct audio_stream audio_stream_t;
+
+/* Audio stream that can be shared across endpoints */
+typedef struct _shared_audio_stream_t {
+ /*! Friendly name for this stream */
+ char name[255];
+ /*! Sampling rate */
+ int sample_rate;
+ /*! Buffer packetization (and therefore timing) */
+ int codec_ms;
+ /*! The PA input device */
+ int indev;
+ /*! Input channels being used */
+ uint8_t inchan_used[MAX_IO_CHANNELS];
+ /*! The PA output device */
+ int outdev;
+ /*! Output channels being used */
+ uint8_t outchan_used[MAX_IO_CHANNELS];
+ /*! How many channels to create (for both indev and outdev) */
+ int channels;
+ /*! The io stream helper to buffer audio */
+ PABLIO_Stream *stream;
+ /* It can be shared after all :-) */
+ switch_mutex_t *mutex;
+} shared_audio_stream_t;
+
+typedef struct private_object private_t;
+/* Endpoint that can be called via portaudio/endpoint/ */
+typedef struct _audio_endpoint {
+ /*! Friendly name for this endpoint */
+ char name[255];
+
+ /*! Input stream for this endpoint */
+ shared_audio_stream_t *in_stream;
+
+ /*! Output stream for this endpoint */
+ shared_audio_stream_t *out_stream;
+
+ /*! Channel index within the input stream where we get the audio for this endpoint */
+ int inchan;
+
+ /*! Channel index within the output stream where we get the audio for this endpoint */
+ int outchan;
+
+ /*! Associated private information if involved in a call */
+ private_t *master;
+
+ /*! For timed read and writes */
+ switch_timer_t read_timer;
+ switch_timer_t write_timer;
+
+ /* We need our own read frame */
+ switch_frame_t read_frame;
+ unsigned char read_buf[SWITCH_RECOMMENDED_BUFFER_SIZE];
+
+ /* Needed codecs for the core to read/write in the proper format */
+ switch_codec_t read_codec;
+ switch_codec_t write_codec;
+
+ /*! Let's be safe */
+ switch_mutex_t *mutex;
+} audio_endpoint_t;
+
struct private_object {
unsigned int flags;
switch_core_session_t *session;
@@ -92,19 +166,10 @@ struct private_object {
switch_file_handle_t *hfh;
switch_frame_t hold_frame;
unsigned char holdbuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
+ audio_endpoint_t *audio_endpoint;
struct private_object *next;
};
-typedef struct private_object private_t;
-
-struct audio_stream {
- int indev;
- int outdev;
- PABLIO_Stream *stream;
- switch_timer_t write_timer;
- struct audio_stream *next;
-};
-typedef struct audio_stream audio_stream_t;
static struct {
int debug;
@@ -138,6 +203,10 @@ static struct {
unsigned char cngbuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
private_t *call_list;
audio_stream_t *stream_list;
+ /*! Streams that can be used by multiple endpoints at the same time */
+ switch_hash_t *sh_streams;
+ /*! Endpoints configured */
+ switch_hash_t *endpoints;
int ring_interval;
GFLAGS flags;
switch_timer_t read_timer;
@@ -243,13 +312,16 @@ static switch_status_t channel_on_routing(switch_core_session_t *session)
if (hold_file) {
tech_pvt->hold_file = switch_core_session_strdup(session, hold_file);
}
- if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
- if (validate_main_audio_stream() != SWITCH_STATUS_SUCCESS) {
+ if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
+ if (!tech_pvt->audio_endpoint && validate_main_audio_stream() != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
return SWITCH_STATUS_FALSE;
}
- if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND) && !switch_test_flag(tech_pvt, TFLAG_AUTO_ANSWER)) {
+ if (!tech_pvt->audio_endpoint &&
+ switch_test_flag(tech_pvt, TFLAG_OUTBOUND) &&
+ !switch_test_flag(tech_pvt, TFLAG_AUTO_ANSWER)) {
+
add_pvt(tech_pvt, PA_SLAVE);
ring_file = globals.ring_file;
@@ -281,18 +353,22 @@ static switch_status_t channel_on_routing(switch_core_session_t *session)
}
}
- if (switch_test_flag(tech_pvt, TFLAG_AUTO_ANSWER)) {
+ if (tech_pvt->audio_endpoint || switch_test_flag(tech_pvt, TFLAG_AUTO_ANSWER)) {
switch_mutex_lock(globals.pvt_lock);
add_pvt(tech_pvt, PA_MASTER);
- switch_channel_mark_answered(channel);
- switch_set_flag(tech_pvt, TFLAG_ANSWER);
+ if (switch_test_flag(tech_pvt, TFLAG_AUTO_ANSWER)) {
+ switch_channel_mark_answered(channel);
+ switch_set_flag(tech_pvt, TFLAG_ANSWER);
+ }
switch_mutex_unlock(globals.pvt_lock);
switch_yield(1000000);
} else {
switch_channel_mark_ring_ready(channel);
}
- while (switch_channel_get_state(channel) == CS_ROUTING && !switch_test_flag(tech_pvt, TFLAG_ANSWER)) {
+ while (switch_channel_get_state(channel) == CS_ROUTING &&
+ !switch_channel_test_flag(channel, CF_ANSWERED) &&
+ !switch_test_flag(tech_pvt, TFLAG_ANSWER)) {
switch_size_t olen = globals.readfile_timer.samples;
if (switch_micro_time_now() - last >= waitsec) {
@@ -325,7 +401,7 @@ static switch_status_t channel_on_routing(switch_core_session_t *session)
if (globals.ring_stream && (! switch_test_flag(globals.call_list, TFLAG_MASTER) ||
( !globals.no_ring_during_call && globals.main_stream != globals.ring_stream)) ) { //if there is a ring stream and not an active call or if there is an active call and we are allowed to ring during it AND the ring stream is not the main stream
- WriteAudioStream(globals.ring_stream->stream, abuf, (long) olen, &globals.ring_stream->write_timer);
+ WriteAudioStream(globals.ring_stream->stream, abuf, (long) olen, 0, &globals.ring_stream->write_timer);
}
} else {
switch_yield(10000);
@@ -339,10 +415,12 @@ static switch_status_t channel_on_routing(switch_core_session_t *session)
}
if (switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) {
- if (!switch_test_flag(tech_pvt, TFLAG_ANSWER)) {
+ if (!switch_test_flag(tech_pvt, TFLAG_ANSWER) &&
+ !switch_channel_test_flag(channel, CF_ANSWERED)) {
switch_channel_hangup(channel, SWITCH_CAUSE_NO_ANSWER);
return SWITCH_STATUS_SUCCESS;
}
+ switch_set_flag(tech_pvt, TFLAG_ANSWER);
}
switch_set_flag_locked(tech_pvt, TFLAG_IO);
@@ -389,6 +467,7 @@ static audio_stream_t* find_audio_stream(int indev, int outdev, int already_lock
}
return NULL;
}
+
static void destroy_audio_streams()
{
int close_wait = 4;
@@ -402,6 +481,7 @@ static void destroy_audio_streams()
}
globals.destroying_streams = 0;
}
+
static switch_status_t validate_main_audio_stream()
{
if (globals.read_timer.timer_interface) {
@@ -578,9 +658,12 @@ static void add_pvt(private_t *tech_pvt, int master)
switch_snprintf(tech_pvt->call_id, sizeof(tech_pvt->call_id), "%d", ++globals.call_id);
switch_channel_set_variable(switch_core_session_get_channel(tech_pvt->session), SWITCH_PA_CALL_ID_VARIABLE, tech_pvt->call_id);
switch_core_hash_insert(globals.call_hash, tech_pvt->call_id, tech_pvt);
- switch_core_session_set_read_codec(tech_pvt->session, &globals.read_codec);
- switch_core_session_set_write_codec(tech_pvt->session, &globals.write_codec);
+ if (!tech_pvt->audio_endpoint) {
+ switch_core_session_set_read_codec(tech_pvt->session, &globals.read_codec);
+ switch_core_session_set_write_codec(tech_pvt->session, &globals.write_codec);
+ }
switch_mutex_unlock(globals.pa_mutex);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Added call %s\n", tech_pvt->call_id);
}
for (tp = globals.call_list; tp; tp = tp->next) {
@@ -589,7 +672,7 @@ static void add_pvt(private_t *tech_pvt, int master)
}
if (master && switch_test_flag(tp, TFLAG_MASTER) ) {
switch_clear_flag_locked(tp, TFLAG_MASTER);
- create_hold_event(tp,0);
+ create_hold_event(tp, 0);
}
}
@@ -663,11 +746,30 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session)
return SWITCH_STATUS_SUCCESS;
}
+static int release_stream_channel(shared_audio_stream_t *stream, int index, int input);
static switch_status_t channel_on_hangup(switch_core_session_t *session)
{
private_t *tech_pvt = switch_core_session_get_private(session);
switch_assert(tech_pvt != NULL);
+ if (tech_pvt->audio_endpoint) {
+ audio_endpoint_t *endpoint = tech_pvt->audio_endpoint;
+
+ tech_pvt->audio_endpoint = NULL;
+
+ switch_mutex_lock(endpoint->mutex);
+
+ release_stream_channel(endpoint->in_stream, endpoint->inchan, 1);
+ release_stream_channel(endpoint->out_stream, endpoint->outchan, 0);
+ switch_core_timer_destroy(&endpoint->read_timer);
+ switch_core_timer_destroy(&endpoint->write_timer);
+ switch_core_codec_destroy(&endpoint->read_codec);
+ switch_core_codec_destroy(&endpoint->write_codec);
+ endpoint->master = NULL;
+
+ switch_mutex_unlock(endpoint->mutex);
+ }
+
switch_mutex_lock(globals.pa_mutex);
switch_core_hash_delete(globals.call_hash, tech_pvt->call_id);
switch_mutex_unlock(globals.pa_mutex);
@@ -727,12 +829,46 @@ static switch_status_t channel_send_dtmf(switch_core_session_t *session, const s
return SWITCH_STATUS_SUCCESS;
}
+static switch_status_t channel_endpoint_read(audio_endpoint_t *endpoint, switch_frame_t **frame)
+{
+ int samples = 0;
+
+ if (!endpoint->in_stream) {
+ switch_core_timer_next(&endpoint->read_timer);
+ *frame = &globals.cng_frame;
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ endpoint->read_frame.data = endpoint->read_buf;
+ endpoint->read_frame.buflen = sizeof(endpoint->read_buf);
+ endpoint->read_frame.source = __FILE__;
+ samples = ReadAudioStream(endpoint->in_stream->stream,
+ endpoint->read_frame.data, STREAM_SAMPLES_PER_PACKET(endpoint->in_stream),
+ endpoint->inchan, &endpoint->read_timer);
+
+ if (!samples) {
+ switch_core_timer_next(&endpoint->read_timer);
+ *frame = &globals.cng_frame;
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ endpoint->read_frame.datalen = (samples * sizeof(int16_t));
+ endpoint->read_frame.samples = samples;
+ endpoint->read_frame.codec = &endpoint->read_codec;
+ *frame = &endpoint->read_frame;
+ return SWITCH_STATUS_SUCCESS;
+}
+
static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
{
private_t *tech_pvt = switch_core_session_get_private(session);
int samples = 0;
switch_status_t status = SWITCH_STATUS_FALSE;
switch_assert(tech_pvt != NULL);
+
+ if (tech_pvt->audio_endpoint) {
+ return channel_endpoint_read(tech_pvt->audio_endpoint, frame);
+ }
if (!globals.main_stream) {
goto normal_return;
@@ -796,7 +932,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
}
switch_mutex_lock(globals.device_lock);
- samples = ReadAudioStream(globals.main_stream->stream, globals.read_frame.data, globals.read_codec.implementation->samples_per_packet, &globals.read_timer);
+ samples = ReadAudioStream(globals.main_stream->stream, globals.read_frame.data, globals.read_codec.implementation->samples_per_packet, 0, &globals.read_timer);
switch_mutex_unlock(globals.device_lock);
if (samples) {
@@ -827,12 +963,37 @@ normal_return:
}
+static switch_status_t channel_endpoint_write(audio_endpoint_t *endpoint, switch_frame_t *frame)
+{
+ if (!endpoint->out_stream) {
+ switch_core_timer_next(&endpoint->write_timer);
+ return SWITCH_STATUS_SUCCESS;
+ }
+ if (!endpoint->master) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+ if (switch_test_flag(endpoint->master, TFLAG_HUP)) {
+ return SWITCH_STATUS_FALSE;
+ }
+ if (!switch_test_flag(endpoint->master, TFLAG_IO)) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+ WriteAudioStream(endpoint->out_stream->stream, (short *)frame->data,
+ (int)(frame->datalen / sizeof(SAMPLE)),
+ endpoint->outchan, &(endpoint->write_timer));
+ return SWITCH_STATUS_SUCCESS;
+}
+
static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
{
switch_status_t status = SWITCH_STATUS_FALSE;
private_t *tech_pvt = switch_core_session_get_private(session);
switch_assert(tech_pvt != NULL);
+ if (tech_pvt->audio_endpoint) {
+ return channel_endpoint_write(tech_pvt->audio_endpoint, frame);
+ }
+
if (!globals.main_stream) {
return SWITCH_STATUS_FALSE;
}
@@ -847,7 +1008,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
if (globals.main_stream) {
if (switch_test_flag((&globals), GFLAG_EAR)) {
- WriteAudioStream(globals.main_stream->stream, (short *) frame->data, (int) (frame->datalen / sizeof(SAMPLE)), &(globals.main_stream->write_timer));
+ WriteAudioStream(globals.main_stream->stream, (short *) frame->data, (int) (frame->datalen / sizeof(SAMPLE)), 0, &(globals.main_stream->write_timer));
}
status = SWITCH_STATUS_SUCCESS;
}
@@ -904,6 +1065,72 @@ switch_io_routines_t portaudio_io_routines = {
/*.receive_message */ channel_receive_message
};
+static int create_shared_audio_stream(shared_audio_stream_t *stream);
+static int destroy_shared_audio_stream(shared_audio_stream_t *stream);
+static int take_stream_channel(shared_audio_stream_t *stream, int index, int input)
+{
+ int rc = 0;
+ if (!stream) {
+ return rc;
+ }
+
+ switch_mutex_lock(stream->mutex);
+
+ if (!stream->stream && create_shared_audio_stream(stream)) {
+ rc = -1;
+ goto done;
+ }
+
+ if (input) {
+ if (stream->inchan_used[index]) {
+ rc = -1;
+ goto done;
+ }
+ stream->inchan_used[index] = 1;
+ } else {
+ if (!input && stream->outchan_used[index]) {
+ rc = -1;
+ goto done;
+ }
+ stream->outchan_used[index] = 1;
+ }
+
+done:
+ switch_mutex_unlock(stream->mutex);
+ return rc;
+}
+
+static int release_stream_channel(shared_audio_stream_t *stream, int index, int input)
+{
+ int i = 0;
+ int destroy_stream = 1;
+ int rc = 0;
+
+ if (!stream) {
+ return rc;
+ }
+
+ switch_mutex_lock(stream->mutex);
+
+ if (input) {
+ stream->inchan_used[index] = 0;
+ } else {
+ stream->outchan_used[index] = 0;
+ }
+
+ for (i = 0; i < stream->channels; i++) {
+ if (stream->inchan_used[i] || stream->outchan_used[i]) {
+ destroy_stream = 0;
+ }
+ }
+ if (destroy_stream) {
+ destroy_shared_audio_stream(stream);
+ }
+
+ switch_mutex_unlock(stream->mutex);
+ return rc;
+}
+
/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines
that allocate memory or you will have 1 channel with memory allocated from another channel's pool!
*/
@@ -912,51 +1139,161 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
switch_call_cause_t *cancel_cause)
{
+ char name[128];
+ const char *id = NULL;
+ private_t *tech_pvt = NULL;
+ switch_channel_t *channel = NULL;
+ switch_caller_profile_t *caller_profile = NULL;
+ switch_call_cause_t retcause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ int codec_ms = -1;
+ int samples_per_packet = -1;
+ int sample_rate = 0;
+ audio_endpoint_t *endpoint = NULL;
+ char *endpoint_name = NULL;
+ const char *endpoint_answer = NULL;
- if ((*new_session = switch_core_session_request(portaudio_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool)) != 0) {
- private_t *tech_pvt;
- switch_channel_t *channel;
- switch_caller_profile_t *caller_profile;
-
- switch_core_session_add_stream(*new_session, NULL);
- if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) {
- memset(tech_pvt, 0, sizeof(*tech_pvt));
- switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(*new_session));
- channel = switch_core_session_get_channel(*new_session);
- switch_core_session_set_private(*new_session, tech_pvt);
- tech_pvt->session = *new_session;
- } else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
- switch_core_session_destroy(new_session);
- return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
- }
-
- if (outbound_profile) {
- char name[128];
- const char *id = !zstr(outbound_profile->caller_id_number) ? outbound_profile->caller_id_number : "na";
- switch_snprintf(name, sizeof(name), "portaudio/%s", id);
-
- switch_channel_set_name(channel, name);
-
- caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
- switch_channel_set_caller_profile(channel, caller_profile);
- tech_pvt->caller_profile = caller_profile;
- if (outbound_profile->destination_number && !strcasecmp(outbound_profile->destination_number, "auto_answer")) {
- switch_set_flag(tech_pvt, TFLAG_AUTO_ANSWER);
- }
-
- } else {
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_ERROR, "Doh! no caller profile\n");
- switch_core_session_destroy(new_session);
- return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
- }
-
- switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND);
- switch_channel_set_state(channel, CS_INIT);
- return SWITCH_CAUSE_SUCCESS;
+ if (!outbound_profile) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing caller profile\n");
+ return retcause;
}
- return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ if (!(*new_session = switch_core_session_request(portaudio_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool))) {
+ return retcause;
+ }
+
+ switch_core_session_add_stream(*new_session, NULL);
+ if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) {
+ memset(tech_pvt, 0, sizeof(*tech_pvt));
+ switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(*new_session));
+ channel = switch_core_session_get_channel(*new_session);
+ switch_core_session_set_private(*new_session, tech_pvt);
+ tech_pvt->session = *new_session;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
+ switch_core_session_destroy(new_session);
+ return retcause;
+ }
+
+ if (outbound_profile->destination_number && !strncasecmp(outbound_profile->destination_number, "endpoint", sizeof("endpoint")-1)) {
+ codec_ms = -1;
+ samples_per_packet = -1;
+ endpoint = NULL;
+ endpoint_name = switch_core_strdup(outbound_profile->pool, outbound_profile->destination_number);
+ endpoint_name = strchr(endpoint_name, '/');
+ if (!endpoint_name) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_CRIT, "No portaudio endpoint specified\n");
+ goto error;
+ }
+ endpoint_name++;
+ endpoint = switch_core_hash_find(globals.endpoints, endpoint_name);
+ if (!endpoint) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_CRIT, "Invalid portaudio endpoint %s\n", endpoint_name);
+ goto error;
+ }
+
+ switch_mutex_lock(endpoint->mutex);
+
+ if (endpoint->master) {
+ /* someone already has this endpoint */
+ retcause = SWITCH_CAUSE_USER_BUSY;
+ goto error;
+ }
+
+ codec_ms = endpoint->in_stream ? endpoint->in_stream->codec_ms : endpoint->out_stream->codec_ms;
+ samples_per_packet = endpoint->in_stream ?
+ STREAM_SAMPLES_PER_PACKET(endpoint->in_stream) : STREAM_SAMPLES_PER_PACKET(endpoint->out_stream);
+ sample_rate = endpoint->in_stream ? endpoint->in_stream->sample_rate : endpoint->out_stream->sample_rate;
+
+ if (switch_core_timer_init(&endpoint->read_timer,
+ globals.timer_name, codec_ms,
+ samples_per_packet, module_pool) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to setup read timer for endpoint '%s'!\n", endpoint->name);
+ goto error;
+ }
+
+ /* The write timer must be setup regardless */
+ if (switch_core_timer_init(&endpoint->write_timer,
+ globals.timer_name, codec_ms,
+ samples_per_packet, module_pool) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to setup read timer for endpoint '%s'!\n", endpoint->name);
+ goto error;
+ }
+
+ if (switch_core_codec_init(&endpoint->read_codec,
+ "L16", NULL, sample_rate, codec_ms, 1,
+ SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
+ goto error;
+ }
+
+ if (switch_core_codec_init(&endpoint->write_codec,
+ "L16", NULL, sample_rate, codec_ms, 1,
+ SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't load codec?\n");
+ goto error;
+ }
+ switch_core_session_set_read_codec(tech_pvt->session, &endpoint->read_codec);
+ switch_core_session_set_write_codec(tech_pvt->session, &endpoint->write_codec);
+
+ /* try to acquire the stream */
+ if (take_stream_channel(endpoint->in_stream, endpoint->inchan, 1)) {
+ retcause = SWITCH_CAUSE_USER_BUSY;
+ goto error;
+ }
+ if (take_stream_channel(endpoint->out_stream, endpoint->outchan, 0)) {
+ release_stream_channel(endpoint->in_stream, endpoint->inchan, 1);
+ retcause = SWITCH_CAUSE_USER_BUSY;
+ goto error;
+ }
+ switch_snprintf(name, sizeof(name), "portaudio/endpoint-%s", endpoint_name);
+ if (var_event && (endpoint_answer = (switch_event_get_header(var_event, "endpoint_answer")))) {
+ if (switch_true(endpoint_answer)) {
+ switch_set_flag(tech_pvt, TFLAG_AUTO_ANSWER);
+ }
+ } else {
+ switch_set_flag(tech_pvt, TFLAG_AUTO_ANSWER);
+ }
+ endpoint->master = tech_pvt;
+ tech_pvt->audio_endpoint = endpoint;
+ switch_mutex_unlock(endpoint->mutex);
+ } else {
+ id = !zstr(outbound_profile->caller_id_number) ? outbound_profile->caller_id_number : "na";
+ switch_snprintf(name, sizeof(name), "portaudio/%s", id);
+ if (outbound_profile->destination_number && !strcasecmp(outbound_profile->destination_number, "auto_answer")) {
+ switch_set_flag(tech_pvt, TFLAG_AUTO_ANSWER);
+ }
+ }
+ switch_channel_set_name(channel, name);
+ caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
+ switch_channel_set_caller_profile(channel, caller_profile);
+ tech_pvt->caller_profile = caller_profile;
+
+ switch_set_flag_locked(tech_pvt, TFLAG_OUTBOUND);
+ switch_channel_set_state(channel, CS_INIT);
+ return SWITCH_CAUSE_SUCCESS;
+
+error:
+ if (endpoint) {
+ if (!endpoint->master) {
+ if (endpoint->read_timer.interval) {
+ switch_core_timer_destroy(&endpoint->read_timer);
+ }
+ if (endpoint->write_timer.interval) {
+ switch_core_timer_destroy(&endpoint->write_timer);
+ }
+ if (endpoint->read_codec.codec_interface) {
+ switch_core_codec_destroy(&endpoint->read_codec);
+ }
+ if (endpoint->write_codec.codec_interface) {
+ switch_core_codec_destroy(&endpoint->write_codec);
+ }
+ }
+ switch_mutex_unlock(endpoint->mutex);
+ }
+ if (new_session && *new_session) {
+ switch_core_session_destroy(new_session);
+ }
+ return retcause;
}
@@ -971,12 +1308,14 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_portaudio_load)
memset(&globals, 0, sizeof(globals));
switch_core_hash_init(&globals.call_hash, module_pool);
+ switch_core_hash_init(&globals.sh_streams, module_pool);
+ switch_core_hash_init(&globals.endpoints, module_pool);
switch_mutex_init(&globals.device_lock, SWITCH_MUTEX_NESTED, module_pool);
switch_mutex_init(&globals.pvt_lock, SWITCH_MUTEX_NESTED, module_pool);
switch_mutex_init(&globals.streams_lock, SWITCH_MUTEX_NESTED, module_pool);
switch_mutex_init(&globals.flag_mutex, SWITCH_MUTEX_NESTED, module_pool);
switch_mutex_init(&globals.pa_mutex, SWITCH_MUTEX_NESTED, module_pool);
- globals.codecs_inited=0;
+ globals.codecs_inited = 0;
globals.read_frame.data = globals.databuf;
globals.read_frame.buflen = sizeof(globals.databuf);
globals.cng_frame.data = globals.cngbuf;
@@ -1055,16 +1394,248 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_portaudio_load)
switch_console_set_complete("add pa play");
switch_console_set_complete("add pa playdev");
switch_console_set_complete("add pa looptest");
+ switch_console_set_complete("add pa shstreams");
+ switch_console_set_complete("add pa endpoints");
/* indicate that the module should continue to be loaded */
return SWITCH_STATUS_SUCCESS;
}
+static int check_device(char *devstr, int check_input)
+{
+ int devval;
+ if (devstr[0] == '#') {
+ devval = get_dev_by_number(devstr + 1, check_input);
+ } else {
+ devval = get_dev_by_name(devstr, check_input);
+ }
+ return devval;
+}
+
+static switch_status_t load_streams(switch_xml_t streams)
+{
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ switch_xml_t param, mystream;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Loading streams ...\n");
+ for (mystream = switch_xml_child(streams, "stream"); mystream; mystream = mystream->next) {
+ shared_audio_stream_t *stream = NULL;
+ int devval = -1;
+ char *stream_name = (char *) switch_xml_attr_soft(mystream, "name");
+
+ if (!stream_name) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing stream name attribute, skipping ...\n");
+ continue;
+ }
+
+ /* check if that stream name is not already used */
+ stream = switch_core_hash_find(globals.sh_streams, stream_name);
+ if (stream) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "A stream with name '%s' already exists\n", stream_name);
+ continue;
+ }
+
+ stream = switch_core_alloc(module_pool, sizeof(*stream));
+ if (!stream) {
+ continue;
+ }
+ switch_mutex_init(&stream->mutex, SWITCH_MUTEX_NESTED, module_pool);
+ stream->indev = -1;
+ stream->outdev = -1;
+ stream->sample_rate = globals.sample_rate;
+ stream->codec_ms = globals.codec_ms;
+ stream->channels = 1;
+ switch_snprintf(stream->name, sizeof(stream->name), "%s", stream_name);
+ for (param = switch_xml_child(mystream, "param"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Parsing stream '%s' parameter %s = %s\n", stream_name, var, val);
+ if (!strcmp(var, "indev")) {
+ devval = check_device(val, 1);
+ if (devval < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "Invalid indev specified for stream '%s'\n", stream_name);
+ stream->indev = -1;
+ continue;
+ }
+ stream->indev = devval;
+ } else if (!strcmp(var, "outdev")) {
+ devval = check_device(val, 0);
+ if (devval < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "Invalid outdev specified for stream '%s'\n", stream_name);
+ stream->outdev = -1;
+ continue;
+ }
+ stream->outdev = devval;
+ } else if (!strcmp(var, "sample-rate")) {
+ stream->sample_rate = atoi(val);
+ if (stream->sample_rate < MIN_STREAM_SAMPLE_RATE) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "Invalid sample rate specified for stream '%s', forcing to 8000\n", stream_name);
+ stream->sample_rate = MIN_STREAM_SAMPLE_RATE;
+ }
+ } else if (!strcmp(var, "codec-ms")) {
+ int tmp = atoi(val);
+ if (switch_check_interval(stream->sample_rate, tmp)) {
+ stream->codec_ms = tmp;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
+ "codec-ms must be multiple of 10 and less than %d, Using default of 20\n", SWITCH_MAX_INTERVAL);
+ }
+ } else if (!strcmp(var, "channels")) {
+ stream->channels = atoi(val);
+ if (stream->channels < 1 || stream->channels > MAX_IO_CHANNELS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "Invalid number of channels specified for stream '%s', forcing to 1\n", stream_name);
+ stream->channels = 1;
+ }
+ }
+ }
+ if (stream->indev < 0 && stream->outdev < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "You need at least one device for stream '%s'\n", stream_name);
+ continue;
+ }
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,
+ "Created stream '%s', sample-rate = %d, codec-ms = %d\n", stream->name, stream->sample_rate, stream->codec_ms);
+ switch_core_hash_insert(globals.sh_streams, stream->name, stream);
+ }
+ return status;
+}
+
+static int check_stream_compat(shared_audio_stream_t *in_stream, shared_audio_stream_t *out_stream)
+{
+ if (!in_stream || !out_stream) {
+ /* nothing to be compatible with */
+ return 0;
+ }
+ if (in_stream->sample_rate != out_stream->sample_rate) {
+ return -1;
+ }
+ if (in_stream->codec_ms != out_stream->codec_ms) {
+ return -1;
+ }
+ return 0;
+}
+
+static shared_audio_stream_t *check_stream(char *streamstr, int check_input, int *chanindex)
+{
+ shared_audio_stream_t *stream = NULL;
+ int cnum = 0;
+ char stream_name[255];
+ char *chan = NULL;
+
+ *chanindex = -1;
+
+ switch_snprintf(stream_name, sizeof(stream_name), "%s", streamstr);
+
+ chan = strchr(stream_name, ':');
+ if (!chan) {
+ return NULL;
+ }
+ *chan = 0;
+ chan++;
+ cnum = atoi(chan);
+
+ stream = switch_core_hash_find(globals.sh_streams, stream_name);
+ if (!stream) {
+ return NULL;
+ }
+
+ if (cnum < 0 || cnum > stream->channels) {
+ return NULL;
+ }
+
+ if (check_input && stream->indev < 0) {
+ return NULL;
+ }
+
+ if (!check_input && stream->outdev < 0) {
+ return NULL;
+ }
+
+ *chanindex = cnum;
+
+ return stream;
+}
+
+static switch_status_t load_endpoints(switch_xml_t endpoints)
+{
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ switch_xml_t param, myendpoint;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Loading endpoints ...\n");
+ for (myendpoint = switch_xml_child(endpoints, "endpoint"); myendpoint; myendpoint = myendpoint->next) {
+ audio_endpoint_t *endpoint = NULL;
+ shared_audio_stream_t *stream = NULL;
+ char *endpoint_name = (char *) switch_xml_attr_soft(myendpoint, "name");
+
+ if (!endpoint_name) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing endpoint name attribute, skipping ...\n");
+ continue;
+ }
+
+ /* check if that endpoint name is not already used */
+ endpoint = switch_core_hash_find(globals.endpoints, endpoint_name);
+ if (endpoint) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "An endpoint with name '%s' already exists\n", endpoint_name);
+ continue;
+ }
+
+ endpoint = switch_core_alloc(module_pool, sizeof(*endpoint));
+ if (!endpoint) {
+ continue;
+ }
+ switch_mutex_init(&endpoint->mutex, SWITCH_MUTEX_NESTED, module_pool);
+ endpoint->inchan = -1;
+ endpoint->outchan = -1;
+ switch_snprintf(endpoint->name, sizeof(endpoint->name), "%s", endpoint_name);
+ for (param = switch_xml_child(myendpoint, "param"); param; param = param->next) {
+ char *var = (char *) switch_xml_attr_soft(param, "name");
+ char *val = (char *) switch_xml_attr_soft(param, "value");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Parsing endpoint '%s' parameter %s = %s\n", endpoint_name, var, val);
+ if (!strcmp(var, "instream")) {
+ stream = check_stream(val, 1, &endpoint->inchan) ;
+ if (!stream) {
+ endpoint->in_stream = NULL;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "Invalid instream specified for endpoint '%s'\n", endpoint_name);
+ continue;
+ }
+ endpoint->in_stream = stream;
+ } else if (!strcmp(var, "outstream")) {
+ stream = check_stream(val, 0, &endpoint->outchan);
+ if (!stream) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "Invalid outstream specified for endpoint '%s'\n", endpoint_name);
+ endpoint->out_stream = NULL;
+ continue;
+ }
+ endpoint->out_stream = stream;
+ }
+ }
+ if (!endpoint->in_stream && !endpoint->out_stream) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "You need at least one stream for endpoint '%s'\n", endpoint_name);
+ continue;
+ }
+ if (check_stream_compat(endpoint->in_stream, endpoint->out_stream)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "Incomatible input and output streams for endpoint '%s'\n", endpoint_name);
+ continue;
+ }
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE,
+ "Created endpoint '%s', instream = %s, outstream = %s\n", endpoint->name,
+ endpoint->in_stream ? endpoint->in_stream->name : "(none)",
+ endpoint->out_stream ? endpoint->out_stream->name : "(none)");
+ switch_core_hash_insert(globals.endpoints, endpoint->name, endpoint);
+ }
+ return status;
+}
static switch_status_t load_config(void)
{
char *cf = "portaudio.conf";
- switch_xml_t cfg, xml, settings, param;
+ switch_xml_t cfg, xml, settings, streams, endpoints, param;
switch_status_t status = SWITCH_STATUS_SUCCESS;
if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
@@ -1205,11 +1776,21 @@ static switch_status_t load_config(void)
if (globals.ringdev < 0) {
if (globals.outdev > -1) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid or no ring device configured, using output device as ring device\n");
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Invalid or no ring device configured, using output device as ring device\n");
globals.ringdev = globals.outdev;
}
}
+ /* streams and endpoints must be last, some initialization depend on globals defaults */
+ if ((streams = switch_xml_child(cfg, "streams"))) {
+ load_streams(streams);
+ }
+
+ if ((endpoints = switch_xml_child(cfg, "endpoints"))) {
+ load_endpoints(endpoints);
+ }
+
+
switch_xml_free(xml);
return status;
@@ -1223,6 +1804,8 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_portaudio_shutdown)
Pa_Terminate();
switch_core_hash_destroy(&globals.call_hash);
+ switch_core_hash_destroy(&globals.sh_streams);
+ switch_core_hash_destroy(&globals.endpoints);
switch_event_free_subclass(MY_EVENT_RINGING);
switch_event_free_subclass(MY_EVENT_MAKE_CALL);
@@ -1399,7 +1982,7 @@ static switch_status_t play_dev(switch_stream_handle_t *stream, int outdev, char
break;
}
- WriteAudioStream(audio_stream->stream, abuf, (long) olen, &(audio_stream->write_timer));
+ WriteAudioStream(audio_stream->stream, abuf, (long) olen, 0, &(audio_stream->write_timer));
wrote += (int) olen;
if (samples) {
samples -= (int) olen;
@@ -1706,6 +2289,7 @@ static switch_status_t switch_audio_stream()
return SWITCH_STATUS_SUCCESS;
}
+
PaError open_audio_stream(PABLIO_Stream **stream, const PaStreamParameters * inputParameters, const PaStreamParameters * outputParameters)
{
if (inputParameters->device != -1) {
@@ -1714,6 +2298,75 @@ PaError open_audio_stream(PABLIO_Stream **stream, const PaStreamParameters * inp
return OpenAudioStream(stream, NULL, outputParameters, globals.sample_rate, paClipOff, globals.read_codec.implementation->samples_per_packet, 0);
}
+PaError open_shared_audio_stream(shared_audio_stream_t *shstream, const PaStreamParameters * inputParameters, const PaStreamParameters * outputParameters)
+{
+ PaError err;
+ if (inputParameters->device != -1) {
+ err = OpenAudioStream(&shstream->stream, inputParameters->device != -1 ? inputParameters : NULL,
+ outputParameters->device != -1 ? outputParameters : NULL, shstream->sample_rate,
+ paClipOff, STREAM_SAMPLES_PER_PACKET(shstream), globals.dual_streams);
+ } else {
+ err = OpenAudioStream(&shstream->stream, NULL, outputParameters, shstream->sample_rate,
+ paClipOff, STREAM_SAMPLES_PER_PACKET(shstream), 0);
+ }
+ if (err != paNoError) {
+ shstream->stream = NULL;
+ }
+ return err;
+}
+
+static int create_shared_audio_stream(shared_audio_stream_t *shstream)
+{
+ PaStreamParameters inputParameters, outputParameters;
+ PaError err;
+ switch_event_t *event;
+
+ inputParameters.device = shstream->indev;
+ if (shstream->indev != -1) {
+ inputParameters.channelCount = shstream->channels;
+ inputParameters.sampleFormat = SAMPLE_TYPE;
+ inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)->defaultLowInputLatency;
+ inputParameters.hostApiSpecificStreamInfo = NULL;
+ }
+ outputParameters.device = shstream->outdev;
+ if (shstream->outdev != -1) {
+ outputParameters.channelCount = shstream->channels;
+ outputParameters.sampleFormat = SAMPLE_TYPE;
+ outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
+ outputParameters.hostApiSpecificStreamInfo = NULL;
+ }
+
+ err = open_shared_audio_stream(shstream, &inputParameters, &outputParameters);
+ if (err != paNoError) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
+ "Error opening audio device retrying (indev = %d, outdev = %d, error = %s)\n",
+ inputParameters.device, outputParameters.device, Pa_GetErrorText(err));
+ switch_yield(1000000);
+ err = open_shared_audio_stream(shstream, &inputParameters, &outputParameters);
+ }
+
+ if (err != paNoError) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't open audio device (indev = %d, outdev = %d, error = %s)\n",
+ inputParameters.device, outputParameters.device, Pa_GetErrorText(err));
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_ERROR_AUDIO_DEV) == SWITCH_STATUS_SUCCESS) {
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Reason", Pa_GetErrorText(err));
+ switch_event_fire(&event);
+ }
+ return -1;
+ }
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Created shared audio stream %s: %d channels %d\n",
+ shstream->name, shstream->sample_rate, shstream->channels);
+ return 0;
+}
+
+static int destroy_shared_audio_stream(shared_audio_stream_t *shstream)
+{
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Destroying shared audio stream %s\n", shstream->name);
+ CloseAudioStream(shstream->stream);
+ shstream->stream = NULL;
+ return 0;
+}
+
static audio_stream_t *create_audio_stream(int indev, int outdev)
{
PaStreamParameters inputParameters, outputParameters;
@@ -1721,12 +2374,12 @@ static audio_stream_t *create_audio_stream(int indev, int outdev)
switch_event_t *event;
audio_stream_t *stream;
- stream = malloc(sizeof(audio_stream_t));
+ stream = malloc(sizeof(*stream));
if (stream == NULL) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to alloc memory\n");
return NULL;
}
- memset(stream, 0, sizeof(audio_stream_t));
+ memset(stream, 0, sizeof(*stream));
stream->next = NULL;
stream->stream = NULL;
stream->indev = indev;
@@ -1817,6 +2470,43 @@ static switch_status_t dtmf_call(char **argv, int argc, switch_stream_handle_t *
return SWITCH_STATUS_SUCCESS;
}
+static switch_status_t list_shared_streams(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ switch_hash_index_t *hi;
+ int cnt = 0;
+ for (hi = switch_hash_first(NULL, globals.sh_streams); hi; hi = switch_hash_next(hi)) {
+ const void *var;
+ void *val;
+ shared_audio_stream_t *s = NULL;
+ switch_hash_this(hi, &var, NULL, &val);
+ s = val;
+ stream->write_function(stream, "%s> indev: %d, outdev: %d, sample-rate: %d, codec-ms: %d, channels: %d\n",
+ s->name, s->indev, s->outdev, s->sample_rate, s->codec_ms, s->channels);
+ cnt++;
+ }
+ stream->write_function(stream, "Total streams: %d\n", cnt);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t list_endpoints(char **argv, int argc, switch_stream_handle_t *stream)
+{
+ switch_hash_index_t *hi;
+ int cnt = 0;
+ for (hi = switch_hash_first(NULL, globals.endpoints); hi; hi = switch_hash_next(hi)) {
+ const void *var;
+ void *val;
+ audio_endpoint_t *e = NULL;
+ switch_hash_this(hi, &var, NULL, &val);
+ e = val;
+ stream->write_function(stream, "%s> instream: %s, outstream: %s\n",
+ e->name, e->in_stream ? e->in_stream->name : "(none)",
+ e->out_stream ? e->out_stream->name : "(none)");
+ cnt++;
+ }
+ stream->write_function(stream, "Total endpoints: %d\n", cnt);
+ return SWITCH_STATUS_SUCCESS;
+}
+
static switch_status_t close_streams(char **argv, int argc, switch_stream_handle_t *stream)
{
if (globals.call_list) {
@@ -1978,8 +2668,8 @@ static switch_status_t looptest(char **argv, int argc, switch_stream_handle_t *s
if (globals.destroying_streams || ! globals.main_stream->stream) {
break;
}
- if ((samples = ReadAudioStream(globals.main_stream->stream, globals.read_frame.data, globals.read_codec.implementation->samples_per_packet, &globals.read_timer))) {
- WriteAudioStream(globals.main_stream->stream, globals.read_frame.data, (long) samples, &(globals.main_stream->write_timer));
+ if ((samples = ReadAudioStream(globals.main_stream->stream, globals.read_frame.data, globals.read_codec.implementation->samples_per_packet, 0, &globals.read_timer))) {
+ WriteAudioStream(globals.main_stream->stream, globals.read_frame.data, (long) samples, 0, &(globals.main_stream->write_timer));
success = 1;
}
switch_yield(10000);
@@ -2386,6 +3076,8 @@ SWITCH_STANDARD_API(pa_cmd)
"pa playdev # [ringtest|] [seconds] [no_close]\n"
"pa ringfile [filename]\n"
"pa looptest\n"
+ "pa shstreams\n"
+ "pa endpoints\n"
"--------------------------------------------------------------------------------\n";
@@ -2510,6 +3202,10 @@ SWITCH_STANDARD_API(pa_cmd)
func = looptest;
} else if (!strcasecmp(argv[0], "ringfile")) {
func = set_ringfile;
+ } else if (!strcasecmp(argv[0], "shstreams")) {
+ func = list_shared_streams;
+ } else if (!strcasecmp(argv[0], "endpoints")) {
+ func = list_endpoints;
} else {
stream->write_function(stream, "Unknown Command or not enough args [%s]\n", argv[0]);
}
diff --git a/src/mod/endpoints/mod_portaudio/pablio.c b/src/mod/endpoints/mod_portaudio/pablio.c
index 05fdf0f280..6423dc762d 100644
--- a/src/mod/endpoints/mod_portaudio/pablio.c
+++ b/src/mod/endpoints/mod_portaudio/pablio.c
@@ -78,14 +78,23 @@ static PaError PABLIO_TermFIFO(PaUtilRingBuffer * rbuf);
static int iblockingIOCallback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo * timeInfo, PaStreamCallbackFlags statusFlags, void *userData)
{
+ int c = 0, i = 0, j = 0;
PABLIO_Stream *data = (PABLIO_Stream *) userData;
long numBytes = data->bytesPerFrame * framesPerBuffer;
+ const int16_t *inputSamples = inputBuffer;
+ int16_t *chanSamples = (int16_t*)data->iobuff;
/* This may get called with NULL inputBuffer during initial setup. */
if (inputBuffer != NULL) {
- if (PaUtil_WriteRingBuffer(&data->inFIFO, inputBuffer, numBytes) != numBytes) {
- PaUtil_FlushRingBuffer(&data->inFIFO);
- PaUtil_WriteRingBuffer(&data->inFIFO, inputBuffer, numBytes);
+ /* retrieve the data for each channel and put it in the ring buffer */
+ for (c = 0; c < data->channelCount; c++) {
+ for (i = 0, j = c; i < framesPerBuffer; j += data->channelCount, i++) {
+ chanSamples[i] = inputSamples[j];
+ }
+ if (PaUtil_WriteRingBuffer(&data->inFIFOs[c], chanSamples, numBytes) != numBytes) {
+ PaUtil_FlushRingBuffer(&data->inFIFOs[c]);
+ PaUtil_WriteRingBuffer(&data->inFIFOs[c], inputBuffer, numBytes);
+ }
}
}
@@ -97,13 +106,21 @@ static int oblockingIOCallback(const void *inputBuffer, void *outputBuffer,
{
PABLIO_Stream *data = (PABLIO_Stream *) userData;
long numBytes = data->bytesPerFrame * framesPerBuffer;
+ int16_t *outputSamples = outputBuffer;
+ int16_t *chanSamples = (short *)data->iobuff;
+ int c = 0, i = 0, j = 0;
if (outputBuffer != NULL) {
- int i;
- int numRead = PaUtil_ReadRingBuffer(&data->outFIFO, outputBuffer, numBytes);
- /* Zero out remainder of buffer if we run out of data. */
- for (i = numRead; i < numBytes; i++) {
- ((char *) outputBuffer)[i] = 0;
+ for (c = 0; c < data->channelCount; c++) {
+ int numRead = PaUtil_ReadRingBuffer(&data->outFIFOs[c], chanSamples, numBytes);
+ numRead = numRead / sizeof(int16_t);
+ for (i = 0, j = c; i < framesPerBuffer; j += data->channelCount, i++) {
+ if (i < numRead) {
+ outputSamples[j] = chanSamples[i];
+ } else {
+ outputSamples[j] = 0;
+ }
+ }
}
}
@@ -143,7 +160,7 @@ static PaError PABLIO_TermFIFO(PaUtilRingBuffer * rbuf)
* Write data to ring buffer.
* Will not return until all the data has been written.
*/
-long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch_timer_t *timer)
+long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, int chan, switch_timer_t *timer)
{
long bytesWritten;
char *p = (char *) data;
@@ -151,12 +168,12 @@ long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switc
switch_core_timer_next(timer);
- bytesWritten = PaUtil_WriteRingBuffer(&aStream->outFIFO, p, numBytes);
+ bytesWritten = PaUtil_WriteRingBuffer(&aStream->outFIFOs[chan], p, numBytes);
numBytes -= bytesWritten;
p += bytesWritten;
if (numBytes > 0) {
- PaUtil_FlushRingBuffer(&aStream->outFIFO);
+ PaUtil_FlushRingBuffer(&aStream->outFIFOs[chan]);
return 0;
}
return numFrames;
@@ -166,7 +183,7 @@ long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switc
* Read data from ring buffer.
* Will not return until all the data has been read.
*/
-long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch_timer_t *timer)
+long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, int chan, switch_timer_t *timer)
{
long bytesRead = 0;
char *p = (char *) data;
@@ -177,17 +194,17 @@ long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch
while (totalBytes < neededBytes && --max > 0) {
- avail = PaUtil_GetRingBufferReadAvailable(&aStream->inFIFO);
+ avail = PaUtil_GetRingBufferReadAvailable(&aStream->inFIFOs[chan]);
//printf("AVAILABLE BYTES %ld pass %d\n", avail, 5000 - max);
if (avail >= neededBytes * 6) {
- PaUtil_FlushRingBuffer(&aStream->inFIFO);
+ PaUtil_FlushRingBuffer(&aStream->inFIFOs[chan]);
avail = 0;
} else {
bytesRead = 0;
if (totalBytes < neededBytes && avail >= neededBytes) {
- bytesRead = PaUtil_ReadRingBuffer(&aStream->inFIFO, p, neededBytes);
+ bytesRead = PaUtil_ReadRingBuffer(&aStream->inFIFOs[chan], p, neededBytes);
totalBytes += bytesRead;
}
@@ -206,9 +223,9 @@ long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch
* Return the number of frames that could be written to the stream without
* having to wait.
*/
-long GetAudioStreamWriteable(PABLIO_Stream * aStream)
+long GetAudioStreamWriteable(PABLIO_Stream * aStream, int chan)
{
- int bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFO);
+ int bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFOs[chan]);
return bytesEmpty / aStream->bytesPerFrame;
}
@@ -216,9 +233,9 @@ long GetAudioStreamWriteable(PABLIO_Stream * aStream)
* Return the number of frames that are available to be read from the
* stream without having to wait.
*/
-long GetAudioStreamReadable(PABLIO_Stream * aStream)
+long GetAudioStreamReadable(PABLIO_Stream * aStream, int chan)
{
- int bytesFull = PaUtil_GetRingBufferReadAvailable(&aStream->inFIFO);
+ int bytesFull = PaUtil_GetRingBufferReadAvailable(&aStream->inFIFOs[chan]);
return bytesFull / aStream->bytesPerFrame;
}
@@ -251,7 +268,8 @@ PaError OpenAudioStream(PABLIO_Stream ** rwblPtr,
PABLIO_Stream *aStream;
long numFrames;
//long numBytes;
- //int channels = 1;
+ int c = 0;
+ int channels = 1;
if (!(inputParameters || outputParameters)) {
return -1;
@@ -262,31 +280,34 @@ PaError OpenAudioStream(PABLIO_Stream ** rwblPtr,
switch_assert(aStream);
memset(aStream, 0, sizeof(PABLIO_Stream));
- /*
if (inputParameters) {
channels = inputParameters->channelCount;
} else if (outputParameters) {
channels = outputParameters->channelCount;
}
- */
numFrames = RoundUpToNextPowerOf2(samples_per_packet * 5);
aStream->bytesPerFrame = bytesPerSample;
+ aStream->channelCount = channels;
/* Initialize Ring Buffers */
if (inputParameters) {
- err = PABLIO_InitFIFO(&aStream->inFIFO, numFrames, aStream->bytesPerFrame);
- if (err != paNoError) {
- goto error;
+ for (c = 0; c < channels; c++) {
+ err = PABLIO_InitFIFO(&aStream->inFIFOs[c], numFrames, aStream->bytesPerFrame);
+ if (err != paNoError) {
+ goto error;
+ }
}
aStream->has_in = 1;
}
if (outputParameters) {
- err = PABLIO_InitFIFO(&aStream->outFIFO, numFrames, aStream->bytesPerFrame);
- if (err != paNoError) {
- goto error;
+ for (c = 0; c < channels; c++) {
+ err = PABLIO_InitFIFO(&aStream->outFIFOs[c], numFrames, aStream->bytesPerFrame);
+ if (err != paNoError) {
+ goto error;
+ }
}
aStream->has_out = 1;
}
@@ -355,17 +376,21 @@ PaError CloseAudioStream(PABLIO_Stream * aStream)
{
int bytesEmpty;
int byteSize;
+ int c = 0;
- byteSize = aStream->outFIFO.bufferSize;
-
if (aStream->has_out) {
- /* If we are writing data, make sure we play everything written. */
- if (byteSize > 0) {
- bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFO);
- while (bytesEmpty < byteSize) {
- Pa_Sleep(10);
- bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFO);
+
+ for (c = 0; c < aStream->channelCount; c++) {
+ byteSize = aStream->outFIFOs[c].bufferSize;
+
+ /* If we are writing data, make sure we play everything written. */
+ if (byteSize > 0) {
+ bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFOs[c]);
+ while (bytesEmpty < byteSize) {
+ Pa_Sleep(10);
+ bytesEmpty = PaUtil_GetRingBufferWriteAvailable(&aStream->outFIFOs[c]);
+ }
}
}
}
@@ -401,11 +426,15 @@ PaError CloseAudioStream(PABLIO_Stream * aStream)
}
if (aStream->has_in) {
- PABLIO_TermFIFO(&aStream->inFIFO);
+ for (c = 0; c < aStream->channelCount; c++) {
+ PABLIO_TermFIFO(&aStream->inFIFOs[c]);
+ }
}
if (aStream->has_out) {
- PABLIO_TermFIFO(&aStream->outFIFO);
+ for (c = 0; c < aStream->channelCount; c++) {
+ PABLIO_TermFIFO(&aStream->outFIFOs[c]);
+ }
}
free(aStream);
@@ -413,3 +442,4 @@ PaError CloseAudioStream(PABLIO_Stream * aStream)
return paNoError;
}
+
diff --git a/src/mod/endpoints/mod_portaudio/pablio.h b/src/mod/endpoints/mod_portaudio/pablio.h
index 0bd3c41e46..435e4b0ca7 100644
--- a/src/mod/endpoints/mod_portaudio/pablio.h
+++ b/src/mod/endpoints/mod_portaudio/pablio.h
@@ -56,17 +56,30 @@ extern "C" {
#include
- typedef struct {
- PaUtilRingBuffer inFIFO;
- PaUtilRingBuffer outFIFO;
- PaStream *istream;
- PaStream *ostream;
- PaStream *iostream;
- int bytesPerFrame;
- int do_dual;
- int has_in;
- int has_out;
- } PABLIO_Stream;
+/*! Maximum number of channels per stream */
+#define MAX_IO_CHANNELS 2
+
+/*! Maximum numer of milliseconds per packet */
+#define MAX_IO_MS 100
+
+/*! Maximum sampling rate (48Khz) */
+#define MAX_SAMPLING_RATE 48000
+
+/* Maximum size of a read */
+#define MAX_IO_BUFFER (((MAX_IO_MS * MAX_SAMPLING_RATE)/1000)*sizeof(int16_t))
+typedef struct {
+ PaStream *istream;
+ PaStream *ostream;
+ PaStream *iostream;
+ int bytesPerFrame;
+ int do_dual;
+ int has_in;
+ int has_out;
+ PaUtilRingBuffer inFIFOs[MAX_IO_CHANNELS];
+ PaUtilRingBuffer outFIFOs[MAX_IO_CHANNELS];
+ int channelCount;
+ char iobuff[MAX_IO_BUFFER];
+} PABLIO_Stream;
/* Values for flags for OpenAudioStream(). */
#define PABLIO_READ (1<<0)
@@ -79,25 +92,25 @@ extern "C" {
* Write data to ring buffer.
* Will not return until all the data has been written.
*/
- long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch_timer_t *timer);
+long WriteAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, int chan, switch_timer_t *timer);
/************************************************************
* Read data from ring buffer.
* Will not return until all the data has been read.
*/
- long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, switch_timer_t *timer);
+long ReadAudioStream(PABLIO_Stream * aStream, void *data, long numFrames, int chan, switch_timer_t *timer);
/************************************************************
* Return the number of frames that could be written to the stream without
* having to wait.
*/
- long GetAudioStreamWriteable(PABLIO_Stream * aStream);
+long GetAudioStreamWriteable(PABLIO_Stream * aStream, int chan);
/************************************************************
* Return the number of frames that are available to be read from the
* stream without having to wait.
*/
- long GetAudioStreamReadable(PABLIO_Stream * aStream);
+long GetAudioStreamReadable(PABLIO_Stream * aStream, int chan);
/************************************************************
* Opens a PortAudio stream with default characteristics.
@@ -107,12 +120,12 @@ extern "C" {
* PABLIO_READ, PABLIO_WRITE, or PABLIO_READ_WRITE,
* and either PABLIO_MONO or PABLIO_STEREO
*/
- PaError OpenAudioStream(PABLIO_Stream ** rwblPtr,
- const PaStreamParameters * inputParameters,
- const PaStreamParameters * outputParameters,
- double sampleRate, PaStreamCallbackFlags statusFlags, long samples_per_packet, int do_dual);
+PaError OpenAudioStream(PABLIO_Stream ** rwblPtr,
+ const PaStreamParameters * inputParameters,
+ const PaStreamParameters * outputParameters,
+ double sampleRate, PaStreamCallbackFlags statusFlags, long samples_per_packet, int do_dual);
- PaError CloseAudioStream(PABLIO_Stream * aStream);
+PaError CloseAudioStream(PABLIO_Stream * aStream);
#ifdef __cplusplus
}
diff --git a/src/mod/endpoints/mod_rtmp/Makefile b/src/mod/endpoints/mod_rtmp/Makefile
new file mode 100644
index 0000000000..c2a7e251a8
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/Makefile
@@ -0,0 +1,7 @@
+BASE=../../../..
+
+LIBAMF_OBJS=libamf/src/amf0.o libamf/src/hash.o libamf/src/io.o libamf/src/ptrarray.o libamf/src/types.o
+LOCAL_OBJS=rtmp_sig.o rtmp.o rtmp_tcp.o $(LIBAMF_OBJS)
+LOCAL_CFLAGS=-Ilibamf/src
+
+include $(BASE)/build/modmake.rules
diff --git a/src/mod/endpoints/mod_rtmp/libamf/CMakeLists.txt b/src/mod/endpoints/mod_rtmp/libamf/CMakeLists.txt
new file mode 100644
index 0000000000..af3fca057e
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/CMakeLists.txt
@@ -0,0 +1,64 @@
+cmake_minimum_required(VERSION 2.6)
+project(libamf C)
+
+# generic variables
+set(PACKAGE "libamf")
+set(PACKAGE_NAME ${PACKAGE})
+set(PACKAGE_BUGREPORT "libamf@sf.net")
+set(PACKAGE_VERSION "0.1.0")
+set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
+
+#platform tests
+include(CheckFunctionExists)
+include(CheckIncludeFile)
+include(CheckTypeSize)
+include(TestBigEndian)
+
+check_include_file(sys/types.h HAVE_SYS_TYPES_H)
+check_include_file(stdint.h HAVE_STDINT_H)
+check_include_file(stddef.h HAVE_STDDEF_H)
+check_include_file(inttypes.h HAVE_INTTYPES_H)
+
+check_type_size("double" SIZEOF_DOUBLE)
+check_type_size("float" SIZEOF_FLOAT)
+check_type_size("long double" SIZEOF_LONG_DOUBLE)
+
+if(WIN32)
+ set(int16_t 1)
+ set(int32_t 1)
+ set(int64_t 1)
+ set(int8_t 1)
+ set(uint16_t 1)
+ set(uint32_t 1)
+ set(uint64_t 1)
+ set(uint8_t 1)
+endif(WIN32)
+
+test_big_endian(IS_BIGENDIAN)
+if(IS_BIGENDIAN)
+ set(WORDS_BIGENDIAN 1)
+endif(IS_BIGENDIAN)
+
+# configuration file
+configure_file(amf-cmake.h.in ${CMAKE_BINARY_DIR}/amf.h)
+include_directories(${CMAKE_BINARY_DIR})
+
+install(
+ FILES ${CMAKE_BINARY_DIR}/amf.h
+ DESTINATION include/amf
+)
+
+# Visual C++ specific configuration
+if(MSVC)
+ # use static library
+ set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT")
+
+ # C runtime deprecation in Visual C++ 2005 and later
+ add_definitions(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
+endif(MSVC)
+
+add_subdirectory(src)
+
+# tests
+enable_testing()
+add_subdirectory(tests)
diff --git a/src/mod/endpoints/mod_rtmp/libamf/amf-cmake.h.in b/src/mod/endpoints/mod_rtmp/libamf/amf-cmake.h.in
new file mode 100644
index 0000000000..40ee41139a
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/amf-cmake.h.in
@@ -0,0 +1,105 @@
+#ifndef __AMF_H__
+#define __AMF_H__
+
+/* Name of package */
+#define PACKAGE "@PACKAGE@"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "@PACKAGE_NAME@"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "@PACKAGE_STRING@"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "@PACKAGE_NAME@"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "@PACKAGE_VERSION@"
+
+/* The size of `double', as computed by sizeof. */
+#define SIZEOF_DOUBLE @SIZEOF_DOUBLE@
+
+/* The size of `float', as computed by sizeof. */
+#define SIZEOF_FLOAT @SIZEOF_FLOAT@
+
+/* The size of `long double', as computed by sizeof. */
+#define SIZEOF_LONG_DOUBLE @SIZEOF_LONG_DOUBLE@
+
+/* Version number of package */
+#define VERSION "@PACKAGE_VERSION@"
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_STDINT_H
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_STDDEF_H
+
+/* Define to 1 if you have the header file. */
+#cmakedefine HAVE_INTTYPES_H
+
+/* Define to 1 if your processor stores words with the most significant byte
+ first (like Motorola and SPARC, unlike Intel and VAX). */
+#cmakedefine WORDS_BIGENDIAN
+
+/* Define to the type of an integer type of width exactly 16 bits if
+ such a type exists and the standard includes do not define it. */
+#cmakedefine int16_t short int
+
+/* Define to the type of an integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+#cmakedefine int32_t int
+
+/* Define to the type of an integer type of width exactly 64 bits if
+ such a type exists and the standard includes do not define it. */
+#cmakedefine int64_t long long int
+
+/* Define to the type of an integer type of width exactly 8 bits if
+ such a type exists and the standard includes do not define it. */
+#cmakedefine int8_t char
+
+/* Define to the type of an unsigned integer type of width exactly 16 bits if
+ such a type exists and the standard includes do not define it. */
+#cmakedefine uint16_t unsigned short int
+
+/* Define to the type of an unsigned integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+#cmakedefine uint32_t unsigned int
+
+/* Define to the type of an unsigned integer type of width exactly 64 bits if
+ such a type exists and the standard includes do not define it. */
+#cmakedefine uint64_t unsigned long long int
+
+/* Define to the type of an unsigned integer type of width exactly 8 bits if
+ such a type exists and the standard includes do not define it. */
+#cmakedefine uint8_t unsigned char
+
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include
+
+/* AMF number */
+typedef
+#if SIZEOF_FLOAT == 8
+float
+#elif SIZEOF_DOUBLE == 8
+double
+#elif SIZEOF_LONG_DOUBLE == 8
+long double
+#else
+uint64_t
+#endif
+number64_t;
+
+/* custom read/write function type */
+typedef size_t (*read_proc_t)(void * out_buffer, size_t size, void * user_data);
+typedef size_t (*write_proc_t)(const void * in_buffer, size_t size, void * user_data);
+
+#endif /* __AMF_H__ */
diff --git a/src/mod/endpoints/mod_rtmp/libamf/src/CMakeLists.txt b/src/mod/endpoints/mod_rtmp/libamf/src/CMakeLists.txt
new file mode 100644
index 0000000000..fdf210abee
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/src/CMakeLists.txt
@@ -0,0 +1,26 @@
+set(libamf_src
+ amf0.c
+ amf0.h
+ hash.c
+ hash.h
+ io.c
+ io.h
+ ptrarray.c
+ ptrarray.h
+ types.c
+ types.h
+ ${CMAKE_BINARY_DIR}/amf.h
+)
+
+add_library(amf ${libamf_src})
+
+install(TARGETS amf
+ RUNTIME DESTINATION lib
+ ARCHIVE DESTINATION lib
+ LIBRARY DESTINATION lib
+)
+
+install(
+ FILES amf0.h amf3.h
+ DESTINATION include/amf
+)
diff --git a/src/mod/endpoints/mod_rtmp/libamf/src/amf.h b/src/mod/endpoints/mod_rtmp/libamf/src/amf.h
new file mode 100644
index 0000000000..0a424aeafd
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/src/amf.h
@@ -0,0 +1,13 @@
+#ifndef __AMF_H__
+#define __AMF_H__
+
+#include
+
+/* AMF number */
+typedef double number64_t;
+
+/* custom read/write function type */
+typedef size_t (*read_proc_t)(void * out_buffer, size_t size, void * user_data);
+typedef size_t (*write_proc_t)(const void * in_buffer, size_t size, void * user_data);
+
+#endif /* __AMF_H__ */
diff --git a/src/mod/endpoints/mod_rtmp/libamf/src/amf0.b b/src/mod/endpoints/mod_rtmp/libamf/src/amf0.b
new file mode 100644
index 0000000000..65ec535fd0
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/src/amf0.b
@@ -0,0 +1,1014 @@
+#include
+
+#include "amf0.h"
+#include "io.h"
+#include "types.h"
+
+/* function common to all array types */
+static void amf0_list_init(amf0_list * list) {
+ if (list != NULL) {
+ list->size = 0;
+ list->first_element = NULL;
+ list->last_element = NULL;
+ }
+}
+
+static amf0_data * amf0_list_push(amf0_list * list, amf0_data * data) {
+ amf0_node * node = (amf0_node*)malloc(sizeof(amf0_node));
+ if (node != NULL) {
+ node->data = data;
+ node->next = NULL;
+ node->prev = NULL;
+ if (list->size == 0) {
+ list->first_element = node;
+ list->last_element = node;
+ }
+ else {
+ list->last_element->next = node;
+ node->prev = list->last_element;
+ list->last_element = node;
+ }
+ ++(list->size);
+ return data;
+ }
+ return NULL;
+}
+
+static amf0_data * amf0_list_insert_before(amf0_list * list, amf0_node * node, amf0_data * data) {
+ if (node != NULL) {
+ amf0_node * new_node = (amf0_node*)malloc(sizeof(amf0_node));
+ if (new_node != NULL) {
+ new_node->next = node;
+ new_node->prev = node->prev;
+
+ if (node->prev != NULL) {
+ node->prev->next = new_node;
+ node->prev = new_node;
+ }
+ if (node == list->first_element) {
+ list->first_element = new_node;
+ }
+ ++(list->size);
+ new_node->data = data;
+ return data;
+ }
+ }
+ return NULL;
+}
+
+static amf0_data * amf0_list_insert_after(amf0_list * list, amf0_node * node, amf0_data * data) {
+ if (node != NULL) {
+ amf0_node * new_node = (amf0_node*)malloc(sizeof(amf0_node));
+ if (new_node != NULL) {
+ new_node->next = node->next;
+ new_node->prev = node;
+
+ if (node->next != NULL) {
+ node->next->prev = new_node;
+ node->next = new_node;
+ }
+ if (node == list->last_element) {
+ list->last_element = new_node;
+ }
+ ++(list->size);
+ new_node->data = data;
+ return data;
+ }
+ }
+ return NULL;
+}
+
+static amf0_data * amf0_list_delete(amf0_list * list, amf0_node * node) {
+ amf0_data * data = NULL;
+ if (node != NULL) {
+ if (node->next != NULL) {
+ node->next->prev = node->prev;
+ }
+ if (node->prev != NULL) {
+ node->prev->next = node->next;
+ }
+ if (node == list->first_element) {
+ list->first_element = node->next;
+ }
+ if (node == list->last_element) {
+ list->last_element = node->prev;
+ }
+ data = node->data;
+ free(node);
+ --(list->size);
+ }
+ return data;
+}
+
+static amf0_data * amf0_list_get_at(amf0_list * list, uint32_t n) {
+ if (n < list->size) {
+ uint32_t i;
+ amf0_node * node = list->first_element;
+ for (i = 0; i < n; ++i) {
+ node = node->next;
+ }
+ return node->data;
+ }
+ return NULL;
+}
+
+static amf0_data * amf0_list_pop(amf0_list * list) {
+ return amf0_list_delete(list, list->last_element);
+}
+
+static amf0_node * amf0_list_first(amf0_list * list) {
+ return list->first_element;
+}
+
+static amf0_node * amf0_list_last(amf0_list * list) {
+ return list->last_element;
+}
+
+static void amf0_list_clear(amf0_list * list) {
+ amf0_node * tmp;
+ amf0_node * node = list->first_element;
+ while (node != NULL) {
+ amf0_data_free(node->data);
+ tmp = node;
+ node = node->next;
+ free(tmp);
+ }
+ list->size = 0;
+}
+
+static amf0_list * amf0_list_clone(amf0_list * list, amf0_list * out_list) {
+ amf0_node * node;
+ node = list->first_element;
+ while (node != NULL) {
+ amf0_list_push(out_list, amf0_data_clone(node->data));
+ node = node->next;
+ }
+ return out_list;
+}
+
+/* allocate an AMF data object */
+amf0_data * amf0_data_new(uint8_t type) {
+ amf0_data * data = (amf0_data*)malloc(sizeof(amf0_data));
+ if (data != NULL) {
+ data->type = type;
+ }
+ return data;
+}
+
+/* read AMF data from buffer */
+amf0_data * amf0_data_buffer_read(uint8_t * buffer, size_t maxbytes) {
+ buffer_context ctxt;
+ ctxt.start_address = ctxt.current_address = buffer;
+ ctxt.buffer_size = maxbytes;
+ return amf0_data_read(buffer_read, &ctxt);
+}
+
+/* write AMF data to buffer */
+size_t amf0_data_buffer_write(amf0_data * data, uint8_t * buffer, size_t maxbytes) {
+ buffer_context ctxt;
+ ctxt.start_address = ctxt.current_address = buffer;
+ ctxt.buffer_size = maxbytes;
+ return amf0_data_write(data, buffer_write, &ctxt);
+}
+
+/* load AMF data from a file stream */
+amf0_data * amf0_data_file_read(FILE * stream) {
+ return amf0_data_read(file_read, stream);
+}
+
+/* write AMF data into a file stream */
+size_t amf0_data_file_write(amf0_data * data, FILE * stream) {
+ return amf0_data_write(data, file_write, stream);
+}
+
+/* read a number */
+static amf0_data * amf0_number_read(read_proc_t read_proc, void * user_data) {
+ number64_t val;
+ if (read_proc(&val, sizeof(number64_t), user_data) == sizeof(number64_t)) {
+ return amf0_number_new(swap_number64(val));
+ }
+ return NULL;
+}
+
+/* read a boolean */
+static amf0_data * amf0_boolean_read(read_proc_t read_proc, void * user_data) {
+ uint8_t val;
+ if (read_proc(&val, sizeof(uint8_t), user_data) == sizeof(uint8_t)) {
+ return amf0_boolean_new(val);
+ }
+ return NULL;
+}
+
+/* read a string */
+static amf0_data * amf0_string_read(read_proc_t read_proc, void * user_data) {
+ uint16_t strsize;
+ uint8_t * buffer;
+ if (read_proc(&strsize, sizeof(uint16_t), user_data) == sizeof(uint16_t)) {
+ strsize = swap_uint16(strsize);
+ if (strsize > 0) {
+ buffer = (uint8_t*)calloc(strsize, sizeof(uint8_t));
+ if (buffer != NULL && read_proc(buffer, strsize, user_data) == strsize) {
+ amf0_data * data = amf0_string_new(buffer, strsize);
+ free(buffer);
+ return data;
+ }
+ }
+ else {
+ return amf0_string_new(NULL, 0);
+ }
+ }
+ return NULL;
+}
+
+/* read an object */
+static amf0_data * amf0_object_read(read_proc_t read_proc, void * user_data) {
+ amf0_data * data = amf0_object_new();
+ if (data != NULL) {
+ amf0_data * name;
+ amf0_data * element;
+ while (1) {
+ name = amf0_string_read(read_proc, user_data);
+ if (name != NULL) {
+ element = amf0_data_read(read_proc, user_data);
+ if (element != NULL) {
+ if (amf0_object_add(data, (char *)amf0_string_get_uint8_ts(name), element) == NULL) {
+ amf0_data_free(name);
+ amf0_data_free(element);
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ else {
+ amf0_data_free(name);
+ break;
+ }
+ }
+ else {
+ /* invalid name: error */
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ }
+ return data;
+}
+
+/* read an associative array */
+static amf0_data * amf0_associative_array_read(read_proc_t read_proc, void * user_data) {
+ amf0_data * data = amf0_associative_array_new();
+ if (data != NULL) {
+ amf0_data * name;
+ amf0_data * element;
+ uint32_t size;
+ if (read_proc(&size, sizeof(uint32_t), user_data) == sizeof(uint32_t)) {
+ /* we ignore the 32 bits array size marker */
+ while(1) {
+ name = amf0_string_read(read_proc, user_data);
+ if (name != NULL) {
+ element = amf0_data_read(read_proc, user_data);
+ if (element != NULL) {
+ if (amf0_associative_array_add(data, (char *)amf0_string_get_uint8_ts(name), element) == NULL) {
+ amf0_data_free(name);
+ amf0_data_free(element);
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ else {
+ amf0_data_free(name);
+ break;
+ }
+ }
+ else {
+ /* invalid name: error */
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ }
+ else {
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ return data;
+}
+
+/* read an array */
+static amf0_data * amf0_array_read(read_proc_t read_proc, void * user_data) {
+ size_t i;
+ amf0_data * element;
+ amf0_data * data = amf0_array_new();
+ if (data != NULL) {
+ uint32_t array_size;
+ if (read_proc(&array_size, sizeof(uint32_t), user_data) == sizeof(uint32_t)) {
+ array_size = swap_uint32(array_size);
+
+ for (i = 0; i < array_size; ++i) {
+ element = amf0_data_read(read_proc, user_data);
+
+ if (element != NULL) {
+ if (amf0_array_push(data, element) == NULL) {
+ amf0_data_free(element);
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ else {
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ }
+ else {
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ return data;
+}
+
+/* read a date */
+static amf0_data * amf0_date_read(read_proc_t read_proc, void * user_data) {
+ number64_t milliseconds;
+ int16_t timezone;
+ if (read_proc(&milliseconds, sizeof(number64_t), user_data) == sizeof(number64_t) &&
+ read_proc(&timezone, sizeof(int16_t), user_data) == sizeof(int16_t)) {
+ return amf0_date_new(swap_number64(milliseconds), swap_sint16(timezone));
+ }
+ else {
+ return NULL;
+ }
+}
+
+/* load AMF data from stream */
+amf0_data * amf0_data_read(read_proc_t read_proc, void * user_data) {
+ uint8_t type;
+ if (read_proc(&type, sizeof(uint8_t), user_data) == sizeof(uint8_t)) {
+ switch (type) {
+ case AMF0_TYPE_NUMBER:
+ return amf0_number_read(read_proc, user_data);
+ case AMF0_TYPE_BOOLEAN:
+ return amf0_boolean_read(read_proc, user_data);
+ case AMF0_TYPE_STRING:
+ return amf0_string_read(read_proc, user_data);
+ case AMF0_TYPE_OBJECT:
+ return amf0_object_read(read_proc, user_data);
+ case AMF0_TYPE_NULL:
+ return amf0_null_new();
+ case AMF0_TYPE_UNDEFINED:
+ return amf0_undefined_new();
+ /*case AMF0_TYPE_REFERENCE:*/
+ case AMF0_TYPE_ECMA_ARRAY:
+ return amf0_associative_array_read(read_proc, user_data);
+ case AMF0_TYPE_STRICT_ARRAY:
+ return amf0_array_read(read_proc, user_data);
+ case AMF0_TYPE_DATE:
+ return amf0_date_read(read_proc, user_data);
+ /*case AMF0_TYPE_SIMPLEOBJECT:*/
+ case AMF0_TYPE_XML_DOCUMENT:
+ case AMF0_TYPE_TYPED_OBJECT:
+ case AMF0_TYPE_OBJECT_END:
+ return NULL; /* end of composite object */
+ default:
+ break;
+ }
+ }
+ return NULL;
+}
+
+/* determines the size of the given AMF data */
+size_t amf0_data_size(amf0_data * data) {
+ size_t s = 0;
+ amf0_node * node;
+ if (data != NULL) {
+ s += sizeof(uint8_t);
+ switch (data->type) {
+ case AMF0_TYPE_NUMBER:
+ s += sizeof(number64_t);
+ break;
+ case AMF0_TYPE_BOOLEAN:
+ s += sizeof(uint8_t);
+ break;
+ case AMF0_TYPE_STRING:
+ s += sizeof(uint16_t) + (size_t)amf0_string_get_size(data);
+ break;
+ case AMF0_TYPE_OBJECT:
+ node = amf0_object_first(data);
+ while (node != NULL) {
+ s += sizeof(uint16_t) + (size_t)amf0_string_get_size(amf0_object_get_name(node));
+ s += (size_t)amf0_data_size(amf0_object_get_data(node));
+ node = amf0_object_next(node);
+ }
+ s += sizeof(uint16_t) + sizeof(uint8_t);
+ break;
+ case AMF0_TYPE_NULL:
+ case AMF0_TYPE_UNDEFINED:
+ break;
+ /*case AMF0_TYPE_REFERENCE:*/
+ case AMF0_TYPE_ECMA_ARRAY:
+ s += sizeof(uint32_t);
+ node = amf0_associative_array_first(data);
+ while (node != NULL) {
+ s += sizeof(uint16_t) + (size_t)amf0_string_get_size(amf0_associative_array_get_name(node));
+ s += (size_t)amf0_data_size(amf0_associative_array_get_data(node));
+ node = amf0_associative_array_next(node);
+ }
+ s += sizeof(uint16_t) + sizeof(uint8_t);
+ break;
+ case AMF0_TYPE_STRICT_ARRAY:
+ s += sizeof(uint32_t);
+ node = amf0_array_first(data);
+ while (node != NULL) {
+ s += (size_t)amf0_data_size(amf0_array_get(node));
+ node = amf0_array_next(node);
+ }
+ break;
+ case AMF0_TYPE_DATE:
+ s += sizeof(number64_t) + sizeof(int16_t);
+ break;
+ /*case AMF0_TYPE_SIMPLEOBJECT:*/
+ case AMF0_TYPE_XML_DOCUMENT:
+ case AMF0_TYPE_TYPED_OBJECT:
+ case AMF0_TYPE_OBJECT_END:
+ break; /* end of composite object */
+ default:
+ break;
+ }
+ }
+ return s;
+}
+
+/* write a number */
+static size_t amf0_number_write(amf0_data * data, write_proc_t write_proc, void * user_data) {
+ number64_t n = swap_number64(data->number_data);
+ return write_proc(&n, sizeof(number64_t), user_data);
+}
+
+/* write a boolean */
+static size_t amf0_boolean_write(amf0_data * data, write_proc_t write_proc, void * user_data) {
+ return write_proc(&(data->boolean_data), sizeof(uint8_t), user_data);
+}
+
+/* write a string */
+static size_t amf0_string_write(amf0_data * data, write_proc_t write_proc, void * user_data) {
+ uint16_t s;
+ size_t w = 0;
+
+ s = swap_uint16(data->string_data.size);
+ w = write_proc(&s, sizeof(uint16_t), user_data);
+ if (data->string_data.size > 0) {
+ w += write_proc(data->string_data.mbstr, (size_t)(data->string_data.size), user_data);
+ }
+
+ return w;
+}
+
+/* write an object */
+static size_t amf0_object_write(amf0_data * data, write_proc_t write_proc, void * user_data) {
+ amf0_node * node;
+ size_t w = 0;
+ uint16_t filler = swap_uint16(0);
+ uint8_t terminator = AMF0_TYPE_OBJECT_END;
+
+ node = amf0_object_first(data);
+ while (node != NULL) {
+ w += amf0_string_write(amf0_object_get_name(node), write_proc, user_data);
+ w += amf0_data_write(amf0_object_get_data(node), write_proc, user_data);
+ node = amf0_object_next(node);
+ }
+
+ /* empty string is the last element */
+ w += write_proc(&filler, sizeof(uint16_t), user_data);
+ /* an object ends with 0x09 */
+ w += write_proc(&terminator, sizeof(uint8_t), user_data);
+
+ return w;
+}
+
+/* write an associative array */
+static size_t amf0_associative_array_write(amf0_data * data, write_proc_t write_proc, void * user_data) {
+ amf0_node * node;
+ size_t w = 0;
+ uint32_t s;
+ uint16_t filler = swap_uint16(0);
+ uint8_t terminator = AMF0_TYPE_OBJECT_END;
+
+ s = swap_uint32(data->list_data.size) / 2;
+ w += write_proc(&s, sizeof(uint32_t), user_data);
+ node = amf0_associative_array_first(data);
+ while (node != NULL) {
+ w += amf0_string_write(amf0_associative_array_get_name(node), write_proc, user_data);
+ w += amf0_data_write(amf0_associative_array_get_data(node), write_proc, user_data);
+ node = amf0_associative_array_next(node);
+ }
+
+ /* empty string is the last element */
+ w += write_proc(&filler, sizeof(uint16_t), user_data);
+ /* an object ends with 0x09 */
+ w += write_proc(&terminator, sizeof(uint8_t), user_data);
+
+ return w;
+}
+
+/* write an array */
+static size_t amf0_array_write(amf0_data * data, write_proc_t write_proc, void * user_data) {
+ amf0_node * node;
+ size_t w = 0;
+ uint32_t s;
+
+ s = swap_uint32(data->list_data.size);
+ w += write_proc(&s, sizeof(uint32_t), user_data);
+ node = amf0_array_first(data);
+ while (node != NULL) {
+ w += amf0_data_write(amf0_array_get(node), write_proc, user_data);
+ node = amf0_array_next(node);
+ }
+
+ return w;
+}
+
+/* write a date */
+static size_t amf0_date_write(amf0_data * data, write_proc_t write_proc, void * user_data) {
+ size_t w = 0;
+ number64_t milli;
+ int16_t tz;
+
+ milli = swap_number64(data->date_data.milliseconds);
+ w += write_proc(&milli, sizeof(number64_t), user_data);
+ tz = swap_sint16(data->date_data.timezone);
+ w += write_proc(&tz, sizeof(int16_t), user_data);
+
+ return w;
+}
+
+/* write amf data to stream */
+size_t amf0_data_write(amf0_data * data, write_proc_t write_proc, void * user_data) {
+ size_t s = 0;
+ if (data != NULL) {
+ s += write_proc(&(data->type), sizeof(uint8_t), user_data);
+ switch (data->type) {
+ case AMF0_TYPE_NUMBER:
+ s += amf0_number_write(data, write_proc, user_data);
+ break;
+ case AMF0_TYPE_BOOLEAN:
+ s += amf0_boolean_write(data, write_proc, user_data);
+ break;
+ case AMF0_TYPE_STRING:
+ s += amf0_string_write(data, write_proc, user_data);
+ break;
+ case AMF0_TYPE_OBJECT:
+ s += amf0_object_write(data, write_proc, user_data);
+ break;
+ case AMF0_TYPE_NULL:
+ case AMF0_TYPE_UNDEFINED:
+ break;
+ /*case AMF0_TYPE_REFERENCE:*/
+ case AMF0_TYPE_ECMA_ARRAY:
+ s += amf0_associative_array_write(data, write_proc, user_data);
+ break;
+ case AMF0_TYPE_STRICT_ARRAY:
+ s += amf0_array_write(data, write_proc, user_data);
+ break;
+ case AMF0_TYPE_DATE:
+ s += amf0_date_write(data, write_proc, user_data);
+ break;
+ /*case AMF0_TYPE_SIMPLEOBJECT:*/
+ case AMF0_TYPE_XML_DOCUMENT:
+ case AMF0_TYPE_TYPED_OBJECT:
+ case AMF0_TYPE_OBJECT_END:
+ break; /* end of composite object */
+ default:
+ break;
+ }
+ }
+ return s;
+}
+
+/* data type */
+uint8_t amf0_data_get_type(amf0_data * data) {
+ return (data != NULL) ? data->type : AMF0_TYPE_NULL;
+}
+
+/* clone AMF data */
+amf0_data * amf0_data_clone(amf0_data * data) {
+ /* we copy data recursively */
+ if (data != NULL) {
+ switch (data->type) {
+ case AMF0_TYPE_NUMBER: return amf0_number_new(amf0_number_get_value(data));
+ case AMF0_TYPE_BOOLEAN: return amf0_boolean_new(amf0_boolean_get_value(data));
+ case AMF0_TYPE_STRING:
+ if (data->string_data.mbstr != NULL) {
+ return amf0_string_new((uint8_t *)strdup((char *)amf0_string_get_uint8_ts(data)), amf0_string_get_size(data));
+ }
+ else {
+ return amf0_str(NULL);
+ }
+ case AMF0_TYPE_NULL: return NULL;
+ case AMF0_TYPE_UNDEFINED: return NULL;
+ /*case AMF0_TYPE_REFERENCE:*/
+ case AMF0_TYPE_OBJECT:
+ case AMF0_TYPE_ECMA_ARRAY:
+ case AMF0_TYPE_STRICT_ARRAY:
+ {
+ amf0_data * d = amf0_data_new(data->type);
+ if (d != NULL) {
+ amf0_list_init(&d->list_data);
+ amf0_list_clone(&data->list_data, &d->list_data);
+ }
+ return d;
+ }
+ case AMF0_TYPE_DATE: return amf0_date_new(amf0_date_get_milliseconds(data), amf0_date_get_timezone(data));
+ /*case AMF0_TYPE_SIMPLEOBJECT:*/
+ case AMF0_TYPE_XML_DOCUMENT: return NULL;
+ case AMF0_TYPE_TYPED_OBJECT: return NULL;
+ }
+ }
+ return NULL;
+}
+
+/* free AMF data */
+void amf0_data_free(amf0_data * data) {
+ if (data != NULL) {
+ switch (data->type) {
+ case AMF0_TYPE_NUMBER: break;
+ case AMF0_TYPE_BOOLEAN: break;
+ case AMF0_TYPE_STRING:
+ if (data->string_data.mbstr != NULL) {
+ free(data->string_data.mbstr);
+ } break;
+ case AMF0_TYPE_NULL: break;
+ case AMF0_TYPE_UNDEFINED: break;
+ /*case AMF0_TYPE_REFERENCE:*/
+ case AMF0_TYPE_OBJECT:
+ case AMF0_TYPE_ECMA_ARRAY:
+ case AMF0_TYPE_STRICT_ARRAY: amf0_list_clear(&data->list_data); break;
+ case AMF0_TYPE_DATE: break;
+ /*case AMF0_TYPE_SIMPLEOBJECT:*/
+ case AMF0_TYPE_XML_DOCUMENT: break;
+ case AMF0_TYPE_TYPED_OBJECT: break;
+ default: break;
+ }
+ free(data);
+ }
+}
+
+/* dump AMF data into a stream as text */
+void amf0_data_dump(FILE * stream, amf0_data * data, int indent_level) {
+ if (data != NULL) {
+ amf0_node * node;
+ time_t time;
+ struct tm * t;
+ char datestr[128];
+ switch (data->type) {
+ case AMF0_TYPE_NUMBER:
+ fprintf(stream, "%.12g", data->number_data);
+ break;
+ case AMF0_TYPE_BOOLEAN:
+ fprintf(stream, "%s", (data->boolean_data) ? "true" : "false");
+ break;
+ case AMF0_TYPE_STRING:
+ fprintf(stream, "\'%.*s\'", data->string_data.size, data->string_data.mbstr);
+ break;
+ case AMF0_TYPE_OBJECT:
+ node = amf0_object_first(data);
+ fprintf(stream, "{\n");
+ while (node != NULL) {
+ fprintf(stream, "%*s", (indent_level+1)*4, "");
+ amf0_data_dump(stream, amf0_object_get_name(node), indent_level+1);
+ fprintf(stream, ": ");
+ amf0_data_dump(stream, amf0_object_get_data(node), indent_level+1);
+ node = amf0_object_next(node);
+ fprintf(stream, "\n");
+ }
+ fprintf(stream, "%*s", indent_level*4 + 1, "}");
+ break;
+ case AMF0_TYPE_NULL:
+ fprintf(stream, "null");
+ break;
+ case AMF0_TYPE_UNDEFINED:
+ fprintf(stream, "undefined");
+ break;
+ /*case AMF0_TYPE_REFERENCE:*/
+ case AMF0_TYPE_ECMA_ARRAY:
+ node = amf0_associative_array_first(data);
+ fprintf(stream, "{\n");
+ while (node != NULL) {
+ fprintf(stream, "%*s", (indent_level+1)*4, "");
+ amf0_data_dump(stream, amf0_associative_array_get_name(node), indent_level+1);
+ fprintf(stream, " => ");
+ amf0_data_dump(stream, amf0_associative_array_get_data(node), indent_level+1);
+ node = amf0_associative_array_next(node);
+ fprintf(stream, "\n");
+ }
+ fprintf(stream, "%*s", indent_level*4 + 1, "}");
+ break;
+ case AMF0_TYPE_STRICT_ARRAY:
+ node = amf0_array_first(data);
+ fprintf(stream, "[\n");
+ while (node != NULL) {
+ fprintf(stream, "%*s", (indent_level+1)*4, "");
+ amf0_data_dump(stream, node->data, indent_level+1);
+ node = amf0_array_next(node);
+ fprintf(stream, "\n");
+ }
+ fprintf(stream, "%*s", indent_level*4 + 1, "]");
+ break;
+ case AMF0_TYPE_DATE:
+ time = amf0_date_to_time_t(data);
+ tzset();
+ t = localtime(&time);
+ strftime(datestr, sizeof(datestr), "%a, %d %b %Y %H:%M:%S %z", t);
+ fprintf(stream, "%s", datestr);
+ break;
+ /*case AMF0_TYPE_SIMPLEOBJECT:*/
+ case AMF0_TYPE_XML_DOCUMENT: break;
+ case AMF0_TYPE_TYPED_OBJECT: break;
+ default: break;
+ }
+ }
+}
+
+/* number functions */
+amf0_data * amf0_number_new(number64_t value) {
+ amf0_data * data = amf0_data_new(AMF0_TYPE_NUMBER);
+ if (data != NULL) {
+ data->number_data = value;
+ }
+ return data;
+}
+
+number64_t amf0_number_get_value(amf0_data * data) {
+ return (data != NULL) ? data->number_data : 0;
+}
+
+void amf0_number_set_value(amf0_data * data, number64_t value) {
+ if (data != NULL) {
+ data->number_data = value;
+ }
+}
+
+/* boolean functions */
+amf0_data * amf0_boolean_new(uint8_t value) {
+ amf0_data * data = amf0_data_new(AMF0_TYPE_BOOLEAN);
+ if (data != NULL) {
+ data->boolean_data = value;
+ }
+ return data;
+}
+
+uint8_t amf0_boolean_get_value(amf0_data * data) {
+ return (data != NULL) ? data->boolean_data : 0;
+}
+
+void amf0_boolean_set_value(amf0_data * data, uint8_t value) {
+ if (data != NULL) {
+ data->boolean_data = value;
+ }
+}
+
+/* string functions */
+amf0_data * amf0_string_new(uint8_t * str, uint16_t size) {
+ amf0_data * data = amf0_data_new(AMF0_TYPE_STRING);
+ if (data != NULL) {
+ data->string_data.size = size;
+ data->string_data.mbstr = (uint8_t*)calloc(size+1, sizeof(uint8_t));
+ if (data->string_data.mbstr != NULL) {
+ if (size > 0) {
+ memcpy(data->string_data.mbstr, str, size);
+ }
+ }
+ else {
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ return data;
+}
+
+amf0_data * amf0_str(const char * str) {
+ return amf0_string_new((uint8_t *)str, (uint16_t)(str != NULL ? strlen(str) : 0));
+}
+
+uint16_t amf0_string_get_size(amf0_data * data) {
+ return (data != NULL) ? data->string_data.size : 0;
+}
+
+uint8_t * amf0_string_get_uint8_ts(amf0_data * data) {
+ return (data != NULL) ? data->string_data.mbstr : NULL;
+}
+
+/* object functions */
+amf0_data * amf0_object_new(void) {
+ amf0_data * data = amf0_data_new(AMF0_TYPE_OBJECT);
+ if (data != NULL) {
+ amf0_list_init(&data->list_data);
+ }
+ return data;
+}
+
+uint32_t amf0_object_size(amf0_data * data) {
+ return (data != NULL) ? data->list_data.size / 2 : 0;
+}
+
+amf0_data * amf0_object_add(amf0_data * data, const char * name, amf0_data * element) {
+ if (data != NULL) {
+ if (amf0_list_push(&data->list_data, amf0_str(name)) != NULL) {
+ if (amf0_list_push(&data->list_data, element) != NULL) {
+ return element;
+ }
+ else {
+ amf0_data_free(amf0_list_pop(&data->list_data));
+ }
+ }
+ }
+ return NULL;
+}
+
+amf0_data * amf0_object_get(amf0_data * data, const char * name) {
+ if (data != NULL) {
+ amf0_node * node = amf0_list_first(&(data->list_data));
+ while (node != NULL) {
+ if (strncmp((char*)(node->data->string_data.mbstr), name, (size_t)(node->data->string_data.size)) == 0) {
+ node = node->next;
+ return (node != NULL) ? node->data : NULL;
+ }
+ /* we have to skip the element data to reach the next name */
+ node = node->next->next;
+ }
+ }
+ return NULL;
+}
+
+amf0_data * amf0_object_set(amf0_data * data, const char * name, amf0_data * element) {
+ if (data != NULL) {
+ amf0_node * node = amf0_list_first(&(data->list_data));
+ while (node != NULL) {
+ if (strncmp((char*)(node->data->string_data.mbstr), name, (size_t)(node->data->string_data.size)) == 0) {
+ node = node->next;
+ if (node != NULL && node->data != NULL) {
+ amf0_data_free(node->data);
+ node->data = element;
+ return element;
+ }
+ }
+ /* we have to skip the element data to reach the next name */
+ node = node->next->next;
+ }
+ }
+ return NULL;
+}
+
+amf0_data * amf0_object_delete(amf0_data * data, const char * name) {
+ if (data != NULL) {
+ amf0_node * node = amf0_list_first(&data->list_data);
+ while (node != NULL) {
+ node = node->next;
+ if (strncmp((char*)(node->data->string_data.mbstr), name, (size_t)(node->data->string_data.size)) == 0) {
+ amf0_node * data_node = node->next;
+ amf0_data_free(amf0_list_delete(&data->list_data, node));
+ return amf0_list_delete(&data->list_data, data_node);
+ }
+ else {
+ node = node->next;
+ }
+ }
+ }
+ return NULL;
+}
+
+amf0_node * amf0_object_first(amf0_data * data) {
+ return (data != NULL) ? amf0_list_first(&data->list_data) : NULL;
+}
+
+amf0_node * amf0_object_last(amf0_data * data) {
+ if (data != NULL) {
+ amf0_node * node = amf0_list_last(&data->list_data);
+ if (node != NULL) {
+ return node->prev;
+ }
+ }
+ return NULL;
+}
+
+amf0_node * amf0_object_next(amf0_node * node) {
+ if (node != NULL) {
+ amf0_node * next = node->next;
+ if (next != NULL) {
+ return next->next;
+ }
+ }
+ return NULL;
+}
+
+amf0_node * amf0_object_prev(amf0_node * node) {
+ if (node != NULL) {
+ amf0_node * prev = node->prev;
+ if (prev != NULL) {
+ return prev->prev;
+ }
+ }
+ return NULL;
+}
+
+amf0_data * amf0_object_get_name(amf0_node * node) {
+ return (node != NULL) ? node->data : NULL;
+}
+
+amf0_data * amf0_object_get_data(amf0_node * node) {
+ if (node != NULL) {
+ amf0_node * next = node->next;
+ if (next != NULL) {
+ return next->data;
+ }
+ }
+ return NULL;
+}
+
+/* associative array functions */
+amf0_data * amf0_associative_array_new(void) {
+ amf0_data * data = amf0_data_new(AMF0_TYPE_ECMA_ARRAY);
+ if (data != NULL) {
+ amf0_list_init(&data->list_data);
+ }
+ return data;
+}
+
+/* array functions */
+amf0_data * amf0_array_new(void) {
+ amf0_data * data = amf0_data_new(AMF0_TYPE_STRICT_ARRAY);
+ if (data != NULL) {
+ amf0_list_init(&data->list_data);
+ }
+ return data;
+}
+
+uint32_t amf0_array_size(amf0_data * data) {
+ return (data != NULL) ? data->list_data.size : 0;
+}
+
+amf0_data * amf0_array_push(amf0_data * data, amf0_data * element) {
+ return (data != NULL) ? amf0_list_push(&data->list_data, element) : NULL;
+}
+
+amf0_data * amf0_array_pop(amf0_data * data) {
+ return (data != NULL) ? amf0_list_pop(&data->list_data) : NULL;
+}
+
+amf0_node * amf0_array_first(amf0_data * data) {
+ return (data != NULL) ? amf0_list_first(&data->list_data) : NULL;
+}
+
+amf0_node * amf0_array_last(amf0_data * data) {
+ return (data != NULL) ? amf0_list_last(&data->list_data) : NULL;
+}
+
+amf0_node * amf0_array_next(amf0_node * node) {
+ return (node != NULL) ? node->next : NULL;
+}
+
+amf0_node * amf0_array_prev(amf0_node * node) {
+ return (node != NULL) ? node->prev : NULL;
+}
+
+amf0_data * amf0_array_get(amf0_node * node) {
+ return (node != NULL) ? node->data : NULL;
+}
+
+amf0_data * amf0_array_get_at(amf0_data * data, uint32_t n) {
+ return (data != NULL) ? amf0_list_get_at(&data->list_data, n) : NULL;
+}
+
+amf0_data * amf0_array_delete(amf0_data * data, amf0_node * node) {
+ return (data != NULL) ? amf0_list_delete(&data->list_data, node) : NULL;
+}
+
+amf0_data * amf0_array_insert_before(amf0_data * data, amf0_node * node, amf0_data * element) {
+ return (data != NULL) ? amf0_list_insert_before(&data->list_data, node, element) : NULL;
+}
+
+amf0_data * amf0_array_insert_after(amf0_data * data, amf0_node * node, amf0_data * element) {
+ return (data != NULL) ? amf0_list_insert_after(&data->list_data, node, element) : NULL;
+}
+
+/* date functions */
+amf0_data * amf0_date_new(number64_t milliseconds, int16_t timezone) {
+ amf0_data * data = amf0_data_new(AMF0_TYPE_DATE);
+ if (data != NULL) {
+ data->date_data.milliseconds = milliseconds;
+ data->date_data.timezone = timezone;
+ }
+ return data;
+}
+
+number64_t amf0_date_get_milliseconds(amf0_data * data) {
+ return (data != NULL) ? data->date_data.milliseconds : 0.0;
+}
+
+int16_t amf0_date_get_timezone(amf0_data * data) {
+ return (data != NULL) ? data->date_data.timezone : 0;
+}
+
+time_t amf0_date_to_time_t(amf0_data * data) {
+ return (time_t)((data != NULL) ? data->date_data.milliseconds / 1000 : 0);
+}
diff --git a/src/mod/endpoints/mod_rtmp/libamf/src/amf0.c b/src/mod/endpoints/mod_rtmp/libamf/src/amf0.c
new file mode 100644
index 0000000000..67a9273e2b
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/src/amf0.c
@@ -0,0 +1,1014 @@
+#include
+
+#include "amf0.h"
+#include "io.h"
+#include "types.h"
+
+/* function common to all array types */
+static void amf0_list_init(amf0_list * list) {
+ if (list != NULL) {
+ list->size = 0;
+ list->first_element = NULL;
+ list->last_element = NULL;
+ }
+}
+
+static amf0_data * amf0_list_push(amf0_list * list, amf0_data * data) {
+ amf0_node * node = (amf0_node*)malloc(sizeof(amf0_node));
+ if (node != NULL) {
+ node->data = data;
+ node->next = NULL;
+ node->prev = NULL;
+ if (list->size == 0) {
+ list->first_element = node;
+ list->last_element = node;
+ }
+ else {
+ list->last_element->next = node;
+ node->prev = list->last_element;
+ list->last_element = node;
+ }
+ ++(list->size);
+ return data;
+ }
+ return NULL;
+}
+
+static amf0_data * amf0_list_insert_before(amf0_list * list, amf0_node * node, amf0_data * data) {
+ if (node != NULL) {
+ amf0_node * new_node = (amf0_node*)malloc(sizeof(amf0_node));
+ if (new_node != NULL) {
+ new_node->next = node;
+ new_node->prev = node->prev;
+
+ if (node->prev != NULL) {
+ node->prev->next = new_node;
+ node->prev = new_node;
+ }
+ if (node == list->first_element) {
+ list->first_element = new_node;
+ }
+ ++(list->size);
+ new_node->data = data;
+ return data;
+ }
+ }
+ return NULL;
+}
+
+static amf0_data * amf0_list_insert_after(amf0_list * list, amf0_node * node, amf0_data * data) {
+ if (node != NULL) {
+ amf0_node * new_node = (amf0_node*)malloc(sizeof(amf0_node));
+ if (new_node != NULL) {
+ new_node->next = node->next;
+ new_node->prev = node;
+
+ if (node->next != NULL) {
+ node->next->prev = new_node;
+ node->next = new_node;
+ }
+ if (node == list->last_element) {
+ list->last_element = new_node;
+ }
+ ++(list->size);
+ new_node->data = data;
+ return data;
+ }
+ }
+ return NULL;
+}
+
+static amf0_data * amf0_list_delete(amf0_list * list, amf0_node * node) {
+ amf0_data * data = NULL;
+ if (node != NULL) {
+ if (node->next != NULL) {
+ node->next->prev = node->prev;
+ }
+ if (node->prev != NULL) {
+ node->prev->next = node->next;
+ }
+ if (node == list->first_element) {
+ list->first_element = node->next;
+ }
+ if (node == list->last_element) {
+ list->last_element = node->prev;
+ }
+ data = node->data;
+ free(node);
+ --(list->size);
+ }
+ return data;
+}
+
+static amf0_data * amf0_list_get_at(amf0_list * list, uint32_t n) {
+ if (n < list->size) {
+ uint32_t i;
+ amf0_node * node = list->first_element;
+ for (i = 0; i < n; ++i) {
+ node = node->next;
+ }
+ return node->data;
+ }
+ return NULL;
+}
+
+static amf0_data * amf0_list_pop(amf0_list * list) {
+ return amf0_list_delete(list, list->last_element);
+}
+
+static amf0_node * amf0_list_first(amf0_list * list) {
+ return list->first_element;
+}
+
+static amf0_node * amf0_list_last(amf0_list * list) {
+ return list->last_element;
+}
+
+static void amf0_list_clear(amf0_list * list) {
+ amf0_node * tmp;
+ amf0_node * node = list->first_element;
+ while (node != NULL) {
+ amf0_data_free(node->data);
+ tmp = node;
+ node = node->next;
+ free(tmp);
+ }
+ list->size = 0;
+}
+
+static amf0_list * amf0_list_clone(amf0_list * list, amf0_list * out_list) {
+ amf0_node * node;
+ node = list->first_element;
+ while (node != NULL) {
+ amf0_list_push(out_list, amf0_data_clone(node->data));
+ node = node->next;
+ }
+ return out_list;
+}
+
+/* allocate an AMF data object */
+amf0_data * amf0_data_new(uint8_t type) {
+ amf0_data * data = (amf0_data*)malloc(sizeof(amf0_data));
+ if (data != NULL) {
+ data->type = type;
+ }
+ return data;
+}
+
+/* read AMF data from buffer */
+amf0_data * amf0_data_buffer_read(uint8_t * buffer, size_t maxbytes) {
+ buffer_context ctxt;
+ ctxt.start_address = ctxt.current_address = buffer;
+ ctxt.buffer_size = maxbytes;
+ return amf0_data_read(buffer_read, &ctxt);
+}
+
+/* write AMF data to buffer */
+size_t amf0_data_buffer_write(amf0_data * data, uint8_t * buffer, size_t maxbytes) {
+ buffer_context ctxt;
+ ctxt.start_address = ctxt.current_address = buffer;
+ ctxt.buffer_size = maxbytes;
+ return amf0_data_write(data, buffer_write, &ctxt);
+}
+
+/* load AMF data from a file stream */
+amf0_data * amf0_data_file_read(FILE * stream) {
+ return amf0_data_read(file_read, stream);
+}
+
+/* write AMF data into a file stream */
+size_t amf0_data_file_write(amf0_data * data, FILE * stream) {
+ return amf0_data_write(data, file_write, stream);
+}
+
+/* read a number */
+static amf0_data * amf0_number_read(read_proc_t read_proc, void * user_data) {
+ number64_t val;
+ if (read_proc(&val, sizeof(number64_t), user_data) == sizeof(number64_t)) {
+ return amf0_number_new(swap_number64(val));
+ }
+ return NULL;
+}
+
+/* read a boolean */
+static amf0_data * amf0_boolean_read(read_proc_t read_proc, void * user_data) {
+ uint8_t val;
+ if (read_proc(&val, sizeof(uint8_t), user_data) == sizeof(uint8_t)) {
+ return amf0_boolean_new(val);
+ }
+ return NULL;
+}
+
+/* read a string */
+static amf0_data * amf0_string_read(read_proc_t read_proc, void * user_data) {
+ uint16_t strsize;
+ uint8_t * buffer;
+ if (read_proc(&strsize, sizeof(uint16_t), user_data) == sizeof(uint16_t)) {
+ strsize = swap_uint16(strsize);
+ if (strsize > 0) {
+ buffer = (uint8_t*)calloc(strsize, sizeof(uint8_t));
+ if (buffer != NULL && read_proc(buffer, strsize, user_data) == strsize) {
+ amf0_data * data = amf0_string_new(buffer, strsize);
+ free(buffer);
+ return data;
+ }
+ }
+ else {
+ return amf0_string_new(NULL, 0);
+ }
+ }
+ return NULL;
+}
+
+/* read an object */
+static amf0_data * amf0_object_read(read_proc_t read_proc, void * user_data) {
+ amf0_data * data = amf0_object_new();
+ if (data != NULL) {
+ amf0_data * name;
+ amf0_data * element;
+ while (1) {
+ name = amf0_string_read(read_proc, user_data);
+ if (name != NULL) {
+ element = amf0_data_read(read_proc, user_data);
+ if (element != NULL) {
+ if (amf0_object_add(data, (char *)amf0_string_get_uint8_ts(name), element) == NULL) {
+ amf0_data_free(name);
+ amf0_data_free(element);
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ else {
+ amf0_data_free(name);
+ break;
+ }
+ }
+ else {
+ /* invalid name: error */
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ }
+ return data;
+}
+
+/* read an associative array */
+static amf0_data * amf0_associative_array_read(read_proc_t read_proc, void * user_data) {
+ amf0_data * data = amf0_associative_array_new();
+ if (data != NULL) {
+ amf0_data * name;
+ amf0_data * element;
+ uint32_t size;
+ if (read_proc(&size, sizeof(uint32_t), user_data) == sizeof(uint32_t)) {
+ /* we ignore the 32 bits array size marker */
+ while(1) {
+ name = amf0_string_read(read_proc, user_data);
+ if (name != NULL) {
+ element = amf0_data_read(read_proc, user_data);
+ if (element != NULL) {
+ if (amf0_associative_array_add(data, (char *)amf0_string_get_uint8_ts(name), element) == NULL) {
+ amf0_data_free(name);
+ amf0_data_free(element);
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ else {
+ amf0_data_free(name);
+ break;
+ }
+ }
+ else {
+ /* invalid name: error */
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ }
+ else {
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ return data;
+}
+
+/* read an array */
+static amf0_data * amf0_array_read(read_proc_t read_proc, void * user_data) {
+ size_t i;
+ amf0_data * element;
+ amf0_data * data = amf0_array_new();
+ if (data != NULL) {
+ uint32_t array_size;
+ if (read_proc(&array_size, sizeof(uint32_t), user_data) == sizeof(uint32_t)) {
+ array_size = swap_uint32(array_size);
+
+ for (i = 0; i < array_size; ++i) {
+ element = amf0_data_read(read_proc, user_data);
+
+ if (element != NULL) {
+ if (amf0_array_push(data, element) == NULL) {
+ amf0_data_free(element);
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ else {
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ }
+ else {
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ return data;
+}
+
+/* read a date */
+static amf0_data * amf0_date_read(read_proc_t read_proc, void * user_data) {
+ number64_t milliseconds;
+ int16_t timezone;
+ if (read_proc(&milliseconds, sizeof(number64_t), user_data) == sizeof(number64_t) &&
+ read_proc(&timezone, sizeof(int16_t), user_data) == sizeof(int16_t)) {
+ return amf0_date_new(swap_number64(milliseconds), swap_sint16(timezone));
+ }
+ else {
+ return NULL;
+ }
+}
+
+/* load AMF data from stream */
+amf0_data * amf0_data_read(read_proc_t read_proc, void * user_data) {
+ uint8_t type;
+ if (read_proc(&type, sizeof(uint8_t), user_data) == sizeof(uint8_t)) {
+ switch (type) {
+ case AMF0_TYPE_NUMBER:
+ return amf0_number_read(read_proc, user_data);
+ case AMF0_TYPE_BOOLEAN:
+ return amf0_boolean_read(read_proc, user_data);
+ case AMF0_TYPE_STRING:
+ return amf0_string_read(read_proc, user_data);
+ case AMF0_TYPE_OBJECT:
+ return amf0_object_read(read_proc, user_data);
+ case AMF0_TYPE_NULL:
+ return amf0_null_new();
+ case AMF0_TYPE_UNDEFINED:
+ return amf0_undefined_new();
+ /*case AMF0_TYPE_REFERENCE:*/
+ case AMF0_TYPE_ECMA_ARRAY:
+ return amf0_associative_array_read(read_proc, user_data);
+ case AMF0_TYPE_STRICT_ARRAY:
+ return amf0_array_read(read_proc, user_data);
+ case AMF0_TYPE_DATE:
+ return amf0_date_read(read_proc, user_data);
+ /*case AMF0_TYPE_SIMPLEOBJECT:*/
+ case AMF0_TYPE_XML_DOCUMENT:
+ case AMF0_TYPE_TYPED_OBJECT:
+ case AMF0_TYPE_OBJECT_END:
+ return NULL; /* end of composite object */
+ default:
+ break;
+ }
+ }
+ return NULL;
+}
+
+/* determines the size of the given AMF data */
+size_t amf0_data_size(amf0_data * data) {
+ size_t s = 0;
+ amf0_node * node;
+ if (data != NULL) {
+ s += sizeof(uint8_t);
+ switch (data->type) {
+ case AMF0_TYPE_NUMBER:
+ s += sizeof(number64_t);
+ break;
+ case AMF0_TYPE_BOOLEAN:
+ s += sizeof(uint8_t);
+ break;
+ case AMF0_TYPE_STRING:
+ s += sizeof(uint16_t) + (size_t)amf0_string_get_size(data);
+ break;
+ case AMF0_TYPE_OBJECT:
+ node = amf0_object_first(data);
+ while (node != NULL) {
+ s += sizeof(uint16_t) + (size_t)amf0_string_get_size(amf0_object_get_name(node));
+ s += (size_t)amf0_data_size(amf0_object_get_data(node));
+ node = amf0_object_next(node);
+ }
+ s += sizeof(uint16_t) + sizeof(uint8_t);
+ break;
+ case AMF0_TYPE_NULL:
+ case AMF0_TYPE_UNDEFINED:
+ break;
+ /*case AMF0_TYPE_REFERENCE:*/
+ case AMF0_TYPE_ECMA_ARRAY:
+ s += sizeof(uint32_t);
+ node = amf0_associative_array_first(data);
+ while (node != NULL) {
+ s += sizeof(uint16_t) + (size_t)amf0_string_get_size(amf0_associative_array_get_name(node));
+ s += (size_t)amf0_data_size(amf0_associative_array_get_data(node));
+ node = amf0_associative_array_next(node);
+ }
+ s += sizeof(uint16_t) + sizeof(uint8_t);
+ break;
+ case AMF0_TYPE_STRICT_ARRAY:
+ s += sizeof(uint32_t);
+ node = amf0_array_first(data);
+ while (node != NULL) {
+ s += (size_t)amf0_data_size(amf0_array_get(node));
+ node = amf0_array_next(node);
+ }
+ break;
+ case AMF0_TYPE_DATE:
+ s += sizeof(number64_t) + sizeof(int16_t);
+ break;
+ /*case AMF0_TYPE_SIMPLEOBJECT:*/
+ case AMF0_TYPE_XML_DOCUMENT:
+ case AMF0_TYPE_TYPED_OBJECT:
+ case AMF0_TYPE_OBJECT_END:
+ break; /* end of composite object */
+ default:
+ break;
+ }
+ }
+ return s;
+}
+
+/* write a number */
+static size_t amf0_number_write(amf0_data * data, write_proc_t write_proc, void * user_data) {
+ number64_t n = swap_number64(data->u.number_data);
+ return write_proc(&n, sizeof(number64_t), user_data);
+}
+
+/* write a boolean */
+static size_t amf0_boolean_write(amf0_data * data, write_proc_t write_proc, void * user_data) {
+ return write_proc(&(data->u.boolean_data), sizeof(uint8_t), user_data);
+}
+
+/* write a string */
+static size_t amf0_string_write(amf0_data * data, write_proc_t write_proc, void * user_data) {
+ uint16_t s;
+ size_t w = 0;
+
+ s = swap_uint16(data->u.string_data.size);
+ w = write_proc(&s, sizeof(uint16_t), user_data);
+ if (data->u.string_data.size > 0) {
+ w += write_proc(data->u.string_data.mbstr, (size_t)(data->u.string_data.size), user_data);
+ }
+
+ return w;
+}
+
+/* write an object */
+static size_t amf0_object_write(amf0_data * data, write_proc_t write_proc, void * user_data) {
+ amf0_node * node;
+ size_t w = 0;
+ uint16_t filler = swap_uint16(0);
+ uint8_t terminator = AMF0_TYPE_OBJECT_END;
+
+ node = amf0_object_first(data);
+ while (node != NULL) {
+ w += amf0_string_write(amf0_object_get_name(node), write_proc, user_data);
+ w += amf0_data_write(amf0_object_get_data(node), write_proc, user_data);
+ node = amf0_object_next(node);
+ }
+
+ /* empty string is the last element */
+ w += write_proc(&filler, sizeof(uint16_t), user_data);
+ /* an object ends with 0x09 */
+ w += write_proc(&terminator, sizeof(uint8_t), user_data);
+
+ return w;
+}
+
+/* write an associative array */
+static size_t amf0_associative_array_write(amf0_data * data, write_proc_t write_proc, void * user_data) {
+ amf0_node * node;
+ size_t w = 0;
+ uint32_t s;
+ uint16_t filler = swap_uint16(0);
+ uint8_t terminator = AMF0_TYPE_OBJECT_END;
+
+ s = swap_uint32(data->u.list_data.size) / 2;
+ w += write_proc(&s, sizeof(uint32_t), user_data);
+ node = amf0_associative_array_first(data);
+ while (node != NULL) {
+ w += amf0_string_write(amf0_associative_array_get_name(node), write_proc, user_data);
+ w += amf0_data_write(amf0_associative_array_get_data(node), write_proc, user_data);
+ node = amf0_associative_array_next(node);
+ }
+
+ /* empty string is the last element */
+ w += write_proc(&filler, sizeof(uint16_t), user_data);
+ /* an object ends with 0x09 */
+ w += write_proc(&terminator, sizeof(uint8_t), user_data);
+
+ return w;
+}
+
+/* write an array */
+static size_t amf0_array_write(amf0_data * data, write_proc_t write_proc, void * user_data) {
+ amf0_node * node;
+ size_t w = 0;
+ uint32_t s;
+
+ s = swap_uint32(data->u.list_data.size);
+ w += write_proc(&s, sizeof(uint32_t), user_data);
+ node = amf0_array_first(data);
+ while (node != NULL) {
+ w += amf0_data_write(amf0_array_get(node), write_proc, user_data);
+ node = amf0_array_next(node);
+ }
+
+ return w;
+}
+
+/* write a date */
+static size_t amf0_date_write(amf0_data * data, write_proc_t write_proc, void * user_data) {
+ size_t w = 0;
+ number64_t milli;
+ int16_t tz;
+
+ milli = swap_number64(data->u.date_data.milliseconds);
+ w += write_proc(&milli, sizeof(number64_t), user_data);
+ tz = swap_sint16(data->u.date_data.timezone);
+ w += write_proc(&tz, sizeof(int16_t), user_data);
+
+ return w;
+}
+
+/* write amf data to stream */
+size_t amf0_data_write(amf0_data * data, write_proc_t write_proc, void * user_data) {
+ size_t s = 0;
+ if (data != NULL) {
+ s += write_proc(&(data->type), sizeof(uint8_t), user_data);
+ switch (data->type) {
+ case AMF0_TYPE_NUMBER:
+ s += amf0_number_write(data, write_proc, user_data);
+ break;
+ case AMF0_TYPE_BOOLEAN:
+ s += amf0_boolean_write(data, write_proc, user_data);
+ break;
+ case AMF0_TYPE_STRING:
+ s += amf0_string_write(data, write_proc, user_data);
+ break;
+ case AMF0_TYPE_OBJECT:
+ s += amf0_object_write(data, write_proc, user_data);
+ break;
+ case AMF0_TYPE_NULL:
+ case AMF0_TYPE_UNDEFINED:
+ break;
+ /*case AMF0_TYPE_REFERENCE:*/
+ case AMF0_TYPE_ECMA_ARRAY:
+ s += amf0_associative_array_write(data, write_proc, user_data);
+ break;
+ case AMF0_TYPE_STRICT_ARRAY:
+ s += amf0_array_write(data, write_proc, user_data);
+ break;
+ case AMF0_TYPE_DATE:
+ s += amf0_date_write(data, write_proc, user_data);
+ break;
+ /*case AMF0_TYPE_SIMPLEOBJECT:*/
+ case AMF0_TYPE_XML_DOCUMENT:
+ case AMF0_TYPE_TYPED_OBJECT:
+ case AMF0_TYPE_OBJECT_END:
+ break; /* end of composite object */
+ default:
+ break;
+ }
+ }
+ return s;
+}
+
+/* data type */
+uint8_t amf0_data_get_type(amf0_data * data) {
+ return (data != NULL) ? data->type : AMF0_TYPE_NULL;
+}
+
+/* clone AMF data */
+amf0_data * amf0_data_clone(amf0_data * data) {
+ /* we copy data recursively */
+ if (data != NULL) {
+ switch (data->type) {
+ case AMF0_TYPE_NUMBER: return amf0_number_new(amf0_number_get_value(data));
+ case AMF0_TYPE_BOOLEAN: return amf0_boolean_new(amf0_boolean_get_value(data));
+ case AMF0_TYPE_STRING:
+ if (data->u.string_data.mbstr != NULL) {
+ return amf0_string_new((uint8_t *)strdup((char *)amf0_string_get_uint8_ts(data)), amf0_string_get_size(data));
+ }
+ else {
+ return amf0_str(NULL);
+ }
+ case AMF0_TYPE_NULL: return NULL;
+ case AMF0_TYPE_UNDEFINED: return NULL;
+ /*case AMF0_TYPE_REFERENCE:*/
+ case AMF0_TYPE_OBJECT:
+ case AMF0_TYPE_ECMA_ARRAY:
+ case AMF0_TYPE_STRICT_ARRAY:
+ {
+ amf0_data * d = amf0_data_new(data->type);
+ if (d != NULL) {
+ amf0_list_init(&d->u.list_data);
+ amf0_list_clone(&data->u.list_data, &d->u.list_data);
+ }
+ return d;
+ }
+ case AMF0_TYPE_DATE: return amf0_date_new(amf0_date_get_milliseconds(data), amf0_date_get_timezone(data));
+ /*case AMF0_TYPE_SIMPLEOBJECT:*/
+ case AMF0_TYPE_XML_DOCUMENT: return NULL;
+ case AMF0_TYPE_TYPED_OBJECT: return NULL;
+ }
+ }
+ return NULL;
+}
+
+/* free AMF data */
+void amf0_data_free(amf0_data * data) {
+ if (data != NULL) {
+ switch (data->type) {
+ case AMF0_TYPE_NUMBER: break;
+ case AMF0_TYPE_BOOLEAN: break;
+ case AMF0_TYPE_STRING:
+ if (data->u.string_data.mbstr != NULL) {
+ free(data->u.string_data.mbstr);
+ } break;
+ case AMF0_TYPE_NULL: break;
+ case AMF0_TYPE_UNDEFINED: break;
+ /*case AMF0_TYPE_REFERENCE:*/
+ case AMF0_TYPE_OBJECT:
+ case AMF0_TYPE_ECMA_ARRAY:
+ case AMF0_TYPE_STRICT_ARRAY: amf0_list_clear(&data->u.list_data); break;
+ case AMF0_TYPE_DATE: break;
+ /*case AMF0_TYPE_SIMPLEOBJECT:*/
+ case AMF0_TYPE_XML_DOCUMENT: break;
+ case AMF0_TYPE_TYPED_OBJECT: break;
+ default: break;
+ }
+ free(data);
+ }
+}
+
+/* dump AMF data into a stream as text */
+void amf0_data_dump(FILE * stream, amf0_data * data, int indent_level) {
+ if (data != NULL) {
+ amf0_node * node;
+ time_t time;
+ struct tm * t;
+ char datestr[128];
+ switch (data->type) {
+ case AMF0_TYPE_NUMBER:
+ fprintf(stream, "%.12g", (double)data->u.number_data);
+ break;
+ case AMF0_TYPE_BOOLEAN:
+ fprintf(stream, "%s", (data->u.boolean_data) ? "true" : "false");
+ break;
+ case AMF0_TYPE_STRING:
+ fprintf(stream, "\'%.*s\'", data->u.string_data.size, data->u.string_data.mbstr);
+ break;
+ case AMF0_TYPE_OBJECT:
+ node = amf0_object_first(data);
+ fprintf(stream, "{\n");
+ while (node != NULL) {
+ fprintf(stream, "%*s", (indent_level+1)*4, "");
+ amf0_data_dump(stream, amf0_object_get_name(node), indent_level+1);
+ fprintf(stream, ": ");
+ amf0_data_dump(stream, amf0_object_get_data(node), indent_level+1);
+ node = amf0_object_next(node);
+ fprintf(stream, "\n");
+ }
+ fprintf(stream, "%*s", indent_level*4 + 1, "}");
+ break;
+ case AMF0_TYPE_NULL:
+ fprintf(stream, "null");
+ break;
+ case AMF0_TYPE_UNDEFINED:
+ fprintf(stream, "undefined");
+ break;
+ /*case AMF0_TYPE_REFERENCE:*/
+ case AMF0_TYPE_ECMA_ARRAY:
+ node = amf0_associative_array_first(data);
+ fprintf(stream, "{\n");
+ while (node != NULL) {
+ fprintf(stream, "%*s", (indent_level+1)*4, "");
+ amf0_data_dump(stream, amf0_associative_array_get_name(node), indent_level+1);
+ fprintf(stream, " => ");
+ amf0_data_dump(stream, amf0_associative_array_get_data(node), indent_level+1);
+ node = amf0_associative_array_next(node);
+ fprintf(stream, "\n");
+ }
+ fprintf(stream, "%*s", indent_level*4 + 1, "}");
+ break;
+ case AMF0_TYPE_STRICT_ARRAY:
+ node = amf0_array_first(data);
+ fprintf(stream, "[\n");
+ while (node != NULL) {
+ fprintf(stream, "%*s", (indent_level+1)*4, "");
+ amf0_data_dump(stream, node->data, indent_level+1);
+ node = amf0_array_next(node);
+ fprintf(stream, "\n");
+ }
+ fprintf(stream, "%*s", indent_level*4 + 1, "]");
+ break;
+ case AMF0_TYPE_DATE:
+ time = amf0_date_to_time_t(data);
+ tzset();
+ t = localtime(&time);
+ strftime(datestr, sizeof(datestr), "%a, %d %b %Y %H:%M:%S %z", t);
+ fprintf(stream, "%s", datestr);
+ break;
+ /*case AMF0_TYPE_SIMPLEOBJECT:*/
+ case AMF0_TYPE_XML_DOCUMENT: break;
+ case AMF0_TYPE_TYPED_OBJECT: break;
+ default: break;
+ }
+ }
+}
+
+/* number functions */
+amf0_data * amf0_number_new(number64_t value) {
+ amf0_data * data = amf0_data_new(AMF0_TYPE_NUMBER);
+ if (data != NULL) {
+ data->u.number_data = value;
+ }
+ return data;
+}
+
+number64_t amf0_number_get_value(amf0_data * data) {
+ return (data != NULL) ? data->u.number_data : 0;
+}
+
+void amf0_number_set_value(amf0_data * data, number64_t value) {
+ if (data != NULL) {
+ data->u.number_data = value;
+ }
+}
+
+/* boolean functions */
+amf0_data * amf0_boolean_new(uint8_t value) {
+ amf0_data * data = amf0_data_new(AMF0_TYPE_BOOLEAN);
+ if (data != NULL) {
+ data->u.boolean_data = value;
+ }
+ return data;
+}
+
+uint8_t amf0_boolean_get_value(amf0_data * data) {
+ return (data != NULL) ? data->u.boolean_data : 0;
+}
+
+void amf0_boolean_set_value(amf0_data * data, uint8_t value) {
+ if (data != NULL) {
+ data->u.boolean_data = value;
+ }
+}
+
+/* string functions */
+amf0_data * amf0_string_new(uint8_t * str, uint16_t size) {
+ amf0_data * data = amf0_data_new(AMF0_TYPE_STRING);
+ if (data != NULL) {
+ data->u.string_data.size = size;
+ data->u.string_data.mbstr = (uint8_t*)calloc(size+1, sizeof(uint8_t));
+ if (data->u.string_data.mbstr != NULL) {
+ if (size > 0) {
+ memcpy(data->u.string_data.mbstr, str, size);
+ }
+ }
+ else {
+ amf0_data_free(data);
+ return NULL;
+ }
+ }
+ return data;
+}
+
+amf0_data * amf0_str(const char * str) {
+ return amf0_string_new((uint8_t *)str, (uint16_t)(str != NULL ? strlen(str) : 0));
+}
+
+uint16_t amf0_string_get_size(amf0_data * data) {
+ return (data != NULL) ? data->u.string_data.size : 0;
+}
+
+uint8_t * amf0_string_get_uint8_ts(amf0_data * data) {
+ return (data != NULL) ? data->u.string_data.mbstr : NULL;
+}
+
+/* object functions */
+amf0_data * amf0_object_new(void) {
+ amf0_data * data = amf0_data_new(AMF0_TYPE_OBJECT);
+ if (data != NULL) {
+ amf0_list_init(&data->u.list_data);
+ }
+ return data;
+}
+
+uint32_t amf0_object_size(amf0_data * data) {
+ return (data != NULL) ? data->u.list_data.size / 2 : 0;
+}
+
+amf0_data * amf0_object_add(amf0_data * data, const char * name, amf0_data * element) {
+ if (data != NULL) {
+ if (amf0_list_push(&data->u.list_data, amf0_str(name)) != NULL) {
+ if (amf0_list_push(&data->u.list_data, element) != NULL) {
+ return element;
+ }
+ else {
+ amf0_data_free(amf0_list_pop(&data->u.list_data));
+ }
+ }
+ }
+ return NULL;
+}
+
+amf0_data * amf0_object_get(amf0_data * data, const char * name) {
+ if (data != NULL) {
+ amf0_node * node = amf0_list_first(&(data->u.list_data));
+ while (node != NULL) {
+ if (strncmp((char*)(node->data->u.string_data.mbstr), name, (size_t)(node->data->u.string_data.size)) == 0) {
+ node = node->next;
+ return (node != NULL) ? node->data : NULL;
+ }
+ /* we have to skip the element data to reach the next name */
+ node = node->next->next;
+ }
+ }
+ return NULL;
+}
+
+amf0_data * amf0_object_set(amf0_data * data, const char * name, amf0_data * element) {
+ if (data != NULL) {
+ amf0_node * node = amf0_list_first(&(data->u.list_data));
+ while (node != NULL) {
+ if (strncmp((char*)(node->data->u.string_data.mbstr), name, (size_t)(node->data->u.string_data.size)) == 0) {
+ node = node->next;
+ if (node != NULL && node->data != NULL) {
+ amf0_data_free(node->data);
+ node->data = element;
+ return element;
+ }
+ }
+ /* we have to skip the element data to reach the next name */
+ node = node->next->next;
+ }
+ }
+ return NULL;
+}
+
+amf0_data * amf0_object_delete(amf0_data * data, const char * name) {
+ if (data != NULL) {
+ amf0_node * node = amf0_list_first(&data->u.list_data);
+ while (node != NULL) {
+ node = node->next;
+ if (strncmp((char*)(node->data->u.string_data.mbstr), name, (size_t)(node->data->u.string_data.size)) == 0) {
+ amf0_node * data_node = node->next;
+ amf0_data_free(amf0_list_delete(&data->u.list_data, node));
+ return amf0_list_delete(&data->u.list_data, data_node);
+ }
+ else {
+ node = node->next;
+ }
+ }
+ }
+ return NULL;
+}
+
+amf0_node * amf0_object_first(amf0_data * data) {
+ return (data != NULL) ? amf0_list_first(&data->u.list_data) : NULL;
+}
+
+amf0_node * amf0_object_last(amf0_data * data) {
+ if (data != NULL) {
+ amf0_node * node = amf0_list_last(&data->u.list_data);
+ if (node != NULL) {
+ return node->prev;
+ }
+ }
+ return NULL;
+}
+
+amf0_node * amf0_object_next(amf0_node * node) {
+ if (node != NULL) {
+ amf0_node * next = node->next;
+ if (next != NULL) {
+ return next->next;
+ }
+ }
+ return NULL;
+}
+
+amf0_node * amf0_object_prev(amf0_node * node) {
+ if (node != NULL) {
+ amf0_node * prev = node->prev;
+ if (prev != NULL) {
+ return prev->prev;
+ }
+ }
+ return NULL;
+}
+
+amf0_data * amf0_object_get_name(amf0_node * node) {
+ return (node != NULL) ? node->data : NULL;
+}
+
+amf0_data * amf0_object_get_data(amf0_node * node) {
+ if (node != NULL) {
+ amf0_node * next = node->next;
+ if (next != NULL) {
+ return next->data;
+ }
+ }
+ return NULL;
+}
+
+/* associative array functions */
+amf0_data * amf0_associative_array_new(void) {
+ amf0_data * data = amf0_data_new(AMF0_TYPE_ECMA_ARRAY);
+ if (data != NULL) {
+ amf0_list_init(&data->u.list_data);
+ }
+ return data;
+}
+
+/* array functions */
+amf0_data * amf0_array_new(void) {
+ amf0_data * data = amf0_data_new(AMF0_TYPE_STRICT_ARRAY);
+ if (data != NULL) {
+ amf0_list_init(&data->u.list_data);
+ }
+ return data;
+}
+
+uint32_t amf0_array_size(amf0_data * data) {
+ return (data != NULL) ? data->u.list_data.size : 0;
+}
+
+amf0_data * amf0_array_push(amf0_data * data, amf0_data * element) {
+ return (data != NULL) ? amf0_list_push(&data->u.list_data, element) : NULL;
+}
+
+amf0_data * amf0_array_pop(amf0_data * data) {
+ return (data != NULL) ? amf0_list_pop(&data->u.list_data) : NULL;
+}
+
+amf0_node * amf0_array_first(amf0_data * data) {
+ return (data != NULL) ? amf0_list_first(&data->u.list_data) : NULL;
+}
+
+amf0_node * amf0_array_last(amf0_data * data) {
+ return (data != NULL) ? amf0_list_last(&data->u.list_data) : NULL;
+}
+
+amf0_node * amf0_array_next(amf0_node * node) {
+ return (node != NULL) ? node->next : NULL;
+}
+
+amf0_node * amf0_array_prev(amf0_node * node) {
+ return (node != NULL) ? node->prev : NULL;
+}
+
+amf0_data * amf0_array_get(amf0_node * node) {
+ return (node != NULL) ? node->data : NULL;
+}
+
+amf0_data * amf0_array_get_at(amf0_data * data, uint32_t n) {
+ return (data != NULL) ? amf0_list_get_at(&data->u.list_data, n) : NULL;
+}
+
+amf0_data * amf0_array_delete(amf0_data * data, amf0_node * node) {
+ return (data != NULL) ? amf0_list_delete(&data->u.list_data, node) : NULL;
+}
+
+amf0_data * amf0_array_insert_before(amf0_data * data, amf0_node * node, amf0_data * element) {
+ return (data != NULL) ? amf0_list_insert_before(&data->u.list_data, node, element) : NULL;
+}
+
+amf0_data * amf0_array_insert_after(amf0_data * data, amf0_node * node, amf0_data * element) {
+ return (data != NULL) ? amf0_list_insert_after(&data->u.list_data, node, element) : NULL;
+}
+
+/* date functions */
+amf0_data * amf0_date_new(number64_t milliseconds, int16_t timezone) {
+ amf0_data * data = amf0_data_new(AMF0_TYPE_DATE);
+ if (data != NULL) {
+ data->u.date_data.milliseconds = milliseconds;
+ data->u.date_data.timezone = timezone;
+ }
+ return data;
+}
+
+number64_t amf0_date_get_milliseconds(amf0_data * data) {
+ return (data != NULL) ? data->u.date_data.milliseconds : 0.0;
+}
+
+int16_t amf0_date_get_timezone(amf0_data * data) {
+ return (data != NULL) ? data->u.date_data.timezone : 0;
+}
+
+time_t amf0_date_to_time_t(amf0_data * data) {
+ return (time_t)((data != NULL) ? data->u.date_data.milliseconds / 1000 : 0);
+}
diff --git a/src/mod/endpoints/mod_rtmp/libamf/src/amf0.h b/src/mod/endpoints/mod_rtmp/libamf/src/amf0.h
new file mode 100644
index 0000000000..9cb5b7f1c6
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/src/amf0.h
@@ -0,0 +1,190 @@
+#ifndef __AMF0_H__
+#define __AMF0_H__
+
+#include
+#include
+
+#include "amf.h"
+
+/* AMF data types */
+#define AMF0_TYPE_NUMBER 0x00
+#define AMF0_TYPE_BOOLEAN 0x01
+#define AMF0_TYPE_STRING 0x02
+#define AMF0_TYPE_OBJECT 0x03
+#define AMF0_TYPE_MOVIECLIP 0x04 /* reserved, not supported */
+#define AMF0_TYPE_NULL 0x05
+#define AMF0_TYPE_UNDEFINED 0x06
+#define AMF0_TYPE_REFERENCE 0x07
+#define AMF0_TYPE_ECMA_ARRAY 0x08
+#define AMF0_TYPE_OBJECT_END 0x09
+#define AMF0_TYPE_STRICT_ARRAY 0x0A
+#define AMF0_TYPE_DATE 0x0B
+#define AMF0_TYPE_LONG_STRING 0x0C
+#define AMF0_TYPE_UNSUPPORTED 0x0D
+#define AMF0_TYPE_RECORDSET 0x0E /* reserved, not supported */
+#define AMF0_TYPE_XML_DOCUMENT 0x0F
+#define AMF0_TYPE_TYPED_OBJECT 0x10
+
+typedef struct __amf0_node * p_amf0_node;
+
+/* string type */
+typedef struct __amf0_string {
+ uint16_t size;
+ uint8_t * mbstr;
+} amf0_string;
+
+/* array type */
+typedef struct __amf0_list {
+ uint32_t size;
+ p_amf0_node first_element;
+ p_amf0_node last_element;
+} amf0_list;
+
+/* date type */
+typedef struct __amf0_date {
+ number64_t milliseconds;
+ int16_t timezone;
+} amf0_date;
+
+/* XML string type */
+typedef struct __amf0_xmlstring {
+ uint32_t size;
+ uint8_t * mbstr;
+} amf0_xmlstring;
+
+/* class type */
+typedef struct __amf0_class {
+ amf0_string name;
+ amf0_list elements;
+} amf0_class;
+
+/* structure encapsulating the various AMF objects */
+typedef struct __amf0_data {
+ uint8_t type;
+ union {
+ number64_t number_data;
+ uint8_t boolean_data;
+ amf0_string string_data;
+ amf0_list list_data;
+ amf0_date date_data;
+ amf0_xmlstring xmlstring_data;
+ amf0_class class_data;
+ } u;
+} amf0_data;
+
+/* node used in lists, relies on amf0_data */
+typedef struct __amf0_node {
+ amf0_data * data;
+ p_amf0_node prev;
+ p_amf0_node next;
+} amf0_node;
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* read AMF data */
+amf0_data * amf0_data_read(read_proc_t read_proc, void * user_data);
+
+/* write AMF data */
+size_t amf0_data_write(amf0_data * data, write_proc_t write_proc, void * user_data);
+
+/* generic functions */
+
+/* allocate an AMF data object */
+amf0_data * amf0_data_new(uint8_t type);
+/* load AMF data from buffer */
+amf0_data * amf0_data_buffer_read(uint8_t * buffer, size_t maxbytes);
+/* load AMF data from stream */
+amf0_data * amf0_data_file_read(FILE * stream);
+/* AMF data size */
+size_t amf0_data_size(amf0_data * data);
+/* write encoded AMF data into a buffer */
+size_t amf0_data_buffer_write(amf0_data * data, uint8_t * buffer, size_t maxbytes);
+/* write encoded AMF data into a stream */
+size_t amf0_data_file_write(amf0_data * data, FILE * stream);
+/* get the type of AMF data */
+uint8_t amf0_data_get_type(amf0_data * data);
+/* return a new copy of AMF data */
+amf0_data * amf0_data_clone(amf0_data * data);
+/* release the memory of AMF data */
+void amf0_data_free(amf0_data * data);
+/* dump AMF data into a stream as text */
+void amf0_data_dump(FILE * stream, amf0_data * data, int indent_level);
+
+/* number functions */
+amf0_data * amf0_number_new(number64_t value);
+number64_t amf0_number_get_value(amf0_data * data);
+void amf0_number_set_value(amf0_data * data, number64_t value);
+
+/* boolean functions */
+amf0_data * amf0_boolean_new(uint8_t value);
+uint8_t amf0_boolean_get_value(amf0_data * data);
+void amf0_boolean_set_value(amf0_data * data, uint8_t value);
+
+/* string functions */
+amf0_data * amf0_string_new(uint8_t * str, uint16_t size);
+amf0_data * amf0_str(const char * str);
+uint16_t amf0_string_get_size(amf0_data * data);
+uint8_t * amf0_string_get_uint8_ts(amf0_data * data);
+
+/* object functions */
+amf0_data * amf0_object_new(void);
+uint32_t amf0_object_size(amf0_data * data);
+amf0_data * amf0_object_add(amf0_data * data, const char * name, amf0_data * element);
+amf0_data * amf0_object_get(amf0_data * data, const char * name);
+amf0_data * amf0_object_set(amf0_data * data, const char * name, amf0_data * element);
+amf0_data * amf0_object_delete(amf0_data * data, const char * name);
+amf0_node * amf0_object_first(amf0_data * data);
+amf0_node * amf0_object_last(amf0_data * data);
+amf0_node * amf0_object_next(amf0_node * node);
+amf0_node * amf0_object_prev(amf0_node * node);
+amf0_data * amf0_object_get_name(amf0_node * node);
+amf0_data * amf0_object_get_data(amf0_node * node);
+
+/* null functions */
+#define amf0_null_new() amf0_data_new(AMF0_TYPE_NULL)
+
+/* undefined functions */
+#define amf0_undefined_new() amf0_data_new(AMF0_TYPE_UNDEFINED)
+
+/* associative array functions */
+amf0_data * amf0_associative_array_new(void);
+#define amf0_associative_array_size(d) amf0_object_size(d)
+#define amf0_associative_array_add(d, n, e) amf0_object_add(d, n, e)
+#define amf0_associative_array_get(d, n) amf0_object_get(d, n)
+#define amf0_associative_array_set(d, n, e) amf0_object_set(d, n, e)
+#define amf0_associative_array_delete(d, n) amf0_object_delete(d, n)
+#define amf0_associative_array_first(d) amf0_object_first(d)
+#define amf0_associative_array_last(d) amf0_object_last(d)
+#define amf0_associative_array_next(n) amf0_object_next(n)
+#define amf0_associative_array_prev(n) amf0_object_prev(n)
+#define amf0_associative_array_get_name(n) amf0_object_get_name(n)
+#define amf0_associative_array_get_data(n) amf0_object_get_data(n)
+
+/* array functions */
+amf0_data * amf0_array_new(void);
+uint32_t amf0_array_size(amf0_data * data);
+amf0_data * amf0_array_push(amf0_data * data, amf0_data * element);
+amf0_data * amf0_array_pop(amf0_data * data);
+amf0_node * amf0_array_first(amf0_data * data);
+amf0_node * amf0_array_last(amf0_data * data);
+amf0_node * amf0_array_next(amf0_node * node);
+amf0_node * amf0_array_prev(amf0_node * node);
+amf0_data * amf0_array_get(amf0_node * node);
+amf0_data * amf0_array_get_at(amf0_data * data, uint32_t n);
+amf0_data * amf0_array_delete(amf0_data * data, amf0_node * node);
+amf0_data * amf0_array_insert_before(amf0_data * data, amf0_node * node, amf0_data * element);
+amf0_data * amf0_array_insert_after(amf0_data * data, amf0_node * node, amf0_data * element);
+
+/* date functions */
+amf0_data * amf0_date_new(number64_t milliseconds, int16_t timezone);
+number64_t amf0_date_get_milliseconds(amf0_data * data);
+int16_t amf0_date_get_timezone(amf0_data * data);
+time_t amf0_date_to_time_t(amf0_data * data);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __AMF0_H__ */
diff --git a/src/mod/endpoints/mod_rtmp/libamf/src/amf3.h b/src/mod/endpoints/mod_rtmp/libamf/src/amf3.h
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/src/mod/endpoints/mod_rtmp/libamf/src/amf_list.c b/src/mod/endpoints/mod_rtmp/libamf/src/amf_list.c
new file mode 100644
index 0000000000..47fb65f1e6
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/src/amf_list.c
@@ -0,0 +1,130 @@
+/* function common to all array types */
+static void amf_list_init(amf_list * list) {
+ if (list != NULL) {
+ list->size = 0;
+ list->first_element = NULL;
+ list->last_element = NULL;
+ }
+}
+
+static amf_data * amf_list_push(amf_list * list, amf_data * data) {
+ amf_node * node = (amf_node*)malloc(sizeof(amf_node));
+ if (node != NULL) {
+ node->data = data;
+ node->next = NULL;
+ node->prev = NULL;
+ if (list->size == 0) {
+ list->first_element = node;
+ list->last_element = node;
+ }
+ else {
+ list->last_element->next = node;
+ node->prev = list->last_element;
+ list->last_element = node;
+ }
+ ++(list->size);
+ return data;
+ }
+ return NULL;
+}
+
+static amf_data * amf_list_insert_before(amf_list * list, amf_node * node, amf_data * data) {
+ if (node != NULL) {
+ amf_node * new_node = (amf_node*)malloc(sizeof(amf_node));
+ if (new_node != NULL) {
+ new_node->next = node;
+ new_node->prev = node->prev;
+
+ if (node->prev != NULL) {
+ node->prev->next = new_node;
+ node->prev = new_node;
+ }
+ if (node == list->first_element) {
+ list->first_element = new_node;
+ }
+ ++(list->size);
+ new_node->data = data;
+ return data;
+ }
+ }
+ return NULL;
+}
+
+static amf_data * amf_list_insert_after(amf_list * list, amf_node * node, amf_data * data) {
+ if (node != NULL) {
+ amf_node * new_node = (amf_node*)malloc(sizeof(amf_node));
+ if (new_node != NULL) {
+ new_node->next = node->next;
+ new_node->prev = node;
+
+ if (node->next != NULL) {
+ node->next->prev = new_node;
+ node->next = new_node;
+ }
+ if (node == list->last_element) {
+ list->last_element = new_node;
+ }
+ ++(list->size);
+ new_node->data = data;
+ return data;
+ }
+ }
+ return NULL;
+}
+
+static amf_data * amf_list_delete(amf_list * list, amf_node * node) {
+ amf_data * data = NULL;
+ if (node != NULL) {
+ if (node->next != NULL) {
+ node->next->prev = node->prev;
+ }
+ if (node->prev != NULL) {
+ node->prev->next = node->next;
+ }
+ if (node == list->first_element) {
+ list->first_element = node->next;
+ }
+ if (node == list->last_element) {
+ list->last_element = node->prev;
+ }
+ data = node->data;
+ free(node);
+ --(list->size);
+ }
+ return data;
+}
+
+static amf_data * amf_list_get_at(amf_list * list, uint32 n) {
+ if (n < list->size) {
+ uint32 i;
+ amf_node * node = list->first_element;
+ for (i = 0; i < n; ++i) {
+ node = node->next;
+ }
+ return node->data;
+ }
+ return NULL;
+}
+
+static amf_data * amf_list_pop(amf_list * list) {
+ return amf_list_delete(list, list->last_element);
+}
+
+static amf_node * amf_list_first(amf_list * list) {
+ return list->first_element;
+}
+
+static amf_node * amf_list_last(amf_list * list) {
+ return list->last_element;
+}
+
+static void amf_list_clear(amf_list * list) {
+ amf_node * node = list->first_element;
+ while (node != NULL) {
+ amf_data_free(node->data);
+ amf_node * tmp = node;
+ node = node->next;
+ free(tmp);
+ }
+ list->size = 0;
+}
diff --git a/src/mod/endpoints/mod_rtmp/libamf/src/amf_list.h b/src/mod/endpoints/mod_rtmp/libamf/src/amf_list.h
new file mode 100644
index 0000000000..b22b7eee73
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/src/amf_list.h
@@ -0,0 +1,5 @@
+typedef struct __amf_list {
+ uint32 size;
+ p_amf_node first_element;
+ p_amf_node last_element;
+} amf_list;
\ No newline at end of file
diff --git a/src/mod/endpoints/mod_rtmp/libamf/src/hash.c b/src/mod/endpoints/mod_rtmp/libamf/src/hash.c
new file mode 100644
index 0000000000..eaea511b14
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/src/hash.c
@@ -0,0 +1,312 @@
+#include
+#include
+
+#include "hash.h"
+
+#define assert(x)
+
+/*static void *malloc_and_zero(int n){
+ void *p = malloc(n);
+ if( p ){
+ memset(p, 0, n);
+ }
+ return p;
+}*/
+
+/**
+ Create a hash table
+*/
+Hash * HashCreate(char copyKey) {
+ return HashCreateAlloc(copyKey, malloc, free);
+}
+
+Hash * HashCreateAlloc(char copyKey, void *(*xMalloc)(size_t), void (*xFree)(void *)) {
+ Hash * pHash = (Hash*)xMalloc(sizeof(Hash));
+ if (pHash != NULL) {
+ HashInit(pHash, copyKey, xMalloc, xFree);
+ return pHash;
+ }
+ else {
+ return 0;
+ }
+}
+
+/**
+ Erase the hash table
+*/
+void HashFree(Hash* pHash) {
+ pHash->xFree(pHash);
+}
+
+/*
+ insert a string key element
+*/
+void * HashInsertSz(Hash *pH, const char *pKey, void *data) {
+ return HashInsert(pH, pKey, (int) strlen(pKey)+1, data);
+}
+
+/*
+ find a string key element
+*/
+void * HashFindSz(const Hash* pH, const char *pKey) {
+ return HashFind(pH, pKey, (int) strlen(pKey)+1);
+}
+
+/* Turn bulk memory into a hash table object by initializing the
+** fields of the Hash structure.
+**
+** "pNew" is a pointer to the hash table that is to be initialized.
+** "copyKey" is true if the hash table should make its own private
+** copy of keys and false if it should just use the supplied pointer.
+*/
+void HashInit(Hash* pNew, char copyKey, void *(*xMalloc)(size_t), void (*xFree)(void *)){
+ assert( pNew!=0 );
+ pNew->copyKey = copyKey;
+ pNew->first = 0;
+ pNew->count = 0;
+ pNew->htsize = 0;
+ pNew->ht = 0;
+ pNew->xMalloc = xMalloc;
+ pNew->xFree = xFree;
+}
+
+/* Remove all entries from a hash table. Reclaim all memory.
+** Call this routine to delete a hash table or to reset a hash table
+** to the empty state.
+*/
+void HashClear(Hash *pH){
+ HashElem *elem; /* For looping over all elements of the table */
+
+ assert( pH!=0 );
+ elem = pH->first;
+ pH->first = 0;
+ if( pH->ht ) pH->xFree(pH->ht);
+ pH->ht = 0;
+ pH->htsize = 0;
+ while( elem ){
+ HashElem *next_elem = elem->next;
+ if( pH->copyKey && elem->pKey ){
+ pH->xFree(elem->pKey);
+ }
+ pH->xFree(elem);
+ elem = next_elem;
+ }
+ pH->count = 0;
+}
+
+/*
+** Hash and comparison functions
+*/
+static int binHash(const void *pKey, int nKey){
+ int h = 0;
+ const char *z = (const char *)pKey;
+ while( nKey-- > 0 ){
+ h = (h<<3) ^ h ^ *(z++);
+ }
+ return h & 0x7fffffff;
+}
+
+static int binCompare(const void *pKey1, int n1, const void *pKey2, int n2){
+ if( n1!=n2 ) return 1;
+ return memcmp(pKey1,pKey2,n1);
+}
+
+/* Link an element into the hash table
+*/
+static void insertElement(
+ Hash *pH, /* The complete hash table */
+ struct _ht *pEntry, /* The entry into which pNew is inserted */
+ HashElem *pNew /* The element to be inserted */
+){
+ HashElem *pHead; /* First element already in pEntry */
+ pHead = pEntry->chain;
+ if( pHead ){
+ pNew->next = pHead;
+ pNew->prev = pHead->prev;
+ if( pHead->prev ){ pHead->prev->next = pNew; }
+ else { pH->first = pNew; }
+ pHead->prev = pNew;
+ }else{
+ pNew->next = pH->first;
+ if( pH->first ){ pH->first->prev = pNew; }
+ pNew->prev = 0;
+ pH->first = pNew;
+ }
+ pEntry->count++;
+ pEntry->chain = pNew;
+}
+
+
+/* Resize the hash table so that it cantains "new_size" buckets.
+** "new_size" must be a power of 2. The hash table might fail
+** to resize if malloc fails.
+*/
+static void rehash(Hash *pH, int new_size){
+ struct _ht *new_ht; /* The new hash table */
+ HashElem *elem, *next_elem; /* For looping over existing elements */
+
+ assert( (new_size & (new_size-1))==0 );
+ new_ht = (struct _ht *)pH->xMalloc( new_size*sizeof(struct _ht) );
+ if( new_ht==0 ) return;
+ if( pH->ht ) pH->xFree(pH->ht);
+ pH->ht = new_ht;
+ pH->htsize = new_size;
+ for(elem=pH->first, pH->first=0; elem; elem = next_elem){
+ int h = binHash(elem->pKey, elem->nKey) & (new_size-1);
+ next_elem = elem->next;
+ insertElement(pH, &new_ht[h], elem);
+ }
+}
+
+/* This function (for internal use only) locates an element in an
+** hash table that matches the given key. The hash for this key has
+** already been computed and is passed as the 4th parameter.
+*/
+static HashElem *findElementGivenHash(
+ const Hash *pH, /* The pH to be searched */
+ const void *pKey, /* The key we are searching for */
+ int nKey,
+ int h /* The hash for this key. */
+){
+ HashElem *elem; /* Used to loop thru the element list */
+ int count; /* Number of elements left to test */
+
+ if( pH->ht ){
+ struct _ht *pEntry = &pH->ht[h];
+ elem = pEntry->chain;
+ count = pEntry->count;
+ while( count-- && elem ){
+ if( binCompare(elem->pKey,elem->nKey,pKey,nKey)==0 ){
+ return elem;
+ }
+ elem = elem->next;
+ }
+ }
+ return 0;
+}
+
+/* Remove a single entry from the hash table given a pointer to that
+** element and a hash on the element's key.
+*/
+static void removeElementGivenHash(
+ Hash *pH, /* The pH containing "elem" */
+ HashElem* elem, /* The element to be removed from the pH */
+ int h /* Hash value for the element */
+){
+ struct _ht *pEntry;
+ if( elem->prev ){
+ elem->prev->next = elem->next;
+ }else{
+ pH->first = elem->next;
+ }
+ if( elem->next ){
+ elem->next->prev = elem->prev;
+ }
+ pEntry = &pH->ht[h];
+ if( pEntry->chain==elem ){
+ pEntry->chain = elem->next;
+ }
+ pEntry->count--;
+ if( pEntry->count<=0 ){
+ pEntry->chain = 0;
+ }
+ if( pH->copyKey && elem->pKey ){
+ pH->xFree(elem->pKey);
+ }
+ pH->xFree( elem );
+ pH->count--;
+ if( pH->count<=0 ){
+ assert( pH->first==0 );
+ assert( pH->count==0 );
+ HashClear(pH);
+ }
+}
+
+/* Attempt to locate an element of the hash table pH with a key
+** that matches pKey,nKey. Return the data for this element if it is
+** found, or NULL if there is no match.
+*/
+void * HashFind(const Hash *pH, const void *pKey, int nKey){
+ int h; /* A hash on key */
+ HashElem *elem; /* The element that matches key */
+
+ if( pH==0 || pH->ht==0 ) return 0;
+ h = binHash(pKey,nKey);
+ assert( (pH->htsize & (pH->htsize-1))==0 );
+ elem = findElementGivenHash(pH,pKey,nKey, h & (pH->htsize-1));
+ return elem ? elem->data : 0;
+}
+
+/* Insert an element into the hash table pH. The key is pKey,nKey
+** and the data is "data".
+**
+** If no element exists with a matching key, then a new
+** element is created. A copy of the key is made if the copyKey
+** flag is set. NULL is returned.
+**
+** If another element already exists with the same key, then the
+** new data replaces the old data and the old data is returned.
+** The key is not copied in this instance. If a malloc fails, then
+** the new data is returned and the hash table is unchanged.
+**
+** If the "data" parameter to this function is NULL, then the
+** element corresponding to "key" is removed from the hash table.
+*/
+void * HashInsert(
+ Hash *pH, /* The hash table to insert into */
+ const void *pKey, /* The key */
+ int nKey, /* Number of bytes in the key */
+ void *data /* The data */
+){
+ int hraw; /* Raw hash value of the key */
+ int h; /* the hash of the key modulo hash table size */
+ HashElem *elem; /* Used to loop thru the element list */
+ HashElem *new_elem; /* New element added to the pH */
+
+ assert( pH!=0 );
+ hraw = binHash(pKey, nKey);
+ assert( (pH->htsize & (pH->htsize-1))==0 );
+ h = hraw & (pH->htsize-1);
+ elem = findElementGivenHash(pH,pKey,nKey,h);
+ if( elem ){
+ void *old_data = elem->data;
+ if( data==0 ){
+ removeElementGivenHash(pH,elem,h);
+ }else{
+ elem->data = data;
+ }
+ return old_data;
+ }
+ if( data==0 ) return 0;
+ new_elem = (HashElem*)pH->xMalloc( sizeof(HashElem) );
+ if( new_elem==0 ) return data;
+ if( pH->copyKey && pKey!=0 ){
+ new_elem->pKey = pH->xMalloc( nKey );
+ if( new_elem->pKey==0 ){
+ pH->xFree(new_elem);
+ return data;
+ }
+ memcpy((void*)new_elem->pKey, pKey, nKey);
+ }else{
+ new_elem->pKey = (void*)pKey;
+ }
+ new_elem->nKey = nKey;
+ pH->count++;
+ if( pH->htsize==0 ){
+ rehash(pH,8);
+ if( pH->htsize==0 ){
+ pH->count = 0;
+ pH->xFree(new_elem);
+ return data;
+ }
+ }
+ if( pH->count > pH->htsize ){
+ rehash(pH,pH->htsize*2);
+ }
+ assert( pH->htsize>0 );
+ assert( (pH->htsize & (pH->htsize-1))==0 );
+ h = hraw & (pH->htsize-1);
+ insertElement(pH, &pH->ht[h], new_elem);
+ new_elem->data = data;
+ return 0;
+}
diff --git a/src/mod/endpoints/mod_rtmp/libamf/src/hash.h b/src/mod/endpoints/mod_rtmp/libamf/src/hash.h
new file mode 100644
index 0000000000..18ea2f88bf
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/src/hash.h
@@ -0,0 +1,107 @@
+#ifndef _HASH_H_
+#define _HASH_H_
+
+/* Forward declarations of structures. */
+typedef struct Hash Hash;
+typedef struct HashElem HashElem;
+
+/* A complete hash table is an instance of the following structure.
+** The internals of this structure are intended to be opaque -- client
+** code should not attempt to access or modify the fields of this structure
+** directly. Change this structure only by using the routines below.
+** However, many of the "procedures" and "functions" for modifying and
+** accessing this structure are really macros, so we can't really make
+** this structure opaque.
+*/
+struct Hash {
+ char copyKey; /* True if copy of key made on insert */
+ int count; /* Number of entries in this table */
+ HashElem *first; /* The first element of the array */
+ void *(*xMalloc)(size_t); /* malloc() function to use */
+ void (*xFree)(void *); /* free() function to use */
+ int htsize; /* Number of buckets in the hash table */
+ struct _ht { /* the hash table */
+ int count; /* Number of entries with this hash */
+ HashElem *chain; /* Pointer to first entry with this hash */
+ } *ht;
+};
+
+/* Each element in the hash table is an instance of the following
+** structure. All elements are stored on a single doubly-linked list.
+**
+** Again, this structure is intended to be opaque, but it can't really
+** be opaque because it is used by macros.
+*/
+struct HashElem {
+ HashElem *next, *prev; /* Next and previous elements in the table */
+ void *data; /* Data associated with this element */
+ void *pKey; int nKey; /* Key associated with this element */
+};
+
+/*
+** Access routines. To delete, insert a NULL pointer.
+*/
+Hash * HashCreate(char copyKey);
+Hash * HashCreateAlloc(char copyKey, void *(*xMalloc)(size_t), void (*xFree)(void *));
+
+void HashFree(Hash*);
+
+void HashInit(Hash*, char copyKey, void *(*xMalloc)(size_t), void (*xFree)(void *));
+void * HashInsert(Hash*, const void *pKey, int nKey, void *pData);
+void * HashFind(const Hash*, const void *pKey, int nKey);
+void HashClear(Hash*);
+
+void * HashInsertSz(Hash*, const char *pKey, void *pData);
+void * HashFindSz(const Hash*, const char *pKey);
+
+/*
+ Element deletion macro
+*/
+#define HashDelete(H, K, N) (HashInsert(H, K, N, 0))
+
+/*
+** Macros for looping over all elements of a hash table. The idiom is
+** like this:
+**
+** Hash h;
+** HashElem *p;
+** ...
+** for(p=HashFirst(&h); p; p=HashNext(p)){
+** SomeStructure *pData = HashData(p);
+** // do something with pData
+** }
+*/
+#define HashFirst(H) ((H)->first)
+#define HashNext(E) ((E)->next)
+#define HashData(E) ((E)->data)
+#define HashKey(E) ((E)->pKey)
+#define HashKeysize(E) ((E)->nKey)
+
+/*
+** Number of entries in a hash table
+*/
+#define HashCount(H) ((H)->count)
+
+
+/*
+ more macros
+*/
+typedef struct Hash* hash_table;
+typedef struct HashElem* hash_elem;
+
+#define hash_create() (HashCreate(1))
+#define hash_insert(H, K, V) (HashInsertSz(H, K, V))
+#define hash_find(H, K) (HashFindSz(H, K))
+#define hash_delete(H, K) (HashInsertSz(H, K, 0))
+#define hash_clear(H) (HashClear(H))
+#define hash_free(H) (HashFree(H))
+
+#define hash_first(H) ((H)->first)
+#define hash_next(E) ((E)->next)
+#define hash_data(E) ((E)->data)
+#define hash_key(E) ((E)->pKey)
+#define hash_keysize(E) ((E)->nKey)
+
+#define hash_count(H) ((H)->count)
+
+#endif /* _HASH_H_ */
diff --git a/src/mod/endpoints/mod_rtmp/libamf/src/io.c b/src/mod/endpoints/mod_rtmp/libamf/src/io.c
new file mode 100644
index 0000000000..9b04631429
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/src/io.c
@@ -0,0 +1,44 @@
+#include
+#include
+
+#include "io.h"
+
+/* callback function to mimic fread using a memory buffer */
+size_t buffer_read(void * out_buffer, size_t size, void * user_data) {
+ buffer_context * ctxt = (buffer_context *)user_data;
+ if (ctxt->current_address >= ctxt->start_address &&
+ ctxt->current_address + size <= ctxt->start_address + ctxt->buffer_size) {
+
+ memcpy(out_buffer, ctxt->current_address, size);
+ ctxt->current_address += size;
+ return size;
+ }
+ else {
+ return 0;
+ }
+}
+
+/* callback function to mimic fwrite using a memory buffer */
+size_t buffer_write(const void * in_buffer, size_t size, void * user_data) {
+ buffer_context * ctxt = (buffer_context *)user_data;
+ if (ctxt->current_address >= ctxt->start_address &&
+ ctxt->current_address + size <= ctxt->start_address + ctxt->buffer_size) {
+
+ memcpy(ctxt->current_address, in_buffer, size);
+ ctxt->current_address += size;
+ return size;
+ }
+ else {
+ return 0;
+ }
+}
+
+/* callback function to read data from a file stream */
+size_t file_read(void * out_buffer, size_t size, void * user_data) {
+ return fread(out_buffer, sizeof(uint8_t), size, (FILE *)user_data);
+}
+
+/* callback function to write data to a file stream */
+size_t file_write(const void * in_buffer, size_t size, void * user_data) {
+ return fwrite(in_buffer, sizeof(uint8_t), size, (FILE *)user_data);
+}
diff --git a/src/mod/endpoints/mod_rtmp/libamf/src/io.h b/src/mod/endpoints/mod_rtmp/libamf/src/io.h
new file mode 100644
index 0000000000..5d284e5026
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/src/io.h
@@ -0,0 +1,33 @@
+#ifndef __IO_H__
+#define __IO_H__
+
+#include "amf.h"
+
+/* structure used to mimic a stream with a memory buffer */
+typedef struct __buffer_context {
+ uint8_t * start_address;
+ uint8_t * current_address;
+ size_t buffer_size;
+} buffer_context;
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* callback function to mimic fread using a memory buffer */
+size_t buffer_read(void * out_buffer, size_t size, void * user_data);
+
+/* callback function to mimic fwrite using a memory buffer */
+size_t buffer_write(const void * in_buffer, size_t size, void * user_data);
+
+/* callback function to read data from a file stream */
+size_t file_read(void * out_buffer, size_t size, void * user_data);
+
+/* callback function to write data to a file stream */
+size_t file_write(const void * in_buffer, size_t size, void * user_data);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __IO_H__ */
diff --git a/src/mod/endpoints/mod_rtmp/libamf/src/ptrarray.c b/src/mod/endpoints/mod_rtmp/libamf/src/ptrarray.c
new file mode 100644
index 0000000000..ac73f663bd
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/src/ptrarray.c
@@ -0,0 +1,172 @@
+#include "ptrarray.h"
+#include
+
+/**
+ Customize default capacity
+*/
+#ifndef PTRARRAY_DEFAULT_CAPACITY
+# define PTRARRAY_DEFAULT_CAPACITY 5
+#endif
+
+/**
+ Enable array security checking
+*/
+/* #define PTRARRAY_SECURITY_CHECKS */
+
+/**
+ Customize memory allocation routines
+*/
+#ifndef PTRARRAY_MALLOC
+# define PTRARRAY_MALLOC malloc
+#endif
+
+#ifndef PTRARRAY_FREE
+# define PTRARRAY_FREE free
+#endif
+
+#ifndef PTRARRAY_REALLOC
+# define PTRARRAY_REALLOC realloc
+#endif
+
+/**
+ This function doubles the current capacity
+ of the given dynamic array.
+ */
+static int ptrarray_grow(ptrarray * array) {
+ void * new_mem;
+ size_t new_capacity;
+#ifdef PTRARRAY_SECURITY_CHECKS
+ if (array == NULL)
+ return;
+#endif
+ new_capacity = array->capacity * 2;
+ new_mem = PTRARRAY_REALLOC(array->data, new_capacity * sizeof(void*));
+ if (new_mem != NULL) {
+ array->data = new_mem;
+ array->capacity = new_capacity;
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
+void ptrarray_init(ptrarray * array, size_t initial_capacity, data_free_proc free_proc) {
+ if (free_proc == NULL) {
+ free_proc = PTRARRAY_FREE;
+ }
+ array->data_free = free_proc;
+ if (initial_capacity <= 0) {
+ initial_capacity = PTRARRAY_DEFAULT_CAPACITY;
+ }
+ array->capacity = initial_capacity;
+ array->data = PTRARRAY_MALLOC(initial_capacity * sizeof(void*));
+ array->size = 0;
+}
+
+/*size_t ptrarray_capacity(ptrarray * array) {
+ return array->capacity;
+}*/
+
+/*size_t ptrarray_size(ptrarray * array) {
+ return array->size;
+}*/
+
+/*int ptrarray_empty(ptrarray * array) {
+ return !((array)->size);
+}*/
+
+void ptrarray_reserve(ptrarray * array, size_t new_capacity) {
+ void * new_mem;
+#ifdef PTRARRAY_SECURITY_CHECKS
+ if (array == NULL)
+ return;
+#endif
+ if (new_capacity > array->capacity) {
+ new_mem = PTRARRAY_REALLOC(array->data, new_capacity * sizeof(void*));
+ if (new_mem != NULL) {
+ array->data = new_mem;
+ array->capacity = new_capacity;
+ }
+ }
+ else if (new_capacity < array->capacity) {
+ new_capacity = (new_capacity < array->size) ? array->size : new_capacity;
+ new_capacity = (new_capacity < PTRARRAY_DEFAULT_CAPACITY) ? PTRARRAY_DEFAULT_CAPACITY : new_capacity;
+ new_mem = PTRARRAY_REALLOC(array->data, new_capacity * sizeof(void*));
+ if (new_mem != NULL) {
+ array->data = new_mem;
+ array->capacity = new_capacity;
+ }
+ }
+}
+
+void ptrarray_compact(ptrarray * array) {
+ size_t new_capacity;
+ void * new_mem;
+#ifdef PTRARRAY_SECURITY_CHECKS
+ if (array == NULL)
+ return;
+#endif
+ new_capacity = (array->size < PTRARRAY_DEFAULT_CAPACITY) ? PTRARRAY_DEFAULT_CAPACITY : array->size;
+ new_mem = PTRARRAY_REALLOC(array->data, new_capacity * sizeof(void*));
+ if (new_mem != NULL) {
+ array->data = new_mem;
+ array->capacity = new_capacity;
+ }
+}
+
+void ptrarray_push(ptrarray * array, void * data) {
+#ifdef PTRARRAY_SECURITY_CHECKS
+ if (array == NULL)
+ return;
+#endif
+ if (array->size == array->capacity) {
+ if (!ptrarray_grow(array)) {
+ return;
+ }
+ }
+ array->data[array->size++] = data;
+}
+
+void * ptrarray_pop(ptrarray * array) {
+#ifdef PTRARRAY_SECURITY_CHECKS
+ if (array == NULL)
+ return NULL;
+#endif
+ if (ptrarray_empty(array)) {
+ return NULL;
+ }
+ return array->data[array->size--];
+}
+
+void ptrarray_insert(ptrarray * array, size_t position, void * data) {
+ void ** src_pos;
+
+#ifdef PTRARRAY_SECURITY_CHECKS
+ if (array == NULL)
+ return;
+#endif
+ if (array->size > position) {
+ if (array->size == array->capacity) {
+ if (!ptrarray_grow(array)) {
+ return;
+ }
+ }
+ src_pos = array->data + position;
+ memmove(src_pos + 1, src_pos, array->size - position);
+ *src_pos = data;
+ }
+}
+
+void ptrarray_prepend(ptrarray * array, void * data);
+void * ptrarray_replace(ptrarray * array, size_t position, void * data);
+
+void * ptrarray_remove(ptrarray * array, size_t position);
+void ptrarray_clear(ptrarray * array);
+
+void * ptrarray_first(ptrarray * array);
+void * ptrarray_last(ptrarray * array);
+void * ptrarray_get(size_t position);
+
+void ptrarray_destroy(ptrarray * array) {
+}
diff --git a/src/mod/endpoints/mod_rtmp/libamf/src/ptrarray.h b/src/mod/endpoints/mod_rtmp/libamf/src/ptrarray.h
new file mode 100644
index 0000000000..d4eb2990a3
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/src/ptrarray.h
@@ -0,0 +1,52 @@
+#ifndef __PTRARRAY_H__
+#define __PTRARRAY_H__
+
+#include
+
+typedef void (*data_free_proc)(void *);
+
+typedef struct __ptrarray {
+ size_t capacity;
+ size_t size;
+ void ** data;
+ data_free_proc data_free;
+} ptrarray;
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+void ptrarray_init(ptrarray * array, size_t initial_capacity, data_free_proc free_proc);
+
+/*size_t ptrarray_capacity(ptrarray * array);*/
+#define ptrarray_capacity(a) ((a)->capacity)
+
+/*size_t ptrarray_size(ptrarray * array);*/
+#define ptrarray_size(a) ((a)->size)
+
+/*int ptrarray_empty(ptrarray * array);*/
+#define ptrarray_empty(a) (!((a)->size))
+
+void ptrarray_reserve(ptrarray * array, size_t new_capacity);
+void ptrarray_compact(ptrarray * array);
+
+void ptrarray_push(ptrarray * array, void * data);
+void * ptrarray_pop(ptrarray * array);
+void ptrarray_insert(ptrarray * array, size_t position, void * data);
+void ptrarray_prepend(ptrarray * array, void * data);
+void * ptrarray_replace(ptrarray * array, size_t position, void * data);
+
+void * ptrarray_remove(ptrarray * array, size_t position);
+void ptrarray_clear(ptrarray * array);
+
+void * ptrarray_first(ptrarray * array);
+void * ptrarray_last(ptrarray * array);
+void * ptrarray_get(size_t position);
+
+void ptrarray_destroy(ptrarray * array);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __PTRARRAY_H__ */
diff --git a/src/mod/endpoints/mod_rtmp/libamf/src/types.c b/src/mod/endpoints/mod_rtmp/libamf/src/types.c
new file mode 100644
index 0000000000..006571aa9c
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/src/types.c
@@ -0,0 +1,48 @@
+/*
+ $Id: types.c 1 2009-11-13 00:04:24Z noirotm $
+
+ FLV Metadata updater
+
+ Copyright (C) 2007, 2008 Marc Noirot
+
+ This file is part of FLVMeta.
+
+ FLVMeta is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ FLVMeta is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with FLVMeta; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "types.h"
+
+#ifndef WORDS_BIGENDIAN
+
+/* swap 64 bits doubles */
+typedef union __convert_u {
+ uint64_t i;
+ number64_t f;
+} convert_u;
+
+number64_t swap_number64(number64_t n) {
+ convert_u c;
+ c.f = n;
+ c.i = (((c.i & 0x00000000000000FFULL) << 56) |
+ ((c.i & 0x000000000000FF00ULL) << 40) |
+ ((c.i & 0x0000000000FF0000ULL) << 24) |
+ ((c.i & 0x00000000FF000000ULL) << 8) |
+ ((c.i & 0x000000FF00000000ULL) >> 8) |
+ ((c.i & 0x0000FF0000000000ULL) >> 24) |
+ ((c.i & 0x00FF000000000000ULL) >> 40) |
+ ((c.i & 0xFF00000000000000ULL) >> 56));
+ return c.f;
+}
+#endif /* !WORDS_BIGENDIAN */
diff --git a/src/mod/endpoints/mod_rtmp/libamf/src/types.h b/src/mod/endpoints/mod_rtmp/libamf/src/types.h
new file mode 100644
index 0000000000..535ae2e18e
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/src/types.h
@@ -0,0 +1,60 @@
+/*
+ $Id: types.h 1 2009-11-13 00:04:24Z noirotm $
+
+ FLV Metadata updater
+
+ Copyright (C) 2007, 2008 Marc Noirot
+
+ This file is part of FLVMeta.
+
+ FLVMeta is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ FLVMeta is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with FLVMeta; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+#ifndef __TYPES_H__
+#define __TYPES_H__
+
+#include "amf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#ifdef WORDS_BIGENDIAN
+
+# define swap_uint16(x) (x)
+# define swap_int16(x) (x)
+# define swap_uint32(x) (x)
+# define swap_number64(x) (x)
+
+#else /* WORDS_BIGENDIAN */
+/* swap 16 bits integers */
+# define swap_uint16(x) ((((x) & 0x00FFU) << 8) | (((x) & 0xFF00U) >> 8))
+# define swap_sint16(x) ((((x) & 0x00FF) << 8) | (((x) & 0xFF00) >> 8))
+
+/* swap 32 bits integers */
+# define swap_uint32(x) ((((x) & 0x000000FFU) << 24) | \
+ (((x) & 0x0000FF00U) << 8) | \
+ (((x) & 0x00FF0000U) >> 8) | \
+ (((x) & 0xFF000000U) >> 24))
+
+/* swap 64 bits doubles */
+number64_t swap_number64(number64_t);
+
+#endif /* WORDS_BIGENDIAN */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __TYPES_H__ */
diff --git a/src/mod/endpoints/mod_rtmp/libamf/tests/CMakeLists.txt b/src/mod/endpoints/mod_rtmp/libamf/tests/CMakeLists.txt
new file mode 100644
index 0000000000..95e3b6674b
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/tests/CMakeLists.txt
@@ -0,0 +1,5 @@
+include_directories(${CMAKE_SOURCE_DIR}/src)
+
+add_executable(amf0_demo amf0_demo.c)
+add_dependencies(amf0_demo amf)
+
diff --git a/src/mod/endpoints/mod_rtmp/libamf/tests/amf0 b/src/mod/endpoints/mod_rtmp/libamf/tests/amf0
new file mode 100755
index 0000000000..ce0e5c3fdc
Binary files /dev/null and b/src/mod/endpoints/mod_rtmp/libamf/tests/amf0 differ
diff --git a/src/mod/endpoints/mod_rtmp/libamf/tests/amf0_demo.c b/src/mod/endpoints/mod_rtmp/libamf/tests/amf0_demo.c
new file mode 100644
index 0000000000..06af985103
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/libamf/tests/amf0_demo.c
@@ -0,0 +1,17 @@
+#include
+
+#include "amf0.h"
+#include "io.h"
+#include "types.h"
+
+int main() {
+ amf0_data * test;
+
+ test = amf0_object_new();
+ amf0_object_add(test, "toto", amf0_str("une chaine de caracteres"));
+ amf0_object_add(test, "test_bool", amf0_boolean_new(1));
+
+ amf0_data_dump(stdout, test, 0);
+
+ amf0_data_free(test);
+}
diff --git a/src/mod/endpoints/mod_rtmp/mod_rtmp.c b/src/mod/endpoints/mod_rtmp/mod_rtmp.c
new file mode 100644
index 0000000000..35fe4bb885
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/mod_rtmp.c
@@ -0,0 +1,1827 @@
+/*
+ * mod_rtmp for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2011, Barracuda Networks Inc.
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mod_rtmp for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is Barracuda Networks Inc.
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Mathieu Rene
+ * Anthony Minessale II
+ *
+ * mod_rtmp.c -- RTMP Endpoint Module
+ *
+ */
+
+#define BEEN_PAID
+
+#ifdef BEEN_PAID
+/* Thanks to Barracuda Networks Inc. for sponsoring this work */
+#endif
+
+#include "mod_rtmp.h"
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_rtmp_load);
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_rtmp_shutdown);
+SWITCH_MODULE_DEFINITION(mod_rtmp, mod_rtmp_load, mod_rtmp_shutdown, NULL);
+
+static switch_status_t config_profile(rtmp_profile_t *profile, switch_bool_t reload);
+static switch_xml_config_item_t *get_instructions(rtmp_profile_t *profile);
+
+switch_state_handler_table_t rtmp_state_handlers = {
+ /*.on_init */ rtmp_on_init,
+ /*.on_routing */ rtmp_on_routing,
+ /*.on_execute */ rtmp_on_execute,
+ /*.on_hangup */ rtmp_on_hangup,
+ /*.on_exchange_media */ rtmp_on_exchange_media,
+ /*.on_soft_execute */ rtmp_on_soft_execute,
+ /*.on_consume_media */ NULL,
+ /*.on_hibernate */ NULL,
+ /*.on_reset */ NULL,
+ /*.on_park */ NULL,
+ /*.on_reporting */ NULL,
+ /*.on_destroy */ rtmp_on_destroy
+};
+
+switch_io_routines_t rtmp_io_routines = {
+ /*.outgoing_channel */ rtmp_outgoing_channel,
+ /*.read_frame */ rtmp_read_frame,
+ /*.write_frame */ rtmp_write_frame,
+ /*.kill_channel */ rtmp_kill_channel,
+ /*.send_dtmf */ rtmp_send_dtmf,
+ /*.receive_message */ rtmp_receive_message,
+ /*.receive_event */ rtmp_receive_event
+};
+
+struct mod_rtmp_globals rtmp_globals;
+
+static void rtmp_set_channel_variables(switch_core_session_t *session)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ rtmp_private_t *tech_pvt = switch_core_session_get_private(session);
+ rtmp_session_t *rsession = tech_pvt->rtmp_session;
+
+ switch_channel_set_variable(channel, "rtmp_profile", rsession->profile->name);
+ switch_channel_set_variable(channel, "rtmp_session", rsession->uuid);
+ switch_channel_set_variable(channel, "rtmp_flash_version", rsession->flashVer);
+ switch_channel_set_variable(channel, "rtmp_swf_url", rsession->swfUrl);
+ switch_channel_set_variable(channel, "rtmp_tc_url", rsession->tcUrl);
+ switch_channel_set_variable(channel, "rtmp_page_url", rsession->pageUrl);
+ switch_channel_set_variable(channel, "rtmp_remote_address", rsession->remote_address);
+ switch_channel_set_variable_printf(channel, "rtmp_remote_port", "%d", rsession->remote_port);
+}
+
+switch_status_t rtmp_tech_init(rtmp_private_t *tech_pvt, rtmp_session_t *rtmp_session, switch_core_session_t *session)
+{
+ switch_assert(rtmp_session && session && tech_pvt);
+
+ tech_pvt->read_frame.data = tech_pvt->databuf;
+ tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf);
+ switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+ switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+ switch_mutex_init(&tech_pvt->readbuf_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
+
+ switch_buffer_create_dynamic(&tech_pvt->readbuf, 512, 512, 1024000);
+ //switch_buffer_add_mutex(tech_pvt->readbuf, tech_pvt->readbuf_mutex);
+
+ switch_core_timer_init(&tech_pvt->timer, "soft", 20, (16000 / (1000 / 20)), switch_core_session_get_pool(session));
+
+ tech_pvt->session = session;
+ tech_pvt->rtmp_session = rtmp_session;
+ tech_pvt->channel = switch_core_session_get_channel(session);
+
+ /* Initialize read & write codecs */
+ if (switch_core_codec_init(&tech_pvt->read_codec, /* name */ "SPEEX",
+ /* fmtp */ NULL, /* rate */ 16000, /* ms */ 20, /* channels */ 1,
+ /* flags */ SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
+ /* codec settings */ NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't initialize read codec\n");
+
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (switch_core_codec_init(&tech_pvt->write_codec, /* name */ "SPEEX",
+ /* fmtp */ NULL, /* rate */ 16000, /* ms */ 20, /* channels */ 1,
+ /* flags */ SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE,
+ /* codec settings */ NULL, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't initialize write codec\n");
+
+ return SWITCH_STATUS_FALSE;
+ }
+
+ switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
+ switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
+
+ //static inline uint8_t rtmp_audio_codec(int channels, int bits, int rate, rtmp_audio_format_t format) {
+ tech_pvt->audio_codec = 0xB2; //rtmp_audio_codec(1, 16, 0 /* speex is always 8000 */, RTMP_AUDIO_SPEEX);
+
+ switch_core_session_set_private(session, tech_pvt);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+/*
+ State methods they get called when the state changes to the specific state
+ returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
+ so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
+*/
+switch_status_t rtmp_on_init(switch_core_session_t *session)
+{
+ switch_channel_t *channel;
+ rtmp_private_t *tech_pvt = NULL;
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ rtmp_notify_call_state(session);
+
+ switch_set_flag_locked(tech_pvt, TFLAG_IO);
+
+ /* Move channel's state machine to ROUTING. This means the call is trying
+ to get from the initial start where the call because, to the point
+ where a destination has been identified. If the channel is simply
+ left in the initial state, nothing will happen. */
+ switch_channel_set_state(channel, CS_ROUTING);
+
+
+ switch_mutex_lock(tech_pvt->rtmp_session->profile->mutex);
+ tech_pvt->rtmp_session->profile->calls++;
+ switch_mutex_unlock(tech_pvt->rtmp_session->profile->mutex);
+
+ switch_mutex_lock(tech_pvt->rtmp_session->count_mutex);
+ tech_pvt->rtmp_session->active_sessions++;
+ switch_mutex_unlock(tech_pvt->rtmp_session->count_mutex);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t rtmp_on_routing(switch_core_session_t *session)
+{
+ switch_channel_t *channel = NULL;
+ rtmp_private_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ rtmp_notify_call_state(session);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL ROUTING\n", switch_channel_get_name(channel));
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t rtmp_on_execute(switch_core_session_t *session)
+{
+
+ switch_channel_t *channel = NULL;
+ rtmp_private_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ rtmp_notify_call_state(session);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL EXECUTE\n", switch_channel_get_name(channel));
+
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t rtmp_on_destroy(switch_core_session_t *session)
+{
+ switch_channel_t *channel = NULL;
+ rtmp_private_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+
+ if (tech_pvt) {
+ if (switch_core_codec_ready(&tech_pvt->read_codec)) {
+ switch_core_codec_destroy(&tech_pvt->read_codec);
+ }
+
+ if (switch_core_codec_ready(&tech_pvt->write_codec)) {
+ switch_core_codec_destroy(&tech_pvt->write_codec);
+ }
+
+ switch_buffer_destroy(&tech_pvt->readbuf);
+ switch_core_timer_destroy(&tech_pvt->timer);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+switch_status_t rtmp_on_hangup(switch_core_session_t *session)
+{
+ switch_channel_t *channel = NULL;
+ rtmp_private_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch_clear_flag_locked(tech_pvt, TFLAG_IO);
+ //switch_thread_cond_signal(tech_pvt->cond);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel));
+
+ if (tech_pvt->rtmp_session->tech_pvt == tech_pvt) {
+ rtmp_private_t *other_tech_pvt = NULL;
+ const char *s;
+ if ((s = switch_channel_get_variable(channel, RTMP_ATTACH_ON_HANGUP_VARIABLE)) && !zstr(s)) {
+ other_tech_pvt = rtmp_locate_private(tech_pvt->rtmp_session, s);
+ }
+ rtmp_attach_private(tech_pvt->rtmp_session, other_tech_pvt);
+ }
+
+ rtmp_notify_call_state(session);
+ rtmp_send_onhangup(session);
+
+ switch_mutex_lock(tech_pvt->rtmp_session->count_mutex);
+ tech_pvt->rtmp_session->active_sessions--;
+ switch_mutex_unlock(tech_pvt->rtmp_session->count_mutex);
+
+ switch_core_hash_delete_wrlock(tech_pvt->rtmp_session->session_hash, switch_core_session_get_uuid(session), tech_pvt->rtmp_session->session_rwlock);
+
+ switch_mutex_lock(tech_pvt->rtmp_session->profile->mutex);
+ tech_pvt->rtmp_session->profile->calls--;
+ if (tech_pvt->rtmp_session->profile->calls < 0) {
+ tech_pvt->rtmp_session->profile->calls = 0;
+ }
+ switch_mutex_unlock(tech_pvt->rtmp_session->profile->mutex);
+
+#ifndef RTMP_DONT_HOLD
+ if (switch_channel_test_flag(channel, CF_HOLD)) {
+ switch_channel_mark_hold(channel, SWITCH_FALSE);
+ switch_ivr_unhold(session);
+ }
+#endif
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+switch_status_t rtmp_kill_channel(switch_core_session_t *session, int sig)
+{
+ switch_channel_t *channel = NULL;
+ rtmp_private_t *tech_pvt = NULL;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch (sig) {
+ case SWITCH_SIG_KILL:
+ switch_clear_flag_locked(tech_pvt, TFLAG_IO);
+
+ break;
+ case SWITCH_SIG_BREAK:
+ switch_set_flag_locked(tech_pvt, TFLAG_BREAK);
+ break;
+ default:
+ break;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t rtmp_on_exchange_media(switch_core_session_t *session)
+{
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "CHANNEL LOOPBACK\n");
+ rtmp_notify_call_state(session);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t rtmp_on_soft_execute(switch_core_session_t *session)
+{
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "CHANNEL TRANSMIT\n");
+ rtmp_notify_call_state(session);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t rtmp_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
+{
+ rtmp_private_t *tech_pvt = switch_core_session_get_private(session);
+ switch_assert(tech_pvt != NULL);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t rtmp_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
+{
+ switch_channel_t *channel = NULL;
+ rtmp_private_t *tech_pvt = NULL;
+ //switch_time_t started = switch_time_now();
+ //unsigned int elapsed;
+ switch_byte_t *data;
+ uint16_t len;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ if (tech_pvt->rtmp_session->state >= RS_DESTROY) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (switch_test_flag(tech_pvt, TFLAG_DETACHED)) {
+ switch_core_timer_next(&tech_pvt->timer);
+ goto cng;
+ }
+
+ tech_pvt->read_frame.flags = SFF_NONE;
+ tech_pvt->read_frame.codec = &tech_pvt->read_codec;
+
+ switch_core_timer_next(&tech_pvt->timer);
+
+ if (switch_buffer_inuse(tech_pvt->readbuf) < 2) {
+ /* Not enough data in buffer, return CNG frame */
+ goto cng;
+ } else {
+ switch_mutex_lock(tech_pvt->readbuf_mutex);
+ switch_buffer_peek(tech_pvt->readbuf, &len, 2);
+ if (switch_buffer_inuse(tech_pvt->readbuf) >= len) {
+ if (len == 0) {
+ switch_mutex_unlock(tech_pvt->readbuf_mutex);
+ goto cng;
+ } else {
+ uint8_t codec;
+
+ if (tech_pvt->read_frame.buflen < len) {
+ switch_mutex_unlock(tech_pvt->readbuf_mutex);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Packet of size %u is bigger that the buffer length %u.\n",
+ len, tech_pvt->read_frame.buflen);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ switch_buffer_toss(tech_pvt->readbuf, 2);
+ switch_buffer_read(tech_pvt->readbuf, &codec, 1);
+ switch_buffer_read(tech_pvt->readbuf, tech_pvt->read_frame.data, len-1);
+ tech_pvt->read_frame.datalen = len-1;
+
+ if (codec != tech_pvt->audio_codec) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received codec 0x%x instead of 0x%x\n", codec, tech_pvt->audio_codec);
+ switch_mutex_unlock(tech_pvt->readbuf_mutex);
+ goto cng;
+ }
+ }
+ }
+ switch_mutex_unlock(tech_pvt->readbuf_mutex);
+ }
+
+ *frame = &tech_pvt->read_frame;
+
+ return SWITCH_STATUS_SUCCESS;
+
+cng:
+ data = (switch_byte_t *) tech_pvt->read_frame.data;
+ data[0] = 65;
+ data[1] = 0;
+ tech_pvt->read_frame.datalen = 2;
+ tech_pvt->read_frame.flags = SFF_CNG;
+ tech_pvt->read_frame.codec = &tech_pvt->read_codec;
+
+ switch_core_timer_sync(&tech_pvt->timer);
+
+ *frame = &tech_pvt->read_frame;
+
+ return SWITCH_STATUS_SUCCESS;
+
+}
+
+switch_status_t rtmp_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
+{
+ switch_channel_t *channel = NULL;
+ rtmp_private_t *tech_pvt = NULL;
+ //switch_frame_t *pframe;
+ unsigned char buf[AMF_MAX_SIZE];
+ switch_time_t ts;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+
+ if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "TFLAG_IO not set\n");
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (switch_test_flag(tech_pvt, TFLAG_DETACHED) || !switch_test_flag(tech_pvt->rtmp_session, SFLAG_AUDIO)) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (!tech_pvt->rtmp_session || !tech_pvt->audio_codec || !tech_pvt->write_channel) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing mandatory value\n");
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (tech_pvt->rtmp_session->state >= RS_DESTROY) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (frame->datalen+1 > frame->buflen) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Datalen too big\n");
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (frame->flags & SFF_CNG) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ /* Build message */
+ buf[0] = tech_pvt->audio_codec;
+ memcpy(buf+1, frame->data, frame->datalen);
+
+ /* Send it down the socket */
+ if (!tech_pvt->stream_start_ts) {
+ tech_pvt->stream_start_ts = switch_micro_time_now() / 1000;
+ ts = 0;
+ } else {
+ ts = (switch_micro_time_now() / 1000) - tech_pvt->stream_start_ts;
+ }
+
+ rtmp_send_message(tech_pvt->rtmp_session, RTMP_DEFAULT_STREAM_AUDIO, ts, RTMP_TYPE_AUDIO, tech_pvt->rtmp_session->media_streamid, buf, frame->datalen + 1, 0);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+switch_status_t rtmp_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
+{
+ switch_channel_t *channel;
+ rtmp_private_t *tech_pvt;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ tech_pvt = (rtmp_private_t *) switch_core_session_get_private(session);
+ assert(tech_pvt != NULL);
+
+ switch (msg->message_id) {
+ case SWITCH_MESSAGE_INDICATE_ANSWER:
+ switch_channel_mark_answered(channel);
+ rtmp_notify_call_state(session);
+ break;
+ case SWITCH_MESSAGE_INDICATE_RINGING:
+ switch_channel_mark_ring_ready(channel);
+ rtmp_notify_call_state(session);
+ break;
+ case SWITCH_MESSAGE_INDICATE_PROGRESS:
+ switch_channel_mark_pre_answered(channel);
+ rtmp_notify_call_state(session);
+ break;
+ case SWITCH_MESSAGE_INDICATE_HOLD:
+ case SWITCH_MESSAGE_INDICATE_UNHOLD:
+ rtmp_notify_call_state(session);
+ break;
+
+ case SWITCH_MESSAGE_INDICATE_DISPLAY:
+ {
+ const char *name = msg->string_array_arg[0], *number = msg->string_array_arg[1];
+ char *arg = NULL;
+ char *argv[2] = { 0 };
+ int argc;
+
+ if (zstr(name) && !zstr(msg->string_arg)) {
+ arg = strdup(msg->string_arg);
+ switch_assert(arg);
+
+ argc = switch_separate_string(arg, '|', argv, (sizeof(argv) / sizeof(argv[0])));
+ name = argv[0];
+ number = argv[1];
+
+ }
+
+ if (!zstr(name)) {
+ if (zstr(number)) {
+ switch_caller_profile_t *caller_profile = switch_channel_get_caller_profile(channel);
+ number = caller_profile->destination_number;
+ }
+
+ if (zstr(tech_pvt->display_callee_id_name) || strcmp(tech_pvt->display_callee_id_name, name)) {
+ tech_pvt->display_callee_id_name = switch_core_session_strdup(session, name);
+ }
+
+ if (zstr(tech_pvt->display_callee_id_number) || strcmp(tech_pvt->display_callee_id_number, number)) {
+ tech_pvt->display_callee_id_number = switch_core_session_strdup(session, number);
+ }
+
+ rtmp_send_display_update(session);
+ }
+
+ switch_safe_free(arg);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines
+ that allocate memory or you will have 1 channel with memory allocated from another channel's pool!
+*/
+switch_call_cause_t rtmp_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
+ switch_caller_profile_t *outbound_profile,
+ switch_core_session_t **newsession, switch_memory_pool_t **inpool, switch_originate_flag_t flags,
+ switch_call_cause_t *cancel_cause)
+{
+ rtmp_private_t *tech_pvt;
+ switch_caller_profile_t *caller_profile;
+ switch_channel_t *channel;
+ switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ rtmp_session_t *rsession = NULL;
+ switch_memory_pool_t *pool;
+ char *destination = NULL, *auth, *user, *domain;
+ *newsession = NULL;
+
+ if (zstr(outbound_profile->destination_number)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No destination\n");
+ goto fail;
+ }
+
+ destination = strdup(outbound_profile->destination_number);
+
+ if ((auth = strchr(destination, '/'))) {
+ *auth++ = '\0';
+ }
+
+ /* Locate the user to be called */
+ if (!(rsession = rtmp_session_locate(destination))) {
+ cause = SWITCH_CAUSE_NO_ROUTE_DESTINATION;
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No such session id: %s\n", outbound_profile->destination_number);
+ goto fail;
+ }
+
+ if (!(*newsession = switch_core_session_request(rtmp_globals.rtmp_endpoint_interface, flags, SWITCH_CALL_DIRECTION_OUTBOUND, inpool))) {
+ goto fail;
+ }
+
+ pool = switch_core_session_get_pool(*newsession);
+
+ channel = switch_core_session_get_channel(*newsession);
+ switch_channel_set_name(channel, switch_core_session_sprintf(*newsession, "rtmp/%s/%s", rsession->profile->name, outbound_profile->destination_number));
+
+ caller_profile = switch_caller_profile_dup(pool, outbound_profile);
+ switch_channel_set_caller_profile(channel, caller_profile);
+
+ tech_pvt = switch_core_alloc(pool, sizeof(rtmp_private_t));
+ tech_pvt->rtmp_session = rsession;
+ tech_pvt->write_channel = RTMP_DEFAULT_STREAM_AUDIO;
+ tech_pvt->session = *newsession;
+ tech_pvt->caller_profile = caller_profile;
+ switch_core_session_add_stream(*newsession, NULL);
+
+ if (rtmp_tech_init(tech_pvt, rsession, *newsession) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*newsession), SWITCH_LOG_ERROR, "tech_init failed\n");
+ cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ goto fail;
+ }
+
+ if (!zstr(auth)) {
+ tech_pvt->auth = switch_core_session_strdup(*newsession, auth);
+ switch_split_user_domain(auth, &user, &domain);
+ tech_pvt->auth_user = switch_core_session_strdup(*newsession, user);
+ tech_pvt->auth_domain = switch_core_session_strdup(*newsession, domain);
+ }
+
+ /*switch_channel_mark_pre_answered(channel);*/
+
+ switch_channel_ring_ready(channel);
+ rtmp_send_incoming_call(*newsession);
+
+ switch_channel_set_state(channel, CS_INIT);
+ switch_set_flag_locked(tech_pvt, TFLAG_IO);
+
+ rtmp_set_channel_variables(*newsession);
+
+ switch_core_hash_insert_wrlock(rsession->session_hash, switch_core_session_get_uuid(*newsession), tech_pvt, rsession->session_rwlock);
+
+ if (switch_core_session_thread_launch(tech_pvt->session) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't spawn thread\n");
+ goto fail;
+ }
+
+ if (rsession) {
+ rtmp_session_rwunlock(rsession);
+ }
+
+ return SWITCH_CAUSE_SUCCESS;
+
+fail:
+ if (*newsession) {
+ switch_core_session_destroy(newsession);
+ }
+ if (rsession) {
+ rtmp_session_rwunlock(rsession);
+ }
+ switch_safe_free(destination);
+ return cause;
+
+}
+
+switch_status_t rtmp_receive_event(switch_core_session_t *session, switch_event_t *event)
+{
+ rtmp_private_t *tech_pvt = switch_core_session_get_private(session);
+ switch_assert(tech_pvt != NULL);
+
+ /* Deliver the event as a custom message to the target rtmp session */
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Session", switch_core_session_get_uuid(session));
+
+ rtmp_send_event(tech_pvt->rtmp_session, event);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+rtmp_profile_t *rtmp_profile_locate(const char *name)
+{
+ rtmp_profile_t *profile = switch_core_hash_find_rdlock(rtmp_globals.profile_hash, name, rtmp_globals.profile_rwlock);
+
+ if (profile) {
+ if (switch_thread_rwlock_tryrdlock(profile->rwlock) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Profile %s is locked\n", name);
+ profile = NULL;
+ }
+ }
+
+ return profile;
+}
+
+void rtmp_profile_release(rtmp_profile_t *profile)
+{
+ switch_thread_rwlock_unlock(profile->rwlock);
+}
+
+rtmp_session_t *rtmp_session_locate(const char *uuid)
+{
+ rtmp_session_t *rsession = switch_core_hash_find_rdlock(rtmp_globals.session_hash, uuid, rtmp_globals.session_rwlock);
+
+ if (!rsession || rsession->state == RS_DESTROY) {
+ return NULL;
+ }
+
+ switch_thread_rwlock_rdlock(rsession->rwlock);
+
+ return rsession;
+}
+
+void rtmp_session_rwunlock(rtmp_session_t *rsession)
+{
+ switch_thread_rwlock_unlock(rsession->rwlock);
+}
+
+void rtmp_event_fill(rtmp_session_t *rsession, switch_event_t *event)
+{
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTMP-Session-ID", rsession->uuid);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTMP-Flash-Version", rsession->flashVer);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTMP-SWF-URL", rsession->swfUrl);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTMP-TC-URL", rsession->tcUrl);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTMP-Page-URL", rsession->pageUrl);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTMP-Profile", rsession->profile->name);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Network-Port", "%d", rsession->remote_port);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Network-IP", rsession->remote_address);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "RTMP-Profile", rsession->profile->name);
+}
+
+switch_status_t rtmp_session_request(rtmp_profile_t *profile, rtmp_session_t **newsession)
+{
+ switch_memory_pool_t *pool;
+ switch_uuid_t uuid;
+ switch_core_new_memory_pool(&pool);
+ *newsession = switch_core_alloc(pool, sizeof(rtmp_session_t));
+
+ (*newsession)->pool = pool;
+ (*newsession)->profile = profile;
+ (*newsession)->in_chunksize = (*newsession)->out_chunksize = RTMP_DEFAULT_CHUNKSIZE;
+ (*newsession)->recv_ack_window = RTMP_DEFAULT_ACK_WINDOW;
+ (*newsession)->next_streamid = 1;
+
+ switch_uuid_get(&uuid);
+ switch_uuid_format((*newsession)->uuid, &uuid);
+ switch_mutex_init(&((*newsession)->socket_mutex), SWITCH_MUTEX_NESTED, pool);
+ switch_mutex_init(&((*newsession)->count_mutex), SWITCH_MUTEX_NESTED, pool);
+ switch_thread_rwlock_create(&((*newsession)->rwlock), pool);
+ switch_thread_rwlock_create(&((*newsession)->account_rwlock), pool);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "New RTMP session [%s]\n", (*newsession)->uuid);
+ switch_core_hash_insert_wrlock(rtmp_globals.session_hash, (*newsession)->uuid, *newsession, rtmp_globals.session_rwlock);
+ switch_core_hash_insert_wrlock(profile->session_hash, (*newsession)->uuid, *newsession, profile->session_rwlock);
+
+ switch_core_hash_init(&(*newsession)->session_hash, pool);
+ switch_thread_rwlock_create(&(*newsession)->session_rwlock, pool);
+
+#ifdef RTMP_DEBUG_IO
+ {
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "/tmp/rtmp-%s-in.txt", (*newsession)->uuid);
+ (*newsession)->io_debug_in = fopen(buf, "w");
+ snprintf(buf, sizeof(buf), "/tmp/rtmp-%s-out.txt", (*newsession)->uuid);
+ (*newsession)->io_debug_out = fopen(buf, "w");
+ }
+#endif
+
+ switch_mutex_lock(profile->mutex);
+ profile->clients++;
+ switch_mutex_unlock(profile->mutex);
+
+ {
+ switch_event_t *event;
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, RTMP_EVENT_CONNECT) == SWITCH_STATUS_SUCCESS) {
+ rtmp_event_fill(*newsession, event);
+ switch_event_fire(&event);
+ }
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t rtmp_session_destroy(rtmp_session_t **session)
+{
+ switch_hash_index_t *hi;
+ switch_event_t *event;
+
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, RTMP_EVENT_DISCONNECT) == SWITCH_STATUS_SUCCESS) {
+ rtmp_event_fill(*session, event);
+ switch_event_fire(&event);
+ }
+
+ switch_core_hash_delete_wrlock(rtmp_globals.session_hash, (*session)->uuid, rtmp_globals.session_rwlock);
+ switch_core_hash_delete_wrlock((*session)->profile->session_hash, (*session)->uuid, (*session)->profile->session_rwlock);
+ rtmp_clear_registration(*session, NULL, NULL);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "RTMP session ended [%s]\n", (*session)->uuid);
+
+ (*session)->state = RS_DESTROY;
+
+ switch_thread_rwlock_rdlock((*session)->session_rwlock);
+ for (hi = switch_hash_first(NULL, (*session)->session_hash); hi; hi = switch_hash_next(hi)) {
+ void *val;
+ const void *key;
+ switch_ssize_t keylen;
+ rtmp_private_t *item;
+ switch_channel_t *channel;
+ switch_hash_this(hi, &key, &keylen, &val);
+ item = (rtmp_private_t *)val;
+
+ channel = switch_core_session_get_channel(item->session);
+ switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
+ }
+ switch_thread_rwlock_unlock((*session)->session_rwlock);
+
+
+ while ((*session)->active_sessions > 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Still have %d sessions, waiting\n", (*session)->active_sessions);
+ switch_yield(500000);
+ }
+
+
+ switch_thread_rwlock_wrlock((*session)->rwlock);
+ switch_thread_rwlock_unlock((*session)->rwlock);
+
+ (*session)->profile->io->close(*session);
+
+#ifdef RTMP_DEBUG_IO
+ fclose((*session)->io_debug_in);
+ fclose((*session)->io_debug_out);
+#endif
+
+ switch_mutex_lock((*session)->profile->mutex);
+ (*session)->profile->clients--;
+ switch_mutex_unlock((*session)->profile->mutex);
+
+ switch_core_hash_destroy(&(*session)->session_hash);
+
+ switch_core_destroy_memory_pool(&(*session)->pool);
+
+ *session = NULL;
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_call_cause_t rtmp_session_create_call(rtmp_session_t *rsession, switch_core_session_t **newsession, int read_channel, int write_channel, const char *number, const char *auth_user, const char *auth_domain, switch_event_t *event)
+{
+ switch_memory_pool_t *pool;
+ rtmp_private_t *tech_pvt;
+ switch_caller_profile_t *caller_profile;
+ switch_channel_t *channel;
+ const char *dialplan, *context;
+
+ if (!(*newsession = switch_core_session_request(rtmp_globals.rtmp_endpoint_interface, SOF_NONE, SWITCH_CALL_DIRECTION_INBOUND, NULL))) {
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+ }
+
+ pool = switch_core_session_get_pool(*newsession);
+ channel = switch_core_session_get_channel(*newsession);
+ switch_channel_set_name(channel, switch_core_session_sprintf(*newsession, "rtmp/%s/%s", rsession->profile->name, number));
+
+ if (!zstr(auth_user) && !zstr(auth_domain)) {
+ const char *s = switch_core_session_sprintf(*newsession, "%s@%s", auth_user, auth_domain);
+ switch_ivr_set_user(*newsession, s);
+ switch_channel_set_variable(channel, "rtmp_authorized", "true");
+ }
+
+ if (!(context = switch_channel_get_variable(channel, "user_context"))) {
+ if (!(context = rsession->profile->context)) {
+ context = "public";
+ }
+ }
+
+ if (!(dialplan = switch_channel_get_variable(channel, "inbound_dialplan"))) {
+ if (!(dialplan = rsession->profile->dialplan)) {
+ dialplan = "XML";
+ }
+ }
+
+ caller_profile = switch_caller_profile_new(pool, switch_str_nil(auth_user), dialplan,
+ SWITCH_DEFAULT_CLID_NAME,
+ !zstr(auth_user) ? auth_user : "0000000000",
+ rsession->remote_address /* net addr */,
+ NULL /* ani */,
+ NULL /* anii */,
+ NULL /* rdnis */,
+ "mod_rtmp", context, number);
+
+ switch_channel_set_caller_profile(channel, caller_profile);
+
+ tech_pvt = switch_core_alloc(pool, sizeof(rtmp_private_t));
+ tech_pvt->rtmp_session = rsession;
+ tech_pvt->write_channel = RTMP_DEFAULT_STREAM_AUDIO;
+ tech_pvt->session = *newsession;
+ tech_pvt->caller_profile = caller_profile;
+ switch_core_session_add_stream(*newsession, NULL);
+
+ if (rtmp_tech_init(tech_pvt, rsession, *newsession) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "tech_init failed\n");
+ goto fail;
+ }
+
+ if (!zstr(auth_user) && !zstr(auth_domain)) {
+ tech_pvt->auth_user = switch_core_session_strdup(*newsession, auth_user);
+ tech_pvt->auth_domain = switch_core_session_strdup(*newsession, auth_domain);
+ tech_pvt->auth = switch_core_session_sprintf(*newsession, "%s@%s", auth_user, auth_domain);
+ }
+
+ switch_channel_set_state(channel, CS_INIT);
+ switch_set_flag_locked(tech_pvt, TFLAG_IO);
+ switch_set_flag_locked(tech_pvt, TFLAG_DETACHED);
+ rtmp_set_channel_variables(*newsession);
+
+ if (event) {
+ switch_event_header_t *hp;
+
+ for (hp = event->headers; hp; hp = hp->next) {
+ switch_channel_set_variable_name_printf(channel, hp->value, RTMP_USER_VARIABLE_PREFIX "_%s", hp->name);
+ }
+ }
+
+ switch_core_hash_insert_wrlock(rsession->session_hash, switch_core_session_get_uuid(*newsession), tech_pvt, rsession->session_rwlock);
+
+ if (switch_core_session_thread_launch(tech_pvt->session) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't spawn thread\n");
+ goto fail;
+ }
+
+ return SWITCH_CAUSE_NONE;
+
+fail:
+ switch_core_session_destroy(newsession);
+ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
+}
+
+switch_status_t rtmp_profile_start(const char *profilename)
+{
+ switch_memory_pool_t *pool;
+ rtmp_profile_t *profile;
+
+ switch_assert(profilename);
+
+ switch_core_new_memory_pool(&pool);
+ profile = switch_core_alloc(pool, sizeof(*profile));
+ profile->pool = pool;
+ profile->name = switch_core_strdup(pool, profilename);
+
+ if (config_profile(profile, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Config failed\n");
+ goto fail;
+ }
+
+ switch_thread_rwlock_create(&profile->rwlock, pool);
+ switch_mutex_init(&profile->mutex, SWITCH_MUTEX_NESTED, pool);
+ switch_core_hash_init(&profile->session_hash, pool);
+ switch_thread_rwlock_create(&profile->session_rwlock, pool);
+ switch_thread_rwlock_create(&profile->reg_rwlock, pool);
+ switch_core_hash_init(&profile->reg_hash, pool);
+
+ if (!strcmp(profile->io_name, "tcp")) {
+ if (rtmp_tcp_init(profile, profile->bind_address, &profile->io, pool) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't initialize I/O layer\n");
+ goto fail;
+ }
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No such I/O module [%s]\n", profile->io_name);
+ goto fail;
+ }
+
+ switch_core_hash_insert_wrlock(rtmp_globals.profile_hash, profile->name, profile, rtmp_globals.profile_rwlock);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Started profile %s\n", profile->name);
+
+ return SWITCH_STATUS_SUCCESS;
+fail:
+ switch_core_destroy_memory_pool(&pool);
+ return SWITCH_STATUS_FALSE;
+}
+
+switch_status_t rtmp_profile_destroy(rtmp_profile_t **profile) {
+ int sanity = 0;
+ switch_hash_index_t *hi;
+ switch_xml_config_item_t *instructions = get_instructions(*profile);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Stopping profile: %s\n", (*profile)->name);
+
+ switch_core_hash_delete_wrlock(rtmp_globals.profile_hash, (*profile)->name, rtmp_globals.profile_rwlock);
+
+ switch_thread_rwlock_wrlock((*profile)->rwlock);
+
+ /* Kill all sessions */
+ while ((hi = switch_hash_first(NULL, (*profile)->session_hash))) {
+ void *val;
+ rtmp_session_t *session;
+ const void *key;
+ switch_ssize_t keylen;
+ switch_hash_this(hi, &key, &keylen, &val);
+
+ session = val;
+
+ rtmp_session_destroy(&session);
+ }
+
+ if ((*profile)->io->running > 0) {
+ (*profile)->io->running = 0;
+
+ while (sanity++ < 100 && (*profile)->io->running == 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for thread to end\n");
+ switch_yield(500000);
+ }
+ }
+
+ switch_thread_rwlock_unlock((*profile)->rwlock);
+
+ switch_xml_config_cleanup(instructions);
+
+ switch_core_hash_destroy(&(*profile)->session_hash);
+ switch_core_hash_destroy(&(*profile)->reg_hash);
+
+ switch_core_destroy_memory_pool(&(*profile)->pool);
+
+ free(instructions);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+void rtmp_add_registration(rtmp_session_t *rsession, const char *auth, const char *nickname)
+{
+ rtmp_reg_t *current_reg;
+ rtmp_reg_t *reg;
+ switch_event_t *event;
+
+ if (zstr(auth)) {
+ return;
+ }
+
+ reg = switch_core_alloc(rsession->pool, sizeof(*reg));
+ reg->uuid = rsession->uuid;
+
+ if (!zstr(nickname)) {
+ reg->nickname = switch_core_strdup(rsession->pool, nickname);
+ }
+
+ switch_thread_rwlock_wrlock(rsession->profile->reg_rwlock);
+ if ((current_reg = switch_core_hash_find(rsession->profile->reg_hash, auth))) {
+ for (;current_reg && current_reg->next; current_reg = current_reg->next);
+ current_reg->next = reg;
+ } else {
+ switch_core_hash_insert(rsession->profile->reg_hash, auth, reg);
+ }
+ switch_thread_rwlock_unlock(rsession->profile->reg_rwlock);
+
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, RTMP_EVENT_REGISTER) == SWITCH_STATUS_SUCCESS) {
+ char *user, *domain, *dup;
+ rtmp_event_fill(rsession, event);
+
+ dup = strdup(auth);
+ switch_split_user_domain(dup, &user, &domain);
+
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "User", user);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Domain", domain);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Nickname", switch_str_nil(nickname));
+ switch_event_fire(&event);
+ free(dup);
+ }
+
+}
+
+static void rtmp_clear_reg_auth(rtmp_session_t *rsession, const char *auth, const char *nickname)
+{
+ rtmp_reg_t *reg, *prev = NULL;
+ switch_thread_rwlock_wrlock(rsession->profile->reg_rwlock);
+ if ((reg = switch_core_hash_find(rsession->profile->reg_hash, auth))) {
+ for (; reg; reg = reg->next) {
+ if (!strcmp(reg->uuid, rsession->uuid) && (zstr(nickname) || !strcmp(reg->nickname, nickname))) {
+ switch_event_t *event;
+ if (prev) {
+ prev->next = reg->next;
+ } else {
+ /* Replace hash entry by its next ptr */
+ switch_core_hash_insert(rsession->profile->reg_hash, auth, reg->next);
+ }
+
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, RTMP_EVENT_UNREGISTER) == SWITCH_STATUS_SUCCESS) {
+ rtmp_event_fill(rsession, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Nickname", switch_str_nil(reg->nickname));
+ switch_event_fire(&event);
+ }
+ }
+ prev = reg;
+ }
+ }
+ switch_thread_rwlock_unlock(rsession->profile->reg_rwlock);
+}
+
+
+void rtmp_clear_registration(rtmp_session_t *rsession, const char *auth, const char *nickname)
+{
+ rtmp_account_t *account;
+
+ if (zstr(auth)) {
+ /* Reg data is pool-allocated, no need to free them */
+ switch_thread_rwlock_rdlock(rsession->account_rwlock);
+ for (account = rsession->account; account; account = account->next) {
+ char buf[1024];
+ snprintf(buf, sizeof(buf), "%s@%s", account->user, account->domain);
+ rtmp_clear_reg_auth(rsession, buf, nickname);
+ }
+ switch_thread_rwlock_unlock(rsession->account_rwlock);
+ } else {
+ rtmp_clear_reg_auth(rsession, auth, nickname);
+ }
+
+}
+
+switch_status_t rtmp_session_login(rtmp_session_t *rsession, const char *user, const char *domain)
+{
+ rtmp_account_t *account = switch_core_alloc(rsession->pool, sizeof(*account));
+ switch_event_t *event;
+
+ account->user = switch_core_strdup(rsession->pool, user);
+ account->domain = switch_core_strdup(rsession->pool, domain);
+
+ switch_thread_rwlock_wrlock(rsession->account_rwlock);
+ account->next = rsession->account;
+ rsession->account = account;
+ switch_thread_rwlock_unlock(rsession->account_rwlock);
+
+ rtmp_send_invoke_free(rsession, 3, 0, 0,
+ amf0_str("onLogin"),
+ amf0_number_new(0),
+ amf0_null_new(),
+ amf0_str("success"),
+ amf0_str(user),
+ amf0_str(domain), NULL);
+
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, RTMP_EVENT_LOGIN) == SWITCH_STATUS_SUCCESS) {
+ rtmp_event_fill(rsession, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "User", user);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Domain", domain);
+ switch_event_fire(&event);
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_INFO, "RTMP Session [%s] is now logged into %s@%s\n", rsession->uuid, user, domain);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t rtmp_session_logout(rtmp_session_t *rsession, const char *user, const char *domain)
+{
+ rtmp_account_t *account, *prev = NULL;
+ switch_event_t *event;
+
+ switch_thread_rwlock_wrlock(rsession->account_rwlock);
+ for (account = rsession->account; account; account = account->next) {
+ if (!strcmp(account->user, user) && !strcmp(account->domain, domain)) {
+ if (prev) {
+ prev->next = account->next;
+ } else {
+ rsession->account = account->next;
+ }
+ }
+ }
+ switch_thread_rwlock_unlock(rsession->account_rwlock);
+
+ rtmp_send_invoke_free(rsession, 3, 0, 0,
+ amf0_str("onLogout"),
+ amf0_number_new(0),
+ amf0_null_new(),
+ amf0_str(user),
+ amf0_str(domain), NULL);
+
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, RTMP_EVENT_LOGOUT) == SWITCH_STATUS_SUCCESS) {
+ rtmp_event_fill(rsession, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "User", user);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Domain", domain);
+ switch_event_fire(&event);
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_INFO, "RTMP Session [%s] is now logged out of %s@%s\n", rsession->uuid, user, domain);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+switch_status_t rtmp_session_check_user(rtmp_session_t *rsession, const char *user, const char *domain)
+{
+ rtmp_account_t *account;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+
+ switch_thread_rwlock_rdlock(rsession->account_rwlock);
+ for (account = rsession->account; account; account = account->next) {
+ if (!strcmp(account->user, user) && !strcmp(account->domain, domain)) {
+ status = SWITCH_STATUS_SUCCESS;
+ break;
+ }
+ }
+ switch_thread_rwlock_unlock(rsession->account_rwlock);
+
+ return status;
+}
+
+void rtmp_attach_private(rtmp_session_t *rsession, rtmp_private_t *tech_pvt)
+{
+ switch_event_t *event;
+
+ if (rsession->tech_pvt) {
+ /* Detach current call */
+ switch_set_flag_locked(rsession->tech_pvt, TFLAG_DETACHED);
+#ifndef RTMP_DONT_HOLD
+ switch_ivr_hold(rsession->tech_pvt->session, NULL, SWITCH_TRUE);
+ switch_channel_mark_hold(rsession->tech_pvt->channel, SWITCH_FALSE);
+#endif
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, RTMP_EVENT_DETACH) == SWITCH_STATUS_SUCCESS) {
+ rtmp_event_fill(rsession, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Call-ID",
+ switch_core_session_get_uuid(rsession->tech_pvt->session));
+ switch_event_fire(&event);
+ }
+
+ rsession->tech_pvt = NULL;
+ }
+
+ if (tech_pvt && switch_test_flag(tech_pvt, TFLAG_THREE_WAY)) {
+ const char *s = switch_channel_get_variable(tech_pvt->channel, RTMP_THREE_WAY_UUID_VARIABLE);
+ /* 2nd call of a three-way: attach to other call instead */
+ if (!zstr(s)) {
+ tech_pvt = rtmp_locate_private(rsession, s);
+ } else {
+ tech_pvt = NULL;
+ }
+ }
+
+ rsession->tech_pvt = tech_pvt;
+
+ if (tech_pvt) {
+ /* Attach new call */
+ switch_clear_flag_locked(tech_pvt, TFLAG_DETACHED);
+
+#ifndef RTMP_DONT_HOLD
+ if (switch_channel_test_flag(tech_pvt->channel, CF_HOLD)) {
+ switch_channel_mark_hold(tech_pvt->channel, SWITCH_FALSE);
+ switch_ivr_unhold(tech_pvt->session);
+ }
+#endif
+ if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, RTMP_EVENT_ATTACH) == SWITCH_STATUS_SUCCESS) {
+ rtmp_event_fill(rsession, event);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Call-ID", switch_core_session_get_uuid(tech_pvt->session));
+ switch_event_fire(&event);
+ }
+ }
+
+ /* Let the UI know to which call it has connected */
+ rtmp_session_send_onattach(rsession);
+}
+
+rtmp_private_t *rtmp_locate_private(rtmp_session_t *rsession, const char *uuid)
+{
+ return switch_core_hash_find_rdlock(rsession->session_hash, uuid, rsession->session_rwlock);
+}
+
+static switch_xml_config_item_t *get_instructions(rtmp_profile_t *profile) {
+ switch_xml_config_item_t *dup;
+ static switch_xml_config_int_options_t opt_chunksize = {
+ SWITCH_TRUE, /* enforce min */
+ 128,
+ SWITCH_TRUE, /* Enforce Max */
+ 65536
+ };
+ static switch_xml_config_int_options_t opt_bufferlen = {
+ SWITCH_FALSE,
+ 0,
+ SWITCH_TRUE,
+ INT32_MAX
+ };
+ switch_xml_config_item_t instructions[] = {
+ /* parameter name type reloadable pointer default value options structure */
+ SWITCH_CONFIG_ITEM("context", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &profile->context, "public", &switch_config_string_strdup,
+ "", "The dialplan context to use for inbound calls"),
+ SWITCH_CONFIG_ITEM("dialplan", SWITCH_CONFIG_STRING, CONFIG_RELOADABLE, &profile->dialplan, "XML", &switch_config_string_strdup,
+ "", "The dialplan to use for inbound calls"),
+ SWITCH_CONFIG_ITEM("bind-address", SWITCH_CONFIG_STRING, 0, &profile->bind_address, "0.0.0.0:1935", &switch_config_string_strdup,
+ "ip:port", "IP and port to bind"),
+ SWITCH_CONFIG_ITEM("io", SWITCH_CONFIG_STRING, 0, &profile->io_name, "tcp", &switch_config_string_strdup,
+ "io module", "I/O module to use (if unsure use tcp)"),
+ SWITCH_CONFIG_ITEM("auth-calls", SWITCH_CONFIG_BOOL, CONFIG_RELOADABLE, &profile->auth_calls, SWITCH_FALSE, NULL, "true|false", "Set to true in order to reject unauthenticated calls"),
+ SWITCH_CONFIG_ITEM("chunksize", SWITCH_CONFIG_INT, CONFIG_RELOADABLE, &profile->chunksize, 128, &opt_chunksize, "", "RTMP Sending chunksize"),
+ SWITCH_CONFIG_ITEM("buffer-len", SWITCH_CONFIG_INT, CONFIG_RELOADABLE, &profile->buffer_len, 500, &opt_bufferlen, "", "Length of the receiving buffer to be used by the flash clients, in miliseconds"),
+ SWITCH_CONFIG_ITEM_END()
+ };
+
+ dup = malloc(sizeof(instructions));
+ memcpy(dup, instructions, sizeof(instructions));
+ return dup;
+}
+
+static switch_status_t config_profile(rtmp_profile_t *profile, switch_bool_t reload)
+{
+ switch_xml_t cfg, xml, x_profiles, x_profile, x_settings;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ switch_xml_config_item_t *instructions = (profile ? get_instructions(profile) : NULL);
+ switch_event_t *event = NULL;
+ int count;
+ const char *file = "rtmp.conf";
+
+ if (!(xml = switch_xml_open_cfg(file, &cfg, NULL))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not open %s\n", file);
+ goto done;
+ }
+
+ if (!(x_profiles = switch_xml_child(cfg, "profiles"))) {
+ goto done;
+ }
+
+ for (x_profile = switch_xml_child(x_profiles, "profile"); x_profile; x_profile = x_profile->next) {
+ const char *name = switch_xml_attr_soft(x_profile, "name");
+ if (strcmp(name, profile->name)) {
+ continue;
+ }
+
+ if (!(x_settings = switch_xml_child(x_profile, "settings"))) {
+ goto done;
+ }
+
+
+ count = switch_event_import_xml(switch_xml_child(x_settings, "param"), "name", "value", &event);
+ status = switch_xml_config_parse_event(event, count, reload, instructions);
+ }
+
+
+done:
+ if (xml) {
+ switch_xml_free(xml);
+ }
+ switch_safe_free(instructions);
+ if (event) {
+ switch_event_destroy(&event);
+ }
+ return status;
+}
+
+static void rtmp_event_handler(switch_event_t *event)
+{
+ rtmp_session_t *rsession;
+ const char *uuid;
+
+ if (!event) {
+ return;
+ }
+
+ uuid = switch_event_get_header(event, "RTMP-Session-ID");
+ if (zstr(uuid)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "RTMP Custom event without RTMP-Session-ID\n");
+ return;
+ }
+
+ if ((rsession = rtmp_session_locate(uuid))) {
+ rtmp_send_event(rsession, event);
+ rtmp_session_rwunlock(rsession);
+ }
+}
+
+#define RTMP_CONTACT_FUNCTION_SYNTAX "profile/user@domain[/[!]nickname]"
+SWITCH_STANDARD_API(rtmp_contact_function)
+{
+ int argc;
+ char *argv[5];
+ char *dup = NULL;
+ char *szprofile = NULL, *user = NULL;
+ const char *nickname = NULL;
+ rtmp_profile_t *profile = NULL;
+ rtmp_reg_t *reg;
+ switch_bool_t first = SWITCH_TRUE;
+
+ if (zstr(cmd)) {
+ goto usage;
+ }
+
+ dup = strdup(cmd);
+ argc = switch_split(dup, '/', argv);
+
+ if (argc < 2 || zstr(argv[0]) || zstr(argv[1])) {
+ goto usage;
+ }
+
+ szprofile = argv[0];
+ if (!strchr(argv[1], '@')) {
+ goto usage;
+ }
+
+ user = argv[1];
+ nickname = argv[2];
+
+ if (!(profile = rtmp_profile_locate(szprofile))) {
+ stream->write_function(stream, "-ERR No such profile\n");
+ goto done;
+ }
+
+ switch_thread_rwlock_rdlock(profile->reg_rwlock);
+ if ((reg = switch_core_hash_find(profile->reg_hash, user))) {
+ for (; reg; reg = reg->next) {
+ if (zstr(nickname) ||
+ (nickname[0] == '!' && (zstr(reg->nickname) || strcmp(reg->nickname, nickname+1))) ||
+ (!zstr(reg->nickname) && !strcmp(reg->nickname, nickname))) {
+ if (!first) {
+ stream->write_function(stream, ",");
+ } else {
+ first = SWITCH_FALSE;
+ }
+ stream->write_function(stream, "rtmp/%s/%s", reg->uuid, user);
+ }
+ }
+ } else {
+ stream->write_function(stream, "error/user_not_registered");
+ }
+ switch_thread_rwlock_unlock(profile->reg_rwlock);
+ goto done;
+
+usage:
+ stream->write_function(stream, "Usage: rtmp_contact "RTMP_CONTACT_FUNCTION_SYNTAX"\n");
+
+done:
+ if (profile) {
+ rtmp_profile_release(profile);
+ }
+ switch_safe_free(dup);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+#define RTMP_FUNCTION_SYNTAX "profile [profilename] [start | stop | rescan | restart]\nstatus profile [profilename]\nstatus profile [profilename] [reg | sessions]\nsession [session_id] [kill | login [user@domain] | logout [user@domain]]"
+SWITCH_STANDARD_API(rtmp_function)
+{
+ int argc;
+ char *argv[10];
+ char *dup = NULL;
+
+ if (zstr(cmd)) {
+ goto usage;
+ }
+
+ dup = strdup(cmd);
+ argc = switch_split(dup, ' ', argv);
+
+ if (argc < 1 || zstr(argv[0])) {
+ goto usage;
+ }
+
+ if (!strcmp(argv[0], "profile")) {
+ if (zstr(argv[1]) || zstr(argv[2])) {
+ goto usage;
+ }
+ if (!strcmp(argv[2], "start")) {
+ rtmp_profile_t *profile = rtmp_profile_locate(argv[1]);
+ if (profile) {
+ rtmp_profile_release(profile);
+ stream->write_function(stream, "-ERR Profile %s is already started\n", argv[2]);
+ } else {
+ rtmp_profile_start(argv[1]);
+ stream->write_function(stream, "+OK\n");
+ }
+ } else if (!strcmp(argv[2], "stop")) {
+ rtmp_profile_t *profile = rtmp_profile_locate(argv[1]);
+ if (profile) {
+ rtmp_profile_release(profile);
+ rtmp_profile_destroy(&profile);
+ stream->write_function(stream, "+OK\n");
+ } else {
+ stream->write_function(stream, "-ERR No such profile\n");
+ }
+ } else if (!strcmp(argv[2], "rescan")) {
+ rtmp_profile_t *profile = rtmp_profile_locate(argv[1]);
+ if (config_profile(profile, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
+ stream->write_function(stream, "+OK\n");
+ } else {
+ stream->write_function(stream, "-ERR Config error\n");
+ }
+ rtmp_profile_release(profile);
+ } else if (!strcmp(argv[2], "restart")) {
+ rtmp_profile_t *profile = rtmp_profile_locate(argv[1]);
+ if (profile) {
+ rtmp_profile_release(profile);
+ rtmp_profile_destroy(&profile);
+ rtmp_profile_start(argv[1]);
+ stream->write_function(stream, "+OK\n");
+ } else {
+ rtmp_profile_start(argv[1]);
+ stream->write_function(stream, "-OK (wasn't started, started anyways)\n");
+ }
+ } else {
+ goto usage;
+ }
+ } else if (!strcmp(argv[0], "status")) {
+ if (!zstr(argv[1]) && !strcmp(argv[1], "profile") && !zstr(argv[2])) {
+ rtmp_profile_t *profile;
+
+ if ((profile = rtmp_profile_locate(argv[2]))) {
+ stream->write_function(stream, "Profile: %s\n", profile->name);
+ stream->write_function(stream, "I/O Backend: %s\n", profile->io->name);
+ stream->write_function(stream, "Bind address: %s\n", profile->io->address);
+ stream->write_function(stream, "Active calls: %d\n", profile->calls);
+
+ if (!zstr(argv[3]) && !strcmp(argv[3], "sessions"))
+ {
+ switch_hash_index_t *hi;
+ stream->write_function(stream, "\nSessions:\n");
+ stream->write_function(stream, "uuid,address,user,domain,flashVer\n");
+ switch_thread_rwlock_rdlock(profile->session_rwlock);
+ for (hi = switch_hash_first(NULL, profile->session_hash); hi; hi = switch_hash_next(hi)) {
+ void *val;
+ const void *key;
+ switch_ssize_t keylen;
+ rtmp_session_t *item;
+ switch_hash_this(hi, &key, &keylen, &val);
+
+ item = (rtmp_session_t *)val;
+ stream->write_function(stream, "%s,%s:%d,%s,%s,%s\n",
+ item->uuid, item->remote_address, item->remote_port,
+ item->account ? item->account->user : NULL,
+ item->account ? item->account->domain : NULL,
+ item->flashVer);
+
+ }
+ switch_thread_rwlock_unlock(profile->session_rwlock);
+ } else if (!zstr(argv[3]) && !strcmp(argv[3], "reg")) {
+ switch_hash_index_t *hi;
+ stream->write_function(stream, "\nRegistrations:\n");
+ stream->write_function(stream, "user,nickname,uuid\n");
+
+ switch_thread_rwlock_rdlock(profile->reg_rwlock);
+ for (hi = switch_hash_first(NULL, profile->reg_hash); hi; hi = switch_hash_next(hi)) {
+ void *val;
+ const void *key;
+ switch_ssize_t keylen;
+ rtmp_reg_t *item;
+ switch_hash_this(hi, &key, &keylen, &val);
+
+ item = (rtmp_reg_t *)val;
+ for (;item;item = item->next) {
+ stream->write_function(stream, "%s,%s,%s\n",
+ key, switch_str_nil(item->nickname), item->uuid);
+ }
+ }
+ switch_thread_rwlock_unlock(profile->reg_rwlock);
+ } else {
+ stream->write_function(stream, "Dialplan: %s\n", profile->dialplan);
+ stream->write_function(stream, "Context: %s\n", profile->context);
+ }
+
+ rtmp_profile_release(profile);
+ } else {
+ stream->write_function(stream, "-ERR No such profile [%s]\n", argv[2]);
+ }
+ } else {
+ switch_hash_index_t *hi;
+ switch_thread_rwlock_rdlock(rtmp_globals.profile_rwlock);
+ for (hi = switch_hash_first(NULL, rtmp_globals.profile_hash); hi; hi = switch_hash_next(hi)) {
+ void *val;
+ const void *key;
+ switch_ssize_t keylen;
+ rtmp_profile_t *item;
+ switch_hash_this(hi, &key, &keylen, &val);
+
+ item = (rtmp_profile_t *)val;
+ stream->write_function(stream, "%s\t%s:%s\tprofile\n", item->name, item->io->name, item->io->address);
+
+ }
+ switch_thread_rwlock_unlock(rtmp_globals.profile_rwlock);
+ }
+
+ } else if (!strcmp(argv[0], "session")) {
+ rtmp_session_t *rsession;
+
+ if (zstr(argv[1]) || zstr(argv[2])) {
+ goto usage;
+ }
+
+ rsession = rtmp_session_locate(argv[1]);
+ if (!rsession) {
+ stream->write_function(stream, "-ERR No such session\n");
+ goto done;
+ }
+
+ if (!strcmp(argv[2], "login")) {
+ char *user, *domain;
+ if (zstr(argv[3])) {
+ goto usage;
+ }
+ switch_split_user_domain(argv[3], &user, &domain);
+
+ if (!zstr(user) && !zstr(domain)) {
+ rtmp_session_login(rsession, user, domain);
+ stream->write_function(stream, "+OK\n");
+ } else {
+ stream->write_function(stream, "-ERR I need user@domain\n");
+ }
+ } else if (!strcmp(argv[2], "logout")) {
+ char *user, *domain;
+ if (zstr(argv[3])) {
+ goto usage;
+ }
+ switch_split_user_domain(argv[3], &user, &domain);
+
+ if (!zstr(user) && !zstr(domain)) {
+ rtmp_session_logout(rsession, user, domain);
+ stream->write_function(stream, "+OK\n");
+ } else {
+ stream->write_function(stream, "-ERR I need user@domain\n");
+ }
+ } else if (!strcmp(argv[2], "kill")) {
+ rtmp_session_rwunlock(rsession);
+ rtmp_session_destroy(&rsession);
+ stream->write_function(stream, "+OK\n");
+ } else if (!strcmp(argv[2], "call")) {
+ switch_core_session_t *newsession = NULL;
+ char *dest = argv[3];
+ char *user = argv[4];
+ char *domain = NULL;
+
+ if (!zstr(user) && (domain = strchr(user, '@'))) {
+ *domain++ = '\0';
+ }
+
+ if (!zstr(dest)) {
+ if (rtmp_session_create_call(rsession, &newsession, 0, RTMP_DEFAULT_STREAM_AUDIO, dest, user, domain, NULL) != SWITCH_STATUS_SUCCESS) {
+ stream->write_function(stream, "-ERR Couldn't create new call\n");
+ } else {
+ rtmp_private_t *new_pvt = switch_core_session_get_private(newsession);
+ rtmp_send_invoke_free(rsession, 3, 0, 0,
+ amf0_str("onMakeCall"),
+ amf0_number_new(0),
+ amf0_null_new(),
+ amf0_str(switch_core_session_get_uuid(newsession)),
+ amf0_str(switch_str_nil(dest)),
+ amf0_str(switch_str_nil(new_pvt->auth)),
+ NULL);
+
+ rtmp_attach_private(rsession, switch_core_session_get_private(newsession));
+ stream->write_function(stream, "+OK\n");
+ }
+ } else {
+ stream->write_function(stream, "-ERR Missing destination number\n");
+ }
+ } else if (!strcmp(argv[2], "ping")) {
+ rtmp_ping(rsession);
+ stream->write_function(stream, "+OK\n");
+ } else {
+ stream->write_function(stream, "-ERR No such session action [%s]\n", argv[2]);
+ }
+
+ if (rsession) {
+ rtmp_session_rwunlock(rsession);
+ }
+ } else {
+ goto usage;
+ }
+
+ goto done;
+
+usage:
+ stream->write_function(stream, "-ERR Usage: "RTMP_FUNCTION_SYNTAX"\n");
+
+done:
+ switch_safe_free(dup);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static inline void rtmp_register_invoke_function(const char *name, rtmp_invoke_function_t func)
+{
+ switch_core_hash_insert(rtmp_globals.invoke_hash, name, (void*)(intptr_t)func);
+}
+
+static switch_status_t console_complete_hashtable(switch_hash_t *hash, const char *line, const char *cursor, switch_console_callback_match_t **matches)
+{
+ switch_hash_index_t *hi;
+ void *val;
+ const void *vvar;
+ switch_console_callback_match_t *my_matches = NULL;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+
+ for (hi = switch_hash_first(NULL, hash); hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, &vvar, NULL, &val);
+ switch_console_push_match(&my_matches, (const char *) vvar);
+ }
+
+ if (my_matches) {
+ *matches = my_matches;
+ status = SWITCH_STATUS_SUCCESS;
+ }
+
+ return status;
+}
+
+static switch_status_t list_sessions(const char *line, const char *cursor, switch_console_callback_match_t **matches)
+{
+ switch_status_t status;
+ switch_thread_rwlock_rdlock(rtmp_globals.session_rwlock);
+ status = console_complete_hashtable(rtmp_globals.session_hash, line, cursor, matches);
+ switch_thread_rwlock_unlock(rtmp_globals.session_rwlock);
+ return status;
+}
+
+
+static switch_status_t list_profiles(const char *line, const char *cursor, switch_console_callback_match_t **matches)
+{
+ switch_status_t status;
+ switch_thread_rwlock_rdlock(rtmp_globals.profile_rwlock);
+ status = console_complete_hashtable(rtmp_globals.profile_hash, line, cursor, matches);
+ switch_thread_rwlock_unlock(rtmp_globals.profile_rwlock);
+ return status;
+}
+
+SWITCH_MODULE_LOAD_FUNCTION(mod_rtmp_load)
+{
+ switch_api_interface_t *api_interface;
+ rtmp_globals.pool = pool;
+
+ memset(&rtmp_globals, 0, sizeof(rtmp_globals));
+
+ switch_mutex_init(&rtmp_globals.mutex, SWITCH_MUTEX_NESTED, pool);
+ switch_core_hash_init(&rtmp_globals.profile_hash, pool);
+ switch_core_hash_init(&rtmp_globals.session_hash, pool);
+ switch_core_hash_init(&rtmp_globals.invoke_hash, pool);
+ switch_thread_rwlock_create(&rtmp_globals.profile_rwlock, pool);
+ switch_thread_rwlock_create(&rtmp_globals.session_rwlock, pool);
+
+ rtmp_register_invoke_function("connect", rtmp_i_connect);
+ rtmp_register_invoke_function("createStream", rtmp_i_createStream);
+ rtmp_register_invoke_function("closeStream", rtmp_i_noop);
+ rtmp_register_invoke_function("deleteStream", rtmp_i_noop);
+ rtmp_register_invoke_function("play", rtmp_i_play);
+ rtmp_register_invoke_function("publish", rtmp_i_publish);
+ rtmp_register_invoke_function("makeCall", rtmp_i_makeCall);
+ rtmp_register_invoke_function("login", rtmp_i_login);
+ rtmp_register_invoke_function("logout", rtmp_i_logout);
+ rtmp_register_invoke_function("sendDTMF", rtmp_i_sendDTMF);
+ rtmp_register_invoke_function("register", rtmp_i_register);
+ rtmp_register_invoke_function("unregister", rtmp_i_unregister);
+ rtmp_register_invoke_function("answer", rtmp_i_answer);
+ rtmp_register_invoke_function("attach", rtmp_i_attach);
+ rtmp_register_invoke_function("hangup", rtmp_i_hangup);
+ rtmp_register_invoke_function("transfer", rtmp_i_transfer);
+ rtmp_register_invoke_function("three_way", rtmp_i_three_way);
+ rtmp_register_invoke_function("join", rtmp_i_join);
+ rtmp_register_invoke_function("sendevent", rtmp_i_sendevent);
+ rtmp_register_invoke_function("receiveAudio", rtmp_i_receiveaudio);
+ rtmp_register_invoke_function("receiveVideo", rtmp_i_receivevideo);
+ rtmp_register_invoke_function("log", rtmp_i_log);
+
+ *module_interface = switch_loadable_module_create_module_interface(pool, modname);
+ rtmp_globals.rtmp_endpoint_interface = switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
+ rtmp_globals.rtmp_endpoint_interface->interface_name = "rtmp";
+ rtmp_globals.rtmp_endpoint_interface->io_routines = &rtmp_io_routines;
+ rtmp_globals.rtmp_endpoint_interface->state_handler = &rtmp_state_handlers;
+
+ SWITCH_ADD_API(api_interface, "rtmp", "rtmp management", rtmp_function, RTMP_FUNCTION_SYNTAX);
+ SWITCH_ADD_API(api_interface, "rtmp_contact", "rtmp contact", rtmp_contact_function, RTMP_CONTACT_FUNCTION_SYNTAX);
+
+ switch_console_set_complete("add rtmp status");
+ switch_console_set_complete("add rtmp status profile ::rtmp::list_profiles");
+ switch_console_set_complete("add rtmp status profile ::rtmp::list_profiles sessions");
+ switch_console_set_complete("add rtmp status profile ::rtmp::list_profiles reg");
+ switch_console_set_complete("add rtmp profile ::rtmp::list_profiles start");
+ switch_console_set_complete("add rtmp profile ::rtmp::list_profiles stop");
+ switch_console_set_complete("add rtmp profile ::rtmp::list_profiles restart");
+ switch_console_set_complete("add rtmp profile ::rtmp::list_profiles rescan");
+ switch_console_set_complete("add rtmp session ::rtmp::list_sessions kill");
+ switch_console_set_complete("add rtmp session ::rtmp::list_sessions login");
+ switch_console_set_complete("add rtmp session ::rtmp::list_sessions logout");
+
+ switch_console_add_complete_func("::rtmp::list_profiles", list_profiles);
+ switch_console_add_complete_func("::rtmp::list_sessions", list_sessions);
+
+ switch_event_bind("mod_rtmp", SWITCH_EVENT_CUSTOM, RTMP_EVENT_CUSTOM, rtmp_event_handler, NULL);
+
+ {
+ switch_xml_t cfg, xml, x_profiles, x_profile;
+ const char *file = "rtmp.conf";
+
+ if (!(xml = switch_xml_open_cfg(file, &cfg, NULL))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not open %s\n", file);
+ goto done;
+ }
+
+ if (!(x_profiles = switch_xml_child(cfg, "profiles"))) {
+ goto done;
+ }
+
+ for (x_profile = switch_xml_child(x_profiles, "profile"); x_profile; x_profile = x_profile->next) {
+ const char *name = switch_xml_attr_soft(x_profile, "name");
+ rtmp_profile_start(name);
+ }
+ done:
+ if (xml) {
+ switch_xml_free(xml);
+ }
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_rtmp_shutdown)
+{
+ switch_hash_index_t *hi;
+
+ switch_mutex_lock(rtmp_globals.mutex);
+ while ((hi = switch_hash_first(NULL, rtmp_globals.profile_hash))) {
+ void *val;
+ const void *key;
+ switch_ssize_t keylen;
+ rtmp_profile_t *item;
+ switch_hash_this(hi, &key, &keylen, &val);
+
+ item = (rtmp_profile_t *)val;
+
+ switch_mutex_unlock(rtmp_globals.mutex);
+ rtmp_profile_destroy(&item);
+ switch_mutex_lock(rtmp_globals.mutex);
+ }
+ switch_mutex_unlock(rtmp_globals.mutex);
+
+ switch_event_unbind_callback(rtmp_event_handler);
+
+ switch_core_hash_destroy(&rtmp_globals.profile_hash);
+ switch_core_hash_destroy(&rtmp_globals.session_hash);
+ switch_core_hash_destroy(&rtmp_globals.invoke_hash);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/* 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:
+ */
diff --git a/src/mod/endpoints/mod_rtmp/mod_rtmp.h b/src/mod/endpoints/mod_rtmp/mod_rtmp.h
new file mode 100644
index 0000000000..5d0f853335
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/mod_rtmp.h
@@ -0,0 +1,638 @@
+/*
+ * mod_rtmp for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2011, Barracuda Networks Inc.
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mod_rtmp for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is Barracuda Networks Inc.
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Mathieu Rene
+ *
+ * mod_rtmp.h -- RTMP Endpoint Module
+ *
+ */
+
+#ifndef MOD_RTMP_H
+#define MOD_RTMP_H
+#include
+
+/* AMF */
+#include "amf0.h"
+#include "io.h"
+#include "types.h"
+
+//#define RTMP_DEBUG_IO
+#define RTMP_DONT_HOLD
+
+#define RTMP_THREE_WAY_UUID_VARIABLE "rtmp_three_way_uuid"
+#define RTMP_ATTACH_ON_HANGUP_VARIABLE "rtmp_attach_on_hangup"
+#define RTMP_USER_VARIABLE_PREFIX "rtmp_u_"
+
+#define RTMP_DEFAULT_PORT 1935
+#define RTMP_TCP_READ_BUF 2048
+#define AMF_MAX_SIZE 2048
+
+#define SUPPORT_SND_NONE 0x0000
+#define SUPPORT_SND_ADPCM 0x0002
+#define SUPPORT_SND_MP3 0x0004
+#define SUPPORT_SND_INTEL 0x0008
+#define SUPPORT_SND_UNUSED 0x0010
+#define SUPPORT_SND_NELLY8 0x0020
+#define SUPPORT_SND_NELLY 0x0040
+#define SUPPORT_SND_G711A 0x0080
+#define SUPPORT_SND_G711U 0x0100
+#define SUPPORT_SND_NELLY16 0x0200
+#define SUPPORT_SND_AAC 0x0400
+#define SUPPORT_SND_SPEEX 0x0800
+#define SUPPORT_SND_ALL 0x0FFF
+
+#define SUPPORT_VID_UNUSED 0x0001
+#define SUPPORT_VID_JPEG 0x0002
+#define SUPPORT_VID_SORENSON 0x0004
+#define SUPPORT_VID_HOMEBREW 0x0008
+#define SUPPORT_VID_VP6 0x0010
+#define SUPPORT_VID_VP6ALPHA 0x0020
+#define SUPPORT_VID_HOMEBREWV 0x0040
+#define SUPPORT_VID_H264 0x0080
+#define SUPPORT_VID_ALL 0x00FF
+
+#define SUPPORT_VID_CLIENT_SEEK 1
+
+#define kAMF0 0
+#define kAMF3 3
+
+#define RTMP_DEFAULT_ACK_WINDOW 0x20000
+
+#define RTMP_TYPE_CHUNKSIZE 0x01
+#define RTMP_TYPE_ABORT 0x2
+#define RTMP_TYPE_ACK 0x3
+#define RTMP_TYPE_USERCTRL 0x04
+#define RTMP_TYPE_WINDOW_ACK_SIZE 0x5
+#define RTMP_TYPE_SET_PEER_BW 0x6
+#define RTMP_TYPE_AUDIO 0x08
+#define RTMP_TYPE_VIDEO 0x09
+#define RTMP_TYPE_METADATA 0x12
+#define RTMP_TYPE_INVOKE 0x14
+#define RTMP_TYPE_NOTIFY 0x12
+
+#define RTMP_CTRL_STREAM_BEGIN 0x00
+#define RTMP_CTRL_STREAM_EOF 0x01
+#define RTMP_CTRL_STREAM_DRY 0x02
+#define RTMP_CTRL_SET_BUFFER_LENGTH 0x03
+#define RTMP_CTRL_STREAM_IS_RECORDED 0x04
+#define RTMP_CTRL_PING_REQUEST 0x06
+#define RTMP_CTRL_PING_RESPONSE 0x07
+
+#define RTMP_DEFAULT_STREAM_CONTROL 0x02
+#define RTMP_DEFAULT_STREAM_INVOKE 0x03
+#define RTMP_DEFAULT_STREAM_NOTIFY 0x05
+#define RTMP_DEFAULT_STREAM_VIDEO 0x07
+#define RTMP_DEFAULT_STREAM_AUDIO 0x06
+
+
+#define RTMP_MSGSTREAM_DEFAULT 0x0
+/* It seems everything media-related (play/onStatus and the actual audio data are using this stream) */
+#define RTMP_MSGSTREAM_MEDIA 0x01
+
+#define RTMP_EVENT_CONNECT "rtmp::connect"
+#define RTMP_EVENT_DISCONNECT "rtmp::disconnect"
+#define RTMP_EVENT_REGISTER "rtmp::register"
+#define RTMP_EVENT_UNREGISTER "rtmp::unregister"
+#define RTMP_EVENT_LOGIN "rtmp::login"
+#define RTMP_EVENT_LOGOUT "rtmp::logout"
+#define RTMP_EVENT_ATTACH "rtmp::attach"
+#define RTMP_EVENT_DETACH "rtmp::detach"
+#define RTMP_EVENT_CUSTOM "rtmp::custom"
+#define RTMP_EVENT_CLIENTCUSTOM "rtmp::clientcustom"
+
+#define INT32_LE(x) (x) & 0xFF, ((x) >> 8) & 0xFF, ((x) >> 16) & 0xFF, ((x) >> 24) & 0xFF
+#define INT32(x) ((x) >> 24) & 0xFF, ((x) >> 16) & 0xFF, ((x) >> 8) & 0xFF, (x) & 0xFF
+#define INT24(x) ((x) >> 16) & 0xFF, ((x) >> 8) & 0xFF, (x) & 0xFF
+#define INT16(x) ((x) >> 8) & 0xFF, (x) & 0xFF
+
+
+typedef enum {
+ RTMP_AUDIO_PCM = 0,
+ RTMP_AUDIO_ADPCM = 1,
+ RTMP_AUDIO_MP3 = 2,
+ RTMP_AUDIO_NELLYMOSER_8K_MONO= 5,
+ RTMP_AUDIO_NELLYMOSER = 6,
+ RTMP_AUDIO_SPEEX = 11
+} rtmp_audio_format_t;
+
+/*
+
+From: http://osflash.org/flv
+
+0x08: AUDIO
+The first byte of an audio packet contains bitflags that describe the codec used, with the following layout:
+
+
+
+Name Expression Description
+soundType (byte & 0×01) » 0 0: mono, 1: stereo
+soundSize (byte & 0×02) » 1 0: 8-bit, 1: 16-bit
+soundRate (byte & 0x0C) » 2 0: 5.5 kHz, 1: 11 kHz, 2: 22 kHz, 3: 44 kHz
+soundFormat (byte & 0xf0) » 4 0: Uncompressed, 1: ADPCM, 2: MP3, 5: Nellymoser 8kHz mono, 6: Nellymoser, 11: Speex
+
+0x09: VIDEO
+The first byte of a video packet describes contains bitflags that describe the codec used, and the type of frame
+
+Name Expression Description
+codecID (byte & 0x0f) » 0 2: Sorensen H.263, 3: Screen video, 4: On2 VP6, 5: On2 VP6 Alpha, 6: ScreenVideo 2
+frameType (byte & 0xf0) » 4 1: keyframe, 2: inter frame, 3: disposable inter frame
+
+0x12: META
+The contents of a meta packet are two AMF packets.
+The first is almost always a short uint16_be length-prefixed UTF-8 string (AMF type 0×02),
+and the second is typically a mixed array (AMF type 0×08). However, the second chunk typically contains a variety of types,
+so a full AMF parser should be used.
+*/
+
+
+static inline int rtmp_audio_codec_get_channels(uint8_t codec) {
+ return (codec & 0x01) ? 2 : 1;
+}
+
+static inline int rtmp_audio_codec_get_sample_size(uint8_t codec) {
+ return (codec & 0x02) ? 16 : 8;
+}
+
+static inline int rtmp_audio_codec_get_rate(uint8_t codec) {
+ switch(codec & 0x0C) {
+ case 0:
+ return 5500;
+ case 1:
+ return 11000;
+ case 2:
+ return 22000;
+ case 3:
+ return 44000;
+ default:
+ return 0;
+ }
+}
+
+static inline rtmp_audio_format_t rtmp_audio_codec_get_format(uint8_t codec) {
+ return (rtmp_audio_format_t)(codec & 0xf0);
+}
+
+static inline uint8_t rtmp_audio_codec(int channels, int bits, int rate, rtmp_audio_format_t format) {
+ uint8_t codec = 0;
+
+ switch (channels) {
+ case 1:
+ break;
+ case 2:
+ codec |= 1;
+ default:
+ return 0;
+ }
+
+ switch (bits) {
+ case 8:
+ break;
+ case 16:
+ codec |= 2;
+ default:
+ return 0;
+ }
+
+ switch (rate) {
+ case 0:
+ case 5500:
+ break;
+ case 11000:
+ codec |= 0x4;
+ break;
+ case 22000:
+ codec |= 0x8;
+ break;
+ case 44000:
+ codec |= 0xC;
+ default:
+ return 0;
+ }
+
+ switch(format) {
+ case RTMP_AUDIO_PCM:
+ break;
+ case RTMP_AUDIO_ADPCM:
+ codec |= 0x10;
+ break;
+ case RTMP_AUDIO_MP3:
+ codec |= 0x20;
+ break;
+ case RTMP_AUDIO_NELLYMOSER_8K_MONO:
+ codec |= 0x50;
+ break;
+ case RTMP_AUDIO_NELLYMOSER:
+ codec |= 0x60;
+ break;
+ case RTMP_AUDIO_SPEEX:
+ codec |= 0x80;
+ break;
+ default:
+ return 0;
+ }
+
+ return codec;
+}
+
+
+struct rtmp_session;
+typedef struct rtmp_session rtmp_session_t;
+
+struct rtmp_profile;
+typedef struct rtmp_profile rtmp_profile_t;
+
+typedef struct rtmp_state rtmp_state_t;
+
+#define RTMP_INVOKE_FUNCTION_ARGS rtmp_session_t *rsession, rtmp_state_t *state, int amfnumber, int transaction_id, int argc, amf0_data *argv[]
+
+typedef switch_status_t (*rtmp_invoke_function_t)(RTMP_INVOKE_FUNCTION_ARGS);
+
+#define RTMP_INVOKE_FUNCTION(_x) switch_status_t _x (RTMP_INVOKE_FUNCTION_ARGS)
+
+/* AMF Helpers */
+
+#define amf0_is_string(_x) (_x && (_x)->type == AMF0_TYPE_STRING)
+#define amf0_is_number(_x) (_x && (_x)->type == AMF0_TYPE_NUMBER)
+#define amf0_is_boolean(_x) (_x && (_x)->type == AMF0_TYPE_BOOLEAN)
+#define amf0_is_object(_x) (_x && (_x)->type == AMF0_TYPE_OBJECT)
+
+static inline char *amf0_get_string(amf0_data *x)
+{
+ return (amf0_is_string(x) ? (char*)amf0_string_get_uint8_ts(x) : NULL);
+}
+
+static inline int amf0_get_number(amf0_data *x)
+{
+ return (amf0_is_number(x) ? amf0_number_get_value(x) : 0);
+}
+
+static inline switch_bool_t amf0_get_boolean(amf0_data *x)
+{
+ return (amf0_is_boolean(x) ? amf0_boolean_get_value(x) : SWITCH_FALSE);
+}
+
+struct rtmp_io {
+ switch_status_t (*read)(rtmp_session_t *rsession, unsigned char *buf, switch_size_t *len);
+ switch_status_t (*write)(rtmp_session_t *rsession, const unsigned char *buf, switch_size_t *len);
+ switch_status_t (*close)(rtmp_session_t *rsession);
+ rtmp_profile_t *profile;
+ switch_memory_pool_t *pool;
+ int running;
+ const char *name;
+ const char *address;
+};
+
+typedef struct rtmp_io rtmp_io_t;
+
+typedef enum {
+ TFLAG_IO = (1 << 0),
+ TFLAG_DETACHED = (1 << 1), /* Call isn't the current active call */
+ TFLAG_BREAK = (1 << 2),
+ TFLAG_THREE_WAY = (1 << 3), /* In a three-way call */
+ TFLAG_VID_WAIT_KEYFRAME = (1 << 4) /* Wait for video keyframe */
+} TFLAGS;
+
+
+/* Session flags */
+typedef enum {
+ SFLAG_AUDIO = (1 << 0), /* < Send audio */
+ SFLAG_VIDEO = (1 << 1) /* < Send video */
+} SFLAGS;
+
+typedef enum {
+ PFLAG_RUNNING = (1 << 0)
+} PFLAGS;
+
+struct mod_rtmp_globals {
+ switch_endpoint_interface_t *rtmp_endpoint_interface;
+ switch_memory_pool_t *pool;
+ switch_mutex_t *mutex;
+ switch_hash_t *profile_hash;
+ switch_thread_rwlock_t *profile_rwlock;
+ switch_hash_t *session_hash;
+ switch_thread_rwlock_t *session_rwlock;
+ switch_hash_t *invoke_hash;
+};
+
+extern struct mod_rtmp_globals rtmp_globals;
+
+struct rtmp_profile {
+ char *name; /* < Profile name */
+ switch_memory_pool_t *pool; /* < Memory pool */
+ rtmp_io_t *io; /* < IO Module instance */
+ switch_thread_rwlock_t *rwlock; /* < Rwlock for reference counting */
+ uint32_t flags; /* < PFLAGS */
+ switch_mutex_t *mutex; /* < Mutex for call count */
+ int calls; /* < Active calls count */
+ int clients; /* < Number of connected clients */
+ switch_hash_t *session_hash; /* < Active rtmp sessions */
+ switch_thread_rwlock_t *session_rwlock; /* < rwlock for session hashtable */
+ const char *context; /* < Default dialplan name */
+ const char *dialplan; /* < Default dialplan context */
+ const char *bind_address; /* < Bind address */
+ const char *io_name; /* < Name of I/O module (from config) */
+ int chunksize; /* < Override default chunksize (from config) */
+ int buffer_len; /* < Receive buffer length the flash clients should use */
+
+ switch_hash_t *reg_hash; /* < Registration hashtable */
+ switch_thread_rwlock_t *reg_rwlock; /* < Registration hash rwlock */
+
+ switch_bool_t auth_calls; /* < Require authentiation */
+};
+
+typedef struct {
+ unsigned ts:24;
+ unsigned len:24;
+ unsigned type:8;
+ unsigned src:16;
+ unsigned dst:16;
+} rtmp_hdr_t;
+
+#define RTMP_DEFAULT_CHUNKSIZE 128
+
+struct rtmp_state {
+ union {
+ char sz[12];
+ rtmp_hdr_t packed;
+ } header;
+ int remainlen;
+ int origlen;
+
+ uint32_t ts; /* 24 bits max */
+ uint32_t ts_delta; /* 24 bits max */
+ uint8_t type;
+ uint32_t stream_id;
+ unsigned char buf[AMF_MAX_SIZE];
+ switch_size_t buf_pos;
+};
+
+
+typedef enum {
+ RS_HANDSHAKE = 0,
+ RS_HANDSHAKE2 = 1,
+ RS_ESTABLISHED = 2,
+ RS_DESTROY = 3
+} rtmp_session_state_t;
+
+struct rtmp_private;
+typedef struct rtmp_private rtmp_private_t;
+
+
+struct rtmp_account;
+typedef struct rtmp_account rtmp_account_t;
+
+struct rtmp_account {
+ const char *user;
+ const char *domain;
+ rtmp_account_t *next;
+};
+
+struct rtmp_session {
+ switch_memory_pool_t *pool;
+ rtmp_profile_t *profile;
+ char uuid[SWITCH_UUID_FORMATTED_LENGTH+1];
+ void *io_private;
+
+ rtmp_session_state_t state;
+ int parse_state;
+ uint16_t parse_remain; /* < Remaining bytes required before changing parse state */
+
+ int hdrsize; /* < The current header size */
+ int amfnumber; /* < The current AMF number */
+
+ rtmp_state_t amfstate[64];
+ rtmp_state_t amfstate_out[64];
+
+ switch_mutex_t *socket_mutex;
+ switch_mutex_t *count_mutex;
+ int active_sessions;
+
+ unsigned char hsbuf[2048];
+ int hspos;
+ uint16_t in_chunksize;
+ uint16_t out_chunksize;
+
+ /* Connect params */
+ const char *flashVer;
+ const char *swfUrl;
+ const char *tcUrl;
+ const char *app;
+ const char *pageUrl;
+
+ uint32_t capabilities;
+ uint32_t audioCodecs;
+ uint32_t videoCodecs;
+ uint32_t videoFunction;
+
+ switch_thread_rwlock_t *rwlock;
+
+ rtmp_private_t *tech_pvt; /* < Active call's tech_pvt */
+#ifdef RTMP_DEBUG_IO
+ FILE *io_debug_in;
+ FILE *io_debug_out;
+#endif
+
+ const char *remote_address;
+ switch_port_t remote_port;
+
+ switch_hash_t *session_hash; /* < Hash of call uuids and tech_pvt */
+ switch_thread_rwlock_t *session_rwlock; /* < RWLock protecting session_hash */
+
+ rtmp_account_t *account;
+ switch_thread_rwlock_t *account_rwlock;
+ uint_least32_t flags;
+
+ int8_t sendAudio, sendVideo;
+ uint64_t recv_ack_window; /* < ACK Window */
+ uint64_t recv_ack_sent; /* < Bytes ack'd */
+ uint64_t recv; /* < Bytes received */
+
+ uint32_t send_ack_window;
+ uint32_t send_ack;
+ uint32_t send;
+ switch_time_t send_ack_ts;
+
+ uint32_t send_bw; /* < Current send bandwidth (in bytes/sec) */
+
+ uint32_t next_streamid; /* < The next stream id that will be used */
+ uint32_t active_streamid; /* < The stream id returned by the last call to createStream */
+
+ uint32_t media_streamid; /* < The stream id that was used for the last "play" command,
+ where we should send media */
+};
+
+struct rtmp_private {
+ unsigned int flags;
+ switch_codec_t read_codec;
+ switch_codec_t write_codec;
+
+ switch_frame_t read_frame;
+ unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; /* < Buffer for read_frame */
+
+ switch_caller_profile_t *caller_profile;
+
+ switch_mutex_t *mutex;
+ switch_mutex_t *flag_mutex;
+
+ switch_core_session_t *session;
+ switch_channel_t *channel;
+ rtmp_session_t *rtmp_session;
+
+ int read_channel; /* RTMP channel #s for read and write */
+ int write_channel;
+ uint8_t audio_codec;
+ uint8_t video_codec;
+
+ switch_time_t stream_start_ts;
+ switch_timer_t timer;
+ switch_buffer_t *readbuf;
+ switch_mutex_t *readbuf_mutex;
+
+ const char *display_callee_id_name;
+ const char *display_callee_id_number;
+
+ const char *auth_user;
+ const char *auth_domain;
+ const char *auth;
+};
+
+struct rtmp_reg;
+typedef struct rtmp_reg rtmp_reg_t;
+
+struct rtmp_reg {
+ const char *uuid; /* < The rtmp session id */
+ const char *nickname; /* < This instance's nickname, optional */
+ rtmp_reg_t *next; /* < Next entry */
+};
+
+
+typedef enum {
+ MSG_FULLHEADER = 1
+} rtmp_message_send_flag_t;
+
+
+/* Invokable functions from flash */
+RTMP_INVOKE_FUNCTION(rtmp_i_connect);
+RTMP_INVOKE_FUNCTION(rtmp_i_createStream);
+RTMP_INVOKE_FUNCTION(rtmp_i_noop);
+RTMP_INVOKE_FUNCTION(rtmp_i_play);
+RTMP_INVOKE_FUNCTION(rtmp_i_publish);
+RTMP_INVOKE_FUNCTION(rtmp_i_makeCall);
+RTMP_INVOKE_FUNCTION(rtmp_i_sendDTMF);
+RTMP_INVOKE_FUNCTION(rtmp_i_login);
+RTMP_INVOKE_FUNCTION(rtmp_i_logout);
+RTMP_INVOKE_FUNCTION(rtmp_i_register);
+RTMP_INVOKE_FUNCTION(rtmp_i_unregister);
+RTMP_INVOKE_FUNCTION(rtmp_i_answer);
+RTMP_INVOKE_FUNCTION(rtmp_i_attach);
+RTMP_INVOKE_FUNCTION(rtmp_i_hangup);
+RTMP_INVOKE_FUNCTION(rtmp_i_transfer);
+RTMP_INVOKE_FUNCTION(rtmp_i_three_way);
+RTMP_INVOKE_FUNCTION(rtmp_i_join);
+RTMP_INVOKE_FUNCTION(rtmp_i_sendevent);
+RTMP_INVOKE_FUNCTION(rtmp_i_receiveaudio);
+RTMP_INVOKE_FUNCTION(rtmp_i_receivevideo);
+RTMP_INVOKE_FUNCTION(rtmp_i_log);
+
+/*** RTMP Sessions ***/
+rtmp_session_t *rtmp_session_locate(const char *uuid);
+void rtmp_session_rwunlock(rtmp_session_t *rsession);
+
+switch_status_t rtmp_session_login(rtmp_session_t *rsession, const char *user, const char *domain);
+switch_status_t rtmp_session_logout(rtmp_session_t *rsession, const char *user, const char *domain);
+switch_status_t rtmp_session_check_user(rtmp_session_t *rsession, const char *user, const char *domain);
+
+switch_status_t rtmp_check_auth(rtmp_session_t *rsession, const char *user, const char *domain, const char *authmd5);
+void rtmp_event_fill(rtmp_session_t *rsession, switch_event_t *event);
+switch_status_t amf_object_to_event(amf0_data *obj, switch_event_t **event);
+switch_status_t amf_event_to_object(amf0_data **obj, switch_event_t *event);
+
+/*** Endpoint interface ***/
+switch_call_cause_t rtmp_session_create_call(rtmp_session_t *rsession, switch_core_session_t **newsession, int read_channel, int write_channel, const char *number, const char *auth_user, const char *auth_domain, switch_event_t *event);
+
+switch_status_t rtmp_on_execute(switch_core_session_t *session);
+switch_status_t rtmp_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf);
+switch_status_t rtmp_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg);
+switch_status_t rtmp_receive_event(switch_core_session_t *session, switch_event_t *event);
+switch_status_t rtmp_on_init(switch_core_session_t *session);
+switch_status_t rtmp_on_hangup(switch_core_session_t *session);
+switch_status_t rtmp_on_destroy(switch_core_session_t *session);
+switch_status_t rtmp_on_routing(switch_core_session_t *session);
+switch_status_t rtmp_on_exchange_media(switch_core_session_t *session);
+switch_status_t rtmp_on_soft_execute(switch_core_session_t *session);
+switch_call_cause_t rtmp_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
+ switch_caller_profile_t *outbound_profile,
+ switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
+ switch_call_cause_t *cancel_cause);
+switch_status_t rtmp_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
+switch_status_t rtmp_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
+switch_status_t rtmp_kill_channel(switch_core_session_t *session, int sig);
+
+switch_status_t rtmp_tech_init(rtmp_private_t *tech_pvt, rtmp_session_t *rtmp_session, switch_core_session_t *session);
+rtmp_profile_t *rtmp_profile_locate(const char *name);
+void rtmp_profile_release(rtmp_profile_t *profile);
+
+/**** I/O ****/
+switch_status_t rtmp_tcp_init(rtmp_profile_t *profile, const char *bindaddr, rtmp_io_t **new_io, switch_memory_pool_t *pool);
+switch_status_t rtmp_session_request(rtmp_profile_t *profile, rtmp_session_t **newsession);
+switch_status_t rtmp_session_destroy(rtmp_session_t **session);
+
+/**** Protocol ****/
+void rtmp_set_chunksize(rtmp_session_t *rsession, uint32_t chunksize);
+switch_status_t rtmp_send_invoke(rtmp_session_t *rsession, uint8_t amfnumber, uint32_t timestamp, uint32_t stream_id, ...);
+switch_status_t rtmp_send_invoke_free(rtmp_session_t *rsession, uint8_t amfnumber, uint32_t timestamp, uint32_t stream_id, ...);
+switch_status_t rtmp_send_notify(rtmp_session_t *rsession, uint8_t amfnumber, uint32_t timestamp, uint32_t stream_id, ...);
+switch_status_t rtmp_send_notify_free(rtmp_session_t *rsession, uint8_t amfnumber, uint32_t timestamp, uint32_t stream_id, ...);
+switch_status_t rtmp_send_invoke_v(rtmp_session_t *rsession, uint8_t amfnumber, uint8_t type, uint32_t timestamp, uint32_t stream_id, va_list list, switch_bool_t freethem);
+switch_status_t rtmp_send_message(rtmp_session_t *rsession, uint8_t amfnumber, uint32_t timestamp, uint8_t type, uint32_t stream_id, const unsigned char *message, switch_size_t len, uint32_t flags);
+
+void rtmp_send_event(rtmp_session_t *rsession, switch_event_t *event);
+void rtmp_notify_call_state(switch_core_session_t *session);
+void rtmp_send_display_update(switch_core_session_t *session);
+void rtmp_send_incoming_call(switch_core_session_t *session);
+void rtmp_send_onhangup(switch_core_session_t *session);
+void rtmp_add_registration(rtmp_session_t *rsession, const char *auth, const char *nickname);
+void rtmp_clear_registration(rtmp_session_t *rsession, const char *auth, const char *nickname);
+/* Attaches an rtmp session to one of its calls, use NULL to hold everything */
+void rtmp_attach_private(rtmp_session_t *rsession, rtmp_private_t *tech_pvt);
+rtmp_private_t *rtmp_locate_private(rtmp_session_t *rsession, const char *uuid);
+void rtmp_ping(rtmp_session_t *rsession);
+
+void rtmp_session_send_onattach(rtmp_session_t *rsession);
+
+/* Protocol handler */
+switch_status_t rtmp_handle_data(rtmp_session_t *rsession);
+
+#endif /* defined(MOD_RTMP_H) */
+
+/* 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:
+ */
diff --git a/src/mod/endpoints/mod_rtmp/rtmp.c b/src/mod/endpoints/mod_rtmp/rtmp.c
new file mode 100644
index 0000000000..724e1b064f
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/rtmp.c
@@ -0,0 +1,913 @@
+/*
+ * mod_rtmp for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2011, Barracuda Networks Inc.
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mod_rtmp for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is Barracuda Networks Inc.
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Mathieu Rene
+ *
+ * rtmp.c -- RTMP Protocol Handler
+ *
+ */
+
+#include "mod_rtmp.h"
+
+typedef struct {
+ unsigned char *buf;
+ size_t pos;
+ size_t len;
+} buffer_helper_t;
+
+size_t my_buffer_read(void * out_buffer, size_t size, void * user_data)
+{
+ buffer_helper_t *helper = (buffer_helper_t*)user_data;
+ size_t len = (helper->len - helper->pos) < size ? (helper->len - helper->pos) : size;
+ if (len <= 0) {
+ return 0;
+ }
+ memcpy(out_buffer, helper->buf + helper->pos, len);
+ helper->pos += len;
+ return len;
+}
+
+size_t my_buffer_write(const void *buffer, size_t size, void * user_data)
+{
+ buffer_helper_t *helper = (buffer_helper_t*)user_data;
+ size_t len = (helper->len - helper->pos) < size ? (helper->len - helper->pos) : size;
+ if (len <= 0) {
+ return 0;
+ }
+ memcpy(helper->buf + helper->pos, buffer, len);
+ helper->pos += len;
+ return len;
+}
+
+void rtmp_handle_control(rtmp_session_t *rsession, int amfnumber)
+{
+ rtmp_state_t *state = &rsession->amfstate[amfnumber];
+ char buf[200] = { 0 };
+ char *p = buf;
+ int type = state->buf[0] << 8 | state->buf[1];
+ int i;
+
+ for (i = 2; i < state->origlen; i++) {
+ p += sprintf(p, "%02x ", state->buf[i] & 0xFF);
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Control (%d): %s\n", type, buf);
+
+ switch(type) {
+ case RTMP_CTRL_STREAM_BEGIN:
+ break;
+ case RTMP_CTRL_PING_REQUEST:
+ {
+ unsigned char buf[] = {
+ INT16(RTMP_CTRL_PING_RESPONSE),
+ state->buf[2], state->buf[3], state->buf[4], state->buf[5]
+ };
+ rtmp_send_message(rsession, amfnumber, 0, RTMP_TYPE_USERCTRL, 0, buf, sizeof(buf), 0);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Ping request\n");
+ }
+ break;
+ case RTMP_CTRL_PING_RESPONSE:
+ {
+ uint32_t now = ((switch_micro_time_now()/1000) & 0xFFFFFFFF);
+ uint32_t sent = state->buf[2] << 24 | state->buf[3] << 16 | state->buf[4] << 8 | state->buf[5];
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Ping reply: %d ms\n", (int)(now - sent));
+ }
+ break;
+ default:
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "[amfnumber=%d] Unhandled control packet (type=0x%x)\n",
+ amfnumber, type);
+ }
+}
+
+void rtmp_handle_invoke(rtmp_session_t *rsession, int amfnumber)
+{
+ rtmp_state_t *state = &rsession->amfstate[amfnumber];
+ //amf0_data *dump;
+ int i = 0;
+ buffer_helper_t helper = { state->buf, 0, state->origlen };
+ int64_t transaction_id;
+ const char *command;
+ int argc = 0;
+ amf0_data *argv[100] = { 0 };
+ rtmp_invoke_function_t function;
+
+#if 0
+ printf(">>>>> BEGIN INVOKE MSG (num=0x%02x, type=0x%02x, stream_id=0x%x)\n", amfnumber, state->type, state->stream_id);
+ while((dump = amf0_data_read(my_buffer_read, &helper))) {
+ amf0_data *dump2;
+ printf("ELM> ");
+ amf0_data_dump(stdout, dump, 0);
+ printf("\n");
+ while ((dump2 = amf0_data_read(my_buffer_read, &helper))) {
+ printf("ELM> ");
+ amf0_data_dump(stdout, dump2, 0);
+ printf("\n");
+ amf0_data_free(dump2);
+ }
+ amf0_data_free(dump);
+ }
+ printf("<<<<< END AMF MSG\n");
+#endif
+
+#ifdef RTMP_DEBUG_IO
+ {
+ helper.pos = 0;
+
+ fprintf(rsession->io_debug_in, ">>>>> BEGIN INVOKE MSG (chunk_stream=0x%02x, type=0x%02x, stream_id=0x%x)\n", amfnumber, state->type, state->stream_id);
+ while((dump = amf0_data_read(my_buffer_read, &helper))) {
+ amf0_data *dump2;
+ fprintf(rsession->io_debug_in, "ELM> ");
+ amf0_data_dump(rsession->io_debug_in, dump, 0);
+ fprintf(rsession->io_debug_in, "\n");
+ while ((dump2 = amf0_data_read(my_buffer_read, &helper))) {
+ fprintf(rsession->io_debug_in, "ELM> ");
+ amf0_data_dump(rsession->io_debug_in, dump2, 0);
+ fprintf(rsession->io_debug_in, "\n");
+ amf0_data_free(dump2);
+ }
+ amf0_data_free(dump);
+ }
+ fprintf(rsession->io_debug_in, "<<<<< END AMF MSG\n");
+ fflush(rsession->io_debug_in);
+ }
+#endif
+
+ helper.pos = 0;
+ while (argc < switch_arraylen(argv) && (argv[argc++] = amf0_data_read(my_buffer_read, &helper)));
+
+ if (!(command = amf0_get_string(argv[i++]))) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Bogus INVOKE request\n");
+ return;
+ }
+
+ transaction_id = amf0_get_number(argv[i++]);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[amfnumber=%d] Got INVOKE for %s\n", amfnumber,
+ command);
+
+ if ((function = (rtmp_invoke_function_t)(intptr_t)switch_core_hash_find(rtmp_globals.invoke_hash, command))) {
+ function(rsession, state, amfnumber, transaction_id, argc - 2, argv + 2);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_WARNING, "Unhandled invoke for \"%s\"\n",
+ command);
+ }
+
+ /* Free all the AMF data we've read */
+ for (i = 0; i < argc; i++) {
+ amf0_data_free(argv[i]);
+ }
+}
+
+switch_status_t rtmp_check_auth(rtmp_session_t *rsession, const char *user, const char *domain, const char *authmd5)
+{
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ char *auth;
+ char md5[SWITCH_MD5_DIGEST_STRING_SIZE];
+ switch_xml_t xml = NULL, x_param, x_params;
+ switch_bool_t allow_empty_password = SWITCH_FALSE;
+ const char *passwd = NULL;
+
+ /* Locate user */
+ if (switch_xml_locate_user_merged("id", user, domain, NULL, &xml, NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_WARNING, "Authentication failed. No such user %s@%s\n", user, domain);
+ goto done;
+ }
+
+ if ((x_params = switch_xml_child(xml, "params"))) {
+ for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
+ const char *var = switch_xml_attr_soft(x_param, "name");
+ const char *val = switch_xml_attr_soft(x_param, "value");
+
+ if (!strcasecmp(var, "password")) {
+ passwd = val;
+ }
+ if (!strcasecmp(var, "allow-empty-password")) {
+ allow_empty_password = switch_true(val);
+ }
+ }
+ }
+
+ if (zstr(passwd)) {
+ if (allow_empty_password) {
+ status = SWITCH_STATUS_SUCCESS;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_WARNING, "Authentication failed for %s@%s: empty password not allowed\n", user, switch_str_nil(domain));
+ }
+ goto done;
+ }
+
+ auth = switch_core_sprintf(rsession->pool, "%s:%s@%s:%s", rsession->uuid, user, domain, passwd);
+ switch_md5_string(md5, auth, strlen(auth));
+
+ if (!strncmp(md5, authmd5, SWITCH_MD5_DIGEST_STRING_SIZE)) {
+ status = SWITCH_STATUS_SUCCESS;
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_WARNING, "Authentication failed for %s@%s\n", user, domain);
+ }
+
+done:
+ if (xml) {
+ switch_xml_free(xml);
+ }
+ return status;
+}
+
+switch_status_t amf_object_to_event(amf0_data *obj, switch_event_t **event)
+{
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+
+ if (obj && obj->type == AMF0_TYPE_OBJECT) {
+ amf0_node *node;
+ if (!*event) {
+ if ((status = switch_event_create(event, SWITCH_EVENT_CUSTOM)) != SWITCH_STATUS_SUCCESS) {
+ return status;
+ }
+ }
+
+ for (node = amf0_object_first(obj); node; node = amf0_object_next(node)) {
+ const char *name = amf0_get_string(amf0_object_get_name(node));
+ const char *value = amf0_get_string(amf0_object_get_data(node));
+
+ if (!zstr(name) && !zstr(value)) {
+ if (!strcmp(name, "_body")) {
+ switch_event_add_body(*event, "%s", value);
+ } else {
+ switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, name, value);
+ }
+ }
+ }
+ } else {
+ status = SWITCH_STATUS_FALSE;
+ }
+
+ return status;
+}
+
+switch_status_t amf_event_to_object(amf0_data **obj, switch_event_t *event)
+{
+ switch_event_header_t *hp;
+ const char *body;
+
+ switch_assert(event);
+ switch_assert(obj);
+
+ if (!*obj) {
+ *obj = amf0_object_new();
+ }
+
+ for (hp = event->headers; hp; hp = hp->next) {
+ amf0_object_add(*obj, hp->name, amf0_str(hp->value));
+ }
+
+ body = switch_event_get_body(event);
+ if (!zstr(body)) {
+ amf0_object_add(*obj, "_body", amf0_str(body));
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+void rtmp_set_chunksize(rtmp_session_t *rsession, uint32_t chunksize)
+{
+ if (rsession->out_chunksize != chunksize) {
+ unsigned char buf[] = {
+ INT32(chunksize)
+ };
+
+ rtmp_send_message(rsession, 2 /*amfnumber*/, 0, RTMP_TYPE_CHUNKSIZE, 0, buf, sizeof(buf), MSG_FULLHEADER);
+ rsession->out_chunksize = chunksize;
+ }
+}
+
+void rtmp_get_user_variables(switch_event_t **event, switch_core_session_t *session)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_event_header_t *he;
+
+ if (!*event && switch_event_create(event, SWITCH_EVENT_CLONE) != SWITCH_STATUS_SUCCESS) {
+ return;
+ }
+
+ if ((he = switch_channel_variable_first(channel))) {
+ for (; he; he = he->next) {
+ if (!strncmp(he->name, RTMP_USER_VARIABLE_PREFIX, strlen(RTMP_USER_VARIABLE_PREFIX))) {
+ switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, he->name, he->value);
+ }
+ }
+ switch_channel_variable_last(channel);
+ }
+}
+
+void rtmp_session_send_onattach(rtmp_session_t *rsession)
+{
+ const char *uuid = "";
+
+ if (rsession->tech_pvt) {
+ uuid = switch_core_session_get_uuid(rsession->tech_pvt->session);
+ }
+
+ rtmp_send_invoke_free(rsession, 3, 0, 0,
+ amf0_str("onAttach"),
+ amf0_number_new(0),
+ amf0_null_new(),
+ amf0_str(uuid), NULL);
+
+}
+
+void rtmp_send_display_update(switch_core_session_t *session)
+{
+ rtmp_private_t *tech_pvt = switch_core_session_get_private(session);
+
+ rtmp_send_invoke_free(tech_pvt->rtmp_session, 3, 0, 0,
+ amf0_str("displayUpdate"),
+ amf0_number_new(0),
+ amf0_null_new(),
+ amf0_str(switch_core_session_get_uuid(session)),
+ amf0_str(switch_str_nil(tech_pvt->display_callee_id_name)),
+ amf0_str(switch_str_nil(tech_pvt->display_callee_id_number)), NULL);
+}
+
+void rtmp_send_incoming_call(switch_core_session_t *session)
+{
+ rtmp_private_t *tech_pvt = switch_core_session_get_private(session);
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_caller_profile_t *caller_profile = switch_channel_get_caller_profile(channel);
+ switch_event_t *event = NULL;
+ amf0_data *obj = NULL;
+
+ rtmp_get_user_variables(&event, session);
+
+ if (event) {
+ amf_event_to_object(&obj, event);
+ switch_event_destroy(&event);
+ }
+
+ rtmp_send_invoke_free(tech_pvt->rtmp_session, 3, 0, 0,
+ amf0_str("incomingCall"),
+ amf0_number_new(0),
+ amf0_null_new(),
+ amf0_str(switch_core_session_get_uuid(session)),
+ amf0_str(switch_str_nil(caller_profile->caller_id_name)),
+ amf0_str(switch_str_nil(caller_profile->caller_id_number)),
+ !zstr(tech_pvt->auth) ? amf0_str(tech_pvt->auth) : amf0_null_new(),
+ obj ? obj : amf0_null_new(), NULL);
+}
+
+void rtmp_send_onhangup(switch_core_session_t *session)
+{
+ rtmp_private_t *tech_pvt = switch_core_session_get_private(session);
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+
+ rtmp_send_invoke_free(tech_pvt->rtmp_session, 3, 0, 0,
+ amf0_str("onHangup"),
+ amf0_number_new(0),
+ amf0_null_new(),
+ amf0_str(switch_core_session_get_uuid(session)),
+ amf0_str(switch_channel_cause2str(switch_channel_get_cause(channel))), NULL);
+}
+
+void rtmp_send_event(rtmp_session_t *rsession, switch_event_t *event)
+{
+ amf0_data *obj = NULL;
+
+ switch_assert(event != NULL);
+ switch_assert(rsession != NULL);
+
+ if (amf_event_to_object(&obj, event) == SWITCH_STATUS_SUCCESS) {
+ rtmp_send_invoke_free(rsession, 3, 0, 0, amf0_str("event"), amf0_number_new(0), amf0_null_new(), obj, NULL);
+ }
+}
+
+void rtmp_ping(rtmp_session_t *rsession)
+{
+ uint32_t now = (uint32_t)((switch_micro_time_now() / 1000) & 0xFFFFFFFF);
+ unsigned char buf[] = {
+ INT16(RTMP_CTRL_PING_REQUEST),
+ INT32(now)
+ };
+ rtmp_send_message(rsession, 2, 0, RTMP_TYPE_USERCTRL, 0, buf, sizeof(buf), 0);
+}
+
+void rtmp_notify_call_state(switch_core_session_t *session)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ const char *state = switch_channel_callstate2str(switch_channel_get_callstate(channel));
+ rtmp_private_t *tech_pvt = switch_core_session_get_private(session);
+
+ rtmp_send_invoke_free(tech_pvt->rtmp_session, 3, 0, 0,
+ amf0_str("callState"),
+ amf0_number_new(0),
+ amf0_null_new(),
+ amf0_str(switch_core_session_get_uuid(session)),
+ amf0_str(state), NULL);
+}
+
+switch_status_t rtmp_send_invoke(rtmp_session_t *rsession, uint8_t amfnumber, uint32_t timestamp, uint32_t stream_id, ...)
+{
+ switch_status_t s;
+ va_list list;
+ va_start(list, stream_id);
+ s = rtmp_send_invoke_v(rsession, amfnumber, RTMP_TYPE_INVOKE, timestamp, stream_id, list, SWITCH_FALSE);
+ va_end(list);
+ return s;
+}
+
+switch_status_t rtmp_send_invoke_free(rtmp_session_t *rsession, uint8_t amfnumber, uint32_t timestamp, uint32_t stream_id, ...)
+{
+ switch_status_t s;
+ va_list list;
+ va_start(list, stream_id);
+ s = rtmp_send_invoke_v(rsession, amfnumber, RTMP_TYPE_INVOKE, timestamp, stream_id, list, SWITCH_TRUE);
+ va_end(list);
+ return s;
+}
+
+switch_status_t rtmp_send_notify(rtmp_session_t *rsession, uint8_t amfnumber, uint32_t timestamp, uint32_t stream_id, ...)
+{
+ switch_status_t s;
+ va_list list;
+ va_start(list, stream_id);
+ s = rtmp_send_invoke_v(rsession, amfnumber, RTMP_TYPE_NOTIFY, timestamp, stream_id, list, SWITCH_FALSE);
+ va_end(list);
+ return s;
+}
+
+switch_status_t rtmp_send_notify_free(rtmp_session_t *rsession, uint8_t amfnumber, uint32_t timestamp, uint32_t stream_id, ...)
+{
+ switch_status_t s;
+ va_list list;
+ va_start(list, stream_id);
+ s = rtmp_send_invoke_v(rsession, amfnumber, RTMP_TYPE_NOTIFY, timestamp, stream_id, list, SWITCH_TRUE);
+ va_end(list);
+ return s;
+}
+
+
+
+switch_status_t rtmp_send_invoke_v(rtmp_session_t *rsession, uint8_t amfnumber, uint8_t type, uint32_t timestamp, uint32_t stream_id, va_list list, switch_bool_t freethem)
+{
+ amf0_data *data;
+ unsigned char buf[AMF_MAX_SIZE];
+ buffer_helper_t helper = { buf, 0, AMF_MAX_SIZE };
+
+ while ((data = va_arg(list, amf0_data*))) {
+ //amf0_data_dump(stdout, data, 0);
+ //printf("\n");
+ amf0_data_write(data, my_buffer_write, &helper);
+ if (freethem) {
+ amf0_data_free(data);
+ }
+ }
+ return rtmp_send_message(rsession, amfnumber, timestamp, type, stream_id, buf, helper.pos, 0);
+}
+
+/* Break message down into 128 bytes chunks, add the appropriate headers and send it out */
+switch_status_t rtmp_send_message(rtmp_session_t *rsession, uint8_t amfnumber, uint32_t timestamp, uint8_t type, uint32_t stream_id, const unsigned char *message, switch_size_t len, uint32_t flags)
+{
+ switch_size_t pos = 0;
+ uint8_t header[12] = { amfnumber & 0x3F, INT24(0), INT24(len), type, INT32_LE(stream_id) };
+ switch_size_t chunksize;
+ uint8_t microhdr = (3 << 6) | amfnumber;
+ switch_size_t hdrsize = 1;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ rtmp_state_t *state = &rsession->amfstate_out[amfnumber];
+
+ if ((rsession->send_ack + rsession->send_ack_window) < rsession->send &&
+ (type == RTMP_TYPE_VIDEO || type == RTMP_TYPE_AUDIO)) {
+ /* We're sending too fast, drop the frame */
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "DROP %s FRAME [amfnumber=%d type=0x%x stream_id=0x%x] len=%"SWITCH_SIZE_T_FMT" \n",
+ type == RTMP_TYPE_AUDIO ? "AUDIO" : "VIDEO", amfnumber, type, stream_id, len);
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (type != RTMP_TYPE_AUDIO && type != RTMP_TYPE_VIDEO && type != RTMP_TYPE_ACK) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[amfnumber=%d type=0x%x stream_id=0x%x] len=%"SWITCH_SIZE_T_FMT" \n", amfnumber, type, stream_id, len);
+ }
+
+#ifdef RTMP_DEBUG_IO
+ {
+ fprintf(rsession->io_debug_out, "[amfnumber=%d type=0x%x stream_id=0x%x] len=%"SWITCH_SIZE_T_FMT" \n", amfnumber, type, stream_id, len);
+ if (type == RTMP_TYPE_INVOKE || type == RTMP_TYPE_NOTIFY) {
+ buffer_helper_t helper = { (unsigned char*)message, 0, len };
+ amf0_data *dump;
+ while((dump = amf0_data_read(my_buffer_read, &helper))) {
+ amf0_data *dump2;
+ fprintf(rsession->io_debug_out, "ELM> ");
+ amf0_data_dump(rsession->io_debug_out, dump, 0);
+ fprintf(rsession->io_debug_out, "\n");
+ while ((dump2 = amf0_data_read(my_buffer_read, &helper))) {
+ fprintf(rsession->io_debug_out, "ELM> ");
+ amf0_data_dump(rsession->io_debug_out, dump2, 0);
+ fprintf(rsession->io_debug_out, "\n");
+ amf0_data_free(dump2);
+ }
+ amf0_data_free(dump);
+ }
+ fprintf(rsession->io_debug_out, "<<<<< END AMF MSG\n");
+ }
+ fflush(rsession->io_debug_out);
+
+ }
+#endif
+
+ /* Find out what is the smallest header we can use */
+ if (!(flags & MSG_FULLHEADER) && stream_id > 0 && state->stream_id == stream_id && timestamp >= state->ts) {
+ if (state->type == type && state->origlen == len) {
+ if (state->ts == timestamp) {
+ /* Type 3: no header! */
+ hdrsize = 1;
+ header[0] |= 3 << 6;
+ } else {
+ uint32_t delta = timestamp - state->ts;
+ /* Type 2: timestamp delta */
+ hdrsize = 4;
+ header[0] |= 2 << 6;
+ header[1] = (delta >> 16) & 0xFF;
+ header[2] = (delta >> 8) & 0xFF;
+ header[3] = delta & 0xFF;
+ }
+ } else {
+ /* Type 1: ts delta + msg len + type */
+ uint32_t delta = timestamp - state->ts;
+ hdrsize = 8;
+ header[0] |= 1 << 6;
+ header[1] = (delta >> 16) & 0xFF;
+ header[2] = (delta >> 8) & 0xFF;
+ header[3] = delta & 0xFF;
+ }
+ } else {
+ hdrsize = 12; /* Type 0, full header */
+ header[1] = (timestamp >> 16) & 0xFF;
+ header[2] = (timestamp >> 8) & 0xFF;
+ header[3] = timestamp & 0xFF;
+ }
+
+ state->ts = timestamp;
+ state->type = type;
+ state->origlen = len;
+ state->stream_id = stream_id;
+
+ switch_mutex_lock(rsession->socket_mutex);
+ chunksize = (len - pos) < rsession->out_chunksize ? (len - pos) : rsession->out_chunksize;
+ if (rsession->profile->io->write(rsession, (unsigned char*)header, &hdrsize) != SWITCH_STATUS_SUCCESS) {
+ switch_goto_status(SWITCH_STATUS_FALSE, end);
+ }
+ rsession->send += hdrsize;
+
+ /* Write one chunk of data */
+ if (rsession->profile->io->write(rsession, (unsigned char*)message, &chunksize) != SWITCH_STATUS_SUCCESS) {
+ switch_goto_status(SWITCH_STATUS_FALSE, end);
+ }
+ rsession->send += chunksize;
+ pos += chunksize;
+
+ /* Send more chunks if we need to */
+ while (((signed)len - (signed)pos) > 0) {
+ switch_mutex_unlock(rsession->socket_mutex);
+ /* Let other threads send data on the socket */
+ switch_mutex_lock(rsession->socket_mutex);
+ hdrsize = 1;
+ if (rsession->profile->io->write(rsession, (unsigned char*)µhdr, &hdrsize) != SWITCH_STATUS_SUCCESS) {
+ switch_goto_status(SWITCH_STATUS_FALSE, end);
+ }
+ rsession->send += hdrsize;
+
+ chunksize = (len - pos) < rsession->out_chunksize ? (len - pos) : rsession->out_chunksize;
+
+ if (rsession->profile->io->write(rsession, message + pos, &chunksize) != SWITCH_STATUS_SUCCESS) {
+ switch_goto_status(SWITCH_STATUS_FALSE, end);
+ }
+ rsession->send += chunksize;
+ pos += chunksize;
+ }
+end:
+ switch_mutex_unlock(rsession->socket_mutex);
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/* Returns SWITCH_STATUS_SUCCESS of the connection is still active or SWITCH_STATUS_FALSE to tear it down */
+switch_status_t rtmp_handle_data(rtmp_session_t *rsession)
+{
+ uint8_t buf[RTMP_TCP_READ_BUF];
+ switch_size_t s = RTMP_TCP_READ_BUF;
+
+ if (rsession->state == RS_HANDSHAKE) {
+ s = 1537 - rsession->hspos;
+
+ if (rsession->profile->io->read(rsession, rsession->hsbuf + rsession->hspos, &s) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read error\n");
+ return SWITCH_STATUS_FALSE;
+ }
+
+ rsession->hspos += s;
+
+ /* Receive C0 and C1 */
+ if (rsession->hspos < 1537) {
+ /* Not quite there yet */
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ /* Send reply (S0 + S1) */
+ memset(buf, 0, sizeof(buf));
+ *buf = '\x03';
+ s = 1537;
+ rsession->profile->io->write(rsession, (unsigned char*)buf, &s);
+
+ /* Send S2 */
+ s = 1536;
+ rsession->profile->io->write(rsession, rsession->hsbuf, &s);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sent handshake response\n");
+
+ rsession->state++;
+ rsession->hspos = 0;
+ } else if (rsession->state == RS_HANDSHAKE2) {
+ s = 1536 - rsession->hspos;
+
+ /* Receive C2 */
+ if (rsession->profile->io->read(rsession, rsession->hsbuf + rsession->hspos, &s) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read error\n");
+ return SWITCH_STATUS_FALSE;
+ }
+
+ rsession->hspos += s;
+
+ if (rsession->hspos < 1536) {
+ /* Not quite there yet */
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ rsession->state++;
+
+ //s = 1536;
+ //rsession->profile->io->write(rsession, (char*)buf, &s);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Done with handshake\n");
+
+
+ return SWITCH_STATUS_SUCCESS;
+ } else if (rsession->state == RS_ESTABLISHED) {
+ /* Process RTMP packet */
+ switch(rsession->parse_state) {
+ case 0:
+ // Read the header's first byte
+ s = 1;
+ if (rsession->profile->io->read(rsession, (unsigned char*)buf, &s) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read error\n");
+ return SWITCH_STATUS_FALSE;
+ }
+
+ rsession->recv += s;
+
+ switch(buf[0] >> 6) {
+ case 0:
+ rsession->hdrsize = 12;
+ break;
+ case 1:
+ rsession->hdrsize = 8;
+ break;
+ case 2:
+ rsession->hdrsize = 4;
+ break;
+ case 3:
+ rsession->hdrsize = 1;
+ break;
+ default:
+ rsession->hdrsize = 0;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "WTF hdrsize 0x%02x %d\n", *buf, *buf >> 6);
+ return SWITCH_STATUS_FALSE;
+ }
+ rsession->amfnumber = buf[0] & 0x3F; /* Get rid of the 2 first bits */
+ if (rsession->amfnumber > 64) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Protocol error\n");
+ return SWITCH_STATUS_FALSE;
+ }
+ //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Header size: %d AMF Number: %d\n", rsession->hdrsize, rsession->amfnumber);
+ rsession->parse_state++;
+ if (rsession->hdrsize == 1) {
+ /* Skip header fetch on one-byte headers since we have it already */
+ rsession->parse_state++;
+ }
+ rsession->parse_remain = 0;
+ break;
+
+ case 1:
+ {
+ /* Read full header and decode */
+ rtmp_state_t *state = &rsession->amfstate[rsession->amfnumber];
+ uint8_t *hdr = (uint8_t*)state->header.sz;
+ unsigned char *readbuf = (unsigned char*)hdr;
+
+ if (!rsession->parse_remain) {
+ rsession->parse_remain = s = rsession->hdrsize - 1;
+ } else {
+ s = rsession->parse_remain;
+ readbuf += (rsession->hdrsize - 1) - s;
+ }
+
+ switch_assert(s < 12 && s > 0); /** XXX **/
+
+ if (rsession->profile->io->read(rsession, readbuf, &s) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read error\n");
+ return SWITCH_STATUS_FALSE;
+ }
+
+ rsession->parse_remain -= s;
+ if (rsession->parse_remain > 0) {
+ /* More data please */
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ rsession->recv += s;
+
+ if (rsession->hdrsize == 12) {
+ state->ts = (hdr[0] << 16) | (hdr[1] << 8) | (hdr[2]);
+ state->ts_delta = 0;
+ } else if (rsession->hdrsize >= 4) {
+ /* Save the timestamp delta since we have to re-use it with type 3 headers */
+ state->ts_delta = (hdr[0] << 16) | (hdr[1] << 8) | (hdr[2]);
+ state->ts += state->ts_delta;
+ } else if (rsession->hdrsize == 1) {
+ /* Type 3: Re-use timestamp delta if we have one */
+ state->ts += state->ts_delta;
+ }
+
+ if (rsession->hdrsize >= 8) {
+ /* Reset length counter since its included in the header */
+ state->remainlen = state->origlen = (hdr[3] << 16) | (hdr[4] << 8) | (hdr[5]);
+ state->buf_pos = 0;
+ state->type = hdr[6];
+ }
+ if (rsession->hdrsize == 12) {
+ state->stream_id = (hdr[10] << 24) | (hdr[9] << 16) | (hdr[8] << 8) | hdr[7];
+ }
+
+ if (rsession->hdrsize >= 8 && state->origlen == 0) {
+ /* Happens we sometimes get a 0 length packet */
+ rsession->parse_state = 0;
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ /* FIXME: Handle extended timestamps */
+ if (state->ts == 0x00ffffff) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ rsession->parse_state++;
+ }
+ case 2:
+ {
+ rtmp_state_t *state = &rsession->amfstate[rsession->amfnumber];
+
+ if (rsession->parse_remain > 0) {
+ s = rsession->parse_remain;
+ } else {
+ s = state->remainlen < rsession->in_chunksize ? state->remainlen : rsession->in_chunksize;
+ rsession->parse_remain = s;
+ }
+
+ if (!s) {
+ /* Restart from beginning */
+ s = state->remainlen = state->origlen;
+ rsession->parse_remain = s;
+ if (!s) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Protocol error, forcing big read\n");
+ s = sizeof(state->buf);
+ rsession->profile->io->read(rsession, state->buf, &s);
+ return SWITCH_STATUS_FALSE;
+ }
+ }
+
+ /* Sanity check */
+ if ((state->buf_pos + s) > AMF_MAX_SIZE) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "WTF %"SWITCH_SIZE_T_FMT" %"SWITCH_SIZE_T_FMT"\n",
+ state->buf_pos, s);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Protocol error: exceeding max AMF packet size\n");
+ return SWITCH_STATUS_FALSE;
+ }
+
+ switch_assert(s <= rsession->in_chunksize);
+
+ if (rsession->profile->io->read(rsession, state->buf + state->buf_pos, &s) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Read error\n");
+ return SWITCH_STATUS_FALSE;
+ }
+ rsession->recv += s;
+
+ state->remainlen -= s;
+ rsession->parse_remain -= s;
+ state->buf_pos += s;
+
+ if (rsession->parse_remain > 0) {
+ /* Need more data */
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (state->remainlen == 0) {
+
+ if (state->type != RTMP_TYPE_AUDIO && state->type != RTMP_TYPE_VIDEO && state->type != RTMP_TYPE_ACK) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[chunk_stream=%d type=0x%x ts=%d stream_id=0x%x] len=%d\n", rsession->amfnumber, state->type, (int)state->ts, state->stream_id, state->origlen);
+ }
+#ifdef RTMP_DEBUG_IO
+ fprintf(rsession->io_debug_in, "[chunk_stream=%d type=0x%x ts=%d stream_id=0x%x] len=%d\n", rsession->amfnumber, state->type, (int)state->ts, state->stream_id, state->origlen);
+#endif
+ switch(state->type) {
+ case RTMP_TYPE_CHUNKSIZE:
+ rsession->in_chunksize = state->buf[0] << 24 | state->buf[1] << 16 | state->buf[2] << 8 | state->buf[3];
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SET CHUNKSIZE=%d\n", (int)rsession->in_chunksize);
+ break;
+ case RTMP_TYPE_USERCTRL:
+ rtmp_handle_control(rsession, rsession->amfnumber);
+ break;
+ case RTMP_TYPE_INVOKE:
+ rtmp_handle_invoke(rsession, rsession->amfnumber);
+ break;
+ case RTMP_TYPE_AUDIO: /* Audio data */
+ if (rsession->tech_pvt) {
+ uint16_t len = state->origlen;
+ switch_mutex_lock(rsession->tech_pvt->readbuf_mutex);
+ switch_buffer_write(rsession->tech_pvt->readbuf, &len, 2);
+ switch_buffer_write(rsession->tech_pvt->readbuf, state->buf, len);
+ switch_mutex_unlock(rsession->tech_pvt->readbuf_mutex);
+ }
+ break;
+ case RTMP_TYPE_VIDEO: /* Video data */
+ case RTMP_TYPE_METADATA: /* Metadata */
+ break;
+ case RTMP_TYPE_WINDOW_ACK_SIZE:
+ rsession->send_ack_window = (state->buf[0] << 24) | (state->buf[1] << 16) | (state->buf[2] << 8) | (state->buf[3]);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Set window size: %lu bytes\n", (long unsigned int)rsession->send_ack_window);
+ break;
+ case RTMP_TYPE_ACK:
+ {
+ switch_time_t now = switch_micro_time_now();
+ uint32_t ack = (state->buf[0] << 24) | (state->buf[1] << 16) | (state->buf[2] << 8) | (state->buf[3]);
+ uint32_t delta = rsession->send_ack_ts == 0 ? 0 : now - rsession->send_ack_ts;
+
+ delta /= 1000000; /* microseconds -> seconds */
+
+ if (delta) {
+ rsession->send_bw = (ack - rsession->send_ack) / delta;
+ }
+
+ rsession->send_ack = ack;
+ rsession->send_ack_ts = switch_micro_time_now();
+ break;
+ }
+ default:
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot handle message type 0x%x\n", state->type);
+ break;
+ }
+ state->buf_pos = 0;
+ }
+
+ rsession->parse_state = 0;
+
+ /* Send an ACK if we need to */
+ if (rsession->recv - rsession->recv_ack_sent >= rsession->recv_ack_window) {
+ unsigned char ackbuf[] = { INT32(rsession->recv) };
+
+ rtmp_send_message(rsession, 2/*chunkstream*/, 0/*ts*/, RTMP_TYPE_ACK, 0/*msg stream id */, ackbuf, sizeof(ackbuf), 0 /*flags*/);
+ rsession->recv_ack_sent = rsession->recv;
+ }
+
+ }
+ }
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/* 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:
+ */
diff --git a/src/mod/endpoints/mod_rtmp/rtmp_sig.c b/src/mod/endpoints/mod_rtmp/rtmp_sig.c
new file mode 100644
index 0000000000..ece43bc050
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/rtmp_sig.c
@@ -0,0 +1,841 @@
+/*
+ * mod_rtmp for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2011, Barracuda Networks Inc.
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mod_rtmp for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is Barracuda Networks Inc.
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Mathieu Rene
+ *
+ * rtmp.c -- RTMP Signalling functions
+ *
+ */
+
+#include "mod_rtmp.h"
+
+/* AMF */
+#include "amf0.h"
+#include "io.h"
+#include "types.h"
+
+/* RTMP_INVOKE_FUNCTION is a macro that expands to:
+switch_status_t function(rtmp_session_t *rsession, rtmp_state_t *state, int amfnumber, int transaction_id, int argc, amf0_data *argv[])
+*/
+
+RTMP_INVOKE_FUNCTION(rtmp_i_connect)
+{
+ amf0_data *object1 = amf0_object_new(), *object2 = amf0_object_new(), *params = argv[0], *d;
+ const char *s;
+
+ if ((d = amf0_object_get(params, "app")) && (s = amf0_get_string(d))) {
+ rsession->app = switch_core_strdup(rsession->pool, s);
+ }
+
+ if ((d = amf0_object_get(params, "flashVer")) && (s = amf0_get_string(d))) {
+ rsession->flashVer = switch_core_strdup(rsession->pool, s);
+ }
+ if ((d = amf0_object_get(params, "swfUrl")) && (s = amf0_get_string(d))) {
+ rsession->swfUrl = switch_core_strdup(rsession->pool, s);
+ }
+ if ((d = amf0_object_get(params, "tcUrl")) && (s = amf0_get_string(d))) {
+ rsession->tcUrl = switch_core_strdup(rsession->pool, s);
+ }
+ if ((d = amf0_object_get(params, "pageUrl")) && (s = amf0_get_string(d))) {
+ rsession->pageUrl = switch_core_strdup(rsession->pool, s);
+ }
+
+ if ((d = amf0_object_get(params, "capabilities"))) {
+ rsession->capabilities = amf0_get_number(d);
+ }
+ if ((d = amf0_object_get(params, "audioCodecs"))) {
+ rsession->audioCodecs = amf0_get_number(d);
+ }
+ if ((d = amf0_object_get(params, "videoCodecs"))) {
+ rsession->videoCodecs = amf0_get_number(d);
+ }
+ if ((d = amf0_object_get(params, "videoFunction"))) {
+ rsession->videoFunction = amf0_get_number(d);
+ }
+
+ amf0_object_add(object1, "fmsVer", amf0_number_new(1));
+ amf0_object_add(object1, "capabilities", amf0_number_new(31));
+
+ amf0_object_add(object2, "level", amf0_str("status"));
+ amf0_object_add(object2, "code", amf0_str("NetConnection.Connect.Success"));
+ amf0_object_add(object2, "description", amf0_str("Connection succeeded"));
+ amf0_object_add(object2, "clientId", amf0_number_new(217834719));
+ amf0_object_add(object2, "objectEncoding", amf0_number_new(0));
+
+ rtmp_set_chunksize(rsession, rsession->profile->chunksize);
+
+ {
+ unsigned char ackbuf[] = { INT32(RTMP_DEFAULT_ACK_WINDOW) };
+ rtmp_send_message(rsession, 2, 0, RTMP_TYPE_WINDOW_ACK_SIZE, 0, ackbuf, sizeof(ackbuf), MSG_FULLHEADER);
+ }
+
+ {
+ unsigned char ackbuf[] = { INT32(RTMP_DEFAULT_ACK_WINDOW), 0x1 /* Soft limit */};
+ rtmp_send_message(rsession, 2, 0, RTMP_TYPE_SET_PEER_BW, 0, ackbuf, sizeof(ackbuf), MSG_FULLHEADER);
+ }
+
+ {
+ unsigned char buf[] = {
+ INT16(RTMP_CTRL_STREAM_BEGIN),
+ INT32(0)
+ };
+
+ rtmp_send_message(rsession, 2, 0, RTMP_TYPE_USERCTRL, 0, buf, sizeof(buf), 0);
+ }
+
+ /* respond with a success message */
+ rtmp_send_invoke_free(rsession, amfnumber, 0, 0,
+ amf0_str("_result"),
+ amf0_number_new(1),
+ object1,
+ object2,
+ NULL);
+
+ rtmp_send_invoke_free(rsession, 3, 0, 0,
+ amf0_str("connected"),
+ amf0_number_new(0),
+ amf0_null_new(),
+ amf0_str(rsession->uuid), NULL);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Sent connect reply\n");
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+RTMP_INVOKE_FUNCTION(rtmp_i_createStream)
+{
+ rtmp_send_invoke_free(rsession, amfnumber, 0, 0,
+ amf0_str("_result"),
+ amf0_number_new(transaction_id),
+ amf0_null_new(),
+ amf0_number_new(rsession->next_streamid),
+ NULL);
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Replied to createStream (%u)\n", rsession->next_streamid);
+
+ rsession->next_streamid++;
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+RTMP_INVOKE_FUNCTION(rtmp_i_noop)
+{
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+RTMP_INVOKE_FUNCTION(rtmp_i_receiveaudio)
+{
+ switch_bool_t enabled = argv[1] ? amf0_boolean_get_value(argv[1]) : SWITCH_FALSE;
+
+ if (enabled) {
+ switch_set_flag(rsession, SFLAG_AUDIO);
+ } else {
+ switch_clear_flag(rsession, SFLAG_AUDIO);
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%sending audio\n", enabled ? "S" : "Not s");
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+RTMP_INVOKE_FUNCTION(rtmp_i_receivevideo)
+{
+ switch_bool_t enabled = argv[1] ? amf0_boolean_get_value(argv[1]) : SWITCH_FALSE;
+
+ if (enabled) {
+ switch_set_flag(rsession, SFLAG_VIDEO);
+ if (rsession->tech_pvt) {
+ switch_set_flag(rsession->tech_pvt, TFLAG_VID_WAIT_KEYFRAME);
+ }
+ } else {
+ switch_clear_flag(rsession, SFLAG_VIDEO);
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%sending video\n", enabled ? "S" : "Not s");
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+RTMP_INVOKE_FUNCTION(rtmp_i_play)
+{
+ amf0_data *obj = amf0_object_new();
+ amf0_data *object = amf0_object_new();
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Got play for %s on stream %d\n", switch_str_nil(amf0_get_string(argv[1])),
+ state->stream_id);
+
+ /* Set outgoing chunk size to 1024 bytes */
+ rtmp_set_chunksize(rsession, 1024);
+
+ rsession->media_streamid = state->stream_id;
+
+ /* Send StreamBegin on the current stream */
+ {
+ unsigned char buf[] = {
+ INT16(RTMP_CTRL_STREAM_BEGIN),
+ INT32(rsession->media_streamid)
+ };
+ rtmp_send_message(rsession, 2, 0, RTMP_TYPE_USERCTRL, 0, buf, sizeof(buf), 0);
+ }
+
+
+ {
+ unsigned char buf[] = {
+ INT16(RTMP_CTRL_SET_BUFFER_LENGTH),
+ INT32(rsession->media_streamid),
+ INT32(rsession->profile->buffer_len)
+ };
+ rtmp_send_message(rsession, 2, 0, RTMP_TYPE_USERCTRL, 0, buf, sizeof(buf), 0);
+ }
+
+ /* Send onStatus */
+ amf0_object_add(object, "level", amf0_str("status"));
+ amf0_object_add(object, "code", amf0_str("NetStream.Play.Reset"));
+ amf0_object_add(object, "description", amf0_str("description"));
+ amf0_object_add(object, "details", amf0_str("details"));
+ amf0_object_add(object, "clientid", amf0_number_new(217834719));
+
+ rtmp_send_invoke_free(rsession, RTMP_DEFAULT_STREAM_NOTIFY, 0, rsession->media_streamid,
+ amf0_str("onStatus"),
+ amf0_number_new(1),
+ amf0_null_new(),
+ object, NULL);
+
+ object = amf0_object_new();
+
+ amf0_object_add(object, "level", amf0_str("status"));
+ amf0_object_add(object, "code", amf0_str("NetStream.Play.Start"));
+ amf0_object_add(object, "description", amf0_str("description"));
+ amf0_object_add(object, "details", amf0_str("details"));
+ amf0_object_add(object, "clientid", amf0_number_new(217834719));
+
+ rtmp_send_invoke_free(rsession, RTMP_DEFAULT_STREAM_NOTIFY, 0, rsession->media_streamid,
+ amf0_str("onStatus"),
+ amf0_number_new(1),
+ amf0_null_new(),
+ object, NULL);
+
+ amf0_object_add(obj, "code", amf0_str("NetStream.Data.Start"));
+
+ rtmp_send_notify_free(rsession, RTMP_DEFAULT_STREAM_NOTIFY, 0, rsession->media_streamid,
+ amf0_str("onStatus"),
+ obj, NULL);
+
+ rtmp_send_notify_free(rsession, RTMP_DEFAULT_STREAM_NOTIFY, 0, rsession->media_streamid,
+ amf0_str("|RtmpSampleAccess"),
+ amf0_boolean_new(1),
+ amf0_boolean_new(1), NULL);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+RTMP_INVOKE_FUNCTION(rtmp_i_publish)
+{
+
+ unsigned char buf[] = {
+ INT16(RTMP_CTRL_STREAM_BEGIN),
+ INT32(state->stream_id)
+ };
+
+ rtmp_send_message(rsession, 2, 0, RTMP_TYPE_USERCTRL, 0, buf, sizeof(buf), 0);
+
+ rtmp_send_invoke_free(rsession, amfnumber, 0, 0,
+ amf0_str("_result"),
+ amf0_number_new(transaction_id),
+ amf0_null_new(),
+ amf0_null_new(),
+ NULL);
+
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Got publish on stream %u.\n", state->stream_id);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+RTMP_INVOKE_FUNCTION(rtmp_i_makeCall)
+{
+ switch_core_session_t *newsession = NULL;
+ char *number = NULL;
+
+ if ((number = amf0_get_string(argv[1]))) {
+ switch_event_t *event = NULL;
+ char *auth, *user = NULL, *domain = NULL;
+
+ if ((auth = amf0_get_string(argv[2])) && !zstr(auth)) {
+ switch_split_user_domain(auth, &user, &domain);
+ if (rtmp_session_check_user(rsession, user, domain) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_WARNING, "Unauthorized call to %s, client is not logged in account [%s@%s]\n",
+ number, switch_str_nil(user), switch_str_nil(domain));
+ return SWITCH_STATUS_FALSE;
+ }
+ } else if (rsession->profile->auth_calls && !rsession->account) {
+ switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_WARNING, "Unauthorized call to %s, client is not logged in\n", number);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (amf0_is_object(argv[3])) {
+ amf_object_to_event(argv[3], &event);
+ }
+
+ if (rtmp_session_create_call(rsession, &newsession, 0, RTMP_DEFAULT_STREAM_AUDIO, number, user, domain, event) != SWITCH_CAUSE_NONE) {
+ switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_ERROR, "Couldn't create call.\n");
+ }
+
+ if (event) {
+ switch_event_destroy(&event);
+ }
+ }
+
+ if (newsession) {
+ rtmp_private_t *new_pvt = switch_core_session_get_private(newsession);
+ rtmp_send_invoke_free(rsession, 3, 0, 0,
+ amf0_str("onMakeCall"),
+ amf0_number_new(transaction_id),
+ amf0_null_new(),
+ amf0_str(switch_core_session_get_uuid(newsession)),
+ amf0_str(switch_str_nil(number)),
+ amf0_str(switch_str_nil(new_pvt->auth)),
+ NULL);
+
+ rtmp_attach_private(rsession, switch_core_session_get_private(newsession));
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+RTMP_INVOKE_FUNCTION(rtmp_i_sendDTMF)
+{
+ /* Send DTMFs on the active channel */
+ switch_dtmf_t dtmf = { 0 };
+ switch_channel_t *channel;
+ char *digits;
+
+ if (!rsession->tech_pvt) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ channel = switch_core_session_get_channel(rsession->tech_pvt->session);
+
+ if (amf0_is_number(argv[2])) {
+ dtmf.duration = amf0_get_number(argv[2]);
+ } else if (!zstr(amf0_get_string(argv[2]))) {
+ dtmf.duration = atoi(amf0_get_string(argv[2]));
+ }
+
+ if ((digits = amf0_get_string(argv[1]))) {
+ size_t len = strlen(digits);
+ size_t j;
+ for (j = 0; j < len; j++) {
+ dtmf.digit = digits[j];
+ switch_channel_queue_dtmf(channel, &dtmf);
+ }
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+RTMP_INVOKE_FUNCTION(rtmp_i_login)
+{
+ char *user, *auth, *domain, *ddomain = NULL;
+
+
+ user = amf0_get_string(argv[1]);
+ auth = amf0_get_string(argv[2]);
+
+ if (zstr(user) || zstr(auth)) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if ((domain = strchr(user, '@'))) {
+ *domain++ = '\0';
+ }
+
+ if (zstr(domain)) {
+ ddomain = switch_core_get_variable_dup("domain");
+ domain = ddomain;
+ }
+
+
+ if (rtmp_check_auth(rsession, user, domain, auth) == SWITCH_STATUS_SUCCESS) {
+ rtmp_session_login(rsession, user, domain);
+ } else {
+ rtmp_send_invoke_free(rsession, 3, 0, 0,
+ amf0_str("onLogin"),
+ amf0_number_new(0),
+ amf0_null_new(),
+ amf0_str("failure"),
+ amf0_null_new(),
+ amf0_null_new(), NULL);
+ }
+
+
+ switch_safe_free(ddomain);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+RTMP_INVOKE_FUNCTION(rtmp_i_logout)
+{
+ char *auth = amf0_get_string(argv[1]);
+ char *user = NULL, *domain = NULL;
+
+ /* Unregister from that user */
+ rtmp_clear_registration(rsession, auth, NULL);
+
+ switch_split_user_domain(auth, &user, &domain);
+
+ if (!zstr(user) && !zstr(domain)) {
+ rtmp_session_logout(rsession, user, domain);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+RTMP_INVOKE_FUNCTION(rtmp_i_register)
+{
+ char *auth = amf0_get_string(argv[1]);
+ const char *user = NULL, *domain = NULL;
+ char *dup = NULL;
+ switch_status_t status;
+
+ if (!rsession->account) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!zstr(auth)) {
+ dup = strdup(auth);
+ switch_split_user_domain(dup, (char**)&user, (char**)&domain);
+ } else {
+ dup = auth = switch_mprintf("%s@%s", rsession->account->user, rsession->account->domain);
+ user = rsession->account->user;
+ domain = rsession->account->domain;
+ }
+
+ if (rtmp_session_check_user(rsession, user, domain) == SWITCH_STATUS_SUCCESS) {
+ rtmp_add_registration(rsession, auth, amf0_get_string(argv[2]));
+ status = SWITCH_STATUS_SUCCESS;
+ } else {
+ status = SWITCH_STATUS_FALSE;
+ }
+
+ switch_safe_free(dup);
+
+ return status;
+}
+
+RTMP_INVOKE_FUNCTION(rtmp_i_unregister)
+{
+ rtmp_clear_registration(rsession, amf0_get_string(argv[1]), amf0_get_string(argv[2]));
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+RTMP_INVOKE_FUNCTION(rtmp_i_answer)
+{
+ switch_channel_t *channel = NULL;
+ char *uuid = amf0_get_string(argv[1]);
+
+ if (!zstr(uuid)) {
+ rtmp_private_t *new_tech_pvt = rtmp_locate_private(rsession, uuid);
+ if (new_tech_pvt) {
+ switch_channel_mark_answered(switch_core_session_get_channel(new_tech_pvt->session));
+ rtmp_attach_private(rsession, new_tech_pvt);
+ }
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!rsession->tech_pvt) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ /* No UUID specified but we're attached to a channel, mark it as answered */
+ channel = switch_core_session_get_channel(rsession->tech_pvt->session);
+ switch_channel_mark_answered(channel);
+ rtmp_attach_private(rsession, rsession->tech_pvt);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+RTMP_INVOKE_FUNCTION(rtmp_i_attach)
+{
+ rtmp_private_t *tech_pvt = NULL;
+ char *uuid = amf0_get_string(argv[1]);
+
+ if (!zstr(uuid)) {
+ tech_pvt = rtmp_locate_private(rsession, uuid);
+ }
+ /* Will detach if an empty (or invalid) uuid is received */
+ rtmp_attach_private(rsession, tech_pvt);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+RTMP_INVOKE_FUNCTION(rtmp_i_hangup)
+{
+ /* CallID (or null/nothing to hangup the current call) */
+ char *uuid = amf0_get_string(argv[1]);
+ char *scause;
+ switch_channel_t *channel = NULL;
+ switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
+
+ if (!zstr(uuid)) {
+ rtmp_private_t *tech_pvt = rtmp_locate_private(rsession, uuid);
+ if (tech_pvt) {
+ channel = switch_core_session_get_channel(tech_pvt->session);
+ }
+ }
+
+ if (!channel) {
+ if (!rsession->tech_pvt) {
+ return SWITCH_STATUS_FALSE;
+ }
+ channel = switch_core_session_get_channel(rsession->tech_pvt->session);
+ }
+
+ if (amf0_is_number(argv[2])) {
+ cause = amf0_get_number(argv[2]);
+ } else if ((scause = amf0_get_string(argv[2])) && !zstr(scause)) {
+ cause = switch_channel_str2cause(scause);
+ }
+
+ switch_channel_hangup(channel, cause);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+RTMP_INVOKE_FUNCTION(rtmp_i_transfer)
+{
+ char *uuid = amf0_get_string(argv[1]);
+ char *dest = amf0_get_string(argv[2]);
+ rtmp_private_t *tech_pvt;
+
+ if (zstr(uuid) || zstr(dest)) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if ((tech_pvt = rtmp_locate_private(rsession, uuid))) {
+ const char *other_uuid = switch_channel_get_variable(tech_pvt->channel, SWITCH_SIGNAL_BOND_VARIABLE);
+ switch_core_session_t *session;
+
+ if (!zstr(other_uuid) && (session = switch_core_session_locate(other_uuid))) {
+ switch_ivr_session_transfer(session, dest, NULL, NULL);
+ switch_core_session_rwunlock(session);
+ }
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+RTMP_INVOKE_FUNCTION(rtmp_i_join)
+{
+ char *uuid[] = { amf0_get_string(argv[1]), amf0_get_string(argv[2]) };
+ const char *other_uuid[2];
+ rtmp_private_t *tech_pvt[2];
+
+ if (zstr(uuid[0]) || zstr(uuid[1])) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (!(tech_pvt[0] = rtmp_locate_private(rsession, uuid[0])) ||
+ !(tech_pvt[1] = rtmp_locate_private(rsession, uuid[1]))) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (tech_pvt[0] == tech_pvt[1]) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if ((other_uuid[0] = switch_channel_get_variable(tech_pvt[0]->channel, SWITCH_SIGNAL_BOND_VARIABLE)) &&
+ (other_uuid[1] = switch_channel_get_variable(tech_pvt[1]->channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
+
+#ifndef RTMP_DONT_HOLD
+ if (switch_test_flag(tech_pvt[0], TFLAG_DETACHED)) {
+ switch_ivr_unhold(tech_pvt[0]->session);
+ }
+ if (switch_test_flag(tech_pvt[1], TFLAG_DETACHED)) {
+ switch_ivr_unhold(tech_pvt[1]->session);
+ }
+#endif
+
+ switch_ivr_uuid_bridge(other_uuid[0], other_uuid[1]);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/*
+
+3-way:
+
+[0] is always the current active call
+[1] is the call to be brought into the call, and that will be running the three_way application
+
+- Set the current app of other[1] to three_way with other_uuid[0]
+- Put tech_pvt[0] to sleep: set state to CS_HIBERNATE
+- set CF_TRANSFER, set state CS_EXECUTE (do we need CF_TRANSFER here?)
+
+- setup a state handler in other[1] to detect when it hangs up
+
+Check list:
+tech_pvt[0] or other[0] hangs up
+ If we were attached to the call, switch the active call to tech_pvt[1]
+tech_pvt[1] or other[1] hangs up
+ Clear up any 3-way indications on the tech_pvt[0]
+
+*/
+
+static switch_status_t three_way_on_soft_execute(switch_core_session_t *session);
+#if 0
+static switch_status_t three_way_on_hangup(switch_core_session_t *session);
+#endif
+
+static const switch_state_handler_table_t three_way_state_handlers_remote = {
+ /*.on_init */ NULL,
+ /*.on_routing */ NULL,
+ /*.on_execute */ NULL,
+ /*.on_hangup */ NULL,
+ /*.on_exchange_media */ NULL,
+ /*.on_soft_execute */ three_way_on_soft_execute,
+ /*.on_consume_media */ NULL,
+ /*.on_hibernate */ NULL
+};
+
+/* runs on other_session[1] */
+static switch_status_t three_way_on_soft_execute(switch_core_session_t *other_session)
+{
+ switch_channel_t *other_channel = switch_core_session_get_channel(other_session);
+ const char *uuid = switch_channel_get_variable(other_channel, RTMP_THREE_WAY_UUID_VARIABLE);
+ const char *my_uuid = switch_channel_get_variable(other_channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE);
+ switch_core_session_t *my_session;
+ switch_channel_t *my_channel;
+ rtmp_private_t *tech_pvt;
+
+ if (zstr(uuid) || zstr(my_uuid)) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (zstr(my_uuid) || !(my_session = switch_core_session_locate(my_uuid))) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ if (!switch_core_session_check_interface(my_session, rtmp_globals.rtmp_endpoint_interface)) {
+ /* In case someone tempers with my variables, since we get tech_pvt from there */
+ switch_core_session_rwunlock(my_session);
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ my_channel = switch_core_session_get_channel(my_session);
+ tech_pvt = switch_core_session_get_private(my_session);
+
+ switch_ivr_eavesdrop_session(other_session, uuid, NULL, ED_MUX_READ | ED_MUX_WRITE);
+
+ /* 3-way call ended, whatever the reason
+ * We need to go back to our original state. */
+ if (!switch_channel_up(other_channel)) {
+ /* channel[1] hung up, check if we have special post-bridge actions, and hangup otherwise */
+ /* if my_channel isn't ready, it means something else has control of it, leave it alone */
+ if (switch_channel_ready(my_channel)) {
+ const char *s;
+ if ((s = switch_channel_get_variable(my_channel, SWITCH_PARK_AFTER_BRIDGE_VARIABLE)) && switch_true(s)) {
+ switch_ivr_park_session(my_session);
+ } else if ((s = switch_channel_get_variable(my_channel, SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE)) && !zstr(s)) {
+ int argc;
+ char *argv[4] = { 0 };
+ char *mydata = switch_core_session_strdup(my_session, s);
+
+ switch_channel_set_variable(my_channel, SWITCH_TRANSFER_AFTER_BRIDGE_VARIABLE, NULL);
+
+ if ((argc = switch_split(mydata, ':', argv)) >= 1) {
+ switch_ivr_session_transfer(my_session, argv[0], argv[1], argv[2]);
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(my_session), SWITCH_LOG_ERROR, "No extension specified.\n");
+ }
+ } else {
+ switch_channel_hangup(my_channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ }
+ }
+ } else if (switch_channel_ready(other_channel)) {
+ /* channel[1] didn't hangup, must be channel[0] then, rebridge this one with its original partner */
+ switch_ivr_uuid_bridge(switch_core_session_get_uuid(other_session), my_uuid);
+ } else {
+ /* channel[1] being taken out of our control, take the other leg out of CS_HIBERNATE if its ready, or else leave it alone */
+ if (switch_channel_ready(my_channel)) {
+ switch_channel_set_state(my_channel, CS_EXECUTE);
+ }
+ }
+
+ switch_channel_clear_state_handler(other_channel, &three_way_state_handlers_remote);
+
+ switch_channel_set_variable(other_channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE, NULL);
+ switch_channel_set_variable(my_channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE, NULL);
+ switch_channel_set_variable(other_channel, RTMP_THREE_WAY_UUID_VARIABLE, NULL);
+
+ switch_clear_flag(tech_pvt, TFLAG_THREE_WAY);
+
+ if (my_session) {
+ switch_core_session_rwunlock(my_session);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+RTMP_INVOKE_FUNCTION(rtmp_i_three_way)
+{
+ /* The first uuid is the (local) uuid of the current call, the 2nd one should be already detached */
+ char *uuid[] = { amf0_get_string(argv[1]), amf0_get_string(argv[2]) };
+ rtmp_private_t *tech_pvt[2];
+ const char *other_uuid[2];
+ switch_core_session_t *other_session[2] = { 0 };
+ switch_channel_t *other_channel[2] = { 0 };
+
+ if (zstr(uuid[0]) || zstr(uuid[1]) ||
+ !(tech_pvt[0] = rtmp_locate_private(rsession, uuid[0])) ||
+ !(tech_pvt[1] = rtmp_locate_private(rsession, uuid[1]))) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ /* Make sure we don't 3-way with the same call, and that it doesnt turn into a 4-way, we aren't that permissive */
+ if (tech_pvt[0] == tech_pvt[1] || switch_test_flag(tech_pvt[0], TFLAG_THREE_WAY) ||
+ switch_test_flag(tech_pvt[1], TFLAG_THREE_WAY)) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!(other_uuid[0] = switch_channel_get_variable(tech_pvt[0]->channel, SWITCH_SIGNAL_BOND_VARIABLE)) ||
+ !(other_uuid[1] = switch_channel_get_variable(tech_pvt[1]->channel, SWITCH_SIGNAL_BOND_VARIABLE))) {
+ return SWITCH_STATUS_FALSE; /* Both calls aren't bridged */
+ }
+
+ if (!(other_session[0] = switch_core_session_locate(other_uuid[0])) ||
+ !(other_session[1] = switch_core_session_locate(other_uuid[1]))) {
+ goto done;
+ }
+
+ other_channel[0] = switch_core_session_get_channel(other_session[0]);
+ other_channel[1] = switch_core_session_get_channel(other_session[1]);
+
+ /* Save which uuid is the 3-way target */
+ switch_channel_set_variable(other_channel[1], RTMP_THREE_WAY_UUID_VARIABLE, uuid[0]);
+ switch_channel_set_variable(tech_pvt[1]->channel, RTMP_THREE_WAY_UUID_VARIABLE, uuid[0]);
+
+ /* Attach redirect */
+ switch_set_flag(tech_pvt[1], TFLAG_THREE_WAY);
+
+ /* Set soft_holding_uuid to the uuid of the other matching channel, so they can can be bridged back when the 3-way is over */
+ switch_channel_set_variable(tech_pvt[1]->channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE, other_uuid[1]);
+ switch_channel_set_variable(other_channel[1], SWITCH_SOFT_HOLDING_UUID_VARIABLE, uuid[1]);
+
+ /* Start the 3-way on the 2nd channel using a media bug */
+ switch_channel_add_state_handler(other_channel[1], &three_way_state_handlers_remote);
+
+ switch_channel_set_flag(tech_pvt[1]->channel, CF_TRANSFER);
+ switch_channel_set_state(tech_pvt[1]->channel, CS_HIBERNATE);
+ switch_channel_set_flag(other_channel[1], CF_TRANSFER);
+ switch_channel_set_state(other_channel[1], CS_SOFT_EXECUTE);
+
+done:
+
+ if (other_session[0]) {
+ switch_core_session_rwunlock(other_session[0]);
+ }
+
+ if (other_session[1]) {
+ switch_core_session_rwunlock(other_session[1]);
+ }
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+RTMP_INVOKE_FUNCTION(rtmp_i_sendevent)
+{
+ amf0_data *obj = NULL;
+ switch_event_t *event = NULL;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ const char *uuid = NULL;
+
+ if (argv[1] && argv[1]->type == AMF0_TYPE_OBJECT) {
+ obj = argv[1];
+ } else if (argv[2] && argv[2]->type == AMF0_TYPE_OBJECT) {
+ uuid = amf0_get_string(argv[1]);
+ obj = argv[2];
+ } else {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Bad argument for sendevent");
+ return SWITCH_STATUS_FALSE;
+ }
+
+
+ if (switch_event_create_subclass(&event, zstr(uuid) ? SWITCH_EVENT_CUSTOM : SWITCH_EVENT_MESSAGE,
+ zstr(uuid) ? RTMP_EVENT_CLIENTCUSTOM : NULL) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_ERROR, "Couldn't create event\n");
+ return SWITCH_STATUS_FALSE;
+ }
+
+ rtmp_event_fill(rsession, event);
+
+ /* Build event using amf array */
+ if ((status = amf_object_to_event(obj, &event)) != SWITCH_STATUS_SUCCESS) {
+ switch_event_destroy(&event);
+ return SWITCH_STATUS_FALSE;
+ }
+
+ if (!zstr(uuid)) {
+ rtmp_private_t *session_pvt = rtmp_locate_private(rsession, uuid);
+ if (session_pvt) {
+ if (switch_core_session_queue_event(session_pvt->session, &event) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session_pvt->session), SWITCH_LOG_ERROR, "Couldn't queue event to session\n");
+ switch_event_destroy(&event);
+ status = SWITCH_STATUS_FALSE;
+ } else {
+ status = SWITCH_STATUS_SUCCESS;
+ }
+ }
+ }
+
+ switch_event_fire(&event);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+RTMP_INVOKE_FUNCTION(rtmp_i_log)
+{
+ const char *data = amf0_get_string(argv[1]);
+
+ switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_INFO, "Log: %s\n", data);
+
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/* 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:
+ */
diff --git a/src/mod/endpoints/mod_rtmp/rtmp_tcp.c b/src/mod/endpoints/mod_rtmp/rtmp_tcp.c
new file mode 100644
index 0000000000..b09cef7ad1
--- /dev/null
+++ b/src/mod/endpoints/mod_rtmp/rtmp_tcp.c
@@ -0,0 +1,368 @@
+/*
+ * mod_rtmp for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2011, Barracuda Networks Inc.
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mod_rtmp for FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is Barracuda Networks Inc.
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Mathieu Rene
+ *
+ * rtmp_tcp.c -- RTMP TCP I/O module
+ *
+ */
+
+#include "mod_rtmp.h"
+
+/* Locally-extended version of rtmp_io_t */
+struct rtmp_io_tcp {
+ rtmp_io_t base;
+
+ switch_pollset_t *pollset;
+ switch_pollfd_t *listen_pollfd;
+ switch_socket_t *listen_socket;
+ const char *ip;
+ switch_port_t port;
+ switch_thread_t *thread;
+ switch_mutex_t *mutex;
+};
+
+typedef struct rtmp_io_tcp rtmp_io_tcp_t;
+
+struct rtmp_tcp_io_private {
+ switch_pollfd_t *pollfd;
+ switch_socket_t *socket;
+ switch_buffer_t *sendq;
+ switch_bool_t poll_send;
+};
+
+typedef struct rtmp_tcp_io_private rtmp_tcp_io_private_t;
+
+static void rtmp_tcp_alter_pollfd(rtmp_session_t *rsession, switch_bool_t pollout)
+{
+ rtmp_tcp_io_private_t *io_pvt = rsession->io_private;
+ rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)rsession->profile->io;
+
+ if (pollout && (io_pvt->pollfd->reqevents & SWITCH_POLLOUT)) {
+ return;
+ } else if (!pollout && !(io_pvt->pollfd->reqevents & SWITCH_POLLOUT)) {
+ return;
+ }
+
+ switch_pollset_remove(io->pollset, io_pvt->pollfd);
+ io_pvt->pollfd->reqevents = SWITCH_POLLIN | SWITCH_POLLERR;
+ if (pollout) {
+ io_pvt->pollfd->reqevents |= SWITCH_POLLOUT;
+ }
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Pollout: %s\n",
+ pollout ? "true" : "false");
+
+ switch_pollset_add(io->pollset, io_pvt->pollfd);
+}
+
+static switch_status_t rtmp_tcp_read(rtmp_session_t *rsession, unsigned char *buf, switch_size_t *len)
+{
+ //rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)rsession->profile->io;
+ rtmp_tcp_io_private_t *io_pvt = rsession->io_private;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+#ifdef RTMP_DEBUG_IO
+ switch_size_t olen = *len;
+#endif
+ switch_assert(*len > 0 && *len < 1024000);
+ status = switch_socket_recv(io_pvt->socket, (char*)buf, len);
+
+#ifdef RTMP_DEBUG_IO
+ {
+ int i;
+
+ fprintf(rsession->io_debug_in, "recv %p max=%"SWITCH_SIZE_T_FMT" got=%"SWITCH_SIZE_T_FMT"\n< ", (void*)buf, olen, *len);
+
+ for (i = 0; i < *len; i++) {
+
+ fprintf(rsession->io_debug_in, "%02X ", (uint8_t)buf[i]);
+
+ if (i != 0 && i % 32 == 0) {
+ fprintf(rsession->io_debug_in, "\n> ");
+ }
+ }
+ fprintf(rsession->io_debug_in, "\n\n");
+ fflush(rsession->io_debug_in);
+ }
+#endif
+
+ return status;
+}
+
+static switch_status_t rtmp_tcp_write(rtmp_session_t *rsession, const unsigned char *buf, switch_size_t *len)
+{
+ //rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)rsession->profile->io;
+ rtmp_tcp_io_private_t *io_pvt = rsession->io_private;
+ switch_status_t status;
+ switch_size_t orig_len = *len;
+
+#ifdef RTMP_DEBUG_IO
+ {
+ int i;
+ fprintf(rsession->io_debug_out,
+ "SEND %"SWITCH_SIZE_T_FMT" bytes\n> ", *len);
+
+ for (i = 0; i < *len; i++) {
+ fprintf(rsession->io_debug_out, "%02X ", (uint8_t)buf[i]);
+
+ if (i != 0 && i % 32 == 0) {
+ fprintf(rsession->io_debug_out, "\n> ");
+ }
+ }
+ fprintf(rsession->io_debug_out, "\n\n ");
+
+ fflush(rsession->io_debug_out);
+ }
+#endif
+
+ if (io_pvt->sendq && switch_buffer_inuse(io_pvt->sendq) > 0) {
+ /* We already have queued data, append it to the sendq */
+ switch_buffer_write(io_pvt->sendq, buf, *len);
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ status = switch_socket_send_nonblock(io_pvt->socket, (char*)buf, len);
+
+ if (*len < orig_len) {
+
+ if (rsession->state >= RS_DESTROY) {
+ return SWITCH_STATUS_FALSE;
+ }
+
+ /* We didnt send it all... add it to the sendq*/
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%"SWITCH_SIZE_T_FMT" bytes added to sendq.\n", (orig_len - *len));
+
+ switch_buffer_write(io_pvt->sendq, (buf + *len), orig_len - *len);
+
+ /* Make sure we poll-write */
+ rtmp_tcp_alter_pollfd(rsession, SWITCH_TRUE);
+ }
+
+ return status;
+}
+
+static switch_status_t rtmp_tcp_close(rtmp_session_t *rsession)
+{
+ rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)rsession->profile->io;
+ rtmp_tcp_io_private_t *io_pvt = rsession->io_private;
+
+ if (io_pvt->socket) {
+ switch_mutex_lock(io->mutex);
+ switch_pollset_remove(io->pollset, io_pvt->pollfd);
+ switch_mutex_unlock(io->mutex);
+
+ switch_socket_close(io_pvt->socket);
+ io_pvt->socket = NULL;
+ }
+ return SWITCH_STATUS_SUCCESS;
+}
+
+
+void *SWITCH_THREAD_FUNC rtmp_io_tcp_thread(switch_thread_t *thread, void *obj)
+{
+ rtmp_io_tcp_t *io = (rtmp_io_tcp_t*)obj;
+ io->base.running = 1;
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s: I/O Thread starting\n", io->base.profile->name);
+
+
+ while(io->base.running) {
+ const switch_pollfd_t *fds;
+ int32_t numfds;
+ int32_t i;
+ switch_status_t status;
+
+ switch_mutex_lock(io->mutex);
+ status = switch_pollset_poll(io->pollset, 500000, &numfds, &fds);
+ switch_mutex_unlock(io->mutex);
+
+ if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_TIMEOUT) {
+ //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "pollset_poll failed\n");
+ continue;
+ } else if (status == SWITCH_STATUS_TIMEOUT) {
+ switch_yield(1);
+ }
+
+ for (i = 0; i < numfds; i++) {
+ if (!fds[i].client_data) {
+ switch_socket_t *newsocket;
+ if (switch_socket_accept(&newsocket, io->listen_socket, io->base.pool) != SWITCH_STATUS_SUCCESS) {
+ if (io->base.running) {
+ /* Don't spam the logs if we are shutting down */
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error [%s]\n", strerror(errno));
+ } else {
+ return NULL;
+ }
+ } else {
+ rtmp_session_t *newsession;
+
+ if (switch_socket_opt_set(newsocket, SWITCH_SO_NONBLOCK, TRUE)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't set socket as non-blocking\n");
+ }
+
+ if (rtmp_session_request(io->base.profile, &newsession) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "RTMP session request failed\n");
+ switch_socket_close(newsocket);
+ } else {
+ switch_sockaddr_t *addr = NULL;
+ char ipbuf[200];
+
+ /* Create out private data and attach it to the rtmp session structure */
+ rtmp_tcp_io_private_t *pvt = switch_core_alloc(newsession->pool, sizeof(*pvt));
+ newsession->io_private = pvt;
+ pvt->socket = newsocket;
+ switch_socket_create_pollfd(&pvt->pollfd, newsocket, SWITCH_POLLIN | SWITCH_POLLERR, newsession, newsession->pool);
+ switch_pollset_add(io->pollset, pvt->pollfd);
+ switch_buffer_create_dynamic(&pvt->sendq, 512, 1024, 0);
+
+ /* Get the remote address/port info */
+ switch_socket_addr_get(&addr, SWITCH_TRUE, newsocket);
+ switch_get_addr(ipbuf, sizeof(ipbuf), addr);
+ newsession->remote_address = switch_core_strdup(newsession->pool, ipbuf);
+ newsession->remote_port = switch_sockaddr_get_port(addr);
+ }
+ }
+ } else {
+ rtmp_session_t *rsession = (rtmp_session_t*)fds[i].client_data;
+ rtmp_tcp_io_private_t *io_pvt = (rtmp_tcp_io_private_t*)rsession->io_private;
+
+ if (fds[i].rtnevents & SWITCH_POLLOUT && switch_buffer_inuse(io_pvt->sendq) > 0) {
+ /* Send as much remaining data as possible */
+ switch_size_t sendlen;
+ const void *ptr;
+ sendlen = switch_buffer_peek_zerocopy(io_pvt->sendq, &ptr);
+ switch_socket_send_nonblock(io_pvt->socket, ptr, &sendlen);
+ switch_buffer_toss(io_pvt->sendq, sendlen);
+ if (switch_buffer_inuse(io_pvt->sendq) == 0) {
+ /* Remove our fd from OUT polling */
+ rtmp_tcp_alter_pollfd(rsession, SWITCH_FALSE);
+ }
+ } else if (fds[i].rtnevents & SWITCH_POLLIN && rtmp_handle_data(rsession) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_UUID_LOG(rsession->uuid), SWITCH_LOG_DEBUG, "Closing socket\n");
+
+ switch_mutex_lock(io->mutex);
+ switch_pollset_remove(io->pollset, io_pvt->pollfd);
+ switch_mutex_unlock(io->mutex);
+
+ switch_socket_close(io_pvt->socket);
+ io_pvt->socket = NULL;
+
+ rtmp_session_destroy(&rsession);
+ }
+ }
+ }
+ }
+
+ io->base.running = -1;
+ switch_socket_close(io->listen_socket);
+
+ return NULL;
+}
+
+switch_status_t rtmp_tcp_init(rtmp_profile_t *profile, const char *bindaddr, rtmp_io_t **new_io, switch_memory_pool_t *pool)
+{
+ char *szport;
+ switch_sockaddr_t *sa;
+ switch_threadattr_t *thd_attr = NULL;
+ rtmp_io_tcp_t *io_tcp;
+
+ io_tcp = (rtmp_io_tcp_t*)switch_core_alloc(pool, sizeof(rtmp_io_tcp_t));
+ io_tcp->base.pool = pool;
+ io_tcp->ip = switch_core_strdup(pool, bindaddr);
+
+ *new_io = (rtmp_io_t*)io_tcp;
+ io_tcp->base.profile = profile;
+ io_tcp->base.read = rtmp_tcp_read;
+ io_tcp->base.write = rtmp_tcp_write;
+ io_tcp->base.close = rtmp_tcp_close;
+ io_tcp->base.name = "tcp";
+ io_tcp->base.address = switch_core_strdup(pool, io_tcp->ip);
+
+ if ((szport = strchr(io_tcp->ip, ':'))) {
+ *szport++ = '\0';
+ io_tcp->port = atoi(szport);
+ } else {
+ io_tcp->port = RTMP_DEFAULT_PORT;
+ }
+
+ if (switch_sockaddr_info_get(&sa, io_tcp->ip, SWITCH_INET, io_tcp->port, 0, pool)) {
+ goto fail;
+ }
+ if (switch_socket_create(&io_tcp->listen_socket, switch_sockaddr_get_family(sa), SOCK_STREAM, SWITCH_PROTO_TCP, pool)) {
+ goto fail;
+ }
+ if (switch_socket_opt_set(io_tcp->listen_socket, SWITCH_SO_REUSEADDR, 1)) {
+ goto fail;
+ }
+ if (switch_socket_bind(io_tcp->listen_socket, sa)) {
+ goto fail;
+ }
+ if (switch_socket_listen(io_tcp->listen_socket, 10)) {
+ goto fail;
+ }
+ if (switch_socket_opt_set(io_tcp->listen_socket, SWITCH_SO_NONBLOCK, TRUE)) {
+ goto fail;
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Listening on %s:%u (tcp)\n", io_tcp->ip, io_tcp->port);
+
+ io_tcp->base.running = 1;
+
+ if (switch_pollset_create(&io_tcp->pollset, 1000 /* max poll fds */, pool, 0) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "pollset_create failed\n");
+ goto fail;
+ }
+
+ switch_socket_create_pollfd(&(io_tcp->listen_pollfd), io_tcp->listen_socket, SWITCH_POLLIN | SWITCH_POLLERR, NULL, pool);
+ if (switch_pollset_add(io_tcp->pollset, io_tcp->listen_pollfd) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "pollset_add failed\n");
+ goto fail;
+ }
+
+ switch_mutex_init(&io_tcp->mutex, SWITCH_MUTEX_NESTED, pool);
+
+ switch_threadattr_create(&thd_attr, pool);
+ switch_threadattr_detach_set(thd_attr, 1);
+ switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+ switch_thread_create(&io_tcp->thread, thd_attr, rtmp_io_tcp_thread, *new_io, pool);
+
+ return SWITCH_STATUS_SUCCESS;
+fail:
+ if (io_tcp->listen_socket) {
+ switch_socket_close(io_tcp->listen_socket);
+ }
+ *new_io = NULL;
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Socket error. Couldn't listen on %s:%u\n", io_tcp->ip, io_tcp->port);
+ return SWITCH_STATUS_FALSE;
+}
+
+/* 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:
+ */
diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c
index 3879cca7d4..3b07472e7e 100644
--- a/src/mod/endpoints/mod_skinny/mod_skinny.c
+++ b/src/mod/endpoints/mod_skinny/mod_skinny.c
@@ -50,58 +50,58 @@ skinny_globals_t globals;
/* SQL TABLES */
/*****************************************************************************/
static char devices_sql[] =
- "CREATE TABLE skinny_devices (\n"
- " name VARCHAR(16),\n"
- " user_id INTEGER,\n"
- " instance INTEGER,\n"
- " ip VARCHAR(15),\n"
- " type INTEGER,\n"
- " max_streams INTEGER,\n"
- " port INTEGER,\n"
- " codec_string VARCHAR(255),\n"
- " headset INTEGER,\n"
- " handset INTEGER,\n"
- " speaker INTEGER\n"
- ");\n";
+"CREATE TABLE skinny_devices (\n"
+" name VARCHAR(16),\n"
+" user_id INTEGER,\n"
+" instance INTEGER,\n"
+" ip VARCHAR(15),\n"
+" type INTEGER,\n"
+" max_streams INTEGER,\n"
+" port INTEGER,\n"
+" codec_string VARCHAR(255),\n"
+" headset INTEGER,\n"
+" handset INTEGER,\n"
+" speaker INTEGER\n"
+");\n";
static char lines_sql[] =
- "CREATE TABLE skinny_lines (\n"
- " device_name VARCHAR(16),\n"
- " device_instance INTEGER,\n"
- " position INTEGER,\n"
- " line_instance INTEGER,\n"
- " label VARCHAR(40),\n"
- " value VARCHAR(24),\n"
- " caller_name VARCHAR(44),\n"
- " ring_on_idle INTEGER,\n"
- " ring_on_active INTEGER,\n"
- " busy_trigger INTEGER,\n"
- " forward_all VARCHAR(255),\n"
- " forward_busy VARCHAR(255),\n"
- " forward_noanswer VARCHAR(255),\n"
- " noanswer_duration INTEGER\n"
- ");\n";
+"CREATE TABLE skinny_lines (\n"
+" device_name VARCHAR(16),\n"
+" device_instance INTEGER,\n"
+" position INTEGER,\n"
+" line_instance INTEGER,\n"
+" label VARCHAR(40),\n"
+" value VARCHAR(24),\n"
+" caller_name VARCHAR(44),\n"
+" ring_on_idle INTEGER,\n"
+" ring_on_active INTEGER,\n"
+" busy_trigger INTEGER,\n"
+" forward_all VARCHAR(255),\n"
+" forward_busy VARCHAR(255),\n"
+" forward_noanswer VARCHAR(255),\n"
+" noanswer_duration INTEGER\n"
+");\n";
static char buttons_sql[] =
- "CREATE TABLE skinny_buttons (\n"
- " device_name VARCHAR(16),\n"
- " device_instance INTEGER,\n"
- " position INTEGER,\n"
- " type INTEGER,\n"
- " label VARCHAR(40),\n"
- " value VARCHAR(255),\n"
- " settings VARCHAR(44)\n"
- ");\n";
+"CREATE TABLE skinny_buttons (\n"
+" device_name VARCHAR(16),\n"
+" device_instance INTEGER,\n"
+" position INTEGER,\n"
+" type INTEGER,\n"
+" label VARCHAR(40),\n"
+" value VARCHAR(255),\n"
+" settings VARCHAR(44)\n"
+");\n";
static char active_lines_sql[] =
- "CREATE TABLE skinny_active_lines (\n"
- " device_name VARCHAR(16),\n"
- " device_instance INTEGER,\n"
- " line_instance INTEGER,\n"
- " channel_uuid VARCHAR(256),\n"
- " call_id INTEGER,\n"
- " call_state INTEGER\n"
- ");\n";
+"CREATE TABLE skinny_active_lines (\n"
+" device_name VARCHAR(16),\n"
+" device_instance INTEGER,\n"
+" line_instance INTEGER,\n"
+" channel_uuid VARCHAR(256),\n"
+" call_id INTEGER,\n"
+" call_state INTEGER\n"
+");\n";
/*****************************************************************************/
/* PROFILES FUNCTIONS */
@@ -238,7 +238,7 @@ char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *l
if(listener) {
device_condition = switch_mprintf("device_name='%s' AND device_instance=%d",
- listener->device_name, listener->device_instance);
+ listener->device_name, listener->device_instance);
} else {
device_condition = switch_mprintf("1=1");
}
@@ -256,14 +256,14 @@ char * skinny_profile_find_session_uuid(skinny_profile_t *profile, listener_t *l
}
switch_assert(call_id_condition);
if((sql = switch_mprintf(
- "SELECT channel_uuid, line_instance "
- "FROM skinny_active_lines "
- "WHERE %s AND %s AND %s "
- "ORDER BY call_state, channel_uuid", /* off hook first */
- device_condition, line_instance_condition, call_id_condition
- ))) {
+ "SELECT channel_uuid, line_instance "
+ "FROM skinny_active_lines "
+ "WHERE %s AND %s AND %s "
+ "ORDER BY call_state, channel_uuid", /* off hook first */
+ device_condition, line_instance_condition, call_id_condition
+ ))) {
skinny_execute_sql_callback(profile, profile->sql_mutex, sql,
- skinny_profile_find_session_uuid_callback, &helper);
+ skinny_profile_find_session_uuid_callback, &helper);
switch_safe_free(sql);
}
switch_safe_free(device_condition);
@@ -291,8 +291,8 @@ switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, l
#endif
if(!result) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
- "Unable to find session %s on %s:%d, line %d\n",
- uuid, listener->device_name, listener->device_instance, *line_instance_p);
+ "Unable to find session %s on %s:%d, line %d\n",
+ uuid, listener->device_name, listener->device_instance, *line_instance_p);
}
switch_safe_free(uuid);
}
@@ -340,7 +340,7 @@ switch_status_t skinny_execute_sql(skinny_profile_t *profile, char *sql, switch_
status = switch_cache_db_execute_sql(dbh, sql, NULL);
- end:
+end:
switch_cache_db_release_db_handle(&dbh);
@@ -352,7 +352,7 @@ switch_status_t skinny_execute_sql(skinny_profile_t *profile, char *sql, switch_
}
switch_bool_t skinny_execute_sql_callback(skinny_profile_t *profile, switch_mutex_t *mutex, char *sql, switch_core_db_callback_func_t callback,
- void *pdata)
+ void *pdata)
{
switch_bool_t ret = SWITCH_FALSE;
char *errmsg = NULL;
@@ -374,7 +374,7 @@ switch_bool_t skinny_execute_sql_callback(skinny_profile_t *profile, switch_mute
free(errmsg);
}
- end:
+end:
switch_cache_db_release_db_handle(&dbh);
@@ -400,9 +400,9 @@ void skinny_line_perform_set_state(const char *file, const char *func, int line,
switch_event_fire(&event);
send_call_state(listener, call_state, line_instance, call_id);
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, NULL, SWITCH_LOG_DEBUG,
- "Device %s:%d, Line %d, Call %d Change State to %s (%d)\n",
- listener->device_name, listener->device_instance, line_instance, call_id,
- skinny_call_state2str(call_state), call_state);
+ "Device %s:%d, Line %d, Call %d Change State to %s (%d)\n",
+ listener->device_name, listener->device_instance, line_instance, call_id,
+ skinny_call_state2str(call_state), call_state);
}
@@ -443,13 +443,13 @@ uint32_t skinny_line_get_state(listener_t *listener, uint32_t line_instance, uin
helper.call_state = -1;
if ((sql = switch_mprintf(
- "SELECT call_state FROM skinny_active_lines "
- "WHERE device_name='%s' AND device_instance=%d "
- "AND %s AND %s "
- "ORDER BY call_state, channel_uuid", /* off hook first */
- listener->device_name, listener->device_instance,
- line_instance_condition, call_id_condition
- ))) {
+ "SELECT call_state FROM skinny_active_lines "
+ "WHERE device_name='%s' AND device_instance=%d "
+ "AND %s AND %s "
+ "ORDER BY call_state, channel_uuid", /* off hook first */
+ listener->device_name, listener->device_instance,
+ line_instance_condition, call_id_condition
+ ))) {
skinny_execute_sql_callback(listener->profile, listener->profile->sql_mutex, sql, skinny_line_get_state_callback, &helper);
switch_safe_free(sql);
}
@@ -475,13 +475,13 @@ switch_status_t skinny_tech_set_codec(private_t *tech_pvt, int force)
switch_goto_status(SWITCH_STATUS_SUCCESS, end);
}
if (strcasecmp(tech_pvt->read_impl.iananame, tech_pvt->iananame) ||
- tech_pvt->read_impl.samples_per_second != tech_pvt->rm_rate ||
- tech_pvt->codec_ms != (uint32_t)tech_pvt->read_impl.microseconds_per_packet / 1000) {
-
+ tech_pvt->read_impl.samples_per_second != tech_pvt->rm_rate ||
+ tech_pvt->codec_ms != (uint32_t)tech_pvt->read_impl.microseconds_per_packet / 1000) {
+
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Changing Codec from %s@%dms to %s@%dms\n",
- tech_pvt->read_impl.iananame, tech_pvt->read_impl.microseconds_per_packet / 1000,
- tech_pvt->rm_encoding, tech_pvt->codec_ms);
-
+ tech_pvt->read_impl.iananame, tech_pvt->read_impl.microseconds_per_packet / 1000,
+ tech_pvt->rm_encoding, tech_pvt->codec_ms);
+
switch_core_session_lock_codec_write(tech_pvt->session);
switch_core_session_lock_codec_read(tech_pvt->session);
resetting = 1;
@@ -494,25 +494,25 @@ switch_status_t skinny_tech_set_codec(private_t *tech_pvt, int force)
}
if (switch_core_codec_init(&tech_pvt->read_codec,
- tech_pvt->iananame,
- tech_pvt->rm_fmtp,
- tech_pvt->rm_rate,
- tech_pvt->codec_ms,
- 1,
- SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | 0 /* TODO tech_pvt->profile->codec_flags */,
- NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
+ tech_pvt->iananame,
+ tech_pvt->rm_fmtp,
+ tech_pvt->rm_rate,
+ tech_pvt->codec_ms,
+ 1,
+ SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | 0 /* TODO tech_pvt->profile->codec_flags */,
+ NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Can't load codec?\n");
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
if (switch_core_codec_init(&tech_pvt->write_codec,
- tech_pvt->iananame,
- tech_pvt->rm_fmtp,
- tech_pvt->rm_rate,
- tech_pvt->codec_ms,
- 1,
- SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | 0 /* TODO tech_pvt->profile->codec_flags */,
- NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
+ tech_pvt->iananame,
+ tech_pvt->rm_fmtp,
+ tech_pvt->rm_rate,
+ tech_pvt->codec_ms,
+ 1,
+ SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE | 0 /* TODO tech_pvt->profile->codec_flags */,
+ NULL, switch_core_session_get_pool(tech_pvt->session)) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, "Can't load codec?\n");
switch_goto_status(SWITCH_STATUS_FALSE, end);
}
@@ -530,9 +530,9 @@ switch_status_t skinny_tech_set_codec(private_t *tech_pvt, int force)
switch_assert(tech_pvt->read_codec.implementation);
if (switch_rtp_change_interval(tech_pvt->rtp_session,
- tech_pvt->read_impl.microseconds_per_packet,
- tech_pvt->read_impl.samples_per_packet
- ) != SWITCH_STATUS_SUCCESS) {
+ tech_pvt->read_impl.microseconds_per_packet,
+ tech_pvt->read_impl.samples_per_packet
+ ) != SWITCH_STATUS_SUCCESS) {
switch_channel_t *channel = switch_core_session_get_channel(tech_pvt->session);
switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER);
@@ -549,8 +549,8 @@ switch_status_t skinny_tech_set_codec(private_t *tech_pvt, int force)
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set Codec %s %s/%ld %d ms %d samples\n",
- "" /* TODO switch_channel_get_name(tech_pvt->channel)*/, tech_pvt->iananame, tech_pvt->rm_rate, tech_pvt->codec_ms,
- tech_pvt->read_impl.samples_per_packet);
+ "" /* TODO switch_channel_get_name(tech_pvt->channel)*/, tech_pvt->iananame, tech_pvt->rm_rate, tech_pvt->codec_ms,
+ tech_pvt->read_impl.samples_per_packet);
tech_pvt->read_frame.codec = &tech_pvt->read_codec;
tech_pvt->write_codec.agreed_pt = tech_pvt->agreed_pt;
@@ -562,16 +562,16 @@ switch_status_t skinny_tech_set_codec(private_t *tech_pvt, int force)
}
/* TODO
- tech_pvt->fmtp_out = switch_core_session_strdup(tech_pvt->session, tech_pvt->write_codec.fmtp_out);
- */
+ tech_pvt->fmtp_out = switch_core_session_strdup(tech_pvt->session, tech_pvt->write_codec.fmtp_out);
+ */
/* TODO
- if (switch_rtp_ready(tech_pvt->rtp_session)) {
- switch_rtp_set_default_payload(tech_pvt->rtp_session, tech_pvt->pt);
- }
- */
+ if (switch_rtp_ready(tech_pvt->rtp_session)) {
+ switch_rtp_set_default_payload(tech_pvt->rtp_session, tech_pvt->pt);
+ }
+ */
- end:
+end:
if (resetting) {
switch_core_session_unlock_codec_write(tech_pvt->session);
switch_core_session_unlock_codec_read(tech_pvt->session);
@@ -600,7 +600,7 @@ void tech_init(private_t *tech_pvt, skinny_profile_t *profile, switch_core_sessi
State methods they get called when the state changes to the specific state
returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
-*/
+ */
switch_status_t channel_on_init(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
@@ -641,23 +641,23 @@ int channel_on_routing_callback(void *pArg, int argc, char **argv, char **column
skinny_profile_find_listener_by_device_name_and_instance(helper->tech_pvt->profile, device_name, device_instance, &listener);
if(listener) {
- if(!strcmp(device_name, helper->listener->device_name)
- && (device_instance == helper->listener->device_instance)
- && (line_instance == helper->line_instance)) {/* the calling line */
+ if(!strcmp(device_name, helper->listener->device_name)
+ && (device_instance == helper->listener->device_instance)
+ && (line_instance == helper->line_instance)) {/* the calling line */
helper->tech_pvt->caller_profile->dialplan = switch_core_strdup(helper->tech_pvt->caller_profile->pool, listener->profile->dialplan);
helper->tech_pvt->caller_profile->context = switch_core_strdup(helper->tech_pvt->caller_profile->pool, listener->profile->context);
send_dialed_number(listener, helper->tech_pvt->caller_profile->destination_number, line_instance, helper->tech_pvt->call_id);
skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_PROCEED);
skinny_session_send_call_info(helper->tech_pvt->session, listener, line_instance);
skinny_session_ring_out(helper->tech_pvt->session, listener, line_instance);
- } else {
+ } else {
send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_ON);
skinny_line_set_state(listener, line_instance, helper->tech_pvt->call_id, SKINNY_IN_USE_REMOTELY);
send_select_soft_keys(listener, line_instance, helper->tech_pvt->call_id, SKINNY_KEY_SET_IN_USE_HINT, 0xffff);
send_display_prompt_status(listener, 0, SKINNY_DISP_IN_USE_REMOTE,
- line_instance, helper->tech_pvt->call_id);
+ line_instance, helper->tech_pvt->call_id);
skinny_session_send_call_info(helper->tech_pvt->session, listener, line_instance);
- }
+ }
}
return 0;
}
@@ -673,15 +673,15 @@ switch_status_t channel_on_routing(switch_core_session_t *session)
struct channel_on_routing_helper helper = {0};
if(switch_test_flag(tech_pvt, TFLAG_FORCE_ROUTE)) {
- action = SKINNY_ACTION_ROUTE;
+ action = SKINNY_ACTION_PROCESS;
} else {
action = skinny_session_dest_match_pattern(session, &data);
}
switch(action) {
- case SKINNY_ACTION_ROUTE:
+ case SKINNY_ACTION_PROCESS:
skinny_profile_find_listener_by_device_name_and_instance(tech_pvt->profile,
- switch_channel_get_variable(channel, "skinny_device_name"),
- atoi(switch_channel_get_variable(channel, "skinny_device_instance")), &listener);
+ switch_channel_get_variable(channel, "skinny_device_name"),
+ atoi(switch_channel_get_variable(channel, "skinny_device_instance")), &listener);
if (listener) {
helper.tech_pvt = tech_pvt;
helper.listener = listener;
@@ -689,8 +689,8 @@ switch_status_t channel_on_routing(switch_core_session_t *session)
skinny_session_walk_lines(tech_pvt->profile, switch_core_session_get_uuid(session), channel_on_routing_callback, &helper);
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Could not find listener %s:%s for Channel %s\n",
- switch_channel_get_variable(channel, "skinny_device_name"), switch_channel_get_variable(channel, "skinny_device_instance"),
- switch_channel_get_name(channel));
+ switch_channel_get_variable(channel, "skinny_device_name"), switch_channel_get_variable(channel, "skinny_device_instance"),
+ switch_channel_get_name(channel));
}
/* Future bridge should go straight */
switch_set_flag_locked(tech_pvt, TFLAG_FORCE_ROUTE);
@@ -777,16 +777,16 @@ int channel_on_hangup_callback(void *pArg, int argc, char **argv, char **columnN
send_set_lamp(listener, SKINNY_BUTTON_LINE, line_instance, SKINNY_LAMP_OFF);
switch (helper->cause) {
case SWITCH_CAUSE_UNALLOCATED_NUMBER:
- send_start_tone(listener, SKINNY_TONE_REORDER, 0, line_instance, call_id);
+ send_start_tone(listener, SKINNY_TONE_REORDER, 0, line_instance, call_id);
skinny_session_send_call_info(helper->tech_pvt->session, listener, line_instance);
send_display_prompt_status(listener, 0, SKINNY_DISP_UNKNOWN_NUMBER, line_instance, call_id);
break;
case SWITCH_CAUSE_USER_BUSY:
- send_start_tone(listener, SKINNY_TONE_BUSYTONE, 0, line_instance, call_id);
+ send_start_tone(listener, SKINNY_TONE_BUSYTONE, 0, line_instance, call_id);
send_display_prompt_status(listener, 0, SKINNY_DISP_BUSY, line_instance, call_id);
- break;
+ break;
case SWITCH_CAUSE_NORMAL_CLEARING:
- send_clear_prompt_status(listener, line_instance, call_id);
+ send_clear_prompt_status(listener, line_instance, call_id);
break;
default:
send_display_prompt_status(listener, 0, switch_channel_cause2str(helper->cause), line_instance, call_id);
@@ -821,9 +821,9 @@ switch_status_t channel_on_hangup(switch_core_session_t *session)
skinny_session_walk_lines(tech_pvt->profile, switch_core_session_get_uuid(session), channel_on_hangup_callback, &helper);
if ((sql = switch_mprintf(
- "DELETE FROM skinny_active_lines WHERE channel_uuid='%s'",
- switch_core_session_get_uuid(session)
- ))) {
+ "DELETE FROM skinny_active_lines WHERE channel_uuid='%s'",
+ switch_core_session_get_uuid(session)
+ ))) {
skinny_execute_sql(tech_pvt->profile, sql, tech_pvt->profile->sql_mutex);
switch_safe_free(sql);
}
@@ -836,16 +836,16 @@ switch_status_t channel_kill_channel(switch_core_session_t *session, int sig)
private_t *tech_pvt = switch_core_session_get_private(session);
switch (sig) {
- case SWITCH_SIG_KILL:
- switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
- break;
- case SWITCH_SIG_BREAK:
- if (switch_rtp_ready(tech_pvt->rtp_session)) {
- switch_rtp_break(tech_pvt->rtp_session);
- }
- break;
- default:
- break;
+ case SWITCH_SIG_KILL:
+ switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
+ break;
+ case SWITCH_SIG_BREAK:
+ if (switch_rtp_ready(tech_pvt->rtp_session)) {
+ switch_rtp_break(tech_pvt->rtp_session);
+ }
+ break;
+ default:
+ break;
}
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL KILL %d\n", switch_channel_get_name(channel), sig);
@@ -968,8 +968,8 @@ switch_status_t channel_answer_channel(switch_core_session_t *session)
listener_t *listener = NULL;
skinny_profile_find_listener_by_device_name_and_instance(tech_pvt->profile,
- switch_channel_get_variable(channel, "skinny_device_name"),
- atoi(switch_channel_get_variable(channel, "skinny_device_instance")), &listener);
+ switch_channel_get_variable(channel, "skinny_device_name"),
+ atoi(switch_channel_get_variable(channel, "skinny_device_instance")), &listener);
if (listener) {
int x = 0;
skinny_session_start_media(session, listener, atoi(switch_channel_get_variable(channel, "skinny_line_instance")));
@@ -978,13 +978,13 @@ switch_status_t channel_answer_channel(switch_core_session_t *session)
switch_cond_next();
if (++x > 1000) {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Wait tooo long to answer %s:%s\n",
- switch_channel_get_variable(channel, "skinny_device_name"), switch_channel_get_variable(channel, "skinny_device_instance"));
+ switch_channel_get_variable(channel, "skinny_device_name"), switch_channel_get_variable(channel, "skinny_device_instance"));
return SWITCH_STATUS_FALSE;
}
}
} else {
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Unable to find listener to answer %s:%s\n",
- switch_channel_get_variable(channel, "skinny_device_name"), switch_channel_get_variable(channel, "skinny_device_instance"));
+ switch_channel_get_variable(channel, "skinny_device_name"), switch_channel_get_variable(channel, "skinny_device_instance"));
}
return SWITCH_STATUS_SUCCESS;
}
@@ -995,24 +995,24 @@ switch_status_t channel_receive_message(switch_core_session_t *session, switch_c
private_t *tech_pvt = switch_core_session_get_private(session);
switch (msg->message_id) {
- case SWITCH_MESSAGE_INDICATE_ANSWER:
- switch_clear_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
- return channel_answer_channel(session);
-
- case SWITCH_MESSAGE_INDICATE_DISPLAY:
- skinny_session_send_call_info_all(session);
- return SWITCH_STATUS_SUCCESS;
-
- case SWITCH_MESSAGE_INDICATE_PROGRESS:
- if (!switch_test_flag(tech_pvt, TFLAG_EARLY_MEDIA)) {
- /* early media */
- switch_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
+ case SWITCH_MESSAGE_INDICATE_ANSWER:
+ switch_clear_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
return channel_answer_channel(session);
- }
- return SWITCH_STATUS_SUCCESS;
- default:
- return SWITCH_STATUS_SUCCESS;
+ case SWITCH_MESSAGE_INDICATE_DISPLAY:
+ skinny_session_send_call_info_all(session);
+ return SWITCH_STATUS_SUCCESS;
+
+ case SWITCH_MESSAGE_INDICATE_PROGRESS:
+ if (!switch_test_flag(tech_pvt, TFLAG_EARLY_MEDIA)) {
+ /* early media */
+ switch_set_flag_locked(tech_pvt, TFLAG_EARLY_MEDIA);
+ return channel_answer_channel(session);
+ }
+ return SWITCH_STATUS_SUCCESS;
+
+ default:
+ return SWITCH_STATUS_SUCCESS;
}
@@ -1020,10 +1020,10 @@ switch_status_t channel_receive_message(switch_core_session_t *session, switch_c
/* Make sure when you have 2 sessions in the same scope that you pass the appropriate one to the routines
that allocate memory or you will have 1 channel with memory allocated from another channel's pool!
-*/
+ */
switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
- switch_caller_profile_t *outbound_profile,
- switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
+ switch_caller_profile_t *outbound_profile,
+ switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause)
{
switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
switch_core_session_t *nsession = NULL;
@@ -1082,13 +1082,13 @@ switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, swi
tech_pvt->caller_profile = caller_profile;
if ((sql = switch_mprintf(
- "INSERT INTO skinny_active_lines "
- "(device_name, device_instance, line_instance, channel_uuid, call_id, call_state) "
- "SELECT device_name, device_instance, line_instance, '%s', %d, %d "
- "FROM skinny_lines "
- "WHERE value='%s'",
- switch_core_session_get_uuid(nsession), tech_pvt->call_id, SKINNY_ON_HOOK, dest
- ))) {
+ "INSERT INTO skinny_active_lines "
+ "(device_name, device_instance, line_instance, channel_uuid, call_id, call_state) "
+ "SELECT device_name, device_instance, line_instance, '%s', %d, %d "
+ "FROM skinny_lines "
+ "WHERE value='%s'",
+ switch_core_session_get_uuid(nsession), tech_pvt->call_id, SKINNY_ON_HOOK, dest
+ ))) {
skinny_execute_sql(profile, sql, profile->sql_mutex);
switch_safe_free(sql);
}
@@ -1098,7 +1098,7 @@ switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, swi
switch_channel_set_variable(switch_core_session_get_channel(session), SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(nsession));
switch_channel_set_variable(nchannel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(session));
}
-
+
cause = skinny_ring_lines(tech_pvt, session);
if(cause != SWITCH_CAUSE_SUCCESS) {
@@ -1116,7 +1116,7 @@ switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, swi
cause = SWITCH_CAUSE_SUCCESS;
goto done;
- error:
+error:
if (nsession) {
switch_core_session_destroy(&nsession);
}
@@ -1126,7 +1126,7 @@ switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, swi
}
- done:
+done:
if (profile) {
if (cause == SWITCH_CAUSE_SUCCESS) {
@@ -1267,37 +1267,37 @@ static void flush_listener(listener_t *listener)
char *sql;
if ((sql = switch_mprintf(
- "SELECT '%q', value, '%q', '%q', '%d' "
- "FROM skinny_lines "
- "WHERE device_name='%s' AND device_instance=%d "
- "ORDER BY position",
- profile->name, profile->domain, listener->device_name, listener->device_instance,
- listener->device_name, listener->device_instance
- ))) {
+ "SELECT '%q', value, '%q', '%q', '%d' "
+ "FROM skinny_lines "
+ "WHERE device_name='%s' AND device_instance=%d "
+ "ORDER BY position",
+ profile->name, profile->domain, listener->device_name, listener->device_instance,
+ listener->device_name, listener->device_instance
+ ))) {
skinny_execute_sql_callback(profile, profile->sql_mutex, sql, flush_listener_callback, NULL);
switch_safe_free(sql);
}
if ((sql = switch_mprintf(
- "DELETE FROM skinny_devices "
- "WHERE name='%s' and instance=%d",
- listener->device_name, listener->device_instance))) {
+ "DELETE FROM skinny_devices "
+ "WHERE name='%s' and instance=%d",
+ listener->device_name, listener->device_instance))) {
skinny_execute_sql(profile, sql, profile->sql_mutex);
switch_safe_free(sql);
}
if ((sql = switch_mprintf(
- "DELETE FROM skinny_lines "
- "WHERE device_name='%s' and device_instance=%d",
- listener->device_name, listener->device_instance))) {
+ "DELETE FROM skinny_lines "
+ "WHERE device_name='%s' and device_instance=%d",
+ listener->device_name, listener->device_instance))) {
skinny_execute_sql(profile, sql, profile->sql_mutex);
switch_safe_free(sql);
}
if ((sql = switch_mprintf(
- "DELETE FROM skinny_buttons "
- "WHERE device_name='%s' and device_instance=%d",
- listener->device_name, listener->device_instance))) {
+ "DELETE FROM skinny_buttons "
+ "WHERE device_name='%s' and device_instance=%d",
+ listener->device_name, listener->device_instance))) {
skinny_execute_sql(profile, sql, profile->sql_mutex);
switch_safe_free(sql);
}
@@ -1348,8 +1348,8 @@ switch_status_t dump_device(skinny_profile_t *profile, const char *device_name,
{
char *sql;
if ((sql = switch_mprintf("SELECT name, user_id, instance, ip, type, max_streams, port, codec_string, headset, handset, speaker "
- "FROM skinny_devices WHERE name='%s'",
- device_name))) {
+ "FROM skinny_devices WHERE name='%s'",
+ device_name))) {
skinny_execute_sql_callback(profile, profile->sql_mutex, sql, dump_device_callback, stream);
switch_safe_free(sql);
}
@@ -1372,7 +1372,7 @@ static void close_socket(switch_socket_t **sock, skinny_profile_t *profile)
static switch_status_t kill_listener(listener_t *listener, void *pvt)
{
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Killing listener %s:%d.\n",
- listener->device_name, listener->device_instance);
+ listener->device_name, listener->device_instance);
switch_clear_flag(listener, LFLAG_RUNNING);
close_socket(&listener->sock, listener->profile);
return SWITCH_STATUS_SUCCESS;
@@ -1435,7 +1435,7 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
switch(status) {
case SWITCH_STATUS_TIMEOUT:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Communication Time Out with %s:%d.\n",
- listener->remote_ip, listener->remote_port);
+ listener->remote_ip, listener->remote_port);
if(listener->expire_time < switch_epoch_time_now(NULL)) {
switch_event_t *event = NULL;
@@ -1446,7 +1446,7 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Communication Error with %s:%d.\n",
- listener->remote_ip, listener->remote_port);
+ listener->remote_ip, listener->remote_port);
}
switch_clear_flag_locked(listener, LFLAG_RUNNING);
break;
@@ -1470,7 +1470,7 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
if (listener->profile->debug > 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Communication Complete with %s:%d.\n",
- listener->remote_ip, listener->remote_port);
+ listener->remote_ip, listener->remote_port);
}
switch_thread_rwlock_wrlock(listener->rwlock);
@@ -1484,7 +1484,7 @@ static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
if (listener->profile->debug > 0) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Communication Closed with %s:%d.\n",
- listener->remote_ip, listener->remote_port);
+ listener->remote_ip, listener->remote_port);
}
if(destroy_pool == 0) {
@@ -1559,7 +1559,7 @@ new_socket:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Socket up listening on %s:%u\n", profile->ip, profile->port);
break;
- sock_fail:
+sock_fail:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error! Could not listen on %s:%u\n", profile->ip, profile->port);
switch_yield(100000);
}
@@ -1622,7 +1622,7 @@ new_socket:
}
- end:
+end:
close_socket(&profile->sock, profile);
@@ -1635,7 +1635,7 @@ new_socket:
}
- fail:
+fail:
return NULL;
}
@@ -1677,7 +1677,7 @@ switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, c
if (profile->sock && !strcasecmp(var, "odbc-dsn")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
- "Skinny profile setting 'odbc-dsn' can't be changed while running\n");
+ "Skinny profile setting 'odbc-dsn' can't be changed while running\n");
return SWITCH_STATUS_FALSE;
}
@@ -1758,7 +1758,7 @@ static switch_status_t load_skinny_config(void)
switch_xml_t xsettings, xdevice_types, xsoft_key_set_sets;
if (zstr(profile_name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
- " is missing name attribute\n");
+ " is missing name attribute\n");
continue;
}
if ((xsettings = switch_xml_child(xprofile, "settings"))) {
@@ -1767,11 +1767,11 @@ static switch_status_t load_skinny_config(void)
switch_core_db_t *db;
skinny_profile_t *profile = NULL;
switch_xml_t param;
-
- if (switch_core_new_memory_pool(&profile_pool) != SWITCH_STATUS_SUCCESS) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "OH OH no pool\n");
- return SWITCH_STATUS_TERM;
- }
+
+ if (switch_core_new_memory_pool(&profile_pool) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "OH OH no pool\n");
+ return SWITCH_STATUS_TERM;
+ }
profile = switch_core_alloc(profile_pool, sizeof(skinny_profile_t));
profile->pool = profile_pool;
profile->name = switch_core_strdup(profile->pool, profile_name);
@@ -1780,17 +1780,17 @@ static switch_status_t load_skinny_config(void)
switch_mutex_init(&profile->listener_mutex, SWITCH_MUTEX_NESTED, profile->pool);
switch_mutex_init(&profile->sock_mutex, SWITCH_MUTEX_NESTED, profile->pool);
switch_mutex_init(&profile->flag_mutex, SWITCH_MUTEX_NESTED, profile->pool);
-
+
for (param = switch_xml_child(xsettings, "param"); param; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if (skinny_profile_set(profile, var, val) != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
- "Unable to set skinny setting '%s'. Does it exists?\n", var);
+ "Unable to set skinny setting '%s'. Does it exists?\n", var);
}
} /* param */
-
+
if (!profile->dialplan) {
skinny_profile_set(profile, "dialplan","XML");
}
@@ -1838,8 +1838,8 @@ static switch_status_t load_skinny_config(void)
}
if (soft_key_set_id > 15) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
- "soft-key-set name '%s' is greater than 15 in soft-key-set-set '%s' in profile %s.\n",
- switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name);
+ "soft-key-set name '%s' is greater than 15 in soft-key-set-set '%s' in profile %s.\n",
+ switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name);
continue;
}
for (string_pos = 0; string_pos <= string_len; string_pos++) {
@@ -1847,8 +1847,8 @@ static switch_status_t load_skinny_config(void)
val[string_pos] = '\0';
if (field_no > 15) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
- "soft-key-set name '%s' is limited to 16 buttons in soft-key-set-set '%s' in profile %s.\n",
- switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name);
+ "soft-key-set name '%s' is limited to 16 buttons in soft-key-set-set '%s' in profile %s.\n",
+ switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name);
break;
}
message->data.soft_key_set.soft_key_set[soft_key_set_id].soft_key_template_index[field_no++] = skinny_str2soft_key_event(&val[start]);
@@ -1857,28 +1857,28 @@ static switch_status_t load_skinny_config(void)
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
- "Unknown soft-key-set name '%s' in soft-key-set-set '%s' in profile %s.\n",
- switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name);
+ "Unknown soft-key-set name '%s' in soft-key-set-set '%s' in profile %s.\n",
+ switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name);
}
} /* soft-key-set */
- switch_core_hash_insert(profile->soft_key_set_sets_hash, soft_key_set_set_name, message);
+ switch_core_hash_insert(profile->soft_key_set_sets_hash, soft_key_set_set_name, message);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
- " is missing a name attribute in profile %s.\n", profile->name);
+ " is missing a name attribute in profile %s.\n", profile->name);
}
} /* soft-key-set-set */
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
- " is missing in profile %s.\n", profile->name);
+ " is missing in profile %s.\n", profile->name);
} /* soft-key-set-sets */
if (!switch_core_hash_find(profile->soft_key_set_sets_hash, "default")) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
- "Profile %s doesn't have a default . Profile ignored.\n", profile->name);
+ "Profile %s doesn't have a default . Profile ignored.\n", profile->name);
switch_core_destroy_memory_pool(&profile_pool);
continue;
}
-
-
+
+
/* Device types */
switch_core_hash_init(&profile->device_type_params_hash, profile->pool);
if ((xdevice_types = switch_xml_child(xprofile, "device-types"))) {
@@ -1893,13 +1893,13 @@ static switch_status_t load_skinny_config(void)
char *val = (char *) switch_xml_attr_soft(param, "value");
if (!strcasecmp(var, "firmware-version")) {
- strncpy(params->firmware_version, val, 16);
+ strncpy(params->firmware_version, val, 16);
}
} /* param */
- switch_core_hash_insert(profile->device_type_params_hash, id_str, params);
+ switch_core_hash_insert(profile->device_type_params_hash, id_str, params);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
- "Unknow device type %s in profile %s.\n", switch_xml_attr_soft(xdevice_type, "id"), profile->name);
+ "Unknow device type %s in profile %s.\n", switch_xml_attr_soft(xdevice_type, "id"), profile->name);
}
}
}
@@ -1936,7 +1936,7 @@ static switch_status_t load_skinny_config(void)
}
switch_core_db_close(db);
}
-
+
skinny_execute_sql_callback(profile, profile->sql_mutex, "DELETE FROM skinny_devices", NULL, NULL);
skinny_execute_sql_callback(profile, profile->sql_mutex, "DELETE FROM skinny_lines", NULL, NULL);
skinny_execute_sql_callback(profile, profile->sql_mutex, "DELETE FROM skinny_buttons", NULL, NULL);
@@ -1945,13 +1945,13 @@ static switch_status_t load_skinny_config(void)
skinny_profile_respawn(profile, 0);
/* Register profile */
- switch_mutex_lock(globals.mutex);
- switch_core_hash_insert(globals.profile_hash, profile->name, profile);
- switch_mutex_unlock(globals.mutex);
+ switch_mutex_lock(globals.mutex);
+ switch_core_hash_insert(globals.profile_hash, profile->name, profile);
+ switch_mutex_unlock(globals.mutex);
profile = NULL;
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
- "Settings are missing from profile %s.\n", profile_name);
+ "Settings are missing from profile %s.\n", profile_name);
} /* settings */
} /* profile */
}
@@ -1991,26 +1991,26 @@ static void skinny_user_to_device_event_handler(switch_event_t *event)
case USER_TO_DEVICE_DATA_MESSAGE:
data_length = strlen(data); /* we ignore data_length sent */
send_data(listener, message_type,
- application_id, line_instance, call_id, transaction_id, data_length,
- data);
+ application_id, line_instance, call_id, transaction_id, data_length,
+ data);
case USER_TO_DEVICE_DATA_VERSION1_MESSAGE:
data_length = strlen(data); /* we ignore data_length sent */
send_extended_data(listener, message_type,
- application_id, line_instance, call_id, transaction_id, data_length,
- sequence_flag, display_priority, conference_id, app_instance_id, routing_id,
- data);
+ application_id, line_instance, call_id, transaction_id, data_length,
+ sequence_flag, display_priority, conference_id, app_instance_id, routing_id,
+ data);
break;
default:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
- "Incorrect message type %s (%d).\n", skinny_message_type2str(message_type), message_type);
+ "Incorrect message type %s (%d).\n", skinny_message_type2str(message_type), message_type);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
- "Device %s:%d in profile '%s' not found.\n", device_name, device_instance, profile_name);
+ "Device %s:%d in profile '%s' not found.\n", device_name, device_instance, profile_name);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
- "Profile '%s' not found.\n", profile_name);
+ "Profile '%s' not found.\n", profile_name);
}
}
@@ -2032,41 +2032,41 @@ static void skinny_call_state_event_handler(switch_event_t *event)
if ((profile = skinny_find_profile(profile_name))) {
skinny_profile_find_listener_by_device_name_and_instance(profile, device_name, device_instance, &listener);
- if(listener) {
- if(line_instance > 0) {
- line_instance_condition = switch_mprintf("line_instance=%d", line_instance);
- } else {
- line_instance_condition = switch_mprintf("1=1");
- }
- switch_assert(line_instance_condition);
- if(call_id > 0) {
- call_id_condition = switch_mprintf("call_id=%d", call_id);
- } else {
- call_id_condition = switch_mprintf("1=1");
- }
- switch_assert(call_id_condition);
+ if(listener) {
+ if(line_instance > 0) {
+ line_instance_condition = switch_mprintf("line_instance=%d", line_instance);
+ } else {
+ line_instance_condition = switch_mprintf("1=1");
+ }
+ switch_assert(line_instance_condition);
+ if(call_id > 0) {
+ call_id_condition = switch_mprintf("call_id=%d", call_id);
+ } else {
+ call_id_condition = switch_mprintf("1=1");
+ }
+ switch_assert(call_id_condition);
- if ((sql = switch_mprintf(
- "UPDATE skinny_active_lines "
- "SET call_state=%d "
- "WHERE device_name='%s' AND device_instance=%d "
- "AND %s AND %s",
- call_state,
- listener->device_name, listener->device_instance,
- line_instance_condition, call_id_condition
- ))) {
- skinny_execute_sql(listener->profile, sql, listener->profile->sql_mutex);
- switch_safe_free(sql);
- }
- switch_safe_free(line_instance_condition);
- switch_safe_free(call_id_condition);
+ if ((sql = switch_mprintf(
+ "UPDATE skinny_active_lines "
+ "SET call_state=%d "
+ "WHERE device_name='%s' AND device_instance=%d "
+ "AND %s AND %s",
+ call_state,
+ listener->device_name, listener->device_instance,
+ line_instance_condition, call_id_condition
+ ))) {
+ skinny_execute_sql(listener->profile, sql, listener->profile->sql_mutex);
+ switch_safe_free(sql);
+ }
+ switch_safe_free(line_instance_condition);
+ switch_safe_free(call_id_condition);
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
- "Device %s:%d in profile '%s' not found.\n", device_name, device_instance, profile_name);
+ "Device %s:%d in profile '%s' not found.\n", device_name, device_instance, profile_name);
}
} else {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING,
- "Profile '%s' not found.\n", profile_name);
+ "Profile '%s' not found.\n", profile_name);
}
}
}
@@ -2089,7 +2089,7 @@ int skinny_message_waiting_event_handler_callback(void *pArg, int argc, char **a
listener_t *listener = NULL;
skinny_profile_find_listener_by_device_name_and_instance(helper->profile,
- device_name, device_instance, &listener);
+ device_name, device_instance, &listener);
if (listener) {
if (helper->yn == SWITCH_TRUE) {
@@ -2143,15 +2143,15 @@ static void skinny_message_waiting_event_handler(switch_event_t *event)
count_str = switch_event_get_header(event, "mwi-voice-message");
if ((sql = switch_mprintf(
- "SELECT device_name, device_instance FROM skinny_lines "
- "WHERE value='%s' AND line_instance=1", user))) {
+ "SELECT device_name, device_instance FROM skinny_lines "
+ "WHERE value='%s' AND line_instance=1", user))) {
struct skinny_message_waiting_event_handler_helper helper = {0};
helper.profile = profile;
helper.yn = switch_true(yn);
if (count_str) {
sscanf(count_str,"%d/%d (%d/%d)",
- &helper.total_new_messages, &helper.total_saved_messages,
- &helper.total_new_urgent_messages, &helper.total_saved_urgent_messages);
+ &helper.total_new_messages, &helper.total_saved_messages,
+ &helper.total_new_urgent_messages, &helper.total_saved_urgent_messages);
}
skinny_execute_sql_callback(profile, profile->sql_mutex, sql, skinny_message_waiting_event_handler_callback, &helper);
switch_safe_free(sql);
@@ -2285,7 +2285,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load)
switch_hash_this(hi, NULL, NULL, &val);
profile = (skinny_profile_t *) val;
-
+
launch_skinny_profile_thread(profile);
}
switch_mutex_unlock(globals.mutex);
@@ -2303,7 +2303,7 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_skinny_shutdown)
int sanity = 0;
skinny_api_unregister();
-
+
/* release events */
switch_event_unbind(&globals.user_to_device_node);
switch_event_unbind(&globals.call_state_node);
diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.h b/src/mod/endpoints/mod_skinny/mod_skinny.h
index eb7e45ebc0..2e4ec1c30a 100644
--- a/src/mod/endpoints/mod_skinny/mod_skinny.h
+++ b/src/mod/endpoints/mod_skinny/mod_skinny.h
@@ -48,66 +48,66 @@
#define SKINNY_EVENT_DEVICE_TO_USER "skinny::device_to_user"
struct skinny_globals {
- int running;
- switch_memory_pool_t *pool;
- switch_mutex_t *mutex;
- switch_hash_t *profile_hash;
- switch_event_node_t *user_to_device_node;
- switch_event_node_t *call_state_node;
- switch_event_node_t *message_waiting_node;
- switch_event_node_t *trap_node;
- int auto_restart;
+ int running;
+ switch_memory_pool_t *pool;
+ switch_mutex_t *mutex;
+ switch_hash_t *profile_hash;
+ switch_event_node_t *user_to_device_node;
+ switch_event_node_t *call_state_node;
+ switch_event_node_t *message_waiting_node;
+ switch_event_node_t *trap_node;
+ int auto_restart;
};
typedef struct skinny_globals skinny_globals_t;
extern skinny_globals_t globals;
typedef enum {
- PFLAG_LISTENER_READY = (1 << 0),
- PFLAG_SHOULD_RESPAWN = (1 << 1),
- PFLAG_RESPAWN = (1 << 2),
+ PFLAG_LISTENER_READY = (1 << 0),
+ PFLAG_SHOULD_RESPAWN = (1 << 1),
+ PFLAG_RESPAWN = (1 << 2),
} profile_flag_t;
struct skinny_profile {
- /* prefs */
- char *name;
- char *domain;
- char *ip;
- unsigned int port;
- char *dialplan;
- char *context;
- char *patterns_dialplan;
- char *patterns_context;
- uint32_t keep_alive;
- char date_format[6];
- int debug;
+ /* prefs */
+ char *name;
+ char *domain;
+ char *ip;
+ unsigned int port;
+ char *dialplan;
+ char *context;
+ char *patterns_dialplan;
+ char *patterns_context;
+ uint32_t keep_alive;
+ char date_format[6];
+ int debug;
int auto_restart;
- switch_hash_t *soft_key_set_sets_hash;
- switch_hash_t *device_type_params_hash;
- /* db */
- char *dbname;
- char *odbc_dsn;
- char *odbc_user;
- char *odbc_pass;
- switch_odbc_handle_t *master_odbc;
- switch_mutex_t *sql_mutex;
- /* stats */
- uint32_t ib_calls;
- uint32_t ob_calls;
- uint32_t ib_failed_calls;
- uint32_t ob_failed_calls;
- /* listener */
- int listener_threads;
- switch_mutex_t *listener_mutex;
- switch_socket_t *sock;
- switch_mutex_t *sock_mutex;
- struct listener *listeners;
- int flags;
- switch_mutex_t *flag_mutex;
- /* call id */
- uint32_t next_call_id;
- /* others */
- switch_memory_pool_t *pool;
+ switch_hash_t *soft_key_set_sets_hash;
+ switch_hash_t *device_type_params_hash;
+ /* db */
+ char *dbname;
+ char *odbc_dsn;
+ char *odbc_user;
+ char *odbc_pass;
+ switch_odbc_handle_t *master_odbc;
+ switch_mutex_t *sql_mutex;
+ /* stats */
+ uint32_t ib_calls;
+ uint32_t ob_calls;
+ uint32_t ib_failed_calls;
+ uint32_t ob_failed_calls;
+ /* listener */
+ int listener_threads;
+ switch_mutex_t *listener_mutex;
+ switch_socket_t *sock;
+ switch_mutex_t *sock_mutex;
+ struct listener *listeners;
+ int flags;
+ switch_mutex_t *flag_mutex;
+ /* call id */
+ uint32_t next_call_id;
+ /* others */
+ switch_memory_pool_t *pool;
};
typedef struct skinny_profile skinny_profile_t;
@@ -117,7 +117,7 @@ struct skinny_device_type_params {
typedef struct skinny_device_type_params skinny_device_type_params_t;
typedef enum {
- SKINNY_ACTION_ROUTE,
+ SKINNY_ACTION_PROCESS,
SKINNY_ACTION_DROP,
SKINNY_ACTION_WAIT
} skinny_action_t;
@@ -127,7 +127,7 @@ typedef enum {
/*****************************************************************************/
typedef enum {
- LFLAG_RUNNING = (1 << 0),
+ LFLAG_RUNNING = (1 << 0),
} listener_flag_t;
#define SKINNY_MAX_LINES 42
@@ -161,25 +161,25 @@ typedef switch_status_t (*skinny_listener_callback_func_t) (listener_t *listener
/* CHANNEL TYPES */
/*****************************************************************************/
typedef enum {
- TFLAG_FORCE_ROUTE = (1 << 0),
- TFLAG_EARLY_MEDIA = (1 << 1),
- TFLAG_IO = (1 << 2),
- TFLAG_READING = (1 << 3),
- TFLAG_WRITING = (1 << 4)
+ TFLAG_FORCE_ROUTE = (1 << 0),
+ TFLAG_EARLY_MEDIA = (1 << 1),
+ TFLAG_IO = (1 << 2),
+ TFLAG_READING = (1 << 3),
+ TFLAG_WRITING = (1 << 4)
} TFLAGS;
typedef enum {
- GFLAG_MY_CODEC_PREFS = (1 << 0)
+ GFLAG_MY_CODEC_PREFS = (1 << 0)
} GFLAGS;
struct private_object {
unsigned int flags;
+ switch_mutex_t *flag_mutex;
switch_frame_t read_frame;
unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
switch_core_session_t *session;
switch_caller_profile_t *caller_profile;
switch_mutex_t *mutex;
- switch_mutex_t *flag_mutex;
/* identification */
skinny_profile_t *profile;
@@ -236,7 +236,7 @@ void profile_walk_listeners(skinny_profile_t *profile, skinny_listener_callback_
switch_cache_db_handle_t *skinny_get_db_handle(skinny_profile_t *profile);
switch_status_t skinny_execute_sql(skinny_profile_t *profile, char *sql, switch_mutex_t *mutex);
switch_bool_t skinny_execute_sql_callback(skinny_profile_t *profile,
- switch_mutex_t *mutex, char *sql, switch_core_db_callback_func_t callback, void *pdata);
+ switch_mutex_t *mutex, char *sql, switch_core_db_callback_func_t callback, void *pdata);
/*****************************************************************************/
/* LISTENER FUNCTIONS */
@@ -261,8 +261,8 @@ switch_status_t channel_on_routing(switch_core_session_t *session);
switch_status_t channel_on_exchange_media(switch_core_session_t *session);
switch_status_t channel_on_soft_execute(switch_core_session_t *session);
switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session, switch_event_t *var_event,
- switch_caller_profile_t *outbound_profile,
- switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause);
+ switch_caller_profile_t *outbound_profile,
+ switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, switch_call_cause_t *cancel_cause);
switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
diff --git a/src/mod/endpoints/mod_skinny/skinny_api.c b/src/mod/endpoints/mod_skinny/skinny_api.c
index 7bbb27afd3..1b2c141341 100644
--- a/src/mod/endpoints/mod_skinny/skinny_api.c
+++ b/src/mod/endpoints/mod_skinny/skinny_api.c
@@ -41,202 +41,202 @@
static switch_status_t skinny_api_list_profiles(const char *line, const char *cursor, switch_console_callback_match_t **matches)
{
- switch_console_callback_match_t *my_matches = NULL;
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_hash_index_t *hi;
- void *val;
- skinny_profile_t *profile;
+ switch_console_callback_match_t *my_matches = NULL;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ switch_hash_index_t *hi;
+ void *val;
+ skinny_profile_t *profile;
- /* walk profiles */
- switch_mutex_lock(globals.mutex);
- for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
- switch_hash_this(hi, NULL, NULL, &val);
- profile = (skinny_profile_t *) val;
+ /* walk profiles */
+ switch_mutex_lock(globals.mutex);
+ for (hi = switch_hash_first(NULL, globals.profile_hash); hi; hi = switch_hash_next(hi)) {
+ switch_hash_this(hi, NULL, NULL, &val);
+ profile = (skinny_profile_t *) val;
- switch_console_push_match(&my_matches, profile->name);
- }
- switch_mutex_unlock(globals.mutex);
+ switch_console_push_match(&my_matches, profile->name);
+ }
+ switch_mutex_unlock(globals.mutex);
- if (my_matches) {
- *matches = my_matches;
- status = SWITCH_STATUS_SUCCESS;
- }
+ if (my_matches) {
+ *matches = my_matches;
+ status = SWITCH_STATUS_SUCCESS;
+ }
- return status;
+ return status;
}
struct match_helper {
- switch_console_callback_match_t *my_matches;
+ switch_console_callback_match_t *my_matches;
};
static int skinny_api_list_devices_callback(void *pArg, int argc, char **argv, char **columnNames)
{
- struct match_helper *h = (struct match_helper *) pArg;
- char *device_name = argv[0];
+ struct match_helper *h = (struct match_helper *) pArg;
+ char *device_name = argv[0];
- switch_console_push_match(&h->my_matches, device_name);
- return 0;
+ switch_console_push_match(&h->my_matches, device_name);
+ return 0;
}
static switch_status_t skinny_api_list_devices(const char *line, const char *cursor, switch_console_callback_match_t **matches)
{
- struct match_helper h = { 0 };
- switch_status_t status = SWITCH_STATUS_FALSE;
- skinny_profile_t *profile = NULL;
- char *sql;
+ struct match_helper h = { 0 };
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ skinny_profile_t *profile = NULL;
+ char *sql;
- char *myline;
- char *argv[1024] = { 0 };
- int argc = 0;
+ char *myline;
+ char *argv[1024] = { 0 };
+ int argc = 0;
- if (!(myline = strdup(line))) {
- status = SWITCH_STATUS_MEMERR;
- return status;
- }
- if (!(argc = switch_separate_string(myline, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) || argc < 4) {
- return status;
- }
+ if (!(myline = strdup(line))) {
+ status = SWITCH_STATUS_MEMERR;
+ return status;
+ }
+ if (!(argc = switch_separate_string(myline, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) || argc < 4) {
+ return status;
+ }
- if(!strcasecmp(argv[1], "profile")) {/* skinny profile ... */
- profile = skinny_find_profile(argv[2]);
- } else if(!strcasecmp(argv[2], "profile")) {/* skinny status profile ... */
- profile = skinny_find_profile(argv[3]);
- }
+ if(!strcasecmp(argv[1], "profile")) {/* skinny profile ... */
+ profile = skinny_find_profile(argv[2]);
+ } else if(!strcasecmp(argv[2], "profile")) {/* skinny status profile ... */
+ profile = skinny_find_profile(argv[3]);
+ }
- if(profile) {
- if ((sql = switch_mprintf("SELECT name FROM skinny_devices"))) {
- skinny_execute_sql_callback(profile, profile->sql_mutex, sql, skinny_api_list_devices_callback, &h);
- switch_safe_free(sql);
- }
- }
+ if(profile) {
+ if ((sql = switch_mprintf("SELECT name FROM skinny_devices"))) {
+ skinny_execute_sql_callback(profile, profile->sql_mutex, sql, skinny_api_list_devices_callback, &h);
+ switch_safe_free(sql);
+ }
+ }
- if (h.my_matches) {
- *matches = h.my_matches;
- status = SWITCH_STATUS_SUCCESS;
- }
+ if (h.my_matches) {
+ *matches = h.my_matches;
+ status = SWITCH_STATUS_SUCCESS;
+ }
- return status;
+ return status;
}
static switch_status_t skinny_api_list_reset_types(const char *line, const char *cursor, switch_console_callback_match_t **matches)
{
- switch_status_t status = SWITCH_STATUS_FALSE;
- SKINNY_PUSH_DEVICE_RESET_TYPES
- return status;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ SKINNY_PUSH_DEVICE_RESET_TYPES
+ return status;
}
static switch_status_t skinny_api_list_stimuli(const char *line, const char *cursor, switch_console_callback_match_t **matches)
{
- switch_status_t status = SWITCH_STATUS_FALSE;
- SKINNY_PUSH_STIMULI
- return status;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ SKINNY_PUSH_STIMULI
+ return status;
}
static switch_status_t skinny_api_list_ring_types(const char *line, const char *cursor, switch_console_callback_match_t **matches)
{
- switch_status_t status = SWITCH_STATUS_FALSE;
- SKINNY_PUSH_RING_TYPES
- return status;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ SKINNY_PUSH_RING_TYPES
+ return status;
}
static switch_status_t skinny_api_list_ring_modes(const char *line, const char *cursor, switch_console_callback_match_t **matches)
{
- switch_status_t status = SWITCH_STATUS_FALSE;
- SKINNY_PUSH_RING_MODES
- return status;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ SKINNY_PUSH_RING_MODES
+ return status;
}
static switch_status_t skinny_api_list_stimulus_instances(const char *line, const char *cursor, switch_console_callback_match_t **matches)
{
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_console_callback_match_t *my_matches = NULL;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ switch_console_callback_match_t *my_matches = NULL;
- switch_console_push_match(&my_matches, "");
- switch_console_push_match(&my_matches, "0");
+ switch_console_push_match(&my_matches, "");
+ switch_console_push_match(&my_matches, "0");
- if (my_matches) {
- *matches = my_matches;
- status = SWITCH_STATUS_SUCCESS;
- }
- return status;
+ if (my_matches) {
+ *matches = my_matches;
+ status = SWITCH_STATUS_SUCCESS;
+ }
+ return status;
}
static switch_status_t skinny_api_list_stimulus_modes(const char *line, const char *cursor, switch_console_callback_match_t **matches)
{
- switch_status_t status = SWITCH_STATUS_FALSE;
- SKINNY_PUSH_LAMP_MODES
- return status;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ SKINNY_PUSH_LAMP_MODES
+ return status;
}
static switch_status_t skinny_api_list_speaker_modes(const char *line, const char *cursor, switch_console_callback_match_t **matches)
{
- switch_status_t status = SWITCH_STATUS_FALSE;
- SKINNY_PUSH_SPEAKER_MODES
- return status;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ SKINNY_PUSH_SPEAKER_MODES
+ return status;
}
static switch_status_t skinny_api_list_call_states(const char *line, const char *cursor, switch_console_callback_match_t **matches)
{
- switch_status_t status = SWITCH_STATUS_FALSE;
- SKINNY_PUSH_CALL_STATES
- return status;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ SKINNY_PUSH_CALL_STATES
+ return status;
}
static switch_status_t skinny_api_list_line_instances(const char *line, const char *cursor, switch_console_callback_match_t **matches)
{
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_console_callback_match_t *my_matches = NULL;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ switch_console_callback_match_t *my_matches = NULL;
- /* TODO */
- switch_console_push_match(&my_matches, "1");
- switch_console_push_match(&my_matches, "");
+ /* TODO */
+ switch_console_push_match(&my_matches, "1");
+ switch_console_push_match(&my_matches, "");
- if (my_matches) {
- *matches = my_matches;
- status = SWITCH_STATUS_SUCCESS;
- }
- return status;
+ if (my_matches) {
+ *matches = my_matches;
+ status = SWITCH_STATUS_SUCCESS;
+ }
+ return status;
}
static switch_status_t skinny_api_list_call_ids(const char *line, const char *cursor, switch_console_callback_match_t **matches)
{
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_console_callback_match_t *my_matches = NULL;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ switch_console_callback_match_t *my_matches = NULL;
- /* TODO */
- switch_console_push_match(&my_matches, "1345");
- switch_console_push_match(&my_matches, "");
+ /* TODO */
+ switch_console_push_match(&my_matches, "1345");
+ switch_console_push_match(&my_matches, "");
- if (my_matches) {
- *matches = my_matches;
- status = SWITCH_STATUS_SUCCESS;
- }
- return status;
+ if (my_matches) {
+ *matches = my_matches;
+ status = SWITCH_STATUS_SUCCESS;
+ }
+ return status;
}
static switch_status_t skinny_api_list_settings(const char *line, const char *cursor, switch_console_callback_match_t **matches)
{
- switch_status_t status = SWITCH_STATUS_FALSE;
- switch_console_callback_match_t *my_matches = NULL;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+ switch_console_callback_match_t *my_matches = NULL;
- switch_console_push_match(&my_matches, "domain");
- switch_console_push_match(&my_matches, "ip");
- switch_console_push_match(&my_matches, "port");
- switch_console_push_match(&my_matches, "patterns-dialplan");
- switch_console_push_match(&my_matches, "patterns-context");
- switch_console_push_match(&my_matches, "dialplan");
- switch_console_push_match(&my_matches, "context");
- switch_console_push_match(&my_matches, "keep-alive");
- switch_console_push_match(&my_matches, "date-format");
- switch_console_push_match(&my_matches, "odbc-dsn");
- switch_console_push_match(&my_matches, "debug");
- switch_console_push_match(&my_matches, "auto-restart");
+ switch_console_push_match(&my_matches, "domain");
+ switch_console_push_match(&my_matches, "ip");
+ switch_console_push_match(&my_matches, "port");
+ switch_console_push_match(&my_matches, "patterns-dialplan");
+ switch_console_push_match(&my_matches, "patterns-context");
+ switch_console_push_match(&my_matches, "dialplan");
+ switch_console_push_match(&my_matches, "context");
+ switch_console_push_match(&my_matches, "keep-alive");
+ switch_console_push_match(&my_matches, "date-format");
+ switch_console_push_match(&my_matches, "odbc-dsn");
+ switch_console_push_match(&my_matches, "debug");
+ switch_console_push_match(&my_matches, "auto-restart");
- if (my_matches) {
- *matches = my_matches;
- status = SWITCH_STATUS_SUCCESS;
- }
- return status;
+ if (my_matches) {
+ *matches = my_matches;
+ status = SWITCH_STATUS_SUCCESS;
+ }
+ return status;
}
/*****************************************************************************/
@@ -244,136 +244,136 @@ static switch_status_t skinny_api_list_settings(const char *line, const char *cu
/*****************************************************************************/
static switch_status_t skinny_api_cmd_status_profile(const char *profile_name, switch_stream_handle_t *stream)
{
- skinny_profile_t *profile;
- if ((profile = skinny_find_profile(profile_name))) {
- skinny_profile_dump(profile, stream);
- } else {
- stream->write_function(stream, "Profile not found!\n");
- }
+ skinny_profile_t *profile;
+ if ((profile = skinny_find_profile(profile_name))) {
+ skinny_profile_dump(profile, stream);
+ } else {
+ stream->write_function(stream, "Profile not found!\n");
+ }
- return SWITCH_STATUS_SUCCESS;
+ return SWITCH_STATUS_SUCCESS;
}
static switch_status_t skinny_api_cmd_status_profile_device(const char *profile_name, const char *device_name, switch_stream_handle_t *stream)
{
- skinny_profile_t *profile;
- if ((profile = skinny_find_profile(profile_name))) {
- dump_device(profile, device_name, stream);
- } else {
- stream->write_function(stream, "Profile not found!\n");
- }
+ skinny_profile_t *profile;
+ if ((profile = skinny_find_profile(profile_name))) {
+ dump_device(profile, device_name, stream);
+ } else {
+ stream->write_function(stream, "Profile not found!\n");
+ }
- return SWITCH_STATUS_SUCCESS;
+ return SWITCH_STATUS_SUCCESS;
}
static switch_status_t skinny_api_cmd_profile_device_send_ringer_message(const char *profile_name, const char *device_name, const char *ring_type, const char *ring_mode, switch_stream_handle_t *stream)
{
- skinny_profile_t *profile;
+ skinny_profile_t *profile;
- if ((profile = skinny_find_profile(profile_name))) {
- listener_t *listener = NULL;
- skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
- if(listener) {
- send_set_ringer(listener, skinny_str2ring_type(ring_type), skinny_str2ring_mode(ring_mode), 0, 0);
+ if ((profile = skinny_find_profile(profile_name))) {
+ listener_t *listener = NULL;
+ skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
+ if(listener) {
+ send_set_ringer(listener, skinny_str2ring_type(ring_type), skinny_str2ring_mode(ring_mode), 0, 0);
stream->write_function(stream, "+OK\n");
- } else {
- stream->write_function(stream, "Listener not found!\n");
- }
- } else {
- stream->write_function(stream, "Profile not found!\n");
- }
+ } else {
+ stream->write_function(stream, "Listener not found!\n");
+ }
+ } else {
+ stream->write_function(stream, "Profile not found!\n");
+ }
- return SWITCH_STATUS_SUCCESS;
+ return SWITCH_STATUS_SUCCESS;
}
static switch_status_t skinny_api_cmd_profile_device_send_lamp_message(const char *profile_name, const char *device_name, const char *stimulus, const char *instance, const char *lamp_mode, switch_stream_handle_t *stream)
{
- skinny_profile_t *profile;
+ skinny_profile_t *profile;
- if ((profile = skinny_find_profile(profile_name))) {
- listener_t *listener = NULL;
- skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
- if(listener) {
- send_set_lamp(listener, skinny_str2button(stimulus), atoi(instance), skinny_str2lamp_mode(lamp_mode));
+ if ((profile = skinny_find_profile(profile_name))) {
+ listener_t *listener = NULL;
+ skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
+ if(listener) {
+ send_set_lamp(listener, skinny_str2button(stimulus), atoi(instance), skinny_str2lamp_mode(lamp_mode));
stream->write_function(stream, "+OK\n");
- } else {
- stream->write_function(stream, "Listener not found!\n");
- }
- } else {
- stream->write_function(stream, "Profile not found!\n");
- }
+ } else {
+ stream->write_function(stream, "Listener not found!\n");
+ }
+ } else {
+ stream->write_function(stream, "Profile not found!\n");
+ }
- return SWITCH_STATUS_SUCCESS;
+ return SWITCH_STATUS_SUCCESS;
}
static switch_status_t skinny_api_cmd_profile_device_send_speaker_mode_message(const char *profile_name, const char *device_name, const char *speaker_mode, switch_stream_handle_t *stream)
{
- skinny_profile_t *profile;
+ skinny_profile_t *profile;
- if ((profile = skinny_find_profile(profile_name))) {
- listener_t *listener = NULL;
- skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
- if(listener) {
- send_set_speaker_mode(listener, skinny_str2speaker_mode(speaker_mode));
+ if ((profile = skinny_find_profile(profile_name))) {
+ listener_t *listener = NULL;
+ skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
+ if(listener) {
+ send_set_speaker_mode(listener, skinny_str2speaker_mode(speaker_mode));
stream->write_function(stream, "+OK\n");
- } else {
- stream->write_function(stream, "Listener not found!\n");
- }
- } else {
- stream->write_function(stream, "Profile not found!\n");
- }
+ } else {
+ stream->write_function(stream, "Listener not found!\n");
+ }
+ } else {
+ stream->write_function(stream, "Profile not found!\n");
+ }
- return SWITCH_STATUS_SUCCESS;
+ return SWITCH_STATUS_SUCCESS;
}
static switch_status_t skinny_api_cmd_profile_device_send_call_state_message(const char *profile_name, const char *device_name, const char *call_state, const char *line_instance, const char *call_id, switch_stream_handle_t *stream)
{
- skinny_profile_t *profile;
+ skinny_profile_t *profile;
- if ((profile = skinny_find_profile(profile_name))) {
- listener_t *listener = NULL;
- skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
- if(listener) {
- send_call_state(listener, skinny_str2call_state(call_state), atoi(line_instance), atoi(call_id));
+ if ((profile = skinny_find_profile(profile_name))) {
+ listener_t *listener = NULL;
+ skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
+ if(listener) {
+ send_call_state(listener, skinny_str2call_state(call_state), atoi(line_instance), atoi(call_id));
stream->write_function(stream, "+OK\n");
- } else {
- stream->write_function(stream, "Listener not found!\n");
- }
- } else {
- stream->write_function(stream, "Profile not found!\n");
- }
+ } else {
+ stream->write_function(stream, "Listener not found!\n");
+ }
+ } else {
+ stream->write_function(stream, "Profile not found!\n");
+ }
- return SWITCH_STATUS_SUCCESS;
+ return SWITCH_STATUS_SUCCESS;
}
static switch_status_t skinny_api_cmd_profile_device_send_reset_message(const char *profile_name, const char *device_name, const char *reset_type, switch_stream_handle_t *stream)
{
- skinny_profile_t *profile;
+ skinny_profile_t *profile;
- if ((profile = skinny_find_profile(profile_name))) {
- listener_t *listener = NULL;
- skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
- if(listener) {
- send_reset(listener, skinny_str2device_reset_type(reset_type));
+ if ((profile = skinny_find_profile(profile_name))) {
+ listener_t *listener = NULL;
+ skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
+ if(listener) {
+ send_reset(listener, skinny_str2device_reset_type(reset_type));
stream->write_function(stream, "+OK\n");
- } else {
- stream->write_function(stream, "Listener not found!\n");
- }
- } else {
- stream->write_function(stream, "Profile not found!\n");
- }
+ } else {
+ stream->write_function(stream, "Listener not found!\n");
+ }
+ } else {
+ stream->write_function(stream, "Profile not found!\n");
+ }
- return SWITCH_STATUS_SUCCESS;
+ return SWITCH_STATUS_SUCCESS;
}
static switch_status_t skinny_api_cmd_profile_device_send_data(const char *profile_name, const char *device_name, const char *message_type, char *params, const char *body, switch_stream_handle_t *stream)
{
- skinny_profile_t *profile;
+ skinny_profile_t *profile;
- if ((profile = skinny_find_profile(profile_name))) {
- listener_t *listener = NULL;
- skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
- if(listener) {
+ if ((profile = skinny_find_profile(profile_name))) {
+ listener_t *listener = NULL;
+ skinny_profile_find_listener_by_device_name(profile, device_name, &listener);
+ if(listener) {
switch_event_t *event = NULL;
char *argv[64] = { 0 };
int argc = 0;
@@ -395,49 +395,49 @@ static switch_status_t skinny_api_cmd_profile_device_send_data(const char *profi
switch_event_add_header(event, SWITCH_STACK_BOTTOM, tmp, "%s", var_value);
switch_safe_free(tmp);
/*
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Application-Id", "%d", request->data.extended_data.application_id);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Line-Instance", "%d", request->data.extended_data.line_instance);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Call-Id", "%d", request->data.extended_data.call_id);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Transaction-Id", "%d", request->data.extended_data.transaction_id);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Data-Length", "%d", request->data.extended_data.data_length);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Sequence-Flag", "%d", request->data.extended_data.sequence_flag);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Display-Priority", "%d", request->data.extended_data.display_priority);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Conference-Id", "%d", request->data.extended_data.conference_id);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-App-Instance-Id", "%d", request->data.extended_data.app_instance_id);
- switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Routing-Id", "%d", request->data.extended_data.routing_id);
- */
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Application-Id", "%d", request->data.extended_data.application_id);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Line-Instance", "%d", request->data.extended_data.line_instance);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Call-Id", "%d", request->data.extended_data.call_id);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Transaction-Id", "%d", request->data.extended_data.transaction_id);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Data-Length", "%d", request->data.extended_data.data_length);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Sequence-Flag", "%d", request->data.extended_data.sequence_flag);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Display-Priority", "%d", request->data.extended_data.display_priority);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Conference-Id", "%d", request->data.extended_data.conference_id);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-App-Instance-Id", "%d", request->data.extended_data.app_instance_id);
+ switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Skinny-UserToDevice-Routing-Id", "%d", request->data.extended_data.routing_id);
+ */
}
}
switch_event_add_body(event, "%s", body);
switch_event_fire(&event);
stream->write_function(stream, "+OK\n");
- } else {
- stream->write_function(stream, "Listener not found!\n");
- }
- } else {
- stream->write_function(stream, "Profile not found!\n");
- }
+ } else {
+ stream->write_function(stream, "Listener not found!\n");
+ }
+ } else {
+ stream->write_function(stream, "Profile not found!\n");
+ }
- return SWITCH_STATUS_SUCCESS;
+ return SWITCH_STATUS_SUCCESS;
}
static switch_status_t skinny_api_cmd_profile_set(const char *profile_name, const char *name, const char *value, switch_stream_handle_t *stream)
{
- skinny_profile_t *profile;
+ skinny_profile_t *profile;
- if ((profile = skinny_find_profile(profile_name))) {
- if (skinny_profile_set(profile, name, value) == SWITCH_STATUS_SUCCESS) {
+ if ((profile = skinny_find_profile(profile_name))) {
+ if (skinny_profile_set(profile, name, value) == SWITCH_STATUS_SUCCESS) {
skinny_profile_respawn(profile, 0);
stream->write_function(stream, "+OK\n");
- } else {
- stream->write_function(stream, "Unable to set skinny setting '%s'. Does it exists?\n", name);
- }
- } else {
- stream->write_function(stream, "Profile not found!\n");
- }
+ } else {
+ stream->write_function(stream, "Unable to set skinny setting '%s'. Does it exists?\n", name);
+ }
+ } else {
+ stream->write_function(stream, "Profile not found!\n");
+ }
- return SWITCH_STATUS_SUCCESS;
+ return SWITCH_STATUS_SUCCESS;
}
/*****************************************************************************/
@@ -445,148 +445,148 @@ static switch_status_t skinny_api_cmd_profile_set(const char *profile_name, cons
/*****************************************************************************/
SWITCH_STANDARD_API(skinny_function)
{
- char *argv[1024] = { 0 };
- int argc = 0;
- char *mycmd = NULL;
- switch_status_t status = SWITCH_STATUS_SUCCESS;
- const char *usage_string = "USAGE:\n"
- "--------------------------------------------------------------------------------\n"
- "skinny help\n"
- "skinny status profile \n"
- "skinny status profile device \n"
- "skinny profile device send ResetMessage [DeviceReset|DeviceRestart]\n"
- "skinny profile device send SetRingerMessage \n"
- "skinny profile device send SetLampMessage \n"
- "skinny profile device send SetSpeakerModeMessage \n"
- "skinny profile device send CallStateMessage \n"
- "skinny profile device send [ =;... ] \n"
- "skinny profile set \n"
- "--------------------------------------------------------------------------------\n";
- if (session) {
- return SWITCH_STATUS_FALSE;
- }
+ char *argv[1024] = { 0 };
+ int argc = 0;
+ char *mycmd = NULL;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ const char *usage_string = "USAGE:\n"
+ "--------------------------------------------------------------------------------\n"
+ "skinny help\n"
+ "skinny status profile \n"
+ "skinny status profile device \n"
+ "skinny profile device send ResetMessage [DeviceReset|DeviceRestart]\n"
+ "skinny profile device send SetRingerMessage \n"
+ "skinny profile device send SetLampMessage \n"
+ "skinny profile device send SetSpeakerModeMessage \n"
+ "skinny profile device send CallStateMessage