From 8f67d2fbfb7c0f70162903efa2e34835348c7720 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 31 Aug 2011 13:52:21 -0500 Subject: [PATCH 001/204] typo --- src/switch_rtp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 121f81101e..020f8aea57 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -4271,7 +4271,7 @@ SWITCH_DECLARE(int) switch_rtp_write_manual(switch_rtp_t *rtp_session, goto end; } - if (!((*flags) && SFF_RTP_HEADER)) { + if (((*flags) & SFF_RTP_HEADER)) { rtp_session->last_write_ts = ts; } From 882ebd67773200c4dd9c1e598f1d8d6c16706cc1 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 31 Aug 2011 16:04:20 -0500 Subject: [PATCH 002/204] FS-3527 this fixes part of the problem with MSSQL --- src/include/switch_core_db.h | 2 ++ src/mod/endpoints/mod_sofia/sofia_presence.c | 3 ++- src/switch_core_sqldb.c | 8 ++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/include/switch_core_db.h b/src/include/switch_core_db.h index 6ea9b4a3fb..3e92e2bdac 100644 --- a/src/include/switch_core_db.h +++ b/src/include/switch_core_db.h @@ -540,6 +540,8 @@ SWITCH_DECLARE(int) switch_core_db_changes(switch_core_db_t *db); * literal. */ +SWITCH_DECLARE(char*)switch_sql_concat(); + SWITCH_END_EXTERN_C #endif /* For Emacs: diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index a85138b8f6..0a63edb690 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -702,7 +702,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) "from sip_registrations " "left join sip_dialogs on " - "sip_dialogs.presence_id = sip_registrations.sip_user || '@' || sip_registrations.sip_host " + "sip_dialogs.presence_id = sip_registrations.sip_user %q '@' %q sip_registrations.sip_host " "or (sip_dialogs.sip_from_user = sip_registrations.sip_user " "and sip_dialogs.sip_from_host = sip_registrations.sip_host) " @@ -713,6 +713,7 @@ static void actual_sofia_presence_event_handler(switch_event_t *event) "(sip_registrations.orig_server_host='%q' or sip_registrations.sip_host='%q' " "or sip_registrations.presence_hosts like '%%%q%%'))", dh.status, dh.rpid, + switch_sql_concat(), switch_sql_concat(), probe_euser, probe_host, probe_euser, probe_host, probe_host, probe_host); switch_assert(sql); diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 665b496c01..60e6c4743b 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -2114,6 +2114,14 @@ SWITCH_DECLARE(void) switch_cache_db_status(switch_stream_handle_t *stream) switch_mutex_unlock(sql_manager.dbh_mutex); } +SWITCH_DECLARE(char*)switch_sql_concat() +{ + if(runtime.odbc_dbtype == DBTYPE_MSSQL) + return "+"; + + return "||"; +} + /* For Emacs: * Local Variables: * mode:c From b9d5dff3d89516ef67fcb4ad636c74ba3f266136 Mon Sep 17 00:00:00 2001 From: Michal Bielicki - cypromis Date: Thu, 1 Sep 2011 00:18:44 +0200 Subject: [PATCH 003/204] no gccisms in Makefile.am please ... --- libs/silk/Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/silk/Makefile.am b/libs/silk/Makefile.am index 235e468913..8b26c971b8 100644 --- a/libs/silk/Makefile.am +++ b/libs/silk/Makefile.am @@ -1,5 +1,4 @@ - -AM_CFLAGS = -Isrc -Iinterface -fPIC -Wall -O3 +AM_CFLAGS = -Isrc -Iinterface -fPIC -all -O3 AUTOMAKE_OPTS = gnu NAME = libSKP_SILK_SDK AM_CPPFLAGS = $(AM_CFLAGS) From fd83dc8e9eed3e9d11db8a093ac2115c8b9d8cf8 Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Wed, 31 Aug 2011 15:44:59 -0700 Subject: [PATCH 004/204] Update ChangeLog through July 31 --- docs/ChangeLog | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/docs/ChangeLog b/docs/ChangeLog index d785d07f46..306ceaaadb 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -26,6 +26,9 @@ freeswitch (1.0.7) build: add support for bz2 to getlibs (r:b61fc396) build: Bump callie sounds to 1.0.15 (r:c8eaef60) build: always use our includes first so we use our srcdir headers over installed versions (r:15c79424) + build: pocketsphinx build for 0.7 windows vs2008 (r:a7613c06/FS-3348) + build: They no longer ship the wsj model in pocketsphinx... and seems the dictionary has moved a bit. (r:23571680) + build: unimrcp vs2010 build fixes for new version (r:2dcca5f4) codec2: working prototype, still for testing only (r:04ca0751) config: move limit.conf to db.conf config: Update VM phrase macros to voice option then action on main, config menus @@ -279,10 +282,27 @@ freeswitch (1.0.7) core: Add the ability to issue a break to switch_ivr_sleep when media is not ready, allowing continuation of processing of the dialplan. (r:dfc30b2e/FS-3373) core: parse events and messages in channel_ready (r:94148095) core: add last_hold_time and hold_accum vars for cdr data (r:676ef808) + core: avoid recursion loop in parse_all_events vs channel_ready (r:22d89943) + core: auto populate global origination_caller_id_name/number from effective_caller_id_name/number in enterprise originate (r:f8c029a1) + core: add --enable-timerfd-wrapper to wrap timefd syscalls for platforms with the right kernel and wrong libc (r:306b332d) + core: don't parse events in channel_ready during hold (r:cad68d53) + core: only parse messages from channel_ready when its a session calling channel ready on itself not when another thread calls it (r:1d12519d) + core: Fix single quote stripping and add %y to turn ' into \' (r:3b5a0ae5/FS-3359) + core: push out signal data into its own queue system (r:f1ee225c) + core: When in a dialplan hunt and we have a custom caller_profile, ${destination_number} and other variable kept the previous value of the original dialplan parsing. This correct this so it take the custom created caller_profile for that hunt (r:b0e0dd22) + core: pause traffic if sql_queue gets to big (r:2939262e) + core: fix detection of tones in monitor_early_media_fail (r:3cbae3fb/FS-3413) + core: use rwlock for global vars to reduce contention (r:0521886d) + core: Fix separate_string_blank_delim to handle strings with '&' (r:f3a42258/FS-3099) + core: Fix setting display on wrong channel on eavesdrop (r:3dc4b530) + core: add new detailed_calls view a version of the channels table that shows only one legged calls or bridged calls (r:beecd937) + core: display update on flip_cid (r:0fc8050c) docs: Major clean up of doxygen generated core API documentation (r:794246e1) docs: Add libteletone back to core API documentation (r:c35c138d) embedded languages: Provide core level support for conditional Set Global Variable (r:c017c24b/FSCORE-612) embedded languages: add insertFile front end to switch_ivr_insert_file and reswig (r:c4e350ab) + flex client: check in basic flex demo as basis to develop a client application (r:25be760b) + flex client: the hotkeys js is broken, get rid of it (r:2f6f71d4) fs_cli: block control-z from fs cli and print a warning how to exit properly (r:dc436b82) fs_cli: skip blocking writes on fs_cli to avoid backing up event socket (r:2ec2a9b0) fs_cli: let ctl-c work until you are connected (r:986f258d) @@ -294,6 +314,7 @@ freeswitch (1.0.7) libdingaling: fix race on shutdown causing crash (FSMOD-47) libdingaling: Fix crash in new GV interface when exceeding 24 calls (r:be00609a/FS-2171) libdingaling: fix crash when GV call ends (r:687140b5/FS-3139) + libdingaling: fix small leak (r:d3ea42d8/FS-3334) libesl: Fix potential race condition (ESL-36) libesl: Add /uuid command to fs_cli to filter logs by uuid libesl: Increase buffer in fs_cli for Win (r:d1d6be88/FSCORE-611) @@ -324,6 +345,7 @@ freeswitch (1.0.7) libesl: use poll instead of select in ESL client lib because select is not your friend.... (r:ae595cd5) libesl: Add digit_timeout to ESL::IVR's playAndGetDigits method (r:f564d383) libesl: add array manipulation to the wraper code (r:ffa0a071) + libesl: fix mem leak - good catch, Jlenk! (r:e420e17f/FS-3386) libfreetdm: implemented freetdm config nodes and ss7 initial configuration libfreetdm: fix codec for CAS signaling (r:b76e7f18) libfreetdm: freetdm: ss7- added support for incoming group blocks, started adding support for ansi (r:c219a73c) @@ -342,6 +364,10 @@ freeswitch (1.0.7) libsofiasip: fix bad assert (r:56404641/FS-3133) libsofiasip: lower stack and boost priority of sofia schedule thread (r:257bc9ff) libsofiasip: Fix for issue reported on the mailing list with a Chinese locale and windows. This commit removes a hidden char that should not have been there anyway. (r:7adaceb8) + libsofiasip: resolve edge case in the 3rd party sofia sip stack library when dealing with a malformed contact and missing ack. Will push upstream to sofia devs (r:d68605f5/FS-3394) + libsofiasip: use individual pools instead of sub-pools for nua handles to avoid pool swell (r:f7612413) + libsofiasip: Fix segfault in sofia's stun code (r:7403db70) + libsofiasip: add homer capture hooks to libsofia (r:3e029f0d) libspandsp: Fixed a typo in spandsp's msvc/inttypes.h Updated sig_tone processing in spandsp to the latest, to allow moy to proceed with his signaling work. libspandsp: removed a saturate16 from spandsp that was causing problems fixed a typo in the MSVC inttypes.h file for spandsp libspandsp: Changes to the signaling tone detector to detect concurrent 2400Hz + 2600Hz tones. This passes voice immunity and other key tests, but it bounces a bit when transitions like 2400 -> 2400+2600 -> 2600 occur. Transitions between tone off and tone on are clean. (r:bc13e944) @@ -351,9 +377,13 @@ freeswitch (1.0.7) 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: 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) + libspandsp: Numerous little changes to spandsp that haven't been pushed to Freeswitch for a while. The only big changes are a majorly rewritten V.42 and V.42bis which are now basically functional. (r:d30e82e2) + libspandsp: Another round of tweaks for spandsp. There should be no functional changes, although quite a few things have changed in the test suite (r:4a7bbf4e) 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) libunimrcp: Update to latest UniMRCP version. MRCP requests can no timeout if there is no server response. (r:17099473) + libunimrcp: unimrcp lib does not notify mod_unimrcp of RTSP TEARDOWN timeouts (r:3484f338) + libunimrcp: fixed unimrcp to prevent double destroy of connection (r:493085bb) 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) @@ -465,6 +495,7 @@ freeswitch (1.0.7) mod_conference: wait for thread to start in mod conference to avoid one in a million race on heavy traffic (r:b1cf5bee) mod_conference: add conference member flag nomoh (r:f35a6814) mod_conference: add hup command to conference (kick without the kick sound) (r:492db906) + mod_conference: see H.264 iFrames (r:765be8c9/FS-3406) 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) @@ -475,7 +506,9 @@ freeswitch (1.0.7) mod_dingaling: fix leak in chat_send (r:eb109a85) mod_dingaling: use the login as message source when not in component mode. (chat_send) (r:58c28aab) mod_dingaling: fix mod_dingaling/iksemel/gnutls link error when using newer autotools (r:294b0779/FS-3182) + mod_dingaling: fix segmentation fault on mod_dingaling when receiving a discovery from the server (r:2e651c8f/FS-3391) mod_directory: Add variable directory_search_order to allow to search by first name by default is set to "first_name" (r:163ca31f) + mod_directory: let mod_directory use non-XML dialplans (r:8895de1b) mod_distributor: Add mod_distributor to VS2010 - not built by default (r:bac79ba1) mod_dptools: add eavesdrop_enable_dtmf chan var (r:596c0012) mod_dptools: Make park app not send 183 session progress (r:76932995/FSCORE-567) @@ -493,6 +526,10 @@ freeswitch (1.0.7) mod_dptools: Set the default lang if not supplied (mod_say_en) (r:5382972a/FS-3215) mod_dptools: add capture dp app (r:860d2a6c) mod_dptools: Allow redefinition of continue_on_fail and failure_causes during bridge execution. (r:01d0250e/FS-1986) + mod_dptools: Fix "dial 0" 3-way call on att x-fer (r:d4fe85ed/FS-3275) + mod_dptools: fix campon to play music even on first run and cancel faster (r:9cf44f3a) + mod_dptools: fix small leak in strftime (r:bbbd67ba) + mod_dptools: resolve Heap corruption in strftime_api_function -thanks (r:707bd05b/FS-3417) 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) @@ -526,6 +563,7 @@ freeswitch (1.0.7) mod_fifo: Fix crash when using fifo_destroy_after_use (r:ee562c82/FS-2879) mod_fifo: don't seg in edge case error conditions (r:9ee13b72) mod_fifo: set tracking data before enabling hooks (r:34267869) + mod_fifo: Fix fifo orbit timeout when not using a chime tested with and without chime (r:7fee1fd1) mod_file_string: Fix segfault when using file string in conference (r:9c40e8e9/FS-3122) mod_freetdm: Fix for TON and NPI not passed through to channel variables on incoming calls mod_freetdm: add pvt data to freetdm channels fix fxs features (r:9d456900) @@ -596,6 +634,7 @@ freeswitch (1.0.7) mod_khomp: Removed alternative contexts / extensions - New struct for matchs - On calls originated from an FXS branch, the Endpoint searches for a valid extension (digits sent) after the DTMF '#' or after the timeout (option fxs-digit-timeout). That search is done in the context defined in section , or if no context configured, the search is done in context defined in context-fxs. - Added "dialplan" configuration: Name of the dialplan module in use (default XML) - Group context enabled. If set, the search for a valid extension is done only in that context. - Updated documentation (r:1ef3fc9a) mod_ladspa: Add mod_ladspa (Audio plugin framework for linux) (r:2d3d8f8d) mod_ladspa: add string params to ladspa so you can connect files to audio ports (string params don't count towards number params) (r:b7891511) + mod_ladspa: putenv() breaks the process environment variables, use setenv() instead. (r:f6dadb58) mod_lcr: Expand variables (MODAPP-418) mod_lcr: add enable_sip_redir parameter (r:70bf7a0a/MODAPP-427) mod_lcr: don't validate profiles with ${} vars since they are dynamic and we can't guess what the proper value should be (r:af33afaa) @@ -625,6 +664,7 @@ 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_managed: resolve Memory leak in mod_managed by EventBinding and swig delete_switch_event (r:c6048134/FS-3381) 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) @@ -648,6 +688,8 @@ freeswitch (1.0.7) mod_portaudio: Fix inbound state (CS_ROUTING not CS_INIT) (MODENDP-302) mod_portaudio: mod_portaudio improvements and bug fixes (r:33b74ca8/FS-3006) mod_portaudio: Add pa devlist to portaudio webapi (r:e8f10ea3) + mod_portaudio: fix crash on bad init (r:6f49e6ba/FS-3361) + mod_portaudio: move load_config a bit lower since it needs to use the hashtables (r:1529c0ec) mod_portaudio_stream: update to specify the channel index (r:d1169d6e) 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) @@ -658,6 +700,14 @@ freeswitch (1.0.7) mod_rtmp: Make all sockets non-blocking (r:affcdb0a) mod_rtmp: mod_rtmp for windows (r:f8cda539/FS-3355) mod_rtmp: flush buffer to avoid lag and enable plc (r:4bb76831) + mod_rtmp: add conf (r:4eaabd28) + mod_rtmp: set variables based on input hash (r:3815d188) + mod_rtmp: Remove duplicate output from rtmp status profile xxx API command (r:2e016541) + mod_rtmp: Make all sockets non-blocking (r:affcdb0a) + mod_rtmp: Lower default buffer size to 50ms (r:d52a254d) + mod_rtmp: CNG frames need to have codec set too (r:36f812d9) + mod_rtmp: remove superfluous hangup (r:50817655) + mod_rtmp: fix crash when call made from user not in domain (r:a5452174/FS-3353) 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 @@ -714,6 +764,8 @@ freeswitch (1.0.7) 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_skypopen: refining oss driver, removing audio sync during call (was each 20 secs), audio sync at the tcp interfacing with the skype client (reading more than 20ms worth) (r:891015e6) + mod_skypopen: fixed a demented bug (incrementing a variable zeroed in the same loop) maybe responsible for moh sputtering under load on virtual machines (r:43eeeb82) 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) @@ -897,6 +949,26 @@ freeswitch (1.0.7) mod_sofia: removed the vid refresh thing (r:49e52b4c/FS-3362) mod_sofia: add sip_liberal_dtmf chanvar and liberal-dtmf profile param to use the maximum methods of DTMF avoiding sticking to the spec which leads to incompatability (r:bc7cb400) mod_sofia: support final response in response header passing (r:acd0898e) + mod_sofia: Fix failure to fall back to g.711 when t.38 attempt fails (r:07a79752/FS-3214) + mod_sofia: pop :: off the domain name in mwi events to hint at the profile (r:e2ed8c08) + mod_sofia: dig into the database to figure out what profile to send mwi on when they are not willing to alais the domain to the profile =/ (r:b14340a5) + mod_sofia: Fix 3pcc codec negotiation issue with bypass_media (r:c5a2275f/FS-3340) + mod_sofia: re-add not-so-superfluous-after-all NUTAG_AUTOANSWER(0) (r:927fde18/FS-3349) + mod_sofia: add mutex around gateway access on per-profile basis and token based access to global profiles to prevent hanging on to the hash mutex while doing sql stmts which may cause issues/slowdowns (r:9df8169d) + mod_sofia: add parallelism to sofia by offsetting sip messages to the concerned sessions and using multiple queue threads for message handling (r:fb68746e) + mod_sofia: Fix sofia hang on shutdown (r:3be64cbf/FS-3354) + mod_sofia: remove vid refresh from SDP on declined video connection (r:49e52b4c/FS-3362) + mod_sofia: fix small mem leak in sofia (r:6f62f391/FS-3386) + mod_sofia: add proxy tag to UPDATE packets if it was set by INVITE (r:e6605139) + mod_sofia: resolve attended transfers, it fails to parse the Replaces when encoded (r:d9bbf129/FS-3304) + mod_sofia: if user has set presence_id, don't override it (r:7cdc8342) + mod_sofia: only list real profiles not aliases in presence code (r:f9969f38) + mod_sofia: Fix 200 OK not passed for Callee-Initiated ReInvite for T.38 (r:b2299035/FS-3421) + mod_sofia: destroy nh if SIP transaction terminated by a 488 (r:a0cec8ab/FS-3444) + mod_sofia: use register contact to determine proper contact in 200 ok response to register (r:f9612fec) + mod_sofia: add NDLB-allow-nondup-sdp to indicate you want to parse a differnt sdp in 200 ok from 1xx (previous default) this is a RFC violation so I decided not to support it by default anymore. Enable this if you want that broken behaviour (r:3f489a2a) + mod_sofia: add homer capture hooks to mod_sofia (r:98473085) + mod_soundtouch: updated soundtouch to library 1.5.0 to fix gcc > 4.3 incompatibilities (r:dfb5c629) 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) @@ -916,6 +988,8 @@ freeswitch (1.0.7) mod_spandsp: add more fax event information (r:0555b702/FS-3345) mod_spandsp: fix memory issue in spandsp_tone_detect (r:8793c2ed) mod_spandsp: add proper tone detect stop (r:8beb10d2/FS-3367) + mod_spandsp: add more fax event information (r:0555b702/FS-3345) + mod_spandsp: fix memory issue in spandsp_tone_detect (r:8793c2ed) 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) @@ -952,6 +1026,8 @@ freeswitch (1.0.7) mod_voicemail: vm-skip-instructions param in xml directory to disable instructions how to record a file (r:ed7e1f39) mod_voicemail: Implement 10 new standard api function call that allow you to control fs voicemail storage system. The goal is to have a standard API set for any additional storage system we wish the voicemail to run off. Current list of added api name are : vm_fsdb_msg_count, vm_fsdb_msg_list, vm_fsdb_msg_get, vm_fsdb_msg_delete, vm_fsdb_msg_undelete, vm_fsdb_msg_purge, vm_fsdb_msg_save, vm_fsdb_pref_greeting_set, vm_fsdb_pref_recname_set, vm_fsdb_pref_password_set. (r:1f4cb488) mod_voicemail: Adding a new voicemail fsdb api vm_fsdb_auth_login that does basic login authentication for a user (r:bfdfac5e) + mod_voicemail: Fix vm to email dial 8 option (r:8592b6d9/FS-3382) + mod_voicemail: Add 2 new profile settings, db-password-override and allow-empty-password-auth. By default, they have value of their previous behavior. If db-password-override=true, the db password will only be used if present, if not present fallback to the xml config file vm-password. If allow-empty-password-auth=false, it will disable login via a authentication method if there is no password set in the user account (This wont affect voicemail_authorize=true login). (r:a9db642a) mod_xml_cdr: add force_process_cdr var to process b leg cdr on a case by case basis when b leg cdr is disabled (XML-17) mod_xml_cdr: add leg param to query string (XML-24) mod_xml_cdr: fix locked sessions (XML-26) From ead5790c99c56ea3df7c8f2369de91ee664460ce Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Wed, 31 Aug 2011 16:36:51 -0700 Subject: [PATCH 005/204] Update ChangeLog through Aug 11 --- docs/ChangeLog | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/docs/ChangeLog b/docs/ChangeLog index 306ceaaadb..89ac7f0231 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -29,6 +29,7 @@ freeswitch (1.0.7) build: pocketsphinx build for 0.7 windows vs2008 (r:a7613c06/FS-3348) build: They no longer ship the wsj model in pocketsphinx... and seems the dictionary has moved a bit. (r:23571680) build: unimrcp vs2010 build fixes for new version (r:2dcca5f4) + build: add sqlite to clean on make current or update-clean (r:2366f429) codec2: working prototype, still for testing only (r:04ca0751) config: move limit.conf to db.conf config: Update VM phrase macros to voice option then action on main, config menus @@ -297,6 +298,17 @@ freeswitch (1.0.7) core: Fix setting display on wrong channel on eavesdrop (r:3dc4b530) core: add new detailed_calls view a version of the channels table that shows only one legged calls or bridged calls (r:beecd937) core: display update on flip_cid (r:0fc8050c) + core: make sql stmt more portable (r:6b948cf1) + core: print ip:port on rtp bind err (r:11d2cd1b) + core: display fixes and add 2 new cols to channels to store last sent display data (r:d364e9f2) + core: sanitize outbound caller id number on one-legged calls (r:dee0f540/FS-3483) + core: clean up originator/ee profile so the right one is prevelant in events (r:3e2c662a) + core: check for answer flag in bridge to do display update properly (r:0f459d4b) + core: add event subclasses in switch_event.c (r:3696ced7/FS-3497) + core: add max_sessions to heartbeat event (r:9c8437a1/FS-3415) + core: fix event firing for CHANNEL_PROGRESS_MEDIA event (r:e2a4fb11/FS-3396) + core: add emulation for asterisk DIALSTATUS magic var (r:9d98d49f) + core: the new code requires accurate timestamps, we were incrementing it by the interval (20) instead of the samples (160) (r:f10566af/FS-3181) docs: Major clean up of doxygen generated core API documentation (r:794246e1) docs: Add libteletone back to core API documentation (r:c35c138d) embedded languages: Provide core level support for conditional Set Global Variable (r:c017c24b/FSCORE-612) @@ -368,6 +380,7 @@ freeswitch (1.0.7) libsofiasip: use individual pools instead of sub-pools for nua handles to avoid pool swell (r:f7612413) libsofiasip: Fix segfault in sofia's stun code (r:7403db70) libsofiasip: add homer capture hooks to libsofia (r:3e029f0d) + libsofiasip: Fix mem leak when homer capture server not available (r:bc177a4b/FS-3475) libspandsp: Fixed a typo in spandsp's msvc/inttypes.h Updated sig_tone processing in spandsp to the latest, to allow moy to proceed with his signaling work. libspandsp: removed a saturate16 from spandsp that was causing problems fixed a typo in the MSVC inttypes.h file for spandsp libspandsp: Changes to the signaling tone detector to detect concurrent 2400Hz + 2600Hz tones. This passes voice immunity and other key tests, but it bounces a bit when transitions like 2400 -> 2400+2600 -> 2600 occur. Transitions between tone off and tone on are clean. (r:bc13e944) @@ -381,6 +394,8 @@ freeswitch (1.0.7) libspandsp: Another round of tweaks for spandsp. There should be no functional changes, although quite a few things have changed in the test suite (r:4a7bbf4e) 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) + libsqlite: make strdup NULL return strdup("") in sqlite for mac bug (r:b6bed14f) + libsqlite: force an update on sqlite build (r:71dd3ca8) libunimrcp: Update to latest UniMRCP version. MRCP requests can no timeout if there is no server response. (r:17099473) libunimrcp: unimrcp lib does not notify mod_unimrcp of RTSP TEARDOWN timeouts (r:3484f338) libunimrcp: fixed unimrcp to prevent double destroy of connection (r:493085bb) @@ -455,6 +470,9 @@ freeswitch (1.0.7) mod_commands: add moh by default to uuid_broadcast when only broadcasting to A leg use aleg arg to disable this (r:d164a797) mod_commands: add API uuid_limit - thanks to Francois Delawarde (r:98a95016/FS-1792) mod_commands: omit file_string:// prefix if input begins with ~ (r:f12ab59e) + mod_commands: fix crash when uuid_break all cannot find bonded uuid channel (r:69e61f76/FS-3468) + mod_commands: fix uuid_dual_transfer for inline dialplan (r:5d84efc3/FS-3403) + mod_commands: update show calls to show both 1 legged calls and bridged calls, also show bridged_calls for previous behaviour of show calls (r:c16c74d9) mod_conference: Fix reporting of volume up/down (MODAPP-419) mod_conference: add last talking time per member to conference xml list mod_conference: add terminate-on-silence conference param @@ -530,6 +548,7 @@ freeswitch (1.0.7) mod_dptools: fix campon to play music even on first run and cancel faster (r:9cf44f3a) mod_dptools: fix small leak in strftime (r:bbbd67ba) mod_dptools: resolve Heap corruption in strftime_api_function -thanks (r:707bd05b/FS-3417) + mod_dptools: fix seg on user_recurse_variables reported on the mailing list (r:01b2bd04) 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) @@ -543,6 +562,7 @@ freeswitch (1.0.7) mod_erlang_event: Rewrite XML fetch conditional wait to be more sane (Reported by James Aimonetti) (r:6941c6eb/FS-2775) mod_erlang_event: Don't urlencode events (and destroy an event after use) (r:4eccdfef) mod_erlang_event Add proper locking for the list of XML bindings (r:9fe440b2) + mod_event_multicast: make multicast loopback configurable (r:97a7668c/FS-3416) mod_event_socket: fix up other users of switch_event_xmlize() to use SWITCH_EVENT_NONE (r:d6eb7562) mod_event_socket: Fix small mem leaks (r:e4f90584/MODEVENT-68) mod_event_socket: Add "-ERR" to api cmd response when failure occurs (r:58759052/FS-2827) @@ -646,6 +666,7 @@ freeswitch (1.0.7) 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_lcr: initial addition of very basic LRN (r:6d1d4a9c) 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) @@ -653,6 +674,7 @@ freeswitch (1.0.7) 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_loopback: Fix loopback_bowout_on_execute failure when doing txfax calls (r:895b505f/FS-3494) 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) @@ -666,6 +688,7 @@ freeswitch (1.0.7) mod_managed: add mono 2.8 patch file see FS-2774 (r:6a948bd9/FS-2774) mod_managed: resolve Memory leak in mod_managed by EventBinding and swig delete_switch_event (r:c6048134/FS-3381) mod_mongo: New mod, initial commit; module for MongoDB (http://www.mongodb.org/) (r:dc6ca6f8/FS-3278) + mod_mongo: add mapreduce API (r:7c5b5797/FS-3357) 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 @@ -690,6 +713,7 @@ freeswitch (1.0.7) mod_portaudio: Add pa devlist to portaudio webapi (r:e8f10ea3) mod_portaudio: fix crash on bad init (r:6f49e6ba/FS-3361) mod_portaudio: move load_config a bit lower since it needs to use the hashtables (r:1529c0ec) + mod_portaudio: Fix Windows crash (r:94c9cbf6/FS-3498) mod_portaudio_stream: update to specify the channel index (r:d1169d6e) 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) @@ -735,6 +759,7 @@ freeswitch (1.0.7) mod_shell_stream: Fix defunct processes being left behind (r:89666f44/FS-3316) mod_shout: bump mod_shout to use mpg123-1.13.2 to hopefully address unwanted calls to exit() and inherit other upstream fixes (r:079f3f73) mod_shout: add append flag to mod_shout, can append MP3's (r:0419c4e0) + mod_shout: add ability to set bitrate, samplerate, and encoder quality in config file (r:8ea3cbd5/FS-1231) mod_silk: Fix mod_silk compliance and performance issues (r:2ddbc457/MODCODEC-20) mod_skinny: Add the missing api files mod_skinny: add example dialplan and directory config (r:1bfcc17e) @@ -766,6 +791,7 @@ freeswitch (1.0.7) mod_skypopen: refining INTERACTIVE INSTALLER for Linux (to be announced :) ) (r:aa7f47ac) mod_skypopen: refining oss driver, removing audio sync during call (was each 20 secs), audio sync at the tcp interfacing with the skype client (reading more than 20ms worth) (r:891015e6) mod_skypopen: fixed a demented bug (incrementing a variable zeroed in the same loop) maybe responsible for moh sputtering under load on virtual machines (r:43eeeb82) + mod_skypopen: avoid accumulating delay on VMs, better debug logging (r:1b4c78bf) 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) @@ -968,6 +994,11 @@ freeswitch (1.0.7) mod_sofia: use register contact to determine proper contact in 200 ok response to register (r:f9612fec) mod_sofia: add NDLB-allow-nondup-sdp to indicate you want to parse a differnt sdp in 200 ok from 1xx (previous default) this is a RFC violation so I decided not to support it by default anymore. Enable this if you want that broken behaviour (r:3f489a2a) mod_sofia: add homer capture hooks to mod_sofia (r:98473085) + mod_sofia: sdp_m_per_ptime is now implied to be true, if you don't like this set it to false but its going to be undefined behaviour. This basically means if you call in with ptime 30 then you have a bunch of ptime 20 codecs in your outbound list that there will be one m= line with 30 and the original inbound codec and more m= lines for each discinct ptime in your list. This is, of course, will depend on disable_trancoding or absolute_codec_string as well (r:56d67ead) + mod_sofia: filter re-transmission of extra SIP headers (r:9e399c19/FS-3439) + mod_sofia: Fix RTP handling bug to allow goofy & undefined behavior (r:77413ba9/FS-3451) + mod_sofia: don't allow auto answer on an non-outbound call (r:61ee7fdc) + mod_sofia: use the call_id of the original register in the unsolicited notify for MWI (r:53b0ecce) mod_soundtouch: updated soundtouch to library 1.5.0 to fix gcc > 4.3 incompatibilities (r:dfb5c629) 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) @@ -1009,6 +1040,7 @@ freeswitch (1.0.7) mod_valet_parking: add event for Valet Parking action exit mod_valet_parking: pass hold class on transfer (r:76a065ec) mod_valet_parking: add valet_announce_slot variable (r:293d7254) + mod_valet_parking: make valet parking reserve a space for 10 seconds to allow time for an attended transfer switcharoo (r:308f44af) mod_voicemail: Fix vm_prefs profile lock (MODAPP-417) mod_voicemail: add 'vm-enabled' param (default true) mod_voicemail: fix vm msg being deleted when pressing key to forward to email (MODAPP-403) @@ -1028,6 +1060,8 @@ freeswitch (1.0.7) mod_voicemail: Adding a new voicemail fsdb api vm_fsdb_auth_login that does basic login authentication for a user (r:bfdfac5e) mod_voicemail: Fix vm to email dial 8 option (r:8592b6d9/FS-3382) mod_voicemail: Add 2 new profile settings, db-password-override and allow-empty-password-auth. By default, they have value of their previous behavior. If db-password-override=true, the db password will only be used if present, if not present fallback to the xml config file vm-password. If allow-empty-password-auth=false, it will disable login via a authentication method if there is no password set in the user account (This wont affect voicemail_authorize=true login). (r:a9db642a) + mod_voicemail: remove pointless update_mwi() in vm_list api command (r:b952b2b2) + mod_voicemail: add message_len to output of vm_list api command (r:77c5000d) mod_xml_cdr: add force_process_cdr var to process b leg cdr on a case by case basis when b leg cdr is disabled (XML-17) mod_xml_cdr: add leg param to query string (XML-24) mod_xml_cdr: fix locked sessions (XML-26) From 41b956fd2442e1f9ef3cbec7ad8332dfb2ab4cb8 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Thu, 1 Sep 2011 01:35:01 +0200 Subject: [PATCH 006/204] FreeTDM: Don't ftdm_safe_free() span information in ftdm_span_destroy() if span provides a custom span_destroy callback. Doing so will cause a NULL-deref segfault while removing the current span from the global hash (cur_span->name == NULL) in ftdm_global_destroy(). Remove all the ftdm_safe_free() calls in the custom callback part of ftdm_span_destroy() and let ftdm_global_destroy() handle that. NOTE: Also adds a missing ftdm_safe_free(cur_span->dtmf_hangup) to ftdm_global_destroy(). Signed-off-by: Stefan Knoblich --- libs/freetdm/src/ftdm_io.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 0205ab36b1..e190becd35 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -649,9 +649,6 @@ static ftdm_status_t ftdm_span_destroy(ftdm_span_t *span) if (span->fio->span_destroy(span) != FTDM_SUCCESS) { status = FTDM_FAIL; } - ftdm_safe_free(span->type); - ftdm_safe_free(span->name); - ftdm_safe_free(span->dtmf_hangup); } /* destroy final basic resources of the span data structure */ @@ -5774,6 +5771,7 @@ FT_DECLARE(ftdm_status_t) ftdm_global_destroy(void) } hashtable_remove(globals.span_hash, (void *)cur_span->name); + ftdm_safe_free(cur_span->dtmf_hangup); ftdm_safe_free(cur_span->type); ftdm_safe_free(cur_span->name); ftdm_safe_free(cur_span); From e1a6fd27e098efb0c5fec652477821e39ff4281d Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Thu, 1 Sep 2011 01:45:06 +0200 Subject: [PATCH 007/204] ftmod_libpri: Always try to close the d-channel to avoid a possible deadlock in case something fails in the I/O module's channel open function. Signed-off-by: Stefan Knoblich --- libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c index a379aeda9c..f31eafd42e 100644 --- a/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c +++ b/libs/freetdm/src/ftmod/ftmod_libpri/ftmod_libpri.c @@ -1938,6 +1938,14 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj) ftdm_sleep(5000); } out: + /* close d-channel, if set */ + if (isdn_data->dchan) { + if (ftdm_channel_close(&isdn_data->dchan) != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_ERROR, "Failed to close D-Channel %d:%d\n", + ftdm_channel_get_span_id(isdn_data->dchan), ftdm_channel_get_id(isdn_data->dchan)); + } + } + ftdm_log(FTDM_LOG_DEBUG, "PRI thread ended on span %d\n", ftdm_span_get_id(span)); ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD); From 996b304019be5531c0d5fd09ab3aa960d96f43db Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 31 Aug 2011 15:33:53 -0500 Subject: [PATCH 008/204] add xferext command to sendmsg parser so you can send a list of instructions to a channel and build and extension and transfer to it from esl --- src/include/switch_channel.h | 3 +++ src/switch_channel.c | 22 ++++++++++++++++++++++ src/switch_core_state_machine.c | 6 ++++++ src/switch_ivr.c | 30 +++++++++++++++++++++++++++++- 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index 8fa0439b47..5481a20c0a 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -627,6 +627,9 @@ SWITCH_DECLARE(void) switch_channel_mark_hold(switch_channel_t *channel, switch_ SWITCH_DECLARE(switch_status_t) switch_channel_execute_on(switch_channel_t *channel, const char *variable_prefix); SWITCH_DECLARE(switch_status_t) switch_channel_api_on(switch_channel_t *channel, const char *variable_prefix); +SWITCH_DECLARE(switch_caller_extension_t *) switch_channel_get_queued_extension(switch_channel_t *channel); +SWITCH_DECLARE(void) switch_channel_transfer_to_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension); + SWITCH_END_EXTERN_C #endif /* For Emacs: diff --git a/src/switch_channel.c b/src/switch_channel.c index 8fd174372c..72bf651e29 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -146,6 +146,7 @@ struct switch_channel { int profile_index; opaque_channel_flag_t opaque_flags; switch_originator_type_t last_profile_type; + switch_caller_extension_t *queued_extension; }; @@ -2688,6 +2689,27 @@ SWITCH_DECLARE(void) switch_channel_sort_cid(switch_channel_t *channel, switch_b } +SWITCH_DECLARE(switch_caller_extension_t *) switch_channel_get_queued_extension(switch_channel_t *channel) +{ + switch_caller_extension_t *caller_extension; + + switch_mutex_lock(channel->profile_mutex); + caller_extension = channel->queued_extension; + channel->queued_extension = NULL; + switch_mutex_unlock(channel->profile_mutex); + + return caller_extension; +} + +SWITCH_DECLARE(void) switch_channel_transfer_to_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension) +{ + switch_mutex_lock(channel->profile_mutex); + channel->queued_extension = caller_extension; + switch_mutex_unlock(channel->profile_mutex); + + switch_channel_set_flag(channel, CF_TRANSFER); + switch_channel_set_state(channel, CS_ROUTING); +} SWITCH_DECLARE(void) switch_channel_set_caller_extension(switch_channel_t *channel, switch_caller_extension_t *caller_extension) { diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index 1bb97aa03d..4c191249df 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -93,6 +93,12 @@ static void switch_core_standard_on_routing(switch_core_session_t *session) char *dp[25]; int argc, x, count = 0; + if ((extension = switch_channel_get_queued_extension(session->channel))) { + switch_channel_set_caller_extension(session->channel, extension); + switch_channel_set_state(session->channel, CS_EXECUTE); + goto end; + } + if (!zstr(caller_profile->dialplan)) { if ((dpstr = switch_core_session_strdup(session, caller_profile->dialplan))) { expanded = switch_channel_expand_variables(session->channel, dpstr); diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 575dc47701..22731c1968 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -484,6 +484,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se unsigned long CMD_HANGUP = switch_hashfunc_default("hangup", &hlen); unsigned long CMD_NOMEDIA = switch_hashfunc_default("nomedia", &hlen); unsigned long CMD_UNICAST = switch_hashfunc_default("unicast", &hlen); + unsigned long CMD_XFEREXT = switch_hashfunc_default("xferext", &hlen); char *lead_frames = switch_event_get_header(event, "lead-frames"); char *event_lock = switch_event_get_header(event, "event-lock"); char *event_lock_pri = switch_event_get_header(event, "event-lock-pri"); @@ -623,6 +624,33 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se switch_ivr_activate_unicast(session, local_ip, (switch_port_t) atoi(local_port), remote_ip, (switch_port_t) atoi(remote_port), transport, flags); + } else if (cmd_hash == CMD_XFEREXT) { + switch_event_header_t *hp; + switch_caller_extension_t *extension = NULL; + + + if ((extension = switch_caller_extension_new(session, "xferext", "xferext")) == 0) { + abort(); + } + + for (hp = event->headers; hp; hp = hp->next) { + char *app; + char *data; + + if (!strcasecmp(hp->name, "application")) { + app = strdup(hp->value); + data = strchr(app, ':'); + + if (data) { + *data++ = '\0'; + } + + switch_caller_extension_add_application(session, extension, app, data); + } + } + + switch_channel_transfer_to_extension(channel, extension); + } else if (cmd_hash == CMD_HANGUP) { char *cause_name = switch_event_get_header(event, "hangup-cause"); switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING; @@ -1661,7 +1689,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_session_transfer(switch_core_session_ switch_channel_set_caller_profile(channel, new_profile); switch_channel_set_flag(channel, CF_TRANSFER); - + switch_channel_set_state(channel, CS_ROUTING); msg.message_id = SWITCH_MESSAGE_INDICATE_TRANSFER; From bff473bf3241592d917abea2d2569b33780e0ece Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 31 Aug 2011 19:30:51 -0500 Subject: [PATCH 009/204] antibiotics for our latest sonus infection --- src/include/switch_types.h | 9 -- src/mod/endpoints/mod_sofia/sofia_glue.c | 8 -- src/switch_rtp.c | 109 ++++++++++++++--------- 3 files changed, 69 insertions(+), 57 deletions(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index f0c6dfed01..783b48e3b1 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -672,15 +672,6 @@ typedef enum { This flag will treat every dtmf as if it were 50ms and queue it on recipt of the leading packet rather than at the end. */ - RTP_BUG_PAUSE_BETWEEN_DTMF = (1 << 7) - - /* - Sonus says they need time to generate the dtmf so we should not send it so fast so with this flag we will wait a few clicks after each send to - start sending the next one. - */ - - - } switch_rtp_bug_flag_t; #ifdef _MSC_VER diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index b9f4ca0f4f..d0d75bfb1f 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -6549,14 +6549,6 @@ void sofia_glue_parse_rtp_bugs(switch_rtp_bug_flag_t *flag_pole, const char *str if (switch_stristr("~IGNORE_DTMF_DURATION", str)) { *flag_pole &= ~RTP_BUG_IGNORE_DTMF_DURATION; } - - if (switch_stristr("PAUSE_BETWEEN_DTMF", str)) { - *flag_pole |= RTP_BUG_PAUSE_BETWEEN_DTMF; - } - - if (switch_stristr("~PAUSE_BETWEEN_DTMF", str)) { - *flag_pole &= ~RTP_BUG_PAUSE_BETWEEN_DTMF; - } } char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_dispatch_event_t *de, sofia_nat_parse_t *np) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 020f8aea57..eb431d0e3b 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -46,9 +46,6 @@ #include #include -/* number of writes to delay sending new DTMF when RTP_BUG_PAUSE_BETWEEN_DTMF flag is set */ -#define BUGGY_DIGIT_DELAY_PERIOD 5 - #define READ_INC(rtp_session) switch_mutex_lock(rtp_session->read_mutex); rtp_session->reading++ #define READ_DEC(rtp_session) switch_mutex_unlock(rtp_session->read_mutex); rtp_session->reading-- #define WRITE_INC(rtp_session) switch_mutex_lock(rtp_session->write_mutex); rtp_session->writing++ @@ -141,7 +138,6 @@ struct switch_rtp_rfc2833_data { switch_queue_t *dtmf_inqueue; switch_mutex_t *dtmf_mutex; uint8_t in_digit_queued; - uint32_t out_digit_delay; }; struct switch_rtp { @@ -187,6 +183,9 @@ struct switch_rtp { uint32_t last_read_ts; uint32_t last_cng_ts; uint32_t last_write_samplecount; + uint32_t next_write_samplecount; + uint32_t max_next_write_samplecount; + uint32_t queue_delay; switch_time_t last_write_timestamp; uint32_t flags; switch_memory_pool_t *pool; @@ -2233,19 +2232,22 @@ SWITCH_DECLARE(void) switch_rtp_clear_flag(switch_rtp_t *rtp_session, switch_rtp } } -static void set_dtmf_delay(switch_rtp_t *rtp_session, uint32_t ms) +static void set_dtmf_delay(switch_rtp_t *rtp_session, uint32_t ms, uint32_t max_ms) { - int mspp = 20; + int upsamp, max_upsamp; + + if (!max_ms) max_ms = ms; - if (rtp_session->ms_per_packet) { - if (!(mspp = (int) (rtp_session->ms_per_packet / 1000))) { - mspp = 20; - } + upsamp = ms * (rtp_session->samples_per_second / 1000); + max_upsamp = max_ms * (rtp_session->samples_per_second / 1000); + + rtp_session->queue_delay = upsamp; + + if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER)) { + rtp_session->max_next_write_samplecount = rtp_session->timer.samplecount + max_upsamp; } - - rtp_session->dtmf_data.out_digit_delay += (ms / mspp); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Queue digit delay of %dms\n", ms); - + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Queue digit delay of %dms\n", ms); } static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session) @@ -2253,16 +2255,15 @@ static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session) switch_frame_flag_t flags = 0; uint32_t samples = rtp_session->samples_per_interval; - if (rtp_session->dtmf_data.out_digit_delay) { - rtp_session->dtmf_data.out_digit_delay--; - return; - } - if (!rtp_session->sending_dtmf > 1) { rtp_session->sending_dtmf--; return; } + if (!rtp_session->last_write_ts) { + return; + } + if (rtp_session->dtmf_data.out_digit_dur > 0) { int x, loops = 1; @@ -2290,29 +2291,32 @@ static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session) rtp_session->stats.outbound.raw_bytes += wrote; rtp_session->stats.outbound.dtmf_packet_count++; + if (loops == 1) { + rtp_session->last_write_ts += samples; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Send %s packet for [%c] ts=%u dur=%d/%d/%d seq=%d\n", + if (rtp_session->rtp_bugs & RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833) { + rtp_session->dtmf_data.timestamp_dtmf = rtp_session->last_write_ts; + } + } + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Send %s packet for [%c] ts=%u dur=%d/%d/%d seq=%d lw=%d\n", loops == 1 ? "middle" : "end", rtp_session->dtmf_data.out_digit, rtp_session->dtmf_data.timestamp_dtmf, rtp_session->dtmf_data.out_digit_sofar, - rtp_session->dtmf_data.out_digit_sub_sofar, rtp_session->dtmf_data.out_digit_dur, rtp_session->seq); - if (loops == 1 && rtp_session->rtp_bugs & RTP_BUG_SONUS_SEND_INVALID_TIMESTAMP_2833) { - rtp_session->dtmf_data.timestamp_dtmf = rtp_session->last_write_ts + samples; - } + rtp_session->dtmf_data.out_digit_sub_sofar, rtp_session->dtmf_data.out_digit_dur, rtp_session->seq, rtp_session->last_write_ts); } if (loops != 1) { - rtp_session->sending_dtmf = -1; + rtp_session->sending_dtmf = 0; rtp_session->need_mark = 1; if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER)) { rtp_session->last_write_samplecount = rtp_session->timer.samplecount; } - rtp_session->dtmf_data.out_digit_dur = 0; - if ((rtp_session->rtp_bugs & RTP_BUG_PAUSE_BETWEEN_DTMF)) { - rtp_session->dtmf_data.out_digit_delay = BUGGY_DIGIT_DELAY_PERIOD; - } + rtp_session->dtmf_data.out_digit_dur = 0; + set_dtmf_delay(rtp_session, 40, 500); + return; } } @@ -2320,6 +2324,25 @@ static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session) if (!rtp_session->dtmf_data.out_digit_dur && rtp_session->dtmf_data.dtmf_queue && switch_queue_size(rtp_session->dtmf_data.dtmf_queue)) { void *pop; + if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_USE_TIMER)) { + if (rtp_session->last_write_ts < rtp_session->next_write_samplecount && rtp_session->timer.samplecount < rtp_session->max_next_write_samplecount) { + return; + } + if (rtp_session->timer.samplecount >= rtp_session->max_next_write_samplecount) { + rtp_session->queue_delay = 0; + } + + } else { + if (rtp_session->last_write_ts < rtp_session->next_write_samplecount) { + return; + } + } + + if (rtp_session->queue_delay) { + return; + } + + if (!rtp_session->sending_dtmf) { rtp_session->sending_dtmf = 2; return; @@ -2330,13 +2353,13 @@ static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session) switch_size_t wrote; if (rdigit->digit == 'w') { - set_dtmf_delay(rtp_session, 500); + set_dtmf_delay(rtp_session, 500, 0); free(rdigit); return; } if (rdigit->digit == 'W') { - set_dtmf_delay(rtp_session, 1000); + set_dtmf_delay(rtp_session, 1000, 0); free(rdigit); return; } @@ -2353,22 +2376,25 @@ static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session) rtp_session->dtmf_data.out_digit_packet[2] = (unsigned char) (rtp_session->dtmf_data.out_digit_sub_sofar >> 8); rtp_session->dtmf_data.out_digit_packet[3] = (unsigned char) rtp_session->dtmf_data.out_digit_sub_sofar; - rtp_session->dtmf_data.timestamp_dtmf = rtp_session->last_write_ts + samples; + rtp_session->dtmf_data.timestamp_dtmf = rtp_session->last_write_ts + samples; + rtp_session->last_write_ts = rtp_session->dtmf_data.timestamp_dtmf; + wrote = switch_rtp_write_manual(rtp_session, rtp_session->dtmf_data.out_digit_packet, 4, rtp_session->rtp_bugs & RTP_BUG_CISCO_SKIP_MARK_BIT_2833 ? 0 : 1, rtp_session->te, rtp_session->dtmf_data.timestamp_dtmf, &flags); + rtp_session->stats.outbound.raw_bytes += wrote; rtp_session->stats.outbound.dtmf_packet_count++; - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Send start packet for [%c] ts=%u dur=%d/%d/%d seq=%d\n", + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Send start packet for [%c] ts=%u dur=%d/%d/%d seq=%d lw=%d\n", rtp_session->dtmf_data.out_digit, rtp_session->dtmf_data.timestamp_dtmf, rtp_session->dtmf_data.out_digit_sofar, - rtp_session->dtmf_data.out_digit_sub_sofar, rtp_session->dtmf_data.out_digit_dur, rtp_session->seq); + rtp_session->dtmf_data.out_digit_sub_sofar, rtp_session->dtmf_data.out_digit_dur, rtp_session->seq, rtp_session->last_write_ts); free(rdigit); } @@ -3768,14 +3794,10 @@ static int rtp_common_write(switch_rtp_t *rtp_session, this_ts = ntohl(send_msg->header.ts); - if (!switch_rtp_ready(rtp_session) || rtp_session->sending_dtmf || !this_ts) { + if (!switch_rtp_ready(rtp_session) || rtp_session->sending_dtmf || !this_ts || this_ts < rtp_session->last_write_ts) { send = 0; } - if (rtp_session->sending_dtmf == -1) { - rtp_session->sending_dtmf = 0; - - } if (send) { send_msg->header.seq = htons(++rtp_session->seq); @@ -3886,6 +3908,13 @@ static int rtp_common_write(switch_rtp_t *rtp_session, } rtp_session->last_write_ts = this_ts; + if (rtp_session->queue_delay) { + rtp_session->next_write_samplecount = rtp_session->last_write_ts + rtp_session->queue_delay; + rtp_session->queue_delay = 0; + } + + + rtp_session->stats.outbound.raw_bytes += bytes; rtp_session->stats.outbound.packet_count++; From a5ae0e32d64abcd8412200848b10fee64e41fa7d Mon Sep 17 00:00:00 2001 From: Brian West Date: Thu, 1 Sep 2011 03:22:30 -0500 Subject: [PATCH 010/204] swigall --- libs/esl/php/esl_wrap.cpp | 90 +++++++++---------- libs/esl/ruby/esl_wrap.cpp | 2 +- .../languages/mod_managed/freeswitch_wrap.cxx | 32 +++++++ src/mod/languages/mod_managed/managed/swig.cs | 28 +++++- src/mod/languages/mod_perl/mod_perl_wrap.cpp | 6 +- 5 files changed, 107 insertions(+), 51 deletions(-) diff --git a/libs/esl/php/esl_wrap.cpp b/libs/esl/php/esl_wrap.cpp index 9e49c7c080..bd599b7fc1 100644 --- a/libs/esl/php/esl_wrap.cpp +++ b/libs/esl/php/esl_wrap.cpp @@ -1091,7 +1091,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_serialized_string_set) { } 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@*/ + /*@SWIG:/usr/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@*/; @@ -1159,7 +1159,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_mine_set) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ + /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ convert_to_long_ex(args[1]); arg2 = (int) Z_LVAL_PP(args[1]); /*@SWIG@*/; @@ -1213,13 +1213,13 @@ ZEND_NAMED_FUNCTION(_wrap_new_ESLevent__SWIG_0) { WRONG_PARAM_COUNT; - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ convert_to_string_ex(args[0]); arg1 = (char *) Z_STRVAL_PP(args[0]); /*@SWIG@*/; if(arg_count > 1) { - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/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@*/; @@ -1254,7 +1254,7 @@ ZEND_NAMED_FUNCTION(_wrap_new_ESLevent__SWIG_1) { } } if(arg_count > 1) { - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ + /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ convert_to_long_ex(args[1]); arg2 = (int) Z_LVAL_PP(args[1]); /*@SWIG@*/; @@ -1384,7 +1384,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_serialize) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); if(arg_count > 1) { - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/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@*/; @@ -1463,13 +1463,13 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_getHeader) { } 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@*/ + /*@SWIG:/usr/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@*/; if(arg_count > 2) { - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ + /*@SWIG:/usr/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@*/; @@ -1567,7 +1567,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_addBody) { } 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@*/ + /*@SWIG:/usr/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@*/; @@ -1601,13 +1601,13 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_addHeader) { } 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@*/ + /*@SWIG:/usr/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@*/ + /*@SWIG:/usr/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@*/; @@ -1641,13 +1641,13 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_pushHeader) { } 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@*/ + /*@SWIG:/usr/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@*/ + /*@SWIG:/usr/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@*/; @@ -1681,13 +1681,13 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_unshiftHeader) { } 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@*/ + /*@SWIG:/usr/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@*/ + /*@SWIG:/usr/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@*/; @@ -1720,7 +1720,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_delHeader) { } 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@*/ + /*@SWIG:/usr/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@*/; @@ -1809,25 +1809,25 @@ ZEND_NAMED_FUNCTION(_wrap_new_ESLconnection__SWIG_0) { } - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ convert_to_string_ex(args[0]); arg1 = (char *) Z_STRVAL_PP(args[0]); /*@SWIG@*/; - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/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@*/ + /*@SWIG:/usr/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@*/; - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ convert_to_string_ex(args[3]); arg4 = (char *) Z_STRVAL_PP(args[3]); /*@SWIG@*/; @@ -1855,19 +1855,19 @@ ZEND_NAMED_FUNCTION(_wrap_new_ESLconnection__SWIG_1) { } - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ convert_to_string_ex(args[0]); arg1 = (char *) Z_STRVAL_PP(args[0]); /*@SWIG@*/; - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/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@*/ + /*@SWIG:/usr/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@*/; @@ -1893,7 +1893,7 @@ ZEND_NAMED_FUNCTION(_wrap_new_ESLconnection__SWIG_2) { } - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ + /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ convert_to_long_ex(args[0]); arg1 = (int) Z_LVAL_PP(args[0]); /*@SWIG@*/; @@ -2070,7 +2070,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_send) { } 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@*/ + /*@SWIG:/usr/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@*/; @@ -2103,7 +2103,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_sendRecv) { } 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@*/ + /*@SWIG:/usr/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@*/; @@ -2139,13 +2139,13 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_api) { } 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@*/ + /*@SWIG:/usr/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@*/; if(arg_count > 2) { - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/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@*/; @@ -2183,20 +2183,20 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_bgapi) { } 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@*/ + /*@SWIG:/usr/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@*/; if(arg_count > 2) { - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/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@*/; } if(arg_count > 3) { - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ convert_to_string_ex(args[3]); arg4 = (char *) Z_STRVAL_PP(args[3]); /*@SWIG@*/; @@ -2288,7 +2288,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_recvEventTimed) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ + /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ convert_to_long_ex(args[1]); arg2 = (int) Z_LVAL_PP(args[1]); /*@SWIG@*/; @@ -2322,13 +2322,13 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_filter) { } 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@*/ + /*@SWIG:/usr/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@*/ + /*@SWIG:/usr/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@*/; @@ -2362,13 +2362,13 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_events) { } 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@*/ + /*@SWIG:/usr/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@*/ + /*@SWIG:/usr/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@*/; @@ -2405,20 +2405,20 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_execute) { } 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@*/ + /*@SWIG:/usr/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@*/; if(arg_count > 2) { - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/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@*/; } if(arg_count > 3) { - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ convert_to_string_ex(args[3]); arg4 = (char *) Z_STRVAL_PP(args[3]); /*@SWIG@*/; @@ -2456,20 +2456,20 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_executeAsync) { } 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@*/ + /*@SWIG:/usr/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@*/; if(arg_count > 2) { - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/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@*/; } if(arg_count > 3) { - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ convert_to_string_ex(args[3]); arg4 = (char *) Z_STRVAL_PP(args[3]); /*@SWIG@*/; @@ -2503,7 +2503,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_setAsyncExecute) { } 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@*/ + /*@SWIG:/usr/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@*/; @@ -2536,7 +2536,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_setEventLock) { } 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@*/ + /*@SWIG:/usr/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@*/; @@ -2587,7 +2587,7 @@ ZEND_NAMED_FUNCTION(_wrap_eslSetLogLevel) { } - /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ + /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ convert_to_long_ex(args[0]); arg1 = (int) Z_LVAL_PP(args[0]); /*@SWIG@*/; diff --git a/libs/esl/ruby/esl_wrap.cpp b/libs/esl/ruby/esl_wrap.cpp index 5afce64cf9..d091157282 100644 --- a/libs/esl/ruby/esl_wrap.cpp +++ b/libs/esl/ruby/esl_wrap.cpp @@ -1902,7 +1902,7 @@ SWIG_ruby_failed(void) } -/*@SWIG:/usr/local/share/swig/1.3.35/ruby/rubyprimtypes.swg,23,%ruby_aux_method@*/ +/*@SWIG:/usr/share/swig/1.3.35/ruby/rubyprimtypes.swg,23,%ruby_aux_method@*/ SWIGINTERN VALUE SWIG_AUX_NUM2LONG(VALUE *args) { VALUE obj = args[0]; diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index c23cd244e9..29879a96bd 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -5411,6 +5411,16 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SWITCH_CORE_DB_DONE_get() { } +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_sql_concat() { + char * jresult ; + char *result = 0 ; + + result = (char *)switch_sql_concat(); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT void * SWIGSTDCALL CSharp_switch_regex_compile(char * jarg1, int jarg2, void * jarg3, void * jarg4, void * jarg5) { void * jresult ; char *arg1 = (char *) 0 ; @@ -25441,6 +25451,28 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_api_on(void * jarg1, char * jar } +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_channel_get_queued_extension(void * jarg1) { + void * jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + switch_caller_extension_t *result = 0 ; + + arg1 = (switch_channel_t *)jarg1; + result = (switch_caller_extension_t *)switch_channel_get_queued_extension(arg1); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_transfer_to_extension(void * jarg1, void * jarg2) { + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + switch_caller_extension_t *arg2 = (switch_caller_extension_t *) 0 ; + + arg1 = (switch_channel_t *)jarg1; + arg2 = (switch_caller_extension_t *)jarg2; + switch_channel_transfer_to_extension(arg1,arg2); +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_buffer_create(void * jarg1, void * jarg2, void * jarg3) { int jresult ; switch_memory_pool_t *arg1 = (switch_memory_pool_t *) 0 ; diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index bbed991074..9f6e7a9fd9 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -909,6 +909,11 @@ public class freeswitch { return ret; } + public static string switch_sql_concat() { + string ret = freeswitchPINVOKE.switch_sql_concat(); + return ret; + } + public static SWIGTYPE_p_real_pcre switch_regex_compile(string pattern, int options, ref string errorptr, SWIGTYPE_p_int erroroffset, SWIGTYPE_p_unsigned_char tables) { IntPtr cPtr = freeswitchPINVOKE.switch_regex_compile(pattern, options, ref errorptr, SWIGTYPE_p_int.getCPtr(erroroffset), SWIGTYPE_p_unsigned_char.getCPtr(tables)); SWIGTYPE_p_real_pcre ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_real_pcre(cPtr, false); @@ -3854,6 +3859,16 @@ public class freeswitch { return ret; } + public static switch_caller_extension switch_channel_get_queued_extension(SWIGTYPE_p_switch_channel channel) { + IntPtr cPtr = freeswitchPINVOKE.switch_channel_get_queued_extension(SWIGTYPE_p_switch_channel.getCPtr(channel)); + switch_caller_extension ret = (cPtr == IntPtr.Zero) ? null : new switch_caller_extension(cPtr, false); + return ret; + } + + public static void switch_channel_transfer_to_extension(SWIGTYPE_p_switch_channel channel, switch_caller_extension caller_extension) { + freeswitchPINVOKE.switch_channel_transfer_to_extension(SWIGTYPE_p_switch_channel.getCPtr(channel), switch_caller_extension.getCPtr(caller_extension)); + } + public static switch_status_t switch_buffer_create(SWIGTYPE_p_apr_pool_t pool, SWIGTYPE_p_p_switch_buffer buffer, SWIGTYPE_p_switch_size_t max_len) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_buffer_create(SWIGTYPE_p_apr_pool_t.getCPtr(pool), SWIGTYPE_p_p_switch_buffer.getCPtr(buffer), SWIGTYPE_p_switch_size_t.getCPtr(max_len)); if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); @@ -7336,6 +7351,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_CORE_DB_DONE_get")] public static extern int SWITCH_CORE_DB_DONE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_switch_sql_concat")] + public static extern string switch_sql_concat(); + [DllImport("mod_managed", EntryPoint="CSharp_switch_regex_compile")] public static extern IntPtr switch_regex_compile(string jarg1, int jarg2, ref string jarg3, HandleRef jarg4, HandleRef jarg5); @@ -12079,6 +12097,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_api_on")] public static extern int switch_channel_api_on(HandleRef jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_queued_extension")] + public static extern IntPtr switch_channel_get_queued_extension(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_transfer_to_extension")] + public static extern void switch_channel_transfer_to_extension(HandleRef jarg1, HandleRef jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_buffer_create")] public static extern int switch_buffer_create(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3); @@ -22298,6 +22322,7 @@ public enum switch_channel_cap_t { CC_PROXY_MEDIA, CC_JITTERBUFFER, CC_FS_RTP, + CC_QUEUEABLE_DTMF_DELAY, CC_FLAG_MAX } @@ -29262,8 +29287,7 @@ public enum switch_rtp_bug_flag_t { RTP_BUG_SEND_LINEAR_TIMESTAMPS = (1 << 3), RTP_BUG_START_SEQ_AT_ZERO = (1 << 4), RTP_BUG_NEVER_SEND_MARKER = (1 << 5), - RTP_BUG_IGNORE_DTMF_DURATION = (1 << 6), - RTP_BUG_PAUSE_BETWEEN_DTMF = (1 << 7) + RTP_BUG_IGNORE_DTMF_DURATION = (1 << 6) } } diff --git a/src/mod/languages/mod_perl/mod_perl_wrap.cpp b/src/mod/languages/mod_perl/mod_perl_wrap.cpp index 3957f52448..19700c2bcd 100644 --- a/src/mod/languages/mod_perl/mod_perl_wrap.cpp +++ b/src/mod/languages/mod_perl/mod_perl_wrap.cpp @@ -9912,17 +9912,17 @@ XS(SWIG_init) { SWIG_TypeClientData(SWIGTYPE_p_IVRMenu, (void*) "freeswitch::IVRMenu"); SWIG_TypeClientData(SWIGTYPE_p_API, (void*) "freeswitch::API"); SWIG_TypeClientData(SWIGTYPE_p_input_callback_state, (void*) "freeswitch::input_callback_state_t"); - /*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { + /*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { SV *sv = get_sv((char*) SWIG_prefix "S_HUP", TRUE | 0x2 | GV_ADDMULTI); sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_HUP))); SvREADONLY_on(sv); } while(0) /*@SWIG@*/; - /*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { + /*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { SV *sv = get_sv((char*) SWIG_prefix "S_FREE", TRUE | 0x2 | GV_ADDMULTI); sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_FREE))); SvREADONLY_on(sv); } while(0) /*@SWIG@*/; - /*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { + /*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { SV *sv = get_sv((char*) SWIG_prefix "S_RDLOCK", TRUE | 0x2 | GV_ADDMULTI); sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_RDLOCK))); SvREADONLY_on(sv); From e817795e841cfcba7d5ebcbed844e521f58ae486 Mon Sep 17 00:00:00 2001 From: Brian West Date: Thu, 1 Sep 2011 03:31:47 -0500 Subject: [PATCH 011/204] hrm --- src/include/switch_core_db.h | 2 +- src/switch_core_sqldb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/include/switch_core_db.h b/src/include/switch_core_db.h index 3e92e2bdac..f72c3c5f45 100644 --- a/src/include/switch_core_db.h +++ b/src/include/switch_core_db.h @@ -540,7 +540,7 @@ SWITCH_DECLARE(int) switch_core_db_changes(switch_core_db_t *db); * literal. */ -SWITCH_DECLARE(char*)switch_sql_concat(); +SWITCH_DECLARE(char*)switch_sql_concat(void); SWITCH_END_EXTERN_C #endif diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index 60e6c4743b..db2cf72c15 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -2114,7 +2114,7 @@ SWITCH_DECLARE(void) switch_cache_db_status(switch_stream_handle_t *stream) switch_mutex_unlock(sql_manager.dbh_mutex); } -SWITCH_DECLARE(char*)switch_sql_concat() +SWITCH_DECLARE(char*)switch_sql_concat(void) { if(runtime.odbc_dbtype == DBTYPE_MSSQL) return "+"; From 04b1720f80e8c64e3ec300a8d49ab52d92de29e5 Mon Sep 17 00:00:00 2001 From: Michal Bielicki - cypromis Date: Thu, 1 Sep 2011 16:36:27 +0200 Subject: [PATCH 012/204] x != dw --- libs/silk/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/silk/Makefile.am b/libs/silk/Makefile.am index 8b26c971b8..071f1ecd64 100644 --- a/libs/silk/Makefile.am +++ b/libs/silk/Makefile.am @@ -1,4 +1,4 @@ -AM_CFLAGS = -Isrc -Iinterface -fPIC -all -O3 +AM_CFLAGS = -Isrc -Iinterface -fPIC -O3 AUTOMAKE_OPTS = gnu NAME = libSKP_SILK_SDK AM_CPPFLAGS = $(AM_CFLAGS) From 0db88b5999beb2c7adb76ad9eedc6e8dc7b959bb Mon Sep 17 00:00:00 2001 From: Daniel Swarbrick Date: Thu, 1 Sep 2011 16:42:00 +0200 Subject: [PATCH 013/204] Tweak link order of some libs to fix build on gcc platforms that have ld flag "--as-needed" as default. Fixes FS-2873 and FS-2874 --- Makefile.am | 4 ++-- libs/esl/Makefile | 4 ++-- src/mod/applications/mod_spandsp/Makefile.am | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile.am b/Makefile.am index 10e35c8694..50cf65fc7a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -300,7 +300,7 @@ endif fs_encode_SOURCES = src/fs_encode.c fs_encode_CFLAGS = $(AM_CFLAGS) fs_encode_LDFLAGS = $(AM_LDFLAGS) $(CORE_LIBS) -fs_encode_LDADD = libfreeswitch.la +fs_encode_LDADD = libfreeswitch.la -lcrypt -lrt ## ## tone2wav () @@ -308,7 +308,7 @@ fs_encode_LDADD = libfreeswitch.la tone2wav_SOURCES = src/tone2wav.c tone2wav_CFLAGS = $(AM_CFLAGS) tone2wav_LDFLAGS = $(AM_LDFLAGS) $(CORE_LIBS) -tone2wav_LDADD = libfreeswitch.la +tone2wav_LDADD = libfreeswitch.la -lcrypt -lrt ## ## fs_ivrd () diff --git a/libs/esl/Makefile b/libs/esl/Makefile index 0e6471a700..746f730124 100644 --- a/libs/esl/Makefile +++ b/libs/esl/Makefile @@ -7,7 +7,7 @@ PICKY=-O2 CFLAGS=$(BASE_FLAGS) $(PICKY) CXXFLAGS=$(BASE_FLAGS) MYLIB=libesl.a -LIBS=-lncurses -lpthread -lesl -lm +LIBS=-lncurses -lesl -lpthread -lm LDFLAGS=-L. OBJS=src/esl.o src/esl_event.o src/esl_threadmutex.o src/esl_config.o src/esl_json.o src/esl_buffer.o SRC=src/esl.c src/esl_json.c src/esl_event.c src/esl_threadmutex.c src/esl_config.c src/esl_oop.cpp src/esl_json.c src/esl_buffer.c @@ -32,7 +32,7 @@ testclient: $(MYLIB) testclient.c $(CC) $(CC_CFLAGS) $(CFLAGS) testclient.c -o testclient $(LDFLAGS) $(LIBS) fs_cli: $(MYLIB) fs_cli.c - $(CC) $(CC_CFLAGS) $(CFLAGS) fs_cli.c -o fs_cli $(LDFLAGS) -L$(LIBEDIT_DIR)/src/.libs $(LIBS) -ledit + $(CC) $(CC_CFLAGS) $(CFLAGS) fs_cli.c -o fs_cli $(LDFLAGS) -L$(LIBEDIT_DIR)/src/.libs -ledit $(LIBS) %.o: %.c $(HEADERS) $(CC) $(CC_CFLAGS) $(CFLAGS) -c $< -o $@ diff --git a/src/mod/applications/mod_spandsp/Makefile.am b/src/mod/applications/mod_spandsp/Makefile.am index 7d2b30f69d..7865ce5164 100644 --- a/src/mod/applications/mod_spandsp/Makefile.am +++ b/src/mod/applications/mod_spandsp/Makefile.am @@ -12,8 +12,8 @@ SPANDSP_LA=$(SPANDSP_BUILDDIR)/src/libspandsp.la mod_LTLIBRARIES = mod_spandsp.la mod_spandsp_la_SOURCES = mod_spandsp.c udptl.c mod_spandsp_fax.c mod_spandsp_dsp.c mod_spandsp_codecs.c mod_spandsp_la_CFLAGS = $(AM_CFLAGS) -I$(SPANDSP_DIR)/src -I$(TIFF_DIR)/libtiff -I$(SPANDSP_BUILDDIR)/src -I$(TIFF_BUILDDIR)/libtiff -I. -mod_spandsp_la_LIBADD = $(switch_builddir)/libfreeswitch.la $(SPANDSP_LA) $(TIFF_LA) -mod_spandsp_la_LDFLAGS = -avoid-version -module -no-undefined -shared -ljpeg +mod_spandsp_la_LIBADD = $(switch_builddir)/libfreeswitch.la $(SPANDSP_LA) $(TIFF_LA) -ljpeg -lz +mod_spandsp_la_LDFLAGS = -avoid-version -module -no-undefined -shared $(SPANDSP_LA): $(TIFF_LA) $(SPANDSP_DIR) $(SPANDSP_DIR)/.update cd $(SPANDSP_BUILDDIR) && $(MAKE) -j1 From 3a352e67f462b34c9610453b53adddb8a98adfb4 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Thu, 1 Sep 2011 15:53:03 +0000 Subject: [PATCH 014/204] bump to zeromq-2.1.9 --- src/mod/event_handlers/mod_event_zmq/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/event_handlers/mod_event_zmq/Makefile b/src/mod/event_handlers/mod_event_zmq/Makefile index 145055af62..6d193084ed 100644 --- a/src/mod/event_handlers/mod_event_zmq/Makefile +++ b/src/mod/event_handlers/mod_event_zmq/Makefile @@ -1,6 +1,6 @@ BASE=../../../.. -ZMQ=zeromq-2.1.7 +ZMQ=zeromq-2.1.9 ZMQ_BASEURL=http://download.zeromq.org ZMQ_BASEURL_ALT=http://download.zeromq.org/historic From cf9859ea6959699260ef928d2b9fb79f9f0c3389 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 1 Sep 2011 10:11:16 -0500 Subject: [PATCH 015/204] add digit_action_set_target app that can set the target (direction of the dtmf flow and subsequent channel who gets the events) to self or peer (bridged channel when possible) --- src/include/switch_core.h | 3 + src/include/switch_types.h | 7 ++ .../applications/mod_dptools/mod_dptools.c | 84 ++++++++++++++++--- src/switch_core_io.c | 17 +++- src/switch_ivr_async.c | 12 +++ 5 files changed, 107 insertions(+), 16 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 8d4a0cd122..f6e611b91f 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -718,6 +718,9 @@ SWITCH_DECLARE(void) switch_core_session_soft_lock(switch_core_session_t *sessio SWITCH_DECLARE(void) switch_core_session_soft_unlock(switch_core_session_t *session); SWITCH_DECLARE(void) switch_core_session_set_dmachine(switch_core_session_t *session, switch_ivr_dmachine_t *dmachine); SWITCH_DECLARE(switch_ivr_dmachine_t *) switch_core_session_get_dmachine(switch_core_session_t *session); +SWITCH_DECLARE(switch_digit_action_target_t) switch_ivr_dmachine_get_target(switch_ivr_dmachine_t *dmachine); +SWITCH_DECLARE(void) switch_ivr_dmachine_set_target(switch_ivr_dmachine_t *dmachine, switch_digit_action_target_t target); + SWITCH_DECLARE(switch_status_t) switch_core_session_set_codec_slin(switch_core_session_t *session, switch_slin_data_t *data); /*! diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 783b48e3b1..7eb27d2c45 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -221,6 +221,13 @@ typedef enum { SWITCH_DTMF_APP } switch_dtmf_source_t; +typedef enum { + DIGIT_TARGET_SELF, + DIGIT_TARGET_PEER +} switch_digit_action_target_t; + + + typedef enum { DTMF_FLAG_SKIP_PROCESS = (1 << 0) } dtmf_flag_t; diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 271421a9d3..02c64d8093 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -108,23 +108,33 @@ struct action_binding { static switch_status_t digit_nomatch_action_callback(switch_ivr_dmachine_match_t *match) { switch_core_session_t *session = (switch_core_session_t *) match->user_data; - switch_channel_t *channel = switch_core_session_get_channel(session); + switch_channel_t *channel; char str[DMACHINE_MAX_DIGIT_LEN + 2]; switch_event_t *event; switch_status_t status; + switch_core_session_t *use_session = session; + + if (switch_ivr_dmachine_get_target(match->dmachine) == DIGIT_TARGET_PEER) { + if (switch_core_session_get_partner(session, &use_session) != SWITCH_STATUS_SUCCESS) { + use_session = session; + } + } + + channel = switch_core_session_get_channel(use_session); + switch_channel_set_variable(channel, "last_non_matching_digits", match->match_digits); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Digit NOT match binding [%s]\n", + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(use_session), SWITCH_LOG_DEBUG, "%s Digit NOT match binding [%s]\n", switch_channel_get_name(channel), match->match_digits); if (switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "digits", match->match_digits); - if ((status = switch_core_session_queue_event(session, &event)) != SWITCH_STATUS_SUCCESS) { + if ((status = switch_core_session_queue_event(use_session, &event)) != SWITCH_STATUS_SUCCESS) { switch_event_destroy(&event); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s event queue faiure.\n", - switch_core_session_get_name(session)); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(use_session), SWITCH_LOG_WARNING, "%s event queue failure.\n", + switch_core_session_get_name(use_session)); } } @@ -133,6 +143,11 @@ static switch_status_t digit_nomatch_action_callback(switch_ivr_dmachine_match_t switch_channel_queue_dtmf_string(channel, str); + if (use_session != session) { + switch_core_session_rwunlock(use_session); + } + + return SWITCH_STATUS_SUCCESS; } @@ -143,9 +158,19 @@ static switch_status_t digit_action_callback(switch_ivr_dmachine_match_t *match) switch_status_t status; int exec = 0; char *string = act->string; - switch_channel_t *channel = switch_core_session_get_channel(act->session); + switch_channel_t *channel; + switch_core_session_t *use_session = act->session; + + if (switch_ivr_dmachine_get_target(match->dmachine) == DIGIT_TARGET_PEER) { + if (switch_core_session_get_partner(act->session, &use_session) != SWITCH_STATUS_SUCCESS) { + use_session = act->session; + } + } + + channel = switch_core_session_get_channel(use_session); switch_channel_set_variable(channel, "last_matching_digits", match->match_digits); + if (switch_event_create_plain(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(act->session), SWITCH_LOG_DEBUG, "%s Digit match binding [%s][%s]\n", @@ -163,18 +188,24 @@ static switch_status_t digit_action_callback(switch_ivr_dmachine_match_t *match) switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "execute", exec == 2 ? "non-blocking" : "blocking"); } - if ((status = switch_core_session_queue_event(act->session, &event)) != SWITCH_STATUS_SUCCESS) { + if ((status = switch_core_session_queue_event(use_session, &event)) != SWITCH_STATUS_SUCCESS) { switch_event_destroy(&event); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(act->session), SWITCH_LOG_WARNING, "%s event queue faiure.\n", - switch_core_session_get_name(act->session)); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(use_session), SWITCH_LOG_WARNING, "%s event queue faiure.\n", + switch_core_session_get_name(use_session)); } } if (exec) { - char *cmd = switch_core_session_sprintf(act->session, "%s::%s", string, act->value); - switch_ivr_broadcast_in_thread(act->session, cmd, SMF_ECHO_ALEG|SMF_HOLD_BLEG); + char *cmd = switch_core_session_sprintf(use_session, "%s::%s", string, act->value); + switch_ivr_broadcast_in_thread(use_session, cmd, SMF_ECHO_ALEG|SMF_HOLD_BLEG); } + + if (use_session != act->session) { + switch_core_session_rwunlock(use_session); + } + + return SWITCH_STATUS_SUCCESS; } @@ -212,6 +243,30 @@ SWITCH_STANDARD_APP(digit_action_set_realm_function) } + +#define DIGIT_ACTION_SET_TARGET_USAGE "" +SWITCH_STANDARD_APP(digit_action_set_target_function) +{ + switch_ivr_dmachine_t *dmachine; + char *target_str = (char *) data; + + if (zstr(data)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", DIGIT_ACTION_SET_TARGET_USAGE); + return; + } + + if ((dmachine = switch_core_session_get_dmachine(session))) { + switch_digit_action_target_t target = DIGIT_TARGET_SELF; + + if (!strcasecmp(target_str, "peer")) { + target = DIGIT_TARGET_PEER; + } + + switch_ivr_dmachine_set_target(dmachine, target); + } + +} + #define BIND_DIGIT_ACTION_USAGE ",,," SWITCH_STANDARD_APP(bind_digit_action_function) { @@ -219,7 +274,7 @@ SWITCH_STANDARD_APP(bind_digit_action_function) switch_ivr_dmachine_t *dmachine; char *mydata; int argc = 0; - char *argv[4] = { 0 }; + char *argv[5] = { 0 }; struct action_binding *act; if (zstr(data)) { @@ -266,7 +321,7 @@ SWITCH_STANDARD_APP(bind_digit_action_function) act->string = argv[2]; act->value = argv[3]; act->session = session; - + switch_ivr_dmachine_bind(dmachine, act->realm, act->input, 0, digit_action_callback, act); } @@ -3788,6 +3843,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "digit_action_set_realm", "change binding realm", "", digit_action_set_realm_function, DIGIT_ACTION_SET_REALM_USAGE, SAF_SUPPORT_NOMEDIA); + + SWITCH_ADD_APP(app_interface, "digit_action_set_target", "change binding target", "", + digit_action_set_target_function, DIGIT_ACTION_SET_TARGET_USAGE, SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "privacy", "Set privacy on calls", "Set caller privacy on calls.", privacy_function, "off|on|name|full|number", diff --git a/src/switch_core_io.c b/src/switch_core_io.c index 100d8bf9f6..3a30cdaf74 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -1293,9 +1293,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(switch_core_sessio } else if (!new_dtmf.duration) { new_dtmf.duration = switch_core_default_dtmf_duration(0); } - + if (!switch_test_flag(dtmf, DTMF_FLAG_SKIP_PROCESS)) { - if (session->dmachine && !switch_channel_test_flag(session->channel, CF_BROADCAST)) { + if (session->dmachine && switch_ivr_dmachine_get_target(session->dmachine) == DIGIT_TARGET_SELF && + !switch_channel_test_flag(session->channel, CF_BROADCAST)) { char str[2] = { dtmf->digit, '\0' }; switch_ivr_dmachine_feed(session->dmachine, str, NULL); fed = 1; @@ -1337,13 +1338,23 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_sessio new_dtmf.duration = switch_core_default_dtmf_duration(0); } - + for (ptr = session->event_hooks.send_dtmf; ptr; ptr = ptr->next) { if ((status = ptr->send_dtmf(session, dtmf, SWITCH_DTMF_SEND)) != SWITCH_STATUS_SUCCESS) { return SWITCH_STATUS_SUCCESS; } } + if (!switch_test_flag(dtmf, DTMF_FLAG_SKIP_PROCESS)) { + if (session->dmachine && switch_ivr_dmachine_get_target(session->dmachine) == DIGIT_TARGET_PEER && + !switch_channel_test_flag(session->channel, CF_BROADCAST)) { + char str[2] = { new_dtmf.digit, '\0' }; + switch_ivr_dmachine_feed(session->dmachine, str, NULL); + return SWITCH_STATUS_SUCCESS; + } + } + + if (session->endpoint_interface->io_routines->send_dtmf) { int send = 0; status = SWITCH_STATUS_SUCCESS; diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 7eeb1404e5..fe8d9ddb1b 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -59,6 +59,7 @@ struct switch_ivr_dmachine { uint32_t input_timeout_ms; switch_hash_t *binding_hash; switch_ivr_dmachine_match_t match; + switch_digit_action_target_t target; char digits[DMACHINE_MAX_DIGIT_LEN]; char last_matching_digits[DMACHINE_MAX_DIGIT_LEN]; char last_failed_digits[DMACHINE_MAX_DIGIT_LEN]; @@ -74,6 +75,17 @@ struct switch_ivr_dmachine { }; +SWITCH_DECLARE(switch_digit_action_target_t) switch_ivr_dmachine_get_target(switch_ivr_dmachine_t *dmachine) +{ + return dmachine->target; +} + +SWITCH_DECLARE(void) switch_ivr_dmachine_set_target(switch_ivr_dmachine_t *dmachine, switch_digit_action_target_t target) +{ + dmachine->target = target; +} + + SWITCH_DECLARE(void) switch_ivr_dmachine_set_match_callback(switch_ivr_dmachine_t *dmachine, switch_ivr_dmachine_callback_t match_callback) { From 4f58ad4fb7a89e0ce1cf1e0ccccf80f5c979f878 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 1 Sep 2011 12:25:08 -0500 Subject: [PATCH 016/204] misplaced ! --- src/mod/endpoints/mod_sofia/sofia_glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index d0d75bfb1f..124982c1de 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -3034,7 +3034,7 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f } if (!(sofia_test_pflag(tech_pvt->profile, PFLAG_REWRITE_TIMESTAMPS) || - ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_rewrite_timestamps")) && !switch_true(val)))) { + ((val = switch_channel_get_variable(tech_pvt->channel, "rtp_rewrite_timestamps")) && switch_true(val)))) { flags |= SWITCH_RTP_FLAG_RAW_WRITE; } From 2e9724d2ec8c0065731421f1629a1a24e321aade Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 1 Sep 2011 12:37:58 -0500 Subject: [PATCH 017/204] pass cancel_cause into enterprise_originate --- src/include/switch_ivr.h | 3 ++- src/switch_ivr_originate.c | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index 5ce8c882d2..6b2a10d43f 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -464,7 +464,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_enterprise_originate(switch_core_sess const char *cid_name_override, const char *cid_num_override, switch_caller_profile_t *caller_profile_override, - switch_event_t *ovars, switch_originate_flag_t flags); + switch_event_t *ovars, switch_originate_flag_t flags, + switch_call_cause_t *cancel_cause); SWITCH_DECLARE(void) switch_ivr_bridge_display(switch_core_session_t *session, switch_core_session_t *peer_session); diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index 418c9dd2b5..3addeb3c46 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -1330,7 +1330,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_enterprise_originate(switch_core_sess const char *cid_name_override, const char *cid_num_override, switch_caller_profile_t *caller_profile_override, - switch_event_t *ovars, switch_originate_flag_t flags) + switch_event_t *ovars, switch_originate_flag_t flags, + switch_call_cause_t *cancel_cause) { int x_argc = 0; char *x_argv[MAX_PEERS] = { 0 }; @@ -1480,6 +1481,10 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_enterprise_originate(switch_core_sess break; } + if (cancel_cause && *cancel_cause > 0) { + break; + } + for (i = 0; i < x_argc; i++) { @@ -1521,7 +1526,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_enterprise_originate(switch_core_sess if (hp == &handles[i]) { continue; } - handles[i].cancel_cause = SWITCH_CAUSE_LOSE_RACE; + + if (cancel_cause && *cancel_cause > 0) { + handles[i].cancel_cause = *cancel_cause; + } else { + handles[i].cancel_cause = SWITCH_CAUSE_LOSE_RACE; + } } for (i = 0; i < x_argc; i++) { @@ -1738,7 +1748,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_originate(switch_core_session_t *sess if (strstr(bridgeto, SWITCH_ENT_ORIGINATE_DELIM)) { return switch_ivr_enterprise_originate(session, bleg, cause, bridgeto, timelimit_sec, table, cid_name_override, cid_num_override, - caller_profile_override, ovars, flags); + caller_profile_override, ovars, flags, cancel_cause); } oglobals.ringback_ok = 1; From 7efa4fb209f2d6fa5740226f492b01395c0590e6 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 1 Sep 2011 15:10:23 -0500 Subject: [PATCH 018/204] FS-3532 --resolve --- src/mod/endpoints/mod_sofia/mod_sofia.c | 2 +- src/mod/endpoints/mod_sofia/sofia.c | 54 +++++++++++++++----- src/mod/endpoints/mod_sofia/sofia_presence.c | 23 ++++++--- 3 files changed, 57 insertions(+), 22 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 1043c6ea83..147dc279be 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -2047,7 +2047,7 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi switch_channel_set_variable(channel, "last_sent_callee_id_name", name); switch_channel_set_variable(channel, "last_sent_callee_id_number", number); - + if (switch_event_create(&event, SWITCH_EVENT_CALL_UPDATE) == SWITCH_STATUS_SUCCESS) { const char *uuid = switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Direction", "SEND"); diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 9c453cbbf8..a24c795df1 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -7691,6 +7691,12 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ } } + check_decode(displayname, session); + tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), + from_user, + dialplan, + displayname, from_user, network_ip, from_user, aniii, NULL, MODNAME, context, destination_number); + if (!bnh && sip->sip_replaces) { if (!(bnh = nua_handle_by_replaces(nua, sip->sip_replaces))) { if (!(bnh = nua_handle_by_call_id(nua, sip->sip_replaces->rp_call_id))) { @@ -7711,10 +7717,32 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ private_object_t *b_tech_pvt = NULL; const char *app = switch_channel_get_variable(b_channel, SWITCH_CURRENT_APPLICATION_VARIABLE); const char *data = switch_channel_get_variable(b_channel, SWITCH_CURRENT_APPLICATION_DATA_VARIABLE); + switch_caller_profile_t *orig_cp; + const char *sent_name, *sent_number; + orig_cp = switch_channel_get_caller_profile(b_channel); + + sent_name = switch_channel_get_variable(b_channel, "last_sent_callee_id_name"); + sent_number = switch_channel_get_variable(b_channel, "last_sent_callee_id_number"); + + if (!zstr(sent_name) && !zstr(sent_number)) { + tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, sent_name); + tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, sent_number); + } else { + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { + tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_name); + tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->callee_id_number); + } else { + tech_pvt->caller_profile->callee_id_name = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_name); + tech_pvt->caller_profile->callee_id_number = switch_core_strdup(tech_pvt->caller_profile->pool, orig_cp->caller_id_number); + } + } + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Setting NAT mode based on %s\n", is_nat); + if (app && data && !strcasecmp(app, "conference")) { - destination_number = switch_core_session_sprintf(session, "answer,conference:%s", data); - dialplan = "inline"; + tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, "answer,conference:%s", data); + tech_pvt->caller_profile->dialplan = "inline"; } else { if (switch_core_session_check_interface(b_session, sofia_endpoint_interface)) { b_tech_pvt = switch_core_session_get_private(b_session); @@ -7744,7 +7772,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ if (switch_core_session_check_interface(c_session, sofia_endpoint_interface)) { c_tech_pvt = switch_core_session_get_private(c_session); } - + if (!one_leg && (!b_tech_pvt || !sofia_test_flag(b_tech_pvt, TFLAG_SIP_HOLD)) && @@ -7761,21 +7789,25 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ } if (do_conf) { - destination_number = switch_core_session_sprintf(session, "answer,conference:%s@sla+flags{mintwo}", uuid); + tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, + "answer,conference:%s@sla+flags{mintwo}", uuid); } else { if (one_leg && c_app) { if (c_data) { - destination_number = switch_core_session_sprintf(session, "answer,%s:%s", c_app, c_data); + tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, + "answer,%s:%s", c_app, c_data); } else { - destination_number = switch_core_session_sprintf(session, "answer,%s", c_app); + tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, + "answer,%s", c_app); } } else { switch_channel_mark_hold(b_channel, SWITCH_FALSE); - destination_number = switch_core_session_sprintf(session, "answer,intercept:%s", uuid); + tech_pvt->caller_profile->destination_number = switch_core_sprintf(tech_pvt->caller_profile->pool, + "answer,intercept:%s", uuid); } } - dialplan = "inline"; + tech_pvt->caller_profile->dialplan = "inline"; } } switch_core_session_rwunlock(b_session); @@ -7784,11 +7816,7 @@ void sofia_handle_sip_i_invite(nua_t *nua, sofia_profile_t *profile, nua_handle_ nua_handle_unref(bnh); } - check_decode(displayname, session); - tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), - from_user, - dialplan, - displayname, from_user, network_ip, from_user, aniii, NULL, MODNAME, context, destination_number); + if (tech_pvt->caller_profile) { diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 0a63edb690..0b57a52a4e 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -1984,14 +1984,21 @@ static int broadsoft_sla_gather_state_callback(void *pArg, int argc, char **argv if (uuid && (session = switch_core_session_locate(uuid))) { switch_channel_t *channel = switch_core_session_get_channel(session); - if (zstr((callee_name = switch_channel_get_variable(channel, "effective_callee_id_name"))) && - zstr((callee_name = switch_channel_get_variable(channel, "sip_callee_id_name")))) { - callee_name = switch_channel_get_variable(channel, "callee_id_name"); - } - - if (zstr((callee_number = switch_channel_get_variable(channel, "effective_callee_id_number"))) && - zstr((callee_number = switch_channel_get_variable(channel, "sip_callee_id_number")))) { - callee_number = switch_channel_get_variable(channel, "destination_number"); + if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { + + if (zstr((callee_name = switch_channel_get_variable(channel, "effective_callee_id_name"))) && + zstr((callee_name = switch_channel_get_variable(channel, "sip_callee_id_name")))) { + callee_name = switch_channel_get_variable(channel, "callee_id_name"); + } + + if (zstr((callee_number = switch_channel_get_variable(channel, "effective_callee_id_number"))) && + zstr((callee_number = switch_channel_get_variable(channel, "sip_callee_id_number"))) && + zstr((callee_number = switch_channel_get_variable(channel, "callee_id_number")))) { + callee_number = switch_channel_get_variable(channel, "destination_number"); + } + } else { + callee_name = switch_channel_get_variable(channel, "caller_id_name"); + callee_number = switch_channel_get_variable(channel, "caller_id_number"); } if (zstr(callee_name) && !zstr(callee_number)) { From 2689081bae7dd8e0946bf073e65c5b67f51a36c9 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 1 Sep 2011 21:16:22 -0500 Subject: [PATCH 019/204] vs2010 reswig --- .../mod_managed/freeswitch_wrap.2010.cxx | 104 +++++++++++++++- .../mod_managed/managed/swig.2010.cs | 115 ++++++++++++++++-- 2 files changed, 208 insertions(+), 11 deletions(-) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx index e8782346d0..687d3e9933 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx @@ -1797,6 +1797,28 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_dtmf_t_flags_get(void * jarg1) { } +SWIGEXPORT void SWIGSTDCALL CSharp_switch_dtmf_t_source_set(void * jarg1, int jarg2) { + switch_dtmf_t *arg1 = (switch_dtmf_t *) 0 ; + switch_dtmf_source_t arg2 ; + + arg1 = (switch_dtmf_t *)jarg1; + arg2 = (switch_dtmf_source_t)jarg2; + if (arg1) (arg1)->source = arg2; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_dtmf_t_source_get(void * jarg1) { + int jresult ; + switch_dtmf_t *arg1 = (switch_dtmf_t *) 0 ; + switch_dtmf_source_t result; + + arg1 = (switch_dtmf_t *)jarg1; + result = (switch_dtmf_source_t) ((arg1)->source); + jresult = result; + return jresult; +} + + SWIGEXPORT void * SWIGSTDCALL CSharp_new_switch_dtmf_t() { void * jresult ; switch_dtmf_t *result = 0 ; @@ -5120,6 +5142,16 @@ SWIGEXPORT int SWIGSTDCALL CSharp_SWITCH_CORE_DB_DONE_get() { } +SWIGEXPORT char * SWIGSTDCALL CSharp_switch_sql_concat() { + char * jresult ; + char *result = 0 ; + + result = (char *)switch_sql_concat(); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT void * SWIGSTDCALL CSharp_switch_regex_compile(char * jarg1, int jarg2, void * jarg3, void * jarg4, void * jarg5) { void * jresult ; char *arg1 = (char *) 0 ; @@ -7253,11 +7285,15 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_core_session_get_channel(void * jarg } -SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_session_wake_session_thread(void * jarg1) { +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_wake_session_thread(void * jarg1) { + int jresult ; switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_status_t result; arg1 = (switch_core_session_t *)jarg1; - switch_core_session_wake_session_thread(arg1); + result = (switch_status_t)switch_core_session_wake_session_thread(arg1); + jresult = result; + return jresult; } @@ -7347,6 +7383,28 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_switch_core_session_get_dmachine(void * jar } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_dmachine_get_target(void * jarg1) { + int jresult ; + switch_ivr_dmachine_t *arg1 = (switch_ivr_dmachine_t *) 0 ; + switch_digit_action_target_t result; + + arg1 = (switch_ivr_dmachine_t *)jarg1; + result = (switch_digit_action_target_t)switch_ivr_dmachine_get_target(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_ivr_dmachine_set_target(void * jarg1, int jarg2) { + switch_ivr_dmachine_t *arg1 = (switch_ivr_dmachine_t *) 0 ; + switch_digit_action_target_t arg2 ; + + arg1 = (switch_ivr_dmachine_t *)jarg1; + arg2 = (switch_digit_action_target_t)jarg2; + switch_ivr_dmachine_set_target(arg1,arg2); +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_set_codec_slin(void * jarg1, void * jarg2) { int jresult ; switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; @@ -24735,6 +24793,28 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_channel_api_on(void * jarg1, char * jar } +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_channel_get_queued_extension(void * jarg1) { + void * jresult ; + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + switch_caller_extension_t *result = 0 ; + + arg1 = (switch_channel_t *)jarg1; + result = (switch_caller_extension_t *)switch_channel_get_queued_extension(arg1); + jresult = (void *)result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_channel_transfer_to_extension(void * jarg1, void * jarg2) { + switch_channel_t *arg1 = (switch_channel_t *) 0 ; + switch_caller_extension_t *arg2 = (switch_caller_extension_t *) 0 ; + + arg1 = (switch_channel_t *)jarg1; + arg2 = (switch_caller_extension_t *)jarg2; + switch_channel_transfer_to_extension(arg1,arg2); +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_buffer_create(void * jarg1, void * jarg2, void * jarg3) { int jresult ; switch_memory_pool_t *arg1 = (switch_memory_pool_t *) 0 ; @@ -26993,6 +27073,20 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_parse_all_signal_data(void * jarg1) } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_process_indications(void * jarg1, void * jarg2) { + int jresult ; + switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_core_session_message_t *arg2 = (switch_core_session_message_t *) 0 ; + switch_status_t result; + + arg1 = (switch_core_session_t *)jarg1; + arg2 = (switch_core_session_message_t *)jarg2; + result = (switch_status_t)switch_ivr_process_indications(arg1,arg2); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_sleep(void * jarg1, unsigned long jarg2, int jarg3, void * jarg4) { int jresult ; switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; @@ -27657,7 +27751,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_originate(void * jarg1, void * jarg } -SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_enterprise_originate(void * jarg1, void * jarg2, void * jarg3, char * jarg4, unsigned long jarg5, void * jarg6, char * jarg7, char * jarg8, void * jarg9, void * jarg10, unsigned long jarg11) { +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_enterprise_originate(void * jarg1, void * jarg2, void * jarg3, char * jarg4, unsigned long jarg5, void * jarg6, char * jarg7, char * jarg8, void * jarg9, void * jarg10, unsigned long jarg11, void * jarg12) { int jresult ; switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; switch_core_session_t **arg2 = (switch_core_session_t **) 0 ; @@ -27670,6 +27764,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_enterprise_originate(void * jarg1, switch_caller_profile_t *arg9 = (switch_caller_profile_t *) 0 ; switch_event_t *arg10 = (switch_event_t *) 0 ; switch_originate_flag_t arg11 ; + switch_call_cause_t *arg12 = (switch_call_cause_t *) 0 ; switch_status_t result; arg1 = (switch_core_session_t *)jarg1; @@ -27683,7 +27778,8 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_enterprise_originate(void * jarg1, arg9 = (switch_caller_profile_t *)jarg9; arg10 = (switch_event_t *)jarg10; arg11 = (switch_originate_flag_t)jarg11; - result = (switch_status_t)switch_ivr_enterprise_originate(arg1,arg2,arg3,(char const *)arg4,arg5,(switch_state_handler_table const *)arg6,(char const *)arg7,(char const *)arg8,arg9,arg10,arg11); + arg12 = (switch_call_cause_t *)jarg12; + result = (switch_status_t)switch_ivr_enterprise_originate(arg1,arg2,arg3,(char const *)arg4,arg5,(switch_state_handler_table const *)arg6,(char const *)arg7,(char const *)arg8,arg9,arg10,arg11,arg12); jresult = result; return jresult; } diff --git a/src/mod/languages/mod_managed/managed/swig.2010.cs b/src/mod/languages/mod_managed/managed/swig.2010.cs index c546f467d7..f8d451bca6 100644 --- a/src/mod/languages/mod_managed/managed/swig.2010.cs +++ b/src/mod/languages/mod_managed/managed/swig.2010.cs @@ -919,6 +919,11 @@ public class freeswitch { return ret; } + public static string switch_sql_concat() { + string ret = freeswitchPINVOKE.switch_sql_concat(); + return ret; + } + public static SWIGTYPE_p_real_pcre switch_regex_compile(string pattern, int options, ref string errorptr, SWIGTYPE_p_int erroroffset, SWIGTYPE_p_unsigned_char tables) { IntPtr cPtr = freeswitchPINVOKE.switch_regex_compile(pattern, options, ref errorptr, SWIGTYPE_p_int.getCPtr(erroroffset), SWIGTYPE_p_unsigned_char.getCPtr(tables)); SWIGTYPE_p_real_pcre ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_real_pcre(cPtr, false); @@ -1349,8 +1354,9 @@ public class freeswitch { return ret; } - public static void switch_core_session_wake_session_thread(SWIGTYPE_p_switch_core_session session) { - freeswitchPINVOKE.switch_core_session_wake_session_thread(SWIGTYPE_p_switch_core_session.getCPtr(session)); + public static switch_status_t switch_core_session_wake_session_thread(SWIGTYPE_p_switch_core_session session) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_wake_session_thread(SWIGTYPE_p_switch_core_session.getCPtr(session)); + return ret; } public static void switch_core_session_signal_state_change(SWIGTYPE_p_switch_core_session session) { @@ -1390,6 +1396,15 @@ public class freeswitch { return ret; } + public static switch_digit_action_target_t switch_ivr_dmachine_get_target(SWIGTYPE_p_switch_ivr_dmachine dmachine) { + switch_digit_action_target_t ret = (switch_digit_action_target_t)freeswitchPINVOKE.switch_ivr_dmachine_get_target(SWIGTYPE_p_switch_ivr_dmachine.getCPtr(dmachine)); + return ret; + } + + public static void switch_ivr_dmachine_set_target(SWIGTYPE_p_switch_ivr_dmachine dmachine, switch_digit_action_target_t target) { + freeswitchPINVOKE.switch_ivr_dmachine_set_target(SWIGTYPE_p_switch_ivr_dmachine.getCPtr(dmachine), (int)target); + } + public static switch_status_t switch_core_session_set_codec_slin(SWIGTYPE_p_switch_core_session session, switch_slin_data data) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_set_codec_slin(SWIGTYPE_p_switch_core_session.getCPtr(session), switch_slin_data.getCPtr(data)); return ret; @@ -3863,6 +3878,16 @@ public class freeswitch { return ret; } + public static switch_caller_extension switch_channel_get_queued_extension(SWIGTYPE_p_switch_channel channel) { + IntPtr cPtr = freeswitchPINVOKE.switch_channel_get_queued_extension(SWIGTYPE_p_switch_channel.getCPtr(channel)); + switch_caller_extension ret = (cPtr == IntPtr.Zero) ? null : new switch_caller_extension(cPtr, false); + return ret; + } + + public static void switch_channel_transfer_to_extension(SWIGTYPE_p_switch_channel channel, switch_caller_extension caller_extension) { + freeswitchPINVOKE.switch_channel_transfer_to_extension(SWIGTYPE_p_switch_channel.getCPtr(channel), switch_caller_extension.getCPtr(caller_extension)); + } + public static switch_status_t switch_buffer_create(SWIGTYPE_p_apr_pool_t pool, SWIGTYPE_p_p_switch_buffer buffer, SWIGTYPE_p_switch_size_t max_len) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_buffer_create(SWIGTYPE_p_apr_pool_t.getCPtr(pool), SWIGTYPE_p_p_switch_buffer.getCPtr(buffer), SWIGTYPE_p_switch_size_t.getCPtr(max_len)); if (freeswitchPINVOKE.SWIGPendingException.Pending) throw freeswitchPINVOKE.SWIGPendingException.Retrieve(); @@ -4244,6 +4269,11 @@ public class freeswitch { return ret; } + public static switch_status_t switch_ivr_process_indications(SWIGTYPE_p_switch_core_session session, switch_core_session_message message) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_process_indications(SWIGTYPE_p_switch_core_session.getCPtr(session), switch_core_session_message.getCPtr(message)); + return ret; + } + public static switch_status_t switch_ivr_sleep(SWIGTYPE_p_switch_core_session session, uint ms, switch_bool_t sync, switch_input_args_t args) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_sleep(SWIGTYPE_p_switch_core_session.getCPtr(session), ms, (int)sync, switch_input_args_t.getCPtr(args)); return ret; @@ -4434,8 +4464,8 @@ public class freeswitch { return ret; } - public static switch_status_t switch_ivr_enterprise_originate(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_p_switch_core_session bleg, SWIGTYPE_p_switch_call_cause_t cause, string bridgeto, uint timelimit_sec, switch_state_handler_table table, string cid_name_override, string cid_num_override, switch_caller_profile caller_profile_override, switch_event ovars, uint flags) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_enterprise_originate(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_p_switch_core_session.getCPtr(bleg), SWIGTYPE_p_switch_call_cause_t.getCPtr(cause), bridgeto, timelimit_sec, switch_state_handler_table.getCPtr(table), cid_name_override, cid_num_override, switch_caller_profile.getCPtr(caller_profile_override), switch_event.getCPtr(ovars), flags); + public static switch_status_t switch_ivr_enterprise_originate(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_p_switch_core_session bleg, SWIGTYPE_p_switch_call_cause_t cause, string bridgeto, uint timelimit_sec, switch_state_handler_table table, string cid_name_override, string cid_num_override, switch_caller_profile caller_profile_override, switch_event ovars, uint flags, SWIGTYPE_p_switch_call_cause_t cancel_cause) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_enterprise_originate(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_p_switch_core_session.getCPtr(bleg), SWIGTYPE_p_switch_call_cause_t.getCPtr(cause), bridgeto, timelimit_sec, switch_state_handler_table.getCPtr(table), cid_name_override, cid_num_override, switch_caller_profile.getCPtr(caller_profile_override), switch_event.getCPtr(ovars), flags, SWIGTYPE_p_switch_call_cause_t.getCPtr(cancel_cause)); return ret; } @@ -6480,6 +6510,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_dtmf_t_flags_get")] public static extern int switch_dtmf_t_flags_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_dtmf_t_source_set")] + public static extern void switch_dtmf_t_source_set(HandleRef jarg1, int jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_dtmf_t_source_get")] + public static extern int switch_dtmf_t_source_get(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_new_switch_dtmf_t")] public static extern IntPtr new_switch_dtmf_t(); @@ -7338,6 +7374,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_CORE_DB_DONE_get")] public static extern int SWITCH_CORE_DB_DONE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_switch_sql_concat")] + public static extern string switch_sql_concat(); + [DllImport("mod_managed", EntryPoint="CSharp_switch_regex_compile")] public static extern IntPtr switch_regex_compile(string jarg1, int jarg2, ref string jarg3, HandleRef jarg4, HandleRef jarg5); @@ -7837,7 +7876,7 @@ class freeswitchPINVOKE { public static extern IntPtr switch_core_session_get_channel(HandleRef jarg1); [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_wake_session_thread")] - public static extern void switch_core_session_wake_session_thread(HandleRef jarg1); + public static extern int switch_core_session_wake_session_thread(HandleRef jarg1); [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_signal_state_change")] public static extern void switch_core_session_signal_state_change(HandleRef jarg1); @@ -7863,6 +7902,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_get_dmachine")] public static extern IntPtr switch_core_session_get_dmachine(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_dmachine_get_target")] + public static extern int switch_ivr_dmachine_get_target(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_dmachine_set_target")] + public static extern void switch_ivr_dmachine_set_target(HandleRef jarg1, int jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_set_codec_slin")] public static extern int switch_core_session_set_codec_slin(HandleRef jarg1, HandleRef jarg2); @@ -12081,6 +12126,12 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_api_on")] public static extern int switch_channel_api_on(HandleRef jarg1, string jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_get_queued_extension")] + public static extern IntPtr switch_channel_get_queued_extension(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_channel_transfer_to_extension")] + public static extern void switch_channel_transfer_to_extension(HandleRef jarg1, HandleRef jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_buffer_create")] public static extern int switch_buffer_create(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3); @@ -12591,6 +12642,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_parse_all_signal_data")] public static extern int switch_ivr_parse_all_signal_data(HandleRef jarg1); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_process_indications")] + public static extern int switch_ivr_process_indications(HandleRef jarg1, HandleRef jarg2); + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_sleep")] public static extern int switch_ivr_sleep(HandleRef jarg1, uint jarg2, int jarg3, HandleRef jarg4); @@ -12706,7 +12760,7 @@ class freeswitchPINVOKE { public static extern int switch_ivr_originate(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, string jarg4, uint jarg5, HandleRef jarg6, string jarg7, string jarg8, HandleRef jarg9, HandleRef jarg10, uint jarg11, HandleRef jarg12); [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_enterprise_originate")] - public static extern int switch_ivr_enterprise_originate(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, string jarg4, uint jarg5, HandleRef jarg6, string jarg7, string jarg8, HandleRef jarg9, HandleRef jarg10, uint jarg11); + public static extern int switch_ivr_enterprise_originate(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, string jarg4, uint jarg5, HandleRef jarg6, string jarg7, string jarg8, HandleRef jarg9, HandleRef jarg10, uint jarg11, HandleRef jarg12); [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_bridge_display")] public static extern void switch_ivr_bridge_display(HandleRef jarg1, HandleRef jarg2); @@ -22337,6 +22391,7 @@ public enum switch_channel_cap_t { CC_PROXY_MEDIA, CC_JITTERBUFFER, CC_FS_RTP, + CC_QUEUEABLE_DTMF_DELAY, CC_FLAG_MAX } @@ -23835,7 +23890,8 @@ namespace FreeSWITCH.Native { SCF_USE_WIN32_MONOTONIC = (1 << 12), SCF_AUTO_SCHEMAS = (1 << 13), SCF_MINIMAL = (1 << 14), - SCF_USE_NAT_MAPPING = (1 << 15) + SCF_USE_NAT_MAPPING = (1 << 15), + SCF_CLEAR_SQL = (1 << 16) } } @@ -24504,6 +24560,22 @@ public class switch_dialplan_interface : IDisposable { namespace FreeSWITCH.Native { +public enum switch_digit_action_target_t { + DIGIT_TARGET_SELF, + DIGIT_TARGET_PEER +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + using System; using System.Runtime.InteropServices; @@ -24974,6 +25046,25 @@ public enum switch_dtmf_direction_t { namespace FreeSWITCH.Native { +public enum switch_dtmf_source_t { + SWITCH_DTMF_UNKNOWN, + SWITCH_DTMF_INBAND_AUDIO, + SWITCH_DTMF_RTP, + SWITCH_DTMF_ENDPOINT, + SWITCH_DTMF_APP +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + using System; using System.Runtime.InteropServices; @@ -25037,6 +25128,16 @@ public class switch_dtmf_t : IDisposable { } } + public switch_dtmf_source_t source { + set { + freeswitchPINVOKE.switch_dtmf_t_source_set(swigCPtr, (int)value); + } + get { + switch_dtmf_source_t ret = (switch_dtmf_source_t)freeswitchPINVOKE.switch_dtmf_t_source_get(swigCPtr); + return ret; + } + } + public switch_dtmf_t() : this(freeswitchPINVOKE.new_switch_dtmf_t(), true) { } From 42b64ccd67f0b9fa016a2b15aaa55af9f158cdc1 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 2 Sep 2011 09:34:40 -0500 Subject: [PATCH 020/204] get rid of digit_action_set target and add target,bind_target params to bind_digit_action --- src/include/private/switch_core_pvt.h | 2 +- src/include/switch_core.h | 6 +- src/include/switch_types.h | 3 +- .../applications/mod_dptools/mod_dptools.c | 178 +++++++++++------- src/switch_core_io.c | 19 +- src/switch_core_session.c | 27 ++- src/switch_ivr_async.c | 12 +- src/switch_ivr_bridge.c | 14 +- 8 files changed, 167 insertions(+), 94 deletions(-) diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index 423969fac8..af82f1e88d 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -169,7 +169,7 @@ struct switch_core_session { uint32_t track_id; switch_log_level_t loglevel; uint32_t soft_lock; - switch_ivr_dmachine_t *dmachine; + switch_ivr_dmachine_t *dmachine[2]; plc_state_t *plc; }; diff --git a/src/include/switch_core.h b/src/include/switch_core.h index f6e611b91f..562262c82d 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -712,12 +712,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_set_loglevel(switch_core_ses \return the log level */ SWITCH_DECLARE(switch_log_level_t) switch_core_session_get_loglevel(switch_core_session_t *session); - + SWITCH_DECLARE(void) switch_core_session_soft_lock(switch_core_session_t *session, uint32_t sec); SWITCH_DECLARE(void) switch_core_session_soft_unlock(switch_core_session_t *session); -SWITCH_DECLARE(void) switch_core_session_set_dmachine(switch_core_session_t *session, switch_ivr_dmachine_t *dmachine); -SWITCH_DECLARE(switch_ivr_dmachine_t *) switch_core_session_get_dmachine(switch_core_session_t *session); +SWITCH_DECLARE(void) switch_core_session_set_dmachine(switch_core_session_t *session, switch_ivr_dmachine_t *dmachine, switch_digit_action_target_t target); +SWITCH_DECLARE(switch_ivr_dmachine_t *) switch_core_session_get_dmachine(switch_core_session_t *session, switch_digit_action_target_t target); SWITCH_DECLARE(switch_digit_action_target_t) switch_ivr_dmachine_get_target(switch_ivr_dmachine_t *dmachine); SWITCH_DECLARE(void) switch_ivr_dmachine_set_target(switch_ivr_dmachine_t *dmachine, switch_digit_action_target_t target); diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 7eb27d2c45..312e0bd342 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -223,7 +223,8 @@ typedef enum { typedef enum { DIGIT_TARGET_SELF, - DIGIT_TARGET_PEER + DIGIT_TARGET_PEER, + DIGIT_TARGET_BOTH } switch_digit_action_target_t; diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 02c64d8093..5e9dc13ef6 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -102,6 +102,7 @@ struct action_binding { char *input; char *string; char *value; + switch_digit_action_target_t target; switch_core_session_t *session; }; @@ -160,13 +161,19 @@ static switch_status_t digit_action_callback(switch_ivr_dmachine_match_t *match) char *string = act->string; switch_channel_t *channel; switch_core_session_t *use_session = act->session; - - if (switch_ivr_dmachine_get_target(match->dmachine) == DIGIT_TARGET_PEER) { + int x = 0; + if (switch_ivr_dmachine_get_target(match->dmachine) == DIGIT_TARGET_PEER || act->target == DIGIT_TARGET_PEER || act->target == DIGIT_TARGET_BOTH) { if (switch_core_session_get_partner(act->session, &use_session) != SWITCH_STATUS_SUCCESS) { use_session = act->session; } } + top: + x++; + + string = act->string; + exec = 0; + channel = switch_core_session_get_channel(use_session); switch_channel_set_variable(channel, "last_matching_digits", match->match_digits); @@ -197,28 +204,53 @@ static switch_status_t digit_action_callback(switch_ivr_dmachine_match_t *match) if (exec) { char *cmd = switch_core_session_sprintf(use_session, "%s::%s", string, act->value); - switch_ivr_broadcast_in_thread(use_session, cmd, SMF_ECHO_ALEG|SMF_HOLD_BLEG); + switch_ivr_broadcast_in_thread(use_session, cmd, SMF_ECHO_ALEG | (act->target == DIGIT_TARGET_BOTH ? 0 : SMF_HOLD_BLEG)); } if (use_session != act->session) { switch_core_session_rwunlock(use_session); - } + if (act->target == DIGIT_TARGET_BOTH) { + use_session = act->session; + goto top; + } + } return SWITCH_STATUS_SUCCESS; } -#define CLEAR_DIGIT_ACTION_USAGE "|all" +static switch_digit_action_target_t str2target(const char *target_str) +{ + if (!strcasecmp(target_str, "peer")) { + return DIGIT_TARGET_PEER; + } + + if (!strcasecmp(target_str, "both")) { + return DIGIT_TARGET_BOTH; + } + + return DIGIT_TARGET_SELF; +} + +#define CLEAR_DIGIT_ACTION_USAGE "|all[,target]" SWITCH_STANDARD_APP(clear_digit_action_function) { //switch_channel_t *channel = switch_core_session_get_channel(session); switch_ivr_dmachine_t *dmachine; - char *realm = (char *) data; + char *realm = switch_core_session_strdup(session, data); + char *target_str; + switch_digit_action_target_t target = DIGIT_TARGET_SELF; - if ((dmachine = switch_core_session_get_dmachine(session))) { + if ((target_str = strchr(realm, ' '))) { + *target_str++ = '\0'; + target = str2target(target_str); + } + + + if ((dmachine = switch_core_session_get_dmachine(session, target))) { if (zstr(realm) || !strcasecmp(realm, "all")) { - switch_core_session_set_dmachine(session, NULL); + switch_core_session_set_dmachine(session, NULL, target); switch_ivr_dmachine_destroy(&dmachine); } else { switch_ivr_dmachine_clear_realm(dmachine, realm); @@ -226,73 +258,40 @@ SWITCH_STANDARD_APP(clear_digit_action_function) } } -#define DIGIT_ACTION_SET_REALM_USAGE "" +#define DIGIT_ACTION_SET_REALM_USAGE "[,]" SWITCH_STANDARD_APP(digit_action_set_realm_function) { switch_ivr_dmachine_t *dmachine; - char *realm = (char *) data; + char *realm = switch_core_session_strdup(session, data); + char *target_str; + switch_digit_action_target_t target = DIGIT_TARGET_SELF; + + if ((target_str = strchr(realm, ' '))) { + *target_str++ = '\0'; + target = str2target(target_str); + } if (zstr(data)) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", DIGIT_ACTION_SET_REALM_USAGE); return; } - if ((dmachine = switch_core_session_get_dmachine(session))) { + if ((dmachine = switch_core_session_get_dmachine(session, target))) { switch_ivr_dmachine_set_realm(dmachine, realm); } } -#define DIGIT_ACTION_SET_TARGET_USAGE "" -SWITCH_STANDARD_APP(digit_action_set_target_function) +static void bind_to_session(switch_core_session_t *session, + const char *arg0, const char *arg1, const char *arg2, const char *arg3, + switch_digit_action_target_t target, switch_digit_action_target_t bind_target) { - switch_ivr_dmachine_t *dmachine; - char *target_str = (char *) data; - - if (zstr(data)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", DIGIT_ACTION_SET_TARGET_USAGE); - return; - } - - if ((dmachine = switch_core_session_get_dmachine(session))) { - switch_digit_action_target_t target = DIGIT_TARGET_SELF; - - if (!strcasecmp(target_str, "peer")) { - target = DIGIT_TARGET_PEER; - } - - switch_ivr_dmachine_set_target(dmachine, target); - } - -} - -#define BIND_DIGIT_ACTION_USAGE ",,," -SWITCH_STANDARD_APP(bind_digit_action_function) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_ivr_dmachine_t *dmachine; - char *mydata; - int argc = 0; - char *argv[5] = { 0 }; struct action_binding *act; + switch_ivr_dmachine_t *dmachine; + switch_channel_t *channel = switch_core_session_get_channel(session); - if (zstr(data)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", BIND_DIGIT_ACTION_USAGE); - return; - } - - mydata = switch_core_session_strdup(session, data); - - argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0]))); - - if (argc < 4 || zstr(argv[0]) || zstr(argv[1]) || zstr(argv[2]) || zstr(argv[3])) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", BIND_DIGIT_ACTION_USAGE); - return; - } - - - if (!(dmachine = switch_core_session_get_dmachine(session))) { + if (!(dmachine = switch_core_session_get_dmachine(session, target))) { uint32_t digit_timeout = 1500; uint32_t input_timeout = 0; const char *var; @@ -311,20 +310,69 @@ SWITCH_STANDARD_APP(bind_digit_action_function) } switch_ivr_dmachine_create(&dmachine, "DPTOOLS", NULL, digit_timeout, input_timeout, NULL, digit_nomatch_action_callback, session); - switch_core_session_set_dmachine(session, dmachine); + switch_core_session_set_dmachine(session, dmachine, target); } act = switch_core_session_alloc(session, sizeof(*act)); - act->realm = argv[0]; - act->input = argv[1]; - act->string = argv[2]; - act->value = argv[3]; + act->realm = switch_core_session_strdup(session, arg0); + act->input = switch_core_session_strdup(session, arg1); + act->string = switch_core_session_strdup(session, arg2); + act->value = switch_core_session_strdup(session, arg3); + act->target = bind_target; act->session = session; - switch_ivr_dmachine_bind(dmachine, act->realm, act->input, 0, digit_action_callback, act); } +#define BIND_DIGIT_ACTION_USAGE ",,,[,][,]" +SWITCH_STANDARD_APP(bind_digit_action_function) +{ + + char *mydata; + int argc = 0; + char *argv[6] = { 0 }; + switch_digit_action_target_t target, bind_target; + char *target_str = "self", *bind_target_str = "self"; + + if (zstr(data)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", BIND_DIGIT_ACTION_USAGE); + return; + } + + mydata = switch_core_session_strdup(session, data); + + argc = switch_separate_string(mydata, ',', argv, (sizeof(argv) / sizeof(argv[0]))); + + if (argc < 4 || zstr(argv[0]) || zstr(argv[1]) || zstr(argv[2]) || zstr(argv[3])) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", BIND_DIGIT_ACTION_USAGE); + return; + } + + if (argv[4]) { + target_str = argv[4]; + } + + if (argv[5]) { + bind_target_str = argv[5]; + } + + target = str2target(target_str); + bind_target = str2target(bind_target_str); + + + switch(target) { + case DIGIT_TARGET_PEER: + bind_to_session(session, argv[0], argv[1], argv[2], argv[3], DIGIT_TARGET_PEER, bind_target); + break; + case DIGIT_TARGET_BOTH: + bind_to_session(session, argv[0], argv[1], argv[2], argv[3], DIGIT_TARGET_PEER, bind_target); + bind_to_session(session, argv[0], argv[1], argv[2], argv[3], DIGIT_TARGET_SELF, bind_target); + break; + default: + bind_to_session(session, argv[0], argv[1], argv[2], argv[3], DIGIT_TARGET_SELF, bind_target); + break; + } +} #define DETECT_SPEECH_SYNTAX " [] OR grammar [] OR nogrammar OR grammaron/grammaroff OR grammarsalloff OR pause OR resume OR start_input_timers OR stop OR param " SWITCH_STANDARD_APP(detect_speech_function) @@ -3844,10 +3892,6 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "digit_action_set_realm", "change binding realm", "", digit_action_set_realm_function, DIGIT_ACTION_SET_REALM_USAGE, SAF_SUPPORT_NOMEDIA); - SWITCH_ADD_APP(app_interface, "digit_action_set_target", "change binding target", "", - digit_action_set_target_function, DIGIT_ACTION_SET_TARGET_USAGE, SAF_SUPPORT_NOMEDIA); - - SWITCH_ADD_APP(app_interface, "privacy", "Set privacy on calls", "Set caller privacy on calls.", privacy_function, "off|on|name|full|number", SAF_SUPPORT_NOMEDIA); diff --git a/src/switch_core_io.c b/src/switch_core_io.c index 3a30cdaf74..c2b8c4608f 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -107,6 +107,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi int need_codec, perfect, do_bugs = 0, do_resample = 0, is_cng = 0; switch_codec_implementation_t codec_impl; unsigned int flag = 0; + int i; switch_assert(session != NULL); @@ -146,8 +147,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi top: - if (session->dmachine && !switch_channel_test_flag(session->channel, CF_BROADCAST)) { - switch_ivr_dmachine_ping(session->dmachine, NULL); + for(i = 0; i < 2; i++) { + if (session->dmachine[i] && !switch_channel_test_flag(session->channel, CF_BROADCAST)) { + switch_ivr_dmachine_ping(session->dmachine[i], NULL); + } } if (switch_channel_down(session->channel) || !switch_core_codec_ready(session->read_codec)) { @@ -1273,7 +1276,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(switch_core_sessio switch_status_t status; switch_dtmf_t new_dtmf; int fed = 0; - + if (switch_channel_down(session->channel)) { return SWITCH_STATUS_FALSE; } @@ -1295,10 +1298,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_recv_dtmf(switch_core_sessio } if (!switch_test_flag(dtmf, DTMF_FLAG_SKIP_PROCESS)) { - if (session->dmachine && switch_ivr_dmachine_get_target(session->dmachine) == DIGIT_TARGET_SELF && - !switch_channel_test_flag(session->channel, CF_BROADCAST)) { + if (session->dmachine[0] && !switch_channel_test_flag(session->channel, CF_BROADCAST)) { char str[2] = { dtmf->digit, '\0' }; - switch_ivr_dmachine_feed(session->dmachine, str, NULL); + switch_ivr_dmachine_feed(session->dmachine[0], str, NULL); fed = 1; } @@ -1346,10 +1348,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_sessio } if (!switch_test_flag(dtmf, DTMF_FLAG_SKIP_PROCESS)) { - if (session->dmachine && switch_ivr_dmachine_get_target(session->dmachine) == DIGIT_TARGET_PEER && - !switch_channel_test_flag(session->channel, CF_BROADCAST)) { + if (session->dmachine[1] && !switch_channel_test_flag(session->channel, CF_BROADCAST)) { char str[2] = { new_dtmf.digit, '\0' }; - switch_ivr_dmachine_feed(session->dmachine, str, NULL); + switch_ivr_dmachine_feed(session->dmachine[1], str, NULL); return SWITCH_STATUS_SUCCESS; } } diff --git a/src/switch_core_session.c b/src/switch_core_session.c index 0cc52262f1..b3f6d15eb8 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -38,14 +38,25 @@ struct switch_session_manager session_manager; -SWITCH_DECLARE(void) switch_core_session_set_dmachine(switch_core_session_t *session, switch_ivr_dmachine_t *dmachine) +SWITCH_DECLARE(void) switch_core_session_set_dmachine(switch_core_session_t *session, switch_ivr_dmachine_t *dmachine, switch_digit_action_target_t target) { - session->dmachine = dmachine; + int i = (int) target; + + if (i == 0 || i == 1) { + switch_ivr_dmachine_set_target(dmachine, target); + session->dmachine[i] = dmachine; + } } -SWITCH_DECLARE(switch_ivr_dmachine_t *) switch_core_session_get_dmachine(switch_core_session_t *session) +SWITCH_DECLARE(switch_ivr_dmachine_t *) switch_core_session_get_dmachine(switch_core_session_t *session, switch_digit_action_target_t target) { - return session->dmachine; + int i = (int) target; + + if (i == 0 || i == 1) { + return session->dmachine[i]; + } + + return NULL; } SWITCH_DECLARE(void) switch_core_session_soft_lock(switch_core_session_t *session, uint32_t sec) @@ -1179,7 +1190,7 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t * switch_memory_pool_t *pool; switch_event_t *event; switch_endpoint_interface_t *endpoint_interface = (*session)->endpoint_interface; - + int i; switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, func, line, switch_core_session_get_uuid(*session), SWITCH_LOG_NOTICE, "Close Channel %s [%s]\n", switch_channel_get_name((*session)->channel), switch_channel_state_name(switch_channel_get_state((*session)->channel))); @@ -1216,8 +1227,10 @@ SWITCH_DECLARE(void) switch_core_session_perform_destroy(switch_core_session_t * switch_ivr_clear_speech_cache(*session); switch_channel_uninit((*session)->channel); - if ((*session)->dmachine) { - switch_ivr_dmachine_destroy(&(*session)->dmachine); + for (i = 0; i < 2; i++) { + if ((*session)->dmachine[i]) { + switch_ivr_dmachine_destroy(&(*session)->dmachine[i]); + } } pool = (*session)->pool; diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index fe8d9ddb1b..c99d332c7f 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -72,6 +72,7 @@ struct switch_ivr_dmachine { dm_binding_head_t *realm; switch_ivr_dmachine_binding_t *last_matching_binding; void *user_data; + switch_mutex_t *mutex; }; @@ -124,6 +125,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_create(switch_ivr_dmachine_t dmachine->input_timeout_ms = input_timeout_ms; dmachine->match.dmachine = dmachine; dmachine->name = switch_core_strdup(dmachine->pool, name); + switch_mutex_init(&dmachine->mutex, SWITCH_MUTEX_NESTED, dmachine->pool); switch_core_hash_init(&dmachine->binding_hash, dmachine->pool); @@ -374,7 +376,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t * dm_match_t is_match = switch_ivr_dmachine_check_match(dmachine, is_timeout); switch_status_t r, s; int clear = 0; - + + switch_mutex_lock(dmachine->mutex); + if (zstr(dmachine->digits) && !is_timeout) { r = SWITCH_STATUS_SUCCESS; } else if (dmachine->cur_digit_len > dmachine->max_digit_len) { @@ -465,6 +469,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_ping(switch_ivr_dmachine_t * switch_ivr_dmachine_clear(dmachine); } + switch_mutex_unlock(dmachine->mutex); + return r; } @@ -474,10 +480,12 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_dmachine_feed(switch_ivr_dmachine_t * return SWITCH_STATUS_FALSE; } + switch_mutex_lock(dmachine->mutex); strncat(dmachine->digits, digits, dmachine->max_digit_len); + switch_mutex_unlock(dmachine->mutex); dmachine->cur_digit_len = strlen(dmachine->digits); dmachine->last_digit_time = switch_time_now(); - + return switch_ivr_dmachine_ping(dmachine, match); } diff --git a/src/switch_ivr_bridge.c b/src/switch_ivr_bridge.c index fb8b89096d..e458fe0390 100644 --- a/src/switch_ivr_bridge.c +++ b/src/switch_ivr_bridge.c @@ -897,7 +897,7 @@ static switch_status_t signal_bridge_on_hibernate(switch_core_session_t *session const char *key; switch_core_session_message_t msg = { 0 }; switch_event_t *event = NULL; - switch_ivr_dmachine_t *dmachine; + switch_ivr_dmachine_t *dmachine[2] = { 0 }; channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); @@ -927,18 +927,24 @@ static switch_status_t signal_bridge_on_hibernate(switch_core_session_t *session } } - if ((dmachine = switch_core_session_get_dmachine(session))) { + if ((dmachine[0] = switch_core_session_get_dmachine(session, DIGIT_TARGET_SELF)) || + (dmachine[1] = switch_core_session_get_dmachine(session, DIGIT_TARGET_PEER))) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s not hibernating due to active digit parser, semi-hibernation engaged.\n", switch_channel_get_name(channel)); while(switch_channel_ready(channel) && switch_channel_get_state(channel) == CS_HIBERNATE) { if (!switch_channel_test_flag(channel, CF_BROADCAST)) { - switch_ivr_dmachine_ping(dmachine, NULL); + if (dmachine[0]) { + switch_ivr_dmachine_ping(dmachine[0], NULL); + } + if (dmachine[1]) { + switch_ivr_dmachine_ping(dmachine[1], NULL); + } } switch_yield(20000); } } - + return SWITCH_STATUS_SUCCESS; } From f20b605dfcca11b6f2ff0c82ce306f8612b4d8c6 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 2 Sep 2011 09:50:24 -0500 Subject: [PATCH 021/204] typo --- src/mod/applications/mod_dptools/mod_dptools.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 5e9dc13ef6..ea6e5ca2a4 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -242,7 +242,7 @@ SWITCH_STANDARD_APP(clear_digit_action_function) char *target_str; switch_digit_action_target_t target = DIGIT_TARGET_SELF; - if ((target_str = strchr(realm, ' '))) { + if ((target_str = strchr(realm, ','))) { *target_str++ = '\0'; target = str2target(target_str); } @@ -266,7 +266,7 @@ SWITCH_STANDARD_APP(digit_action_set_realm_function) char *target_str; switch_digit_action_target_t target = DIGIT_TARGET_SELF; - if ((target_str = strchr(realm, ' '))) { + if ((target_str = strchr(realm, ','))) { *target_str++ = '\0'; target = str2target(target_str); } @@ -275,6 +275,7 @@ SWITCH_STANDARD_APP(digit_action_set_realm_function) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Syntax Error, USAGE %s\n", DIGIT_ACTION_SET_REALM_USAGE); return; } + if ((dmachine = switch_core_session_get_dmachine(session, target))) { switch_ivr_dmachine_set_realm(dmachine, realm); From 798651b8f2afe03d0e090cf9fa81442cdcfab8e2 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 2 Sep 2011 10:12:14 -0500 Subject: [PATCH 022/204] update doc --- src/mod/applications/mod_dptools/mod_dptools.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index ea6e5ca2a4..40a68ec471 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -325,7 +325,7 @@ static void bind_to_session(switch_core_session_t *session, switch_ivr_dmachine_bind(dmachine, act->realm, act->input, 0, digit_action_callback, act); } -#define BIND_DIGIT_ACTION_USAGE ",,,[,][,]" +#define BIND_DIGIT_ACTION_USAGE ",,,[,][,]" SWITCH_STANDARD_APP(bind_digit_action_function) { From 6d76dda7f57a31db2d05461cc74885c755ea1c46 Mon Sep 17 00:00:00 2001 From: Brian West Date: Fri, 2 Sep 2011 21:03:21 -0500 Subject: [PATCH 023/204] swigall --- .../languages/mod_managed/freeswitch_wrap.cxx | 40 ++++++++++++--- src/mod/languages/mod_managed/managed/swig.cs | 50 +++++++++++++++---- 2 files changed, 75 insertions(+), 15 deletions(-) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index 29879a96bd..a6ec671a52 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -7662,28 +7662,54 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_session_soft_unlock(void * jarg1) } -SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_session_set_dmachine(void * jarg1, void * jarg2) { +SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_session_set_dmachine(void * jarg1, void * jarg2, int jarg3) { switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; switch_ivr_dmachine_t *arg2 = (switch_ivr_dmachine_t *) 0 ; + switch_digit_action_target_t arg3 ; arg1 = (switch_core_session_t *)jarg1; arg2 = (switch_ivr_dmachine_t *)jarg2; - switch_core_session_set_dmachine(arg1,arg2); + arg3 = (switch_digit_action_target_t)jarg3; + switch_core_session_set_dmachine(arg1,arg2,arg3); } -SWIGEXPORT void * SWIGSTDCALL CSharp_switch_core_session_get_dmachine(void * jarg1) { +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_core_session_get_dmachine(void * jarg1, int jarg2) { void * jresult ; switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_digit_action_target_t arg2 ; switch_ivr_dmachine_t *result = 0 ; arg1 = (switch_core_session_t *)jarg1; - result = (switch_ivr_dmachine_t *)switch_core_session_get_dmachine(arg1); + arg2 = (switch_digit_action_target_t)jarg2; + result = (switch_ivr_dmachine_t *)switch_core_session_get_dmachine(arg1,arg2); jresult = (void *)result; return jresult; } +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_dmachine_get_target(void * jarg1) { + int jresult ; + switch_ivr_dmachine_t *arg1 = (switch_ivr_dmachine_t *) 0 ; + switch_digit_action_target_t result; + + arg1 = (switch_ivr_dmachine_t *)jarg1; + result = (switch_digit_action_target_t)switch_ivr_dmachine_get_target(arg1); + jresult = result; + return jresult; +} + + +SWIGEXPORT void SWIGSTDCALL CSharp_switch_ivr_dmachine_set_target(void * jarg1, int jarg2) { + switch_ivr_dmachine_t *arg1 = (switch_ivr_dmachine_t *) 0 ; + switch_digit_action_target_t arg2 ; + + arg1 = (switch_ivr_dmachine_t *)jarg1; + arg2 = (switch_digit_action_target_t)jarg2; + switch_ivr_dmachine_set_target(arg1,arg2); +} + + SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_session_set_codec_slin(void * jarg1, void * jarg2) { int jresult ; switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; @@ -28448,7 +28474,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_originate(void * jarg1, void * jarg } -SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_enterprise_originate(void * jarg1, void * jarg2, void * jarg3, char * jarg4, unsigned long jarg5, void * jarg6, char * jarg7, char * jarg8, void * jarg9, void * jarg10, unsigned long jarg11) { +SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_enterprise_originate(void * jarg1, void * jarg2, void * jarg3, char * jarg4, unsigned long jarg5, void * jarg6, char * jarg7, char * jarg8, void * jarg9, void * jarg10, unsigned long jarg11, void * jarg12) { int jresult ; switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; switch_core_session_t **arg2 = (switch_core_session_t **) 0 ; @@ -28461,6 +28487,7 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_enterprise_originate(void * jarg1, switch_caller_profile_t *arg9 = (switch_caller_profile_t *) 0 ; switch_event_t *arg10 = (switch_event_t *) 0 ; switch_originate_flag_t arg11 ; + switch_call_cause_t *arg12 = (switch_call_cause_t *) 0 ; switch_status_t result; arg1 = (switch_core_session_t *)jarg1; @@ -28474,7 +28501,8 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_ivr_enterprise_originate(void * jarg1, arg9 = (switch_caller_profile_t *)jarg9; arg10 = (switch_event_t *)jarg10; arg11 = (switch_originate_flag_t)jarg11; - result = (switch_status_t)switch_ivr_enterprise_originate(arg1,arg2,arg3,(char const *)arg4,arg5,(switch_state_handler_table const *)arg6,(char const *)arg7,(char const *)arg8,arg9,arg10,arg11); + arg12 = (switch_call_cause_t *)jarg12; + result = (switch_status_t)switch_ivr_enterprise_originate(arg1,arg2,arg3,(char const *)arg4,arg5,(switch_state_handler_table const *)arg6,(char const *)arg7,(char const *)arg8,arg9,arg10,arg11,arg12); jresult = result; return jresult; } diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index 9f6e7a9fd9..e782107007 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -1376,16 +1376,25 @@ public class freeswitch { freeswitchPINVOKE.switch_core_session_soft_unlock(SWIGTYPE_p_switch_core_session.getCPtr(session)); } - public static void switch_core_session_set_dmachine(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_switch_ivr_dmachine dmachine) { - freeswitchPINVOKE.switch_core_session_set_dmachine(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_switch_ivr_dmachine.getCPtr(dmachine)); + public static void switch_core_session_set_dmachine(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_switch_ivr_dmachine dmachine, switch_digit_action_target_t target) { + freeswitchPINVOKE.switch_core_session_set_dmachine(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_switch_ivr_dmachine.getCPtr(dmachine), (int)target); } - public static SWIGTYPE_p_switch_ivr_dmachine switch_core_session_get_dmachine(SWIGTYPE_p_switch_core_session session) { - IntPtr cPtr = freeswitchPINVOKE.switch_core_session_get_dmachine(SWIGTYPE_p_switch_core_session.getCPtr(session)); + public static SWIGTYPE_p_switch_ivr_dmachine switch_core_session_get_dmachine(SWIGTYPE_p_switch_core_session session, switch_digit_action_target_t target) { + IntPtr cPtr = freeswitchPINVOKE.switch_core_session_get_dmachine(SWIGTYPE_p_switch_core_session.getCPtr(session), (int)target); SWIGTYPE_p_switch_ivr_dmachine ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_switch_ivr_dmachine(cPtr, false); return ret; } + public static switch_digit_action_target_t switch_ivr_dmachine_get_target(SWIGTYPE_p_switch_ivr_dmachine dmachine) { + switch_digit_action_target_t ret = (switch_digit_action_target_t)freeswitchPINVOKE.switch_ivr_dmachine_get_target(SWIGTYPE_p_switch_ivr_dmachine.getCPtr(dmachine)); + return ret; + } + + public static void switch_ivr_dmachine_set_target(SWIGTYPE_p_switch_ivr_dmachine dmachine, switch_digit_action_target_t target) { + freeswitchPINVOKE.switch_ivr_dmachine_set_target(SWIGTYPE_p_switch_ivr_dmachine.getCPtr(dmachine), (int)target); + } + public static switch_status_t switch_core_session_set_codec_slin(SWIGTYPE_p_switch_core_session session, switch_slin_data data) { switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_session_set_codec_slin(SWIGTYPE_p_switch_core_session.getCPtr(session), switch_slin_data.getCPtr(data)); return ret; @@ -4445,8 +4454,8 @@ public class freeswitch { return ret; } - public static switch_status_t switch_ivr_enterprise_originate(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_p_switch_core_session bleg, SWIGTYPE_p_switch_call_cause_t cause, string bridgeto, uint timelimit_sec, switch_state_handler_table table, string cid_name_override, string cid_num_override, switch_caller_profile caller_profile_override, switch_event ovars, uint flags) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_enterprise_originate(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_p_switch_core_session.getCPtr(bleg), SWIGTYPE_p_switch_call_cause_t.getCPtr(cause), bridgeto, timelimit_sec, switch_state_handler_table.getCPtr(table), cid_name_override, cid_num_override, switch_caller_profile.getCPtr(caller_profile_override), switch_event.getCPtr(ovars), flags); + public static switch_status_t switch_ivr_enterprise_originate(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_p_switch_core_session bleg, SWIGTYPE_p_switch_call_cause_t cause, string bridgeto, uint timelimit_sec, switch_state_handler_table table, string cid_name_override, string cid_num_override, switch_caller_profile caller_profile_override, switch_event ovars, uint flags, SWIGTYPE_p_switch_call_cause_t cancel_cause) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_ivr_enterprise_originate(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_p_switch_core_session.getCPtr(bleg), SWIGTYPE_p_switch_call_cause_t.getCPtr(cause), bridgeto, timelimit_sec, switch_state_handler_table.getCPtr(table), cid_name_override, cid_num_override, switch_caller_profile.getCPtr(caller_profile_override), switch_event.getCPtr(ovars), flags, SWIGTYPE_p_switch_call_cause_t.getCPtr(cancel_cause)); return ret; } @@ -7874,10 +7883,16 @@ class freeswitchPINVOKE { public static extern void switch_core_session_soft_unlock(HandleRef jarg1); [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_set_dmachine")] - public static extern void switch_core_session_set_dmachine(HandleRef jarg1, HandleRef jarg2); + public static extern void switch_core_session_set_dmachine(HandleRef jarg1, HandleRef jarg2, int jarg3); [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_get_dmachine")] - public static extern IntPtr switch_core_session_get_dmachine(HandleRef jarg1); + public static extern IntPtr switch_core_session_get_dmachine(HandleRef jarg1, int jarg2); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_dmachine_get_target")] + public static extern int switch_ivr_dmachine_get_target(HandleRef jarg1); + + [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_dmachine_set_target")] + public static extern void switch_ivr_dmachine_set_target(HandleRef jarg1, int jarg2); [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_set_codec_slin")] public static extern int switch_core_session_set_codec_slin(HandleRef jarg1, HandleRef jarg2); @@ -12731,7 +12746,7 @@ class freeswitchPINVOKE { public static extern int switch_ivr_originate(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, string jarg4, uint jarg5, HandleRef jarg6, string jarg7, string jarg8, HandleRef jarg9, HandleRef jarg10, uint jarg11, HandleRef jarg12); [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_enterprise_originate")] - public static extern int switch_ivr_enterprise_originate(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, string jarg4, uint jarg5, HandleRef jarg6, string jarg7, string jarg8, HandleRef jarg9, HandleRef jarg10, uint jarg11); + public static extern int switch_ivr_enterprise_originate(HandleRef jarg1, HandleRef jarg2, HandleRef jarg3, string jarg4, uint jarg5, HandleRef jarg6, string jarg7, string jarg8, HandleRef jarg9, HandleRef jarg10, uint jarg11, HandleRef jarg12); [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_bridge_display")] public static extern void switch_ivr_bridge_display(HandleRef jarg1, HandleRef jarg2); @@ -24463,6 +24478,23 @@ public class switch_dialplan_interface : IDisposable { namespace FreeSWITCH.Native { +public enum switch_digit_action_target_t { + DIGIT_TARGET_SELF, + DIGIT_TARGET_PEER, + DIGIT_TARGET_BOTH +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 1.3.35 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + using System; using System.Runtime.InteropServices; From d0308aaea26128fca2d74177949ce6a57687ed4e Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Fri, 2 Sep 2011 22:46:09 +0200 Subject: [PATCH 024/204] [SDK] Clean up symbol visibility flags and compiler vendor handling Signed-off-by: Stefan Knoblich --- src/mod/sdk/autotools/configure.ac | 82 ++++++++++++--------------- src/mod/sdk/autotools/src/Makefile.am | 28 ++++----- 2 files changed, 46 insertions(+), 64 deletions(-) diff --git a/src/mod/sdk/autotools/configure.ac b/src/mod/sdk/autotools/configure.ac index d4f29f492b..54fe529d9a 100644 --- a/src/mod/sdk/autotools/configure.ac +++ b/src/mod/sdk/autotools/configure.ac @@ -22,35 +22,42 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) # Checks for programs. AC_PROG_CC AM_PROG_CC_C_O +AC_PROG_CC_C99 AC_PROG_LIBTOOL # pkgconfig AC_PATH_PROG([PKG_CONFIG], [pkg-config], ["no"]) -if test "x${PKG_CONFIG}" = "xno" -then - AC_MSG_ERROR([Cannot find pkg-config, make sure it is installed in your PATH]) -fi +AS_IF([test "x${PKG_CONFIG}" = "xno"], + [AC_MSG_ERROR([Cannot find pkg-config, make sure it is installed in your PATH])] +) PKG_PROG_PKG_CONFIG -# Checks for cflags + +## +## Checks for cflags +## AC_MSG_RESULT([${as_nl}<<>> Compiler vendor and features]) +AX_COMPILER_VENDOR + +AM_CONDITIONAL([CC_VENDOR_GNU], [test "x${ax_cv_c_compiler_vendor}" = "xgnu"]) +AM_CONDITIONAL([CC_VENDOR_SUN], [test "x${ax_cv_c_compiler_vendor}" = "xsun"]) + + ## ## Compiler vendor and flag checks ## HAVE_VISIBILITY="no" + AC_ARG_ENABLE([visibility], [AS_HELP_STRING([--disable-visibility], [Disable symbol visibility support (default: enabled, if available)])], [case "${enableval}" in - yes) enable_visibility="yes" ;; - no) enable_visibility="no" ;; - *) AC_MSG_ERROR([Invalid value ${enableval} for parameter --disable-visibility]) ;; + yes|no) enable_visibility="${enableval}" ;; + *) AC_MSG_ERROR([Invalid value ${enableval} for parameter --disable-visibility]) ;; esac], [enable_visibility="yes"] ) -AX_COMPILER_VENDOR - case "${ax_cv_c_compiler_vendor}" in gnu) AC_MSG_CHECKING([whether the compiler supports -fvisibility=hidden]) @@ -63,36 +70,16 @@ gnu) [;] )], - [AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_VISIBILITY],[1],[GCC visibility support]) - HAVE_VISIBILITY="yes"], - - [AC_MSG_RESULT([no]) - HAVE_VISIBILITY="no"] + [HAVE_VISIBILITY="yes" + AC_DEFINE([HAVE_VISIBILITY], [1], [Symbol visibility support]) + AC_SUBST([VISIBILITY_CFLAGS], [-fvisibility=hidden]) + AC_SUBST([VISIBILITY_CXXFLAGS], [-fvisibility=hidden])], + [HAVE_VISIBILITY="no"] ) + AC_MSG_RESULT([${HAVE_VISIBILITY}]) CFLAGS="${save_CFLAGS}"], [AC_MSG_RESULT([disabled by user])] ) - - AS_IF([test "x${HAVE_VISIBILITY}" != "xno"], - [save_CFLAGS="${CFLAGS}" - CFLAGS="${CFLAGS} -fvisibility-inlines-hidden" - AC_MSG_CHECKING([whether the compiler supports -fvisibility-inlines-hidden]) - AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [;], [;] - )], - - [AC_MSG_RESULT([yes]) - HAVE_VISIBILITY_INLINES_HIDDEN="yes"], - - [AC_MSG_RESULT([no]) - HAVE_VISIBILITY_INLINES_HIDDEN="no"] - ) - CFLAGS="${save_CFLAGS}"], - [:] - ) - AC_DEFINE([COMPILER_GCC], [1], [Compiler is GCC]) ;; sun) AC_MSG_CHECKING([whether the compiler supports -xldscope=hidden]) @@ -105,28 +92,24 @@ sun) [;] )], - [AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_VISIBILITY],[1],[SUNCC visibility support]) - HAVE_VISIBILITY="yes"], - - [AC_MSG_RESULT([no]) - HAVE_VISIBILITY="no"] + [HAVE_VISIBILITY="yes" + AC_DEFINE([HAVE_VISIBILITY], [1], [Symbol visibility support]) + AC_SUBST([VISIBILITY_CFLAGS], [-xldscope=hidden]) + AC_SUBST([VISIBILITY_CXXFLAGS], [-xldscope=hidden])], + [HAVE_VISIBILITY="no"] ) + AC_MSG_RESULT([${HAVE_VISIBILITY}]) CFLAGS="${save_CFLAGS}"], [AC_MSG_RESULT([disabled by user])] ) - AC_DEFINE([COMPILER_SUNCC], [1], [Compiler is SunCC]) ;; *) AC_MSG_WARN([No visibility checks for this compiler defined]) ;; esac -AM_CONDITIONAL([COMPILER_GCC], [test "x${ax_cv_c_compiler_vendor}" = "xgnu"]) -AM_CONDITIONAL([COMPILER_SUNCC], [test "x${ax_cv_c_compiler_vendor}" = "xsun"]) +AM_CONDITIONAL([CC_HAS_VISIBILITY], [test "x${HAVE_VISIBILITY}" = "xyes"]) -AM_CONDITIONAL([HAVE_VISIBILITY], [test "x${HAVE_VISIBILITY}" = "xyes"]) -AM_CONDITIONAL([HAVE_VISIBILITY_INLINES_HIDDEN], [test "x${HAVE_VISIBILITY_INLINES_HIDDEN}" = "xyes"]) ## ## pkgconfig based freeswitch detection code @@ -210,6 +193,7 @@ PKG_CHECK_MODULES([freeswitch], [freeswitch], [AC_MSG_ERROR([FreeSWITCH not found])] ) + ## ## Add your other dependency checks here ## @@ -221,6 +205,10 @@ AC_MSG_RESULT([${as_nl}<<>> Other dependencies]) # Checks for library functions. + +## +## Done, create output files and print summary +## AC_MSG_RESULT([${as_nl}<<>> Create output files]) AC_CONFIG_FILES([Makefile src/Makefile]) AC_OUTPUT diff --git a/src/mod/sdk/autotools/src/Makefile.am b/src/mod/sdk/autotools/src/Makefile.am index d2bad5bc80..a8a95b8d15 100644 --- a/src/mod/sdk/autotools/src/Makefile.am +++ b/src/mod/sdk/autotools/src/Makefile.am @@ -10,32 +10,26 @@ AM_CPPFLAGS= -I. -I$(includedir) AM_LDFLAGS = -L. -L$(libdir) -avoid-version -module -no-undefined -shared ### -# GCC specific flags +# GCC (and compatible) specific flags # -if COMPILER_GCC +if CC_VENDOR_GNU AM_CFLAGS += -Wall -# symbol visibility support -if HAVE_VISIBILITY -AM_CFLAGS += -fvisibility=hidden -AM_CXXFLAGS+= -fvisibility=hidden -AM_CPPFLAGS+= -DSWITCH_API_VISIBILITY=1 -endif -if HAVE_VISIBILITY_INLINES_HIDDEN -AM_CXXFLAGS += -fvisibility-inlines-hidden -endif endif ### # SunCC specific flags # -if COMPILER_SUNCC +if CC_VENDOR_SUN AM_CFLAGS += -# symbol visibility support -if HAVE_VISIBILITY -AM_CFLAGS += -xldscope=hidden -AM_CXXFLAGS += -xldscope=hidden -AM_CPPFLAGS += -DSWITCH_API_VISIBILITY=1 endif + +### +# symbol visibility support +# +if CC_HAS_VISIBILITY +AM_CFLAGS += $(VISIBILITY_CFLAGS) +AM_CXXFLAGS += $(VISIBILITY_CXXFLAGS) +AM_CPPFLAGS += -DSWITCH_API_VISIBILITY=1 endif From 6dd1264d0896b00078415a078265d2af0e62a116 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 2 Sep 2011 14:41:20 -0500 Subject: [PATCH 025/204] add support for global nameseace in chat interface to bind to unhandled messages --- .../endpoints/mod_dingaling/mod_dingaling.c | 9 ++++- src/mod/endpoints/mod_sofia/sofia_presence.c | 17 ++++++-- src/switch_core.c | 18 --------- src/switch_loadable_module.c | 40 +++++++++++++++++++ 4 files changed, 61 insertions(+), 23 deletions(-) diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index 77dab2d092..a0b9e7da28 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -2876,6 +2876,8 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi char *proto = MDL_CHAT_PROTO; char *pproto = NULL, *ffrom = NULL; char *hint; + int got_proto = 0; + #ifdef AUTO_REPLY if (profile->auto_reply) { ldl_handle_send_msg(handle, @@ -2890,6 +2892,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi *to++ = '\0'; } proto = pproto; + got_proto++; } hint = from; @@ -2902,10 +2905,14 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi from = ffrom; } - if (strcasecmp(proto, MDL_CHAT_PROTO)) { /* yes no ! on purpose */ + if (strcasecmp(proto, MDL_CHAT_PROTO)) { /* yes no ! on purpose */ switch_core_chat_send(proto, MDL_CHAT_PROTO, from, to, subject, switch_str_nil(msg), NULL, hint); } + if (!got_proto) { + switch_core_chat_send("GLOBAL", MDL_CHAT_PROTO, from, to, subject, switch_str_nil(msg), NULL, hint); + } + switch_safe_free(pproto); switch_safe_free(ffrom); } diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 0b57a52a4e..33154e73ec 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -131,7 +131,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co if (!prof || !(profile = sofia_glue_find_profile(prof))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, - "Chat proto [%s]\nfrom [%s]\nto [%s]\n%s\nInvalid Profile %s\n", proto, from, to, + "Chat proto [%s]\nfrom [%s]\nto [%s]\n%s\nInvalid Profile %s\n", proto, from, to, body ? body : "[no body]", prof ? prof : "NULL"); goto end; } @@ -233,7 +233,7 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co } /* if this cries, add contact here too, change the 1 to 0 and omit the safe_free */ - + msg_nh = nua_handle(profile->nua, NULL, TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), @@ -2891,6 +2891,7 @@ void sofia_presence_handle_sip_i_message(int status, char *p; char *full_from; char proto[512] = SOFIA_CHAT_PROTO; + int got_proto = 0; full_from = sip_header_as_string(nh->nh_home, (void *) sip->sip_from); @@ -2904,11 +2905,12 @@ void sofia_presence_handle_sip_i_message(int status, *p = '@'; } } + got_proto++; } else { to_addr = switch_mprintf("%s@%s", to_user, to_host); } - from_addr = switch_mprintf("%s@%s", from_user, from_host); + from_addr = switch_mprintf("%s/%s@%s", profile->name, from_user, from_host); if (sofia_test_pflag(profile, PFLAG_IN_DIALOG_CHAT)) { sofia_presence_set_hash_key(hash_key, sizeof(hash_key), sip); @@ -2932,8 +2934,15 @@ void sofia_presence_handle_sip_i_message(int status, } } } else { - switch_core_chat_send(proto, SOFIA_CHAT_PROTO, from_addr, to_addr, "", msg, NULL, full_from); + if (strcasecmp(proto, SOFIA_CHAT_PROTO)) { + switch_core_chat_send(proto, SOFIA_CHAT_PROTO, from_addr, to_addr, "", msg, NULL, full_from); + } } + + if (!got_proto) { + switch_core_chat_send("GLOBAL", SOFIA_CHAT_PROTO, from_addr, to_addr, "", msg, NULL, full_from); + } + switch_safe_free(to_addr); switch_safe_free(from_addr); if (full_from) { diff --git a/src/switch_core.c b/src/switch_core.c index af14d5b03c..e9e5b3871c 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -2191,24 +2191,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_destroy(void) return switch_test_flag((&runtime), SCF_RESTART) ? SWITCH_STATUS_RESTART : SWITCH_STATUS_SUCCESS; } -SWITCH_DECLARE(switch_status_t) switch_core_chat_send(const char *name, const char *proto, const char *from, const char *to, - const char *subject, const char *body, const char *type, const char *hint) -{ - switch_chat_interface_t *ci; - switch_status_t status; - - if (!name || !(ci = switch_loadable_module_get_chat_interface(name)) || !ci->chat_send) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid Chat Interface [%s]!\n", name); - return SWITCH_STATUS_FALSE; - } - - status = ci->chat_send(proto, from, to, subject, body, type, hint); - - UNPROTECT_INTERFACE(ci); - - return status; -} - SWITCH_DECLARE(switch_status_t) switch_core_management_exec(char *relative_oid, switch_management_action_t action, char *data, switch_size_t datalen) { const switch_management_interface_t *ptr; diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c index 007309781e..4e663df6e0 100644 --- a/src/switch_loadable_module.c +++ b/src/switch_loadable_module.c @@ -468,6 +468,46 @@ static switch_status_t switch_loadable_module_process(char *key, switch_loadable } +SWITCH_DECLARE(switch_status_t) switch_core_chat_send(const char *name, const char *proto, const char *from, const char *to, + const char *subject, const char *body, const char *type, const char *hint) +{ + switch_chat_interface_t *ci; + switch_status_t status = SWITCH_STATUS_FALSE; + switch_hash_index_t *hi; + const void *var; + void *val; + + if (!name) { + return SWITCH_STATUS_FALSE; + } + + if (!strcasecmp(name, "GLOBAL")) { + switch_mutex_lock(loadable_modules.mutex); + for (hi = switch_hash_first(NULL, loadable_modules.chat_hash); hi; hi = switch_hash_next(hi)) { + switch_hash_this(hi, &var, NULL, &val); + + if ((ci = (switch_chat_interface_t *) val)) { + if (ci->chat_send && !strncasecmp(ci->interface_name, "GLOBAL_", 7)) { + if ((status = ci->chat_send(proto, from, to, subject, body, type, hint)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Chat Interface Error [%s]!\n", name); + break; + } + } + } + } + switch_mutex_unlock(loadable_modules.mutex); + } else { + if (!(ci = switch_loadable_module_get_chat_interface(name)) || !ci->chat_send) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid chat interface [%s]!\n", name); + return SWITCH_STATUS_FALSE; + } + status = ci->chat_send(proto, from, to, subject, body, type, hint); + UNPROTECT_INTERFACE(ci); + } + + return status; +} + static switch_status_t switch_loadable_module_unprocess(switch_loadable_module_t *old_module) { From fba22dc7e998377efe8842af90abacac56150de1 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 2 Sep 2011 16:59:59 -0500 Subject: [PATCH 026/204] don't parse signals in the set_running_state function to avoid livelock situation --- src/include/switch_channel.h | 4 ++++ src/switch_channel.c | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/include/switch_channel.h b/src/include/switch_channel.h index 5481a20c0a..d388777c33 100644 --- a/src/include/switch_channel.h +++ b/src/include/switch_channel.h @@ -87,6 +87,10 @@ SWITCH_DECLARE(int) switch_channel_test_ready(switch_channel_t *channel, switch_ #define switch_channel_up(_channel) (switch_channel_check_signal(_channel, SWITCH_TRUE) || switch_channel_get_state(_channel) < CS_HANGUP) #define switch_channel_down(_channel) (switch_channel_check_signal(_channel, SWITCH_TRUE) || switch_channel_get_state(_channel) >= CS_HANGUP) + +#define switch_channel_up_nosig(_channel) switch_channel_get_state(_channel) < CS_HANGUP +#define switch_channel_down_nosig(_channel) switch_channel_get_state(_channel) >= CS_HANGUP + #define switch_channel_media_ack(_channel) (!switch_channel_test_cap(_channel, CC_MEDIA_ACK) || switch_channel_test_flag(_channel, CF_MEDIA_ACK)) SWITCH_DECLARE(void) switch_channel_wait_for_state(switch_channel_t *channel, switch_channel_t *other_channel, switch_channel_state_t want_state); diff --git a/src/switch_channel.c b/src/switch_channel.c index 72bf651e29..5650b1ef3b 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -1860,7 +1860,7 @@ SWITCH_DECLARE(switch_channel_state_t) switch_channel_perform_set_running_state( switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND || switch_channel_test_flag(channel, CF_DIALPLAN) ? "true" : "false"); - if (switch_channel_down(channel)) { + if (switch_channel_down_nosig(channel)) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "hangup"); } else if (switch_channel_test_flag(channel, CF_ANSWERED)) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "answered"); @@ -2150,7 +2150,7 @@ SWITCH_DECLARE(void) switch_channel_event_set_basic_data(switch_channel_t *chann switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Channel-Call-UUID", switch_core_session_get_uuid(channel->session)); } - if (switch_channel_down(channel)) { + if (switch_channel_down_nosig(channel)) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "hangup"); } else if (switch_channel_test_flag(channel, CF_ANSWERED)) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Answer-State", "answered"); From a966c2b0ef7b35d26ccd54cdc6e28b8ae2c13322 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Sun, 4 Sep 2011 11:09:23 -0500 Subject: [PATCH 027/204] vs2010 reswig --- .../mod_managed/freeswitch_wrap.2010.cxx | 12 ++++++++---- .../languages/mod_managed/managed/swig.2010.cs | 15 ++++++++------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx index 687d3e9933..8c341715ef 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx @@ -7361,23 +7361,27 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_session_soft_unlock(void * jarg1) } -SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_session_set_dmachine(void * jarg1, void * jarg2) { +SWIGEXPORT void SWIGSTDCALL CSharp_switch_core_session_set_dmachine(void * jarg1, void * jarg2, int jarg3) { switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; switch_ivr_dmachine_t *arg2 = (switch_ivr_dmachine_t *) 0 ; + switch_digit_action_target_t arg3 ; arg1 = (switch_core_session_t *)jarg1; arg2 = (switch_ivr_dmachine_t *)jarg2; - switch_core_session_set_dmachine(arg1,arg2); + arg3 = (switch_digit_action_target_t)jarg3; + switch_core_session_set_dmachine(arg1,arg2,arg3); } -SWIGEXPORT void * SWIGSTDCALL CSharp_switch_core_session_get_dmachine(void * jarg1) { +SWIGEXPORT void * SWIGSTDCALL CSharp_switch_core_session_get_dmachine(void * jarg1, int jarg2) { void * jresult ; switch_core_session_t *arg1 = (switch_core_session_t *) 0 ; + switch_digit_action_target_t arg2 ; switch_ivr_dmachine_t *result = 0 ; arg1 = (switch_core_session_t *)jarg1; - result = (switch_ivr_dmachine_t *)switch_core_session_get_dmachine(arg1); + arg2 = (switch_digit_action_target_t)jarg2; + result = (switch_ivr_dmachine_t *)switch_core_session_get_dmachine(arg1,arg2); jresult = (void *)result; return jresult; } diff --git a/src/mod/languages/mod_managed/managed/swig.2010.cs b/src/mod/languages/mod_managed/managed/swig.2010.cs index f8d451bca6..62440a3970 100644 --- a/src/mod/languages/mod_managed/managed/swig.2010.cs +++ b/src/mod/languages/mod_managed/managed/swig.2010.cs @@ -1386,12 +1386,12 @@ public class freeswitch { freeswitchPINVOKE.switch_core_session_soft_unlock(SWIGTYPE_p_switch_core_session.getCPtr(session)); } - public static void switch_core_session_set_dmachine(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_switch_ivr_dmachine dmachine) { - freeswitchPINVOKE.switch_core_session_set_dmachine(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_switch_ivr_dmachine.getCPtr(dmachine)); + public static void switch_core_session_set_dmachine(SWIGTYPE_p_switch_core_session session, SWIGTYPE_p_switch_ivr_dmachine dmachine, switch_digit_action_target_t target) { + freeswitchPINVOKE.switch_core_session_set_dmachine(SWIGTYPE_p_switch_core_session.getCPtr(session), SWIGTYPE_p_switch_ivr_dmachine.getCPtr(dmachine), (int)target); } - public static SWIGTYPE_p_switch_ivr_dmachine switch_core_session_get_dmachine(SWIGTYPE_p_switch_core_session session) { - IntPtr cPtr = freeswitchPINVOKE.switch_core_session_get_dmachine(SWIGTYPE_p_switch_core_session.getCPtr(session)); + public static SWIGTYPE_p_switch_ivr_dmachine switch_core_session_get_dmachine(SWIGTYPE_p_switch_core_session session, switch_digit_action_target_t target) { + IntPtr cPtr = freeswitchPINVOKE.switch_core_session_get_dmachine(SWIGTYPE_p_switch_core_session.getCPtr(session), (int)target); SWIGTYPE_p_switch_ivr_dmachine ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_switch_ivr_dmachine(cPtr, false); return ret; } @@ -7897,10 +7897,10 @@ class freeswitchPINVOKE { public static extern void switch_core_session_soft_unlock(HandleRef jarg1); [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_set_dmachine")] - public static extern void switch_core_session_set_dmachine(HandleRef jarg1, HandleRef jarg2); + public static extern void switch_core_session_set_dmachine(HandleRef jarg1, HandleRef jarg2, int jarg3); [DllImport("mod_managed", EntryPoint="CSharp_switch_core_session_get_dmachine")] - public static extern IntPtr switch_core_session_get_dmachine(HandleRef jarg1); + public static extern IntPtr switch_core_session_get_dmachine(HandleRef jarg1, int jarg2); [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_dmachine_get_target")] public static extern int switch_ivr_dmachine_get_target(HandleRef jarg1); @@ -24562,7 +24562,8 @@ namespace FreeSWITCH.Native { public enum switch_digit_action_target_t { DIGIT_TARGET_SELF, - DIGIT_TARGET_PEER + DIGIT_TARGET_PEER, + DIGIT_TARGET_BOTH } } From 8974f9d62e0346cd0763c508378e740fc0f2ce70 Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Mon, 5 Sep 2011 17:34:25 +0200 Subject: [PATCH 028/204] mod_voicemail: use vm_email as notification address if vm_notify_email isn't set (that behavior was in voicemail_leave_main but not in deliver_vm) --- src/mod/applications/mod_voicemail/mod_voicemail.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index d21fb47ad8..691ede9ba0 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -2773,6 +2773,10 @@ static switch_status_t deliver_vm(vm_profile_t *profile, if (send_notify) { + if (zstr(vm_notify_email)) { + vm_notify_email = vm_email; + } + if (zstr(profile->notify_email_headers)) { headers = switch_mprintf("From: FreeSWITCH mod_voicemail <%s@%s>\n" "Subject: Voicemail from %s %s\nX-Priority: %d", myid, domain_name, caller_id_name, caller_id_number, priority); From 2da308c115d8278595f19746a088e1716484a0d4 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 5 Sep 2011 14:07:16 -0500 Subject: [PATCH 029/204] correct labor day holiday example --- conf/dialplan/default.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/dialplan/default.xml b/conf/dialplan/default.xml index 36f0e52a2e..020507912c 100644 --- a/conf/dialplan/default.xml +++ b/conf/dialplan/default.xml @@ -70,8 +70,8 @@ - - + + From 40990c044c7ce49c9bbfdcd2676163596dfee65c Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 5 Sep 2011 14:40:49 -0500 Subject: [PATCH 030/204] FS-3527 --resolve Syntax Error when using MSSQL in core --- src/switch_core_sqldb.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index db2cf72c15..f85f4b3d8c 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -1640,6 +1640,7 @@ static char create_registrations_sql[] = " reg_user VARCHAR(256),\n" " realm VARCHAR(256),\n" " token VARCHAR(256),\n" +/* If url is modified please check for code in switch_core_sqldb_start for dependencies for MSSQL" */ " url TEXT,\n" " expires INTEGER,\n" " network_ip VARCHAR(256),\n" @@ -1942,17 +1943,18 @@ switch_status_t switch_core_sqldb_start(switch_memory_pool_t *pool, switch_bool_ switch_cache_db_test_reactive(dbh, "select call_uuid, read_bit_rate, sent_callee_name from channels", "DROP TABLE channels", create_channels_sql); switch_cache_db_test_reactive(dbh, "select * from detailed_calls where sent_callee_name=''", "DROP VIEW detailed_calls", detailed_calls_sql); switch_cache_db_test_reactive(dbh, "select * from basic_calls where sent_callee_name=''", "DROP VIEW basic_calls", basic_calls_sql); + switch_cache_db_test_reactive(dbh, "select call_uuid from calls", "DROP TABLE calls", create_calls_sql); if (runtime.odbc_dbtype == DBTYPE_DEFAULT) { - switch_cache_db_test_reactive(dbh, "select call_uuid from calls", "DROP TABLE calls", create_calls_sql); + switch_cache_db_test_reactive(dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", + "DROP TABLE registrations", create_registrations_sql); } else { - char *tmp = switch_string_replace(create_calls_sql, "function", "call_function"); - switch_cache_db_test_reactive(dbh, "select call_uuid from calls", "DROP TABLE calls", tmp); + char *tmp = switch_string_replace(create_registrations_sql, "url TEXT", "url VARCHAR(max)"); + switch_cache_db_test_reactive(dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", + "DROP TABLE registrations", tmp); free(tmp); } switch_cache_db_test_reactive(dbh, "select ikey from interfaces", "DROP TABLE interfaces", create_interfaces_sql); switch_cache_db_test_reactive(dbh, "select hostname from tasks", "DROP TABLE tasks", create_tasks_sql); - switch_cache_db_test_reactive(dbh, "delete from registrations where reg_user='' or network_proto='tcp' or network_proto='tls'", - "DROP TABLE registrations", create_registrations_sql); if (runtime.odbc_dbtype == DBTYPE_DEFAULT) { switch_cache_db_execute_sql(dbh, "begin;delete from channels where hostname='';delete from channels where hostname='';commit;", &err); From 698a50298a93ccac19ec402dfbec995ebf9fbfa2 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Tue, 6 Sep 2011 11:51:29 -0500 Subject: [PATCH 031/204] Revert "FS-3080 --resolve only allow when not playing message" This reverts commit d2daa44d8cfeb65277d61f9f8070f72d748051fe. Working on a better fix --- src/mod/applications/mod_voicemail/mod_voicemail.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 691ede9ba0..2cb1a20417 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -1568,11 +1568,9 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t *cc.buf = '\0'; memset(&fh, 0, sizeof(fh)); cc.fh = &fh; - cc.noexit = 1; if (switch_file_exists(cbt->file_path, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) { TRY_CODE(switch_ivr_play_file(session, &fh, cbt->file_path, &args)); } - cc.noexit = 0; } if (!*cc.buf && (profile->play_date_announcement == VM_DATE_LAST)) { From c6c247d35c7439d1fbea649eaec715b2983df280 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 6 Sep 2011 11:30:28 -0500 Subject: [PATCH 032/204] FS-3543 --resolve nevermind, found it --- src/switch_rtp.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index eb431d0e3b..6d51bf2963 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -2403,18 +2403,23 @@ static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session) SWITCH_DECLARE(void) rtp_flush_read_buffer(switch_rtp_t *rtp_session, switch_rtp_flush_t flush) { - if (switch_rtp_ready(rtp_session) && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) && - !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) { - switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_FLUSH); - switch (flush) { - case SWITCH_RTP_FLUSH_STICK: - switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_STICKY_FLUSH); - break; - case SWITCH_RTP_FLUSH_UNSTICK: - switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_STICKY_FLUSH); - break; - default: - break; + + if (switch_rtp_ready(rtp_session)) { + rtp_session->last_write_ts = 0; + + if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) && + !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) { + switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_FLUSH); + switch (flush) { + case SWITCH_RTP_FLUSH_STICK: + switch_set_flag_locked(rtp_session, SWITCH_RTP_FLAG_STICKY_FLUSH); + break; + case SWITCH_RTP_FLUSH_UNSTICK: + switch_clear_flag_locked(rtp_session, SWITCH_RTP_FLAG_STICKY_FLUSH); + break; + default: + break; + } } } } @@ -3794,6 +3799,10 @@ static int rtp_common_write(switch_rtp_t *rtp_session, this_ts = ntohl(send_msg->header.ts); + if ((this_ts < rtp_session->last_write_ts) && ((rtp_session->last_write_ts - this_ts) > 16000)) { + rtp_session->last_write_ts = 0; + } + if (!switch_rtp_ready(rtp_session) || rtp_session->sending_dtmf || !this_ts || this_ts < rtp_session->last_write_ts) { send = 0; } From fb5f29c2fb992fcd65d2d6a15999133bba5f67d1 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 6 Sep 2011 12:53:29 -0500 Subject: [PATCH 033/204] speed up restart speed of profiles --- src/mod/endpoints/mod_sofia/mod_sofia.h | 1 + src/mod/endpoints/mod_sofia/sofia.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index b6df8170f3..4e8a0585bd 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -251,6 +251,7 @@ typedef enum { PFLAG_LIBERAL_DTMF, PFLAG_AUTO_ASSIGN_PORT, PFLAG_AUTO_ASSIGN_TLS_PORT, + PFLAG_SHUTDOWN, /* No new flags below this line */ PFLAG_MAX } PFLAGS; diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index a24c795df1..6b5e18ec58 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -959,6 +959,7 @@ static void our_sofia_event_callback(nua_event_t event, break; case nua_r_shutdown: if (status >= 200) { + sofia_set_pflag(profile, PFLAG_SHUTDOWN); su_root_break(profile->s_root); } break; @@ -1955,9 +1956,17 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void switch_thread_rwlock_wrlock(profile->rwlock); sofia_reg_unregister(profile); nua_shutdown(profile->nua); - su_root_run(profile->s_root); + sanity = 10; + while (!sofia_test_pflag(profile, PFLAG_SHUTDOWN)) { + su_root_step(profile->s_root, 1000); + if (!--sanity) { + break; + } + } + sofia_clear_pflag_locked(profile, PFLAG_RUNNING); + sofia_clear_pflag_locked(profile, PFLAG_SHUTDOWN); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Waiting for worker thread\n"); switch_thread_join(&st, worker_thread); From 2b7a830d6deaa6230762fb03fdfc9043129476a0 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 6 Sep 2011 13:56:21 -0500 Subject: [PATCH 034/204] allow duplicate headers to be parsed into events received on the wire --- src/mod/event_handlers/mod_event_socket/mod_event_socket.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c index 384b6db0f6..37c238852c 100644 --- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c +++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c @@ -1180,7 +1180,6 @@ static switch_status_t read_packet(listener_t *listener, switch_event_t **event, } } if (var && val) { - switch_event_del_header(*event, var); switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, var, val); if (!strcasecmp(var, "content-length")) { clen = atoi(val); From 96ddc51faa22efd1ce1809dc27e79ac796ecb62a Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 6 Sep 2011 13:56:44 -0500 Subject: [PATCH 035/204] split on space not colon --- src/switch_ivr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 22731c1968..56397ede5c 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -639,7 +639,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_parse_event(switch_core_session_t *se if (!strcasecmp(hp->name, "application")) { app = strdup(hp->value); - data = strchr(app, ':'); + data = strchr(app, ' '); if (data) { *data++ = '\0'; From 2ae688a33b1114a2d96ccd412afda5874ddc07df Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 6 Sep 2011 14:53:38 -0500 Subject: [PATCH 036/204] add sendmsg function to esl --- libs/esl/src/esl.c | 33 +++++++++++++++++++++++++++++++++ libs/esl/src/esl_oop.cpp | 9 +++++++++ libs/esl/src/include/esl.h | 8 ++++++++ libs/esl/src/include/esl_oop.h | 1 + 4 files changed, 51 insertions(+) diff --git a/libs/esl/src/esl.c b/libs/esl/src/esl.c index ef8d7c1cb1..cd3a7067f8 100644 --- a/libs/esl/src/esl.c +++ b/libs/esl/src/esl.c @@ -534,6 +534,39 @@ ESL_DECLARE(esl_status_t) esl_execute(esl_handle_t *handle, const char *app, con } +ESL_DECLARE(esl_status_t) esl_sendmsg(esl_handle_t *handle, esl_event_t *event, const char *uuid) +{ + char cmd_buf[128] = "sendmsg"; + char send_buf[1292] = ""; + char *txt; + + if (!handle || !handle->connected || handle->sock == ESL_SOCK_INVALID) { + return ESL_FAIL; + } + + if (uuid) { + snprintf(cmd_buf, sizeof(cmd_buf), "sendmsg %s", uuid); + } + + esl_event_serialize(event, &txt, ESL_FALSE); + esl_log(ESL_LOG_DEBUG, "SENDMSG\n%s\n", txt); + + if (send(handle->sock, txt, strlen(txt), 0) <= 0) goto fail; + + free(txt); + + return esl_recv(handle); + + fail: + + handle->connected = 0; + + free(txt); + + return ESL_FAIL; +} + + ESL_DECLARE(esl_status_t) esl_filter(esl_handle_t *handle, const char *header, const char *value) { char send_buf[1024] = ""; diff --git a/libs/esl/src/esl_oop.cpp b/libs/esl/src/esl_oop.cpp index 0c4bbd6f90..4f60a928ee 100644 --- a/libs/esl/src/esl_oop.cpp +++ b/libs/esl/src/esl_oop.cpp @@ -205,6 +205,15 @@ ESLevent *ESLconnection::sendEvent(ESLevent *send_me) return new ESLevent("server_disconnected"); } +int ESLconnection::sendMSG(ESLevent *send_me, const char *uuid) +{ + if (esl_sendmsg(&handle, send_me->event, uuid) == ESL_SUCCESS) { + return 0; + } + + return 1; +} + ESLevent *ESLconnection::recvEvent() { if (esl_recv_event(&handle, 1, NULL) == ESL_SUCCESS) { diff --git a/libs/esl/src/include/esl.h b/libs/esl/src/include/esl.h index 095e814a0e..a9e5df140b 100644 --- a/libs/esl/src/include/esl.h +++ b/libs/esl/src/include/esl.h @@ -397,6 +397,14 @@ ESL_DECLARE(esl_status_t) esl_execute(esl_handle_t *handle, const char *app, con */ ESL_DECLARE(esl_status_t) esl_sendevent(esl_handle_t *handle, esl_event_t *event); +/*! + \brief Send an event as a message to be parsed + \param handle Handle to which the event should be sent + \param event Event to be sent + \param uuid a specific uuid if not the default +*/ +ESL_DECLARE(esl_status_t) esl_sendmsg(esl_handle_t *handle, esl_event_t *event, const char *uuid); + /*! \brief Connect a handle to a host/port with a specific password. This will also authenticate against the server \param handle Handle to connect diff --git a/libs/esl/src/include/esl_oop.h b/libs/esl/src/include/esl_oop.h index 947fe453d7..0ea1e5da89 100644 --- a/libs/esl/src/include/esl_oop.h +++ b/libs/esl/src/include/esl_oop.h @@ -86,6 +86,7 @@ class ESLconnection { ESLevent *api(const char *cmd, const char *arg = NULL); ESLevent *bgapi(const char *cmd, const char *arg = NULL, const char *job_uuid = NULL); ESLevent *sendEvent(ESLevent *send_me); + int sendMSG(ESLevent *send_me, const char *uuid = NULL); ESLevent *recvEvent(); ESLevent *recvEventTimed(int ms); ESLevent *filter(const char *header, const char *value); From 391da66cac1d8a88a7129d66d86e02a78c8c1b78 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 6 Sep 2011 16:30:04 -0500 Subject: [PATCH 037/204] reswig --- libs/esl/java/esl_wrap.cpp | 25 ++++ .../org/freeswitch/esl/ESLconnection.java | 4 + libs/esl/java/org/freeswitch/esl/eslJNI.java | 1 + libs/esl/lua/esl_wrap.cpp | 38 +++++ libs/esl/managed/ESLPINVOKE.cs | 3 + libs/esl/managed/ESLconnection.cs | 5 + libs/esl/managed/esl_wrap.cpp | 16 +++ libs/esl/perl/ESL.pm | 1 + libs/esl/perl/esl_wrap.cpp | 52 +++++++ libs/esl/php/ESL.php | 8 ++ libs/esl/php/esl_wrap.cpp | 133 ++++++++++++------ libs/esl/php/php_ESL.h | 1 + libs/esl/python/ESL.py | 1 + libs/esl/python/esl_wrap.cpp | 53 +++++++ libs/esl/ruby/esl_wrap.cpp | 48 ++++++- 15 files changed, 343 insertions(+), 46 deletions(-) diff --git a/libs/esl/java/esl_wrap.cpp b/libs/esl/java/esl_wrap.cpp index 52c5065d00..0550231dde 100644 --- a/libs/esl/java/esl_wrap.cpp +++ b/libs/esl/java/esl_wrap.cpp @@ -904,6 +904,31 @@ SWIGEXPORT jlong JNICALL Java_org_freeswitch_esl_eslJNI_ESLconnection_1sendEvent } +SWIGEXPORT jint JNICALL Java_org_freeswitch_esl_eslJNI_ESLconnection_1sendMSG(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jstring jarg3) { + jint jresult = 0 ; + ESLconnection *arg1 = (ESLconnection *) 0 ; + ESLevent *arg2 = (ESLevent *) 0 ; + char *arg3 = (char *) NULL ; + int result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + (void)jarg2_; + arg1 = *(ESLconnection **)&jarg1; + arg2 = *(ESLevent **)&jarg2; + arg3 = 0; + if (jarg3) { + arg3 = (char *)jenv->GetStringUTFChars(jarg3, 0); + if (!arg3) return 0; + } + result = (int)(arg1)->sendMSG(arg2,(char const *)arg3); + jresult = (jint)result; + if (arg3) jenv->ReleaseStringUTFChars(jarg3, (const char *)arg3); + return jresult; +} + + SWIGEXPORT jlong JNICALL Java_org_freeswitch_esl_eslJNI_ESLconnection_1recvEvent(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) { jlong jresult = 0 ; ESLconnection *arg1 = (ESLconnection *) 0 ; diff --git a/libs/esl/java/org/freeswitch/esl/ESLconnection.java b/libs/esl/java/org/freeswitch/esl/ESLconnection.java index e20509bf10..588cefcc99 100644 --- a/libs/esl/java/org/freeswitch/esl/ESLconnection.java +++ b/libs/esl/java/org/freeswitch/esl/ESLconnection.java @@ -82,6 +82,10 @@ public class ESLconnection { return (cPtr == 0) ? null : new ESLevent(cPtr, true); } + public int sendMSG(ESLevent send_me, String uuid) { + return eslJNI.ESLconnection_sendMSG(swigCPtr, this, ESLevent.getCPtr(send_me), send_me, uuid); + } + public ESLevent recvEvent() { long cPtr = eslJNI.ESLconnection_recvEvent(swigCPtr, this); return (cPtr == 0) ? null : new ESLevent(cPtr, true); diff --git a/libs/esl/java/org/freeswitch/esl/eslJNI.java b/libs/esl/java/org/freeswitch/esl/eslJNI.java index dfdedff60f..ff3744e9df 100644 --- a/libs/esl/java/org/freeswitch/esl/eslJNI.java +++ b/libs/esl/java/org/freeswitch/esl/eslJNI.java @@ -43,6 +43,7 @@ class eslJNI { public final static native long ESLconnection_api(long jarg1, ESLconnection jarg1_, String jarg2, String jarg3); public final static native long ESLconnection_bgapi(long jarg1, ESLconnection jarg1_, String jarg2, String jarg3, String jarg4); public final static native long ESLconnection_sendEvent(long jarg1, ESLconnection jarg1_, long jarg2, ESLevent jarg2_); + public final static native int ESLconnection_sendMSG(long jarg1, ESLconnection jarg1_, long jarg2, ESLevent jarg2_, String jarg3); public final static native long ESLconnection_recvEvent(long jarg1, ESLconnection jarg1_); public final static native long ESLconnection_recvEventTimed(long jarg1, ESLconnection jarg1_, int jarg2); public final static native long ESLconnection_filter(long jarg1, ESLconnection jarg1_, String jarg2, String jarg3); diff --git a/libs/esl/lua/esl_wrap.cpp b/libs/esl/lua/esl_wrap.cpp index c3ee30811e..9420f853bb 100644 --- a/libs/esl/lua/esl_wrap.cpp +++ b/libs/esl/lua/esl_wrap.cpp @@ -2632,6 +2632,43 @@ fail: } +static int _wrap_ESLconnection_sendMSG(lua_State* L) { + int SWIG_arg = -1; + ESLconnection *arg1 = (ESLconnection *) 0 ; + ESLevent *arg2 = (ESLevent *) 0 ; + char *arg3 = (char *) NULL ; + int result; + + SWIG_check_num_args("sendMSG",2,3) + if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("sendMSG",1,"ESLconnection *"); + if(!SWIG_isptrtype(L,2)) SWIG_fail_arg("sendMSG",2,"ESLevent *"); + if(lua_gettop(L)>=3 && !lua_isstring(L,3)) SWIG_fail_arg("sendMSG",3,"char const *"); + + if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_ESLconnection,0))){ + SWIG_fail_ptr("ESLconnection_sendMSG",1,SWIGTYPE_p_ESLconnection); + } + + + if (!SWIG_IsOK(SWIG_ConvertPtr(L,2,(void**)&arg2,SWIGTYPE_p_ESLevent,0))){ + SWIG_fail_ptr("ESLconnection_sendMSG",2,SWIGTYPE_p_ESLevent); + } + + if(lua_gettop(L)>=3){ + arg3 = (char *)lua_tostring(L, 3); + } + result = (int)(arg1)->sendMSG(arg2,(char const *)arg3); + SWIG_arg=0; + lua_pushnumber(L, (lua_Number) result); SWIG_arg++; + return SWIG_arg; + + if(0) SWIG_fail; + +fail: + lua_error(L); + return SWIG_arg; +} + + static int _wrap_ESLconnection_recvEvent(lua_State* L) { int SWIG_arg = -1; ESLconnection *arg1 = (ESLconnection *) 0 ; @@ -2917,6 +2954,7 @@ static swig_lua_method swig_ESLconnection_methods[] = { {"api", _wrap_ESLconnection_api}, {"bgapi", _wrap_ESLconnection_bgapi}, {"sendEvent", _wrap_ESLconnection_sendEvent}, + {"sendMSG", _wrap_ESLconnection_sendMSG}, {"recvEvent", _wrap_ESLconnection_recvEvent}, {"recvEventTimed", _wrap_ESLconnection_recvEventTimed}, {"filter", _wrap_ESLconnection_filter}, diff --git a/libs/esl/managed/ESLPINVOKE.cs b/libs/esl/managed/ESLPINVOKE.cs index ee15a2b702..5ada2c148d 100644 --- a/libs/esl/managed/ESLPINVOKE.cs +++ b/libs/esl/managed/ESLPINVOKE.cs @@ -286,6 +286,9 @@ class ESLPINVOKE { [DllImport("ESL", EntryPoint="CSharp_ESLconnection_SendEvent")] public static extern IntPtr ESLconnection_SendEvent(HandleRef jarg1, HandleRef jarg2); + [DllImport("ESL", EntryPoint="CSharp_ESLconnection_sendMSG")] + public static extern int ESLconnection_sendMSG(HandleRef jarg1, HandleRef jarg2, string jarg3); + [DllImport("ESL", EntryPoint="CSharp_ESLconnection_RecvEvent")] public static extern IntPtr ESLconnection_RecvEvent(HandleRef jarg1); diff --git a/libs/esl/managed/ESLconnection.cs b/libs/esl/managed/ESLconnection.cs index 88435830ad..2d1e6d4dc3 100644 --- a/libs/esl/managed/ESLconnection.cs +++ b/libs/esl/managed/ESLconnection.cs @@ -92,6 +92,11 @@ public class ESLconnection : IDisposable { return ret; } + public int sendMSG(ESLevent send_me, string uuid) { + int ret = ESLPINVOKE.ESLconnection_sendMSG(swigCPtr, ESLevent.getCPtr(send_me), uuid); + return ret; + } + public ESLevent RecvEvent() { IntPtr cPtr = ESLPINVOKE.ESLconnection_RecvEvent(swigCPtr); ESLevent ret = (cPtr == IntPtr.Zero) ? null : new ESLevent(cPtr, true); diff --git a/libs/esl/managed/esl_wrap.cpp b/libs/esl/managed/esl_wrap.cpp index f07b4b3d3f..65da98a15a 100644 --- a/libs/esl/managed/esl_wrap.cpp +++ b/libs/esl/managed/esl_wrap.cpp @@ -743,6 +743,22 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_ESLconnection_SendEvent(void * jarg1, void } +SWIGEXPORT int SWIGSTDCALL CSharp_ESLconnection_sendMSG(void * jarg1, void * jarg2, char * jarg3) { + int jresult ; + ESLconnection *arg1 = (ESLconnection *) 0 ; + ESLevent *arg2 = (ESLevent *) 0 ; + char *arg3 = (char *) NULL ; + int result; + + arg1 = (ESLconnection *)jarg1; + arg2 = (ESLevent *)jarg2; + arg3 = (char *)jarg3; + result = (int)(arg1)->sendMSG(arg2,(char const *)arg3); + jresult = result; + return jresult; +} + + SWIGEXPORT void * SWIGSTDCALL CSharp_ESLconnection_RecvEvent(void * jarg1) { void * jresult ; ESLconnection *arg1 = (ESLconnection *) 0 ; diff --git a/libs/esl/perl/ESL.pm b/libs/esl/perl/ESL.pm index b291d002d7..69c012a577 100644 --- a/libs/esl/perl/ESL.pm +++ b/libs/esl/perl/ESL.pm @@ -138,6 +138,7 @@ sub DESTROY { *api = *ESLc::ESLconnection_api; *bgapi = *ESLc::ESLconnection_bgapi; *sendEvent = *ESLc::ESLconnection_sendEvent; +*sendMSG = *ESLc::ESLconnection_sendMSG; *recvEvent = *ESLc::ESLconnection_recvEvent; *recvEventTimed = *ESLc::ESLconnection_recvEventTimed; *filter = *ESLc::ESLconnection_filter; diff --git a/libs/esl/perl/esl_wrap.cpp b/libs/esl/perl/esl_wrap.cpp index 1bc45fa2e1..832289f156 100644 --- a/libs/esl/perl/esl_wrap.cpp +++ b/libs/esl/perl/esl_wrap.cpp @@ -3282,6 +3282,57 @@ XS(_wrap_ESLconnection_sendEvent) { } +XS(_wrap_ESLconnection_sendMSG) { + { + ESLconnection *arg1 = (ESLconnection *) 0 ; + ESLevent *arg2 = (ESLevent *) 0 ; + char *arg3 = (char *) NULL ; + int result; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + int res3 ; + char *buf3 = 0 ; + int alloc3 = 0 ; + int argvi = 0; + dXSARGS; + + if ((items < 2) || (items > 3)) { + SWIG_croak("Usage: ESLconnection_sendMSG(self,send_me,uuid);"); + } + res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_ESLconnection, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ESLconnection_sendMSG" "', argument " "1"" of type '" "ESLconnection *""'"); + } + arg1 = reinterpret_cast< ESLconnection * >(argp1); + res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_ESLevent, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ESLconnection_sendMSG" "', argument " "2"" of type '" "ESLevent *""'"); + } + arg2 = reinterpret_cast< ESLevent * >(argp2); + if (items > 2) { + res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "ESLconnection_sendMSG" "', argument " "3"" of type '" "char const *""'"); + } + arg3 = reinterpret_cast< char * >(buf3); + } + result = (int)(arg1)->sendMSG(arg2,(char const *)arg3); + ST(argvi) = SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ; + + + if (alloc3 == SWIG_NEWOBJ) delete[] buf3; + XSRETURN(argvi); + fail: + + + if (alloc3 == SWIG_NEWOBJ) delete[] buf3; + SWIG_croak_null(); + } +} + + XS(_wrap_ESLconnection_recvEvent) { { ESLconnection *arg1 = (ESLconnection *) 0 ; @@ -3785,6 +3836,7 @@ static swig_command_info swig_commands[] = { {"ESLc::ESLconnection_api", _wrap_ESLconnection_api}, {"ESLc::ESLconnection_bgapi", _wrap_ESLconnection_bgapi}, {"ESLc::ESLconnection_sendEvent", _wrap_ESLconnection_sendEvent}, +{"ESLc::ESLconnection_sendMSG", _wrap_ESLconnection_sendMSG}, {"ESLc::ESLconnection_recvEvent", _wrap_ESLconnection_recvEvent}, {"ESLc::ESLconnection_recvEventTimed", _wrap_ESLconnection_recvEventTimed}, {"ESLc::ESLconnection_filter", _wrap_ESLconnection_filter}, diff --git a/libs/esl/php/ESL.php b/libs/esl/php/ESL.php index 0bc8c4e724..a35e8feb32 100644 --- a/libs/esl/php/ESL.php +++ b/libs/esl/php/ESL.php @@ -174,6 +174,14 @@ class ESLconnection { return is_resource($r) ? new ESLevent($r) : $r; } + function sendMSG($send_me,$uuid=null) { + switch (func_num_args()) { + case 1: $r=ESLconnection_sendMSG($this->_cPtr,$send_me); break; + default: $r=ESLconnection_sendMSG($this->_cPtr,$send_me,$uuid); + } + return $r; + } + function recvEvent() { $r=ESLconnection_recvEvent($this->_cPtr); return is_resource($r) ? new ESLevent($r) : $r; diff --git a/libs/esl/php/esl_wrap.cpp b/libs/esl/php/esl_wrap.cpp index bd599b7fc1..b5fd7a7d52 100644 --- a/libs/esl/php/esl_wrap.cpp +++ b/libs/esl/php/esl_wrap.cpp @@ -1091,7 +1091,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_serialized_string_set) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; @@ -1159,7 +1159,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_mine_set) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ + /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ convert_to_long_ex(args[1]); arg2 = (int) Z_LVAL_PP(args[1]); /*@SWIG@*/; @@ -1213,13 +1213,13 @@ ZEND_NAMED_FUNCTION(_wrap_new_ESLevent__SWIG_0) { WRONG_PARAM_COUNT; - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ convert_to_string_ex(args[0]); arg1 = (char *) Z_STRVAL_PP(args[0]); /*@SWIG@*/; if(arg_count > 1) { - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; @@ -1254,7 +1254,7 @@ ZEND_NAMED_FUNCTION(_wrap_new_ESLevent__SWIG_1) { } } if(arg_count > 1) { - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ + /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ convert_to_long_ex(args[1]); arg2 = (int) Z_LVAL_PP(args[1]); /*@SWIG@*/; @@ -1384,7 +1384,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_serialize) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); if(arg_count > 1) { - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; @@ -1463,13 +1463,13 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_getHeader) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; if(arg_count > 2) { - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ + /*@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@*/; @@ -1567,7 +1567,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_addBody) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; @@ -1601,13 +1601,13 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_addHeader) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; @@ -1641,13 +1641,13 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_pushHeader) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; @@ -1681,13 +1681,13 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_unshiftHeader) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; @@ -1720,7 +1720,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLevent_delHeader) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; @@ -1809,25 +1809,25 @@ ZEND_NAMED_FUNCTION(_wrap_new_ESLconnection__SWIG_0) { } - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ convert_to_string_ex(args[0]); arg1 = (char *) Z_STRVAL_PP(args[0]); /*@SWIG@*/; - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ convert_to_string_ex(args[3]); arg4 = (char *) Z_STRVAL_PP(args[3]); /*@SWIG@*/; @@ -1855,19 +1855,19 @@ ZEND_NAMED_FUNCTION(_wrap_new_ESLconnection__SWIG_1) { } - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ convert_to_string_ex(args[0]); arg1 = (char *) Z_STRVAL_PP(args[0]); /*@SWIG@*/; - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; @@ -1893,7 +1893,7 @@ ZEND_NAMED_FUNCTION(_wrap_new_ESLconnection__SWIG_2) { } - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ + /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ convert_to_long_ex(args[0]); arg1 = (int) Z_LVAL_PP(args[0]); /*@SWIG@*/; @@ -2070,7 +2070,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_send) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; @@ -2103,7 +2103,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_sendRecv) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; @@ -2139,13 +2139,13 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_api) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; if(arg_count > 2) { - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; @@ -2183,20 +2183,20 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_bgapi) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; if(arg_count > 2) { - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; } if(arg_count > 3) { - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ convert_to_string_ex(args[3]); arg4 = (char *) Z_STRVAL_PP(args[3]); /*@SWIG@*/; @@ -2244,6 +2244,48 @@ fail: } +ZEND_NAMED_FUNCTION(_wrap_ESLconnection_sendMSG) { + ESLconnection *arg1 = (ESLconnection *) 0 ; + ESLevent *arg2 = (ESLevent *) 0 ; + char *arg3 = (char *) NULL ; + int result; + zval **args[3]; + int arg_count; + + SWIG_ResetError(); + 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_ESLconnection, 0) < 0) { + SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of ESLconnection_sendMSG. Expected SWIGTYPE_p_ESLconnection"); + } + } + if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); + { + if(SWIG_ConvertPtr(*args[1], (void **) &arg2, SWIGTYPE_p_ESLevent, 0) < 0) { + SWIG_PHP_Error(E_ERROR, "Type error in argument 2 of ESLconnection_sendMSG. Expected SWIGTYPE_p_ESLevent"); + } + } + if(arg_count > 2) { + /*@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 = (int)(arg1)->sendMSG(arg2,(char const *)arg3); + { + ZVAL_LONG(return_value,result); + } + return; +fail: + zend_error(SWIG_ErrorCode(),SWIG_ErrorMsg()); +} + + ZEND_NAMED_FUNCTION(_wrap_ESLconnection_recvEvent) { ESLconnection *arg1 = (ESLconnection *) 0 ; ESLevent *result = 0 ; @@ -2288,7 +2330,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_recvEventTimed) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ + /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ convert_to_long_ex(args[1]); arg2 = (int) Z_LVAL_PP(args[1]); /*@SWIG@*/; @@ -2322,13 +2364,13 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_filter) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; @@ -2362,13 +2404,13 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_events) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; @@ -2405,20 +2447,20 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_execute) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; if(arg_count > 2) { - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; } if(arg_count > 3) { - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ convert_to_string_ex(args[3]); arg4 = (char *) Z_STRVAL_PP(args[3]); /*@SWIG@*/; @@ -2456,20 +2498,20 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_executeAsync) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; if(arg_count > 2) { - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; } if(arg_count > 3) { - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ convert_to_string_ex(args[3]); arg4 = (char *) Z_STRVAL_PP(args[3]); /*@SWIG@*/; @@ -2503,7 +2545,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_setAsyncExecute) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; @@ -2536,7 +2578,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_setEventLock) { } if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL"); - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/ + /*@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@*/; @@ -2587,7 +2629,7 @@ ZEND_NAMED_FUNCTION(_wrap_eslSetLogLevel) { } - /*@SWIG:/usr/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ + /*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,7,CONVERT_INT_IN@*/ convert_to_long_ex(args[0]); arg1 = (int) Z_LVAL_PP(args[0]); /*@SWIG@*/; @@ -2651,6 +2693,7 @@ static zend_function_entry ESL_functions[] = { SWIG_ZEND_NAMED_FE(eslconnection_api,_wrap_ESLconnection_api,NULL) SWIG_ZEND_NAMED_FE(eslconnection_bgapi,_wrap_ESLconnection_bgapi,NULL) SWIG_ZEND_NAMED_FE(eslconnection_sendevent,_wrap_ESLconnection_sendEvent,NULL) + SWIG_ZEND_NAMED_FE(eslconnection_sendmsg,_wrap_ESLconnection_sendMSG,NULL) SWIG_ZEND_NAMED_FE(eslconnection_recvevent,_wrap_ESLconnection_recvEvent,NULL) SWIG_ZEND_NAMED_FE(eslconnection_recveventtimed,_wrap_ESLconnection_recvEventTimed,NULL) SWIG_ZEND_NAMED_FE(eslconnection_filter,_wrap_ESLconnection_filter,NULL) diff --git a/libs/esl/php/php_ESL.h b/libs/esl/php/php_ESL.h index eceac5dd70..41056b3dda 100644 --- a/libs/esl/php/php_ESL.h +++ b/libs/esl/php/php_ESL.h @@ -60,6 +60,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_sendRecv); ZEND_NAMED_FUNCTION(_wrap_ESLconnection_api); ZEND_NAMED_FUNCTION(_wrap_ESLconnection_bgapi); ZEND_NAMED_FUNCTION(_wrap_ESLconnection_sendEvent); +ZEND_NAMED_FUNCTION(_wrap_ESLconnection_sendMSG); ZEND_NAMED_FUNCTION(_wrap_ESLconnection_recvEvent); ZEND_NAMED_FUNCTION(_wrap_ESLconnection_recvEventTimed); ZEND_NAMED_FUNCTION(_wrap_ESLconnection_filter); diff --git a/libs/esl/python/ESL.py b/libs/esl/python/ESL.py index 6bb4216692..bb2de43a87 100644 --- a/libs/esl/python/ESL.py +++ b/libs/esl/python/ESL.py @@ -87,6 +87,7 @@ class ESLconnection: def api(*args): return apply(_ESL.ESLconnection_api, args) def bgapi(*args): return apply(_ESL.ESLconnection_bgapi, args) def sendEvent(*args): return apply(_ESL.ESLconnection_sendEvent, args) + def sendMSG(*args): return apply(_ESL.ESLconnection_sendMSG, args) def recvEvent(*args): return apply(_ESL.ESLconnection_recvEvent, args) def recvEventTimed(*args): return apply(_ESL.ESLconnection_recvEventTimed, args) def filter(*args): return apply(_ESL.ESLconnection_filter, args) diff --git a/libs/esl/python/esl_wrap.cpp b/libs/esl/python/esl_wrap.cpp index 90f6ed2c79..35d600e0b0 100644 --- a/libs/esl/python/esl_wrap.cpp +++ b/libs/esl/python/esl_wrap.cpp @@ -4370,6 +4370,58 @@ fail: } +SWIGINTERN PyObject *_wrap_ESLconnection_sendMSG(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + ESLconnection *arg1 = (ESLconnection *) 0 ; + ESLevent *arg2 = (ESLevent *) 0 ; + char *arg3 = (char *) NULL ; + int result; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 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 *)"OO|O:ESLconnection_sendMSG",&obj0,&obj1,&obj2)) SWIG_fail; + res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ESLconnection, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ESLconnection_sendMSG" "', argument " "1"" of type '" "ESLconnection *""'"); + } + arg1 = reinterpret_cast< ESLconnection * >(argp1); + res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_ESLevent, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ESLconnection_sendMSG" "', argument " "2"" of type '" "ESLevent *""'"); + } + arg2 = reinterpret_cast< ESLevent * >(argp2); + if (obj2) { + res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "ESLconnection_sendMSG" "', argument " "3"" of type '" "char const *""'"); + } + arg3 = reinterpret_cast< char * >(buf3); + } + { + SWIG_PYTHON_THREAD_BEGIN_ALLOW; + result = (int)(arg1)->sendMSG(arg2,(char const *)arg3); + SWIG_PYTHON_THREAD_END_ALLOW; + } + resultobj = SWIG_From_int(static_cast< int >(result)); + if (alloc3 == SWIG_NEWOBJ) delete[] buf3; + SWIG_PYTHON_THREAD_END_BLOCK; + return resultobj; +fail: + if (alloc3 == SWIG_NEWOBJ) delete[] buf3; + SWIG_PYTHON_THREAD_END_BLOCK; + return NULL; +} + + SWIGINTERN PyObject *_wrap_ESLconnection_recvEvent(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; ESLconnection *arg1 = (ESLconnection *) 0 ; @@ -4859,6 +4911,7 @@ static PyMethodDef SwigMethods[] = { { (char *)"ESLconnection_api", _wrap_ESLconnection_api, METH_VARARGS, NULL}, { (char *)"ESLconnection_bgapi", _wrap_ESLconnection_bgapi, METH_VARARGS, NULL}, { (char *)"ESLconnection_sendEvent", _wrap_ESLconnection_sendEvent, METH_VARARGS, NULL}, + { (char *)"ESLconnection_sendMSG", _wrap_ESLconnection_sendMSG, METH_VARARGS, NULL}, { (char *)"ESLconnection_recvEvent", _wrap_ESLconnection_recvEvent, METH_VARARGS, NULL}, { (char *)"ESLconnection_recvEventTimed", _wrap_ESLconnection_recvEventTimed, METH_VARARGS, NULL}, { (char *)"ESLconnection_filter", _wrap_ESLconnection_filter, METH_VARARGS, NULL}, diff --git a/libs/esl/ruby/esl_wrap.cpp b/libs/esl/ruby/esl_wrap.cpp index d091157282..223ba3ea34 100644 --- a/libs/esl/ruby/esl_wrap.cpp +++ b/libs/esl/ruby/esl_wrap.cpp @@ -1902,7 +1902,7 @@ SWIG_ruby_failed(void) } -/*@SWIG:/usr/share/swig/1.3.35/ruby/rubyprimtypes.swg,23,%ruby_aux_method@*/ +/*@SWIG:/usr/local/share/swig/1.3.35/ruby/rubyprimtypes.swg,23,%ruby_aux_method@*/ SWIGINTERN VALUE SWIG_AUX_NUM2LONG(VALUE *args) { VALUE obj = args[0]; @@ -3245,6 +3245,51 @@ fail: } +SWIGINTERN VALUE +_wrap_ESLconnection_sendMSG(int argc, VALUE *argv, VALUE self) { + ESLconnection *arg1 = (ESLconnection *) 0 ; + ESLevent *arg2 = (ESLevent *) 0 ; + char *arg3 = (char *) NULL ; + int result; + void *argp1 = 0 ; + int res1 = 0 ; + void *argp2 = 0 ; + int res2 = 0 ; + int res3 ; + char *buf3 = 0 ; + int alloc3 = 0 ; + VALUE vresult = Qnil; + + 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_ESLconnection, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), Ruby_Format_TypeError( "", "ESLconnection *","sendMSG", 1, self )); + } + arg1 = reinterpret_cast< ESLconnection * >(argp1); + res2 = SWIG_ConvertPtr(argv[0], &argp2,SWIGTYPE_p_ESLevent, 0 | 0 ); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), Ruby_Format_TypeError( "", "ESLevent *","sendMSG", 2, argv[0] )); + } + arg2 = reinterpret_cast< ESLevent * >(argp2); + if (argc > 1) { + res3 = SWIG_AsCharPtrAndSize(argv[1], &buf3, NULL, &alloc3); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), Ruby_Format_TypeError( "", "char const *","sendMSG", 3, argv[1] )); + } + arg3 = reinterpret_cast< char * >(buf3); + } + result = (int)(arg1)->sendMSG(arg2,(char const *)arg3); + vresult = SWIG_From_int(static_cast< int >(result)); + if (alloc3 == SWIG_NEWOBJ) delete[] buf3; + return vresult; +fail: + if (alloc3 == SWIG_NEWOBJ) delete[] buf3; + return Qnil; +} + + SWIGINTERN VALUE _wrap_ESLconnection_recvEvent(int argc, VALUE *argv, VALUE self) { ESLconnection *arg1 = (ESLconnection *) 0 ; @@ -3958,6 +4003,7 @@ SWIGEXPORT void Init_ESL(void) { rb_define_method(cESLconnection.klass, "api", VALUEFUNC(_wrap_ESLconnection_api), -1); rb_define_method(cESLconnection.klass, "bgapi", VALUEFUNC(_wrap_ESLconnection_bgapi), -1); rb_define_method(cESLconnection.klass, "sendEvent", VALUEFUNC(_wrap_ESLconnection_sendEvent), -1); + rb_define_method(cESLconnection.klass, "sendMSG", VALUEFUNC(_wrap_ESLconnection_sendMSG), -1); rb_define_method(cESLconnection.klass, "recvEvent", VALUEFUNC(_wrap_ESLconnection_recvEvent), -1); rb_define_method(cESLconnection.klass, "recvEventTimed", VALUEFUNC(_wrap_ESLconnection_recvEventTimed), -1); rb_define_method(cESLconnection.klass, "filter", VALUEFUNC(_wrap_ESLconnection_filter), -1); From 1c775c3bf007a2ee8757ec95f4dd96992fb2b0d3 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 6 Sep 2011 15:07:51 -0500 Subject: [PATCH 038/204] finish up last commit --- libs/esl/src/esl.c | 7 ++++--- libs/esl/src/esl_event.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libs/esl/src/esl.c b/libs/esl/src/esl.c index cd3a7067f8..9509572a80 100644 --- a/libs/esl/src/esl.c +++ b/libs/esl/src/esl.c @@ -536,7 +536,7 @@ ESL_DECLARE(esl_status_t) esl_execute(esl_handle_t *handle, const char *app, con ESL_DECLARE(esl_status_t) esl_sendmsg(esl_handle_t *handle, esl_event_t *event, const char *uuid) { - char cmd_buf[128] = "sendmsg"; + char cmd_buf[128] = "sendmsg\n"; char send_buf[1292] = ""; char *txt; @@ -545,12 +545,13 @@ ESL_DECLARE(esl_status_t) esl_sendmsg(esl_handle_t *handle, esl_event_t *event, } if (uuid) { - snprintf(cmd_buf, sizeof(cmd_buf), "sendmsg %s", uuid); + snprintf(cmd_buf, sizeof(cmd_buf), "sendmsg %s\n", uuid); } esl_event_serialize(event, &txt, ESL_FALSE); - esl_log(ESL_LOG_DEBUG, "SENDMSG\n%s\n", txt); + esl_log(ESL_LOG_DEBUG, "%s%s\n", cmd_buf, txt); + if (send(handle->sock, cmd_buf, strlen(cmd_buf), 0) <= 0) goto fail; if (send(handle->sock, txt, strlen(txt), 0) <= 0) goto fail; free(txt); diff --git a/libs/esl/src/esl_event.c b/libs/esl/src/esl_event.c index abd3c2be90..71e7d42b2a 100644 --- a/libs/esl/src/esl_event.c +++ b/libs/esl/src/esl_event.c @@ -791,7 +791,7 @@ ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, es 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); } From 482b319512b10dee9544b3786b28468f55b380f6 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Tue, 6 Sep 2011 21:27:13 -0500 Subject: [PATCH 039/204] FS-3544 --resolve --- libs/esl/src/esl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/esl/src/esl.c b/libs/esl/src/esl.c index 9509572a80..0c387e79ef 100644 --- a/libs/esl/src/esl.c +++ b/libs/esl/src/esl.c @@ -537,7 +537,6 @@ ESL_DECLARE(esl_status_t) esl_execute(esl_handle_t *handle, const char *app, con ESL_DECLARE(esl_status_t) esl_sendmsg(esl_handle_t *handle, esl_event_t *event, const char *uuid) { char cmd_buf[128] = "sendmsg\n"; - char send_buf[1292] = ""; char *txt; if (!handle || !handle->connected || handle->sock == ESL_SOCK_INVALID) { From 247537a959a1fead1b2b17a8ab74daf2ac880dde Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 7 Sep 2011 08:07:04 -0500 Subject: [PATCH 040/204] FS-3545 --resolve this is actually compliant when mixing ptimes in the same sdp but since iLBC uses its own fmtp for ptime I will add this patch to make it beleive its 20 for the sake of arguement. If you have any other problems with this, set the channel or global variable sdp_m_per_ptime=false to completely disable the default correct behaviour --- src/mod/endpoints/mod_sofia/sofia_glue.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 124982c1de..adc0c5347f 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -583,6 +583,10 @@ void sofia_glue_set_local_sdp(private_object_t *tech_pvt, const char *ip, switch this_ptime = imp->microseconds_per_packet / 1000; + if (!strcasecmp(imp->iananame, "ilbc")) { + this_ptime = 20; + } + if (cur_ptime != this_ptime) { char *bp = buf; cur_ptime = this_ptime; From aff4bcbe12079f46a6bb78ac8dd70e58e329b0a8 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 7 Sep 2011 10:50:30 -0500 Subject: [PATCH 041/204] FS-3080 --resolve better fix for voicemail email key match --- .../applications/mod_voicemail/mod_voicemail.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 2cb1a20417..aa06fb6300 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -853,6 +853,7 @@ struct call_control { switch_file_handle_t *fh; char buf[4]; int noexit; + int playback_controls_active; }; typedef struct call_control cc_t; @@ -871,7 +872,13 @@ static switch_status_t control_playback(switch_core_session_t *session, void *in || dtmf->digit == *cc->profile->prev_msg_key || dtmf->digit == *cc->profile->next_msg_key || dtmf->digit == *cc->profile->repeat_msg_key || dtmf->digit == *cc->profile->terminator_key || dtmf->digit == *cc->profile->skip_info_key - || dtmf->digit == *cc->profile->email_key || dtmf->digit == *cc->profile->forward_key)) { + || dtmf->digit == *cc->profile->forward_key)) { + *cc->buf = dtmf->digit; + return SWITCH_STATUS_BREAK; + } + + if (!cc->playback_controls_active + && (dtmf->digit == *cc->profile->email_key)) { *cc->buf = dtmf->digit; return SWITCH_STATUS_BREAK; } @@ -907,10 +914,6 @@ static switch_status_t control_playback(switch_core_session_t *session, void *in switch_core_file_seek(fh, &pos, samps, SEEK_CUR); return SWITCH_STATUS_SUCCESS; } - if (!cc->noexit && dtmf->digit == *cc->profile->terminator_key) { - *cc->buf = dtmf->digit; - return SWITCH_STATUS_BREAK; - } } break; default: @@ -1568,9 +1571,11 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t *cc.buf = '\0'; memset(&fh, 0, sizeof(fh)); cc.fh = &fh; + cc.playback_controls_active = 1; if (switch_file_exists(cbt->file_path, switch_core_session_get_pool(session)) == SWITCH_STATUS_SUCCESS) { TRY_CODE(switch_ivr_play_file(session, &fh, cbt->file_path, &args)); } + cc.playback_controls_active = 0; } if (!*cc.buf && (profile->play_date_announcement == VM_DATE_LAST)) { From a91691999d4410672f37f45cf17306ac8863fcb1 Mon Sep 17 00:00:00 2001 From: Daniel Swarbrick Date: Wed, 7 Sep 2011 23:50:25 +0200 Subject: [PATCH 042/204] add MongoDB CDR module --- .../event_handlers/mod_cdr_mongodb/Makefile | 9 + .../mod_cdr_mongodb/driver/APACHE-2.0.txt | 202 +++ .../mod_cdr_mongodb/driver/HISTORY.md | 139 ++ .../mod_cdr_mongodb/driver/README.md | 60 + .../mod_cdr_mongodb/driver/SConstruct | 178 +++ .../mod_cdr_mongodb/driver/src/bson.c | 978 +++++++++++++ .../mod_cdr_mongodb/driver/src/bson.h | 975 +++++++++++++ .../mod_cdr_mongodb/driver/src/encoding.c | 148 ++ .../mod_cdr_mongodb/driver/src/encoding.h | 54 + .../mod_cdr_mongodb/driver/src/gridfs.c | 685 ++++++++++ .../mod_cdr_mongodb/driver/src/gridfs.h | 326 +++++ .../mod_cdr_mongodb/driver/src/md5.c | 381 ++++++ .../mod_cdr_mongodb/driver/src/md5.h | 91 ++ .../mod_cdr_mongodb/driver/src/mongo.c | 1217 +++++++++++++++++ .../mod_cdr_mongodb/driver/src/mongo.h | 648 +++++++++ .../mod_cdr_mongodb/driver/src/net.c | 98 ++ .../mod_cdr_mongodb/driver/src/net.h | 57 + .../mod_cdr_mongodb/driver/src/numbers.c | 127 ++ .../mod_cdr_mongodb/driver/src/platform.h | 94 ++ .../driver/src/platform/linux/net.c | 183 +++ .../driver/src/platform/linux/net.h | 51 + .../mod_cdr_mongodb/mod_cdr_mongodb.c | 413 ++++++ 22 files changed, 7114 insertions(+) create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/Makefile create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/APACHE-2.0.txt create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/HISTORY.md create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/README.md create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/SConstruct create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/src/bson.c create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/src/bson.h create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/src/encoding.c create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/src/encoding.h create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/src/gridfs.c create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/src/gridfs.h create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/src/md5.c create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/src/md5.h create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/src/mongo.c create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/src/mongo.h create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/src/net.c create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/src/net.h create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/src/numbers.c create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/src/platform.h create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/src/platform/linux/net.c create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/driver/src/platform/linux/net.h create mode 100644 src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c diff --git a/src/mod/event_handlers/mod_cdr_mongodb/Makefile b/src/mod/event_handlers/mod_cdr_mongodb/Makefile new file mode 100644 index 0000000000..b9e04b983d --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/Makefile @@ -0,0 +1,9 @@ +include ../../../../build/modmake.rules + +MONGODB_DRIVER=./driver/src +LOCAL_CFLAGS=-I$(MONGODB_DRIVER) +LOCAL_OBJS=$(MONGODB_DRIVER)/md5.o \ + $(MONGODB_DRIVER)/mongo.o $(MONGODB_DRIVER)/net.o \ + $(MONGODB_DRIVER)/bson.o $(MONGODB_DRIVER)/numbers.o $(MONGODB_DRIVER)/encoding.o \ + +local_depend: $(LOCAL_OBJS) diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/APACHE-2.0.txt b/src/mod/event_handlers/mod_cdr_mongodb/driver/APACHE-2.0.txt new file mode 100644 index 0000000000..d645695673 --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/APACHE-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/HISTORY.md b/src/mod/event_handlers/mod_cdr_mongodb/driver/HISTORY.md new file mode 100644 index 0000000000..f3f0fab21d --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/HISTORY.md @@ -0,0 +1,139 @@ +# MongoDB C Driver History + +## 0.4 + +THIS RELEASE INCLUDES NUMEROUS BACKWARD-BREAKING CHANGES. +These changes have been made for extensibility, consistency, +and ease of use. Please read the following release notes +carefully, and study the updated tutorial. + +API Principles: + +1. Present a consistent interface for all objects: connections, + cursors, bson objects, and bson iterators. +2. Require no knowledge of an object's implementation to use the API. +3. Allow users to allocate objects on the stack or on the heap. +4. Integrate API with new error reporting strategy. +5. Be concise, except where it impairs clarity. + +Changes: + +* mongo_replset_init_conn has been renamed to mongo_replset_init. +* bson_buffer has been removed. All functions for building bson + objects now take objects of type bson. The new pattern looks like this: + + Example: + + bson b[1]; + bson_init( b ); + bson_append_int( b, "foo", 1 ); + bson_finish( b ); + /* The object is ready to use. + When finished, destroy it. */ + bson_destroy( b ); + +* mongo_connection has been renamed to mongo. + + Example: + + mongo conn[1]; + mongo_connect( conn, '127.0.0.1', 27017 ); + /* Connection is ready. Destroy when down. */ + mongo_destroy( conn ); + +* New cursor builder API for clearer code: + + Example: + + mongo_cursor cursor[1]; + mongo_cursor_init( cursor, conn, "test.foo" ); + + bson query[1]; + + bson_init( query ); + bson_append_int( query, "bar", 1 ); + bson_finish( query ); + + bson fields[1]; + + bson_init( fields ); + bson_append_int( fields, "baz", 1 ); + bson_finish( fields ); + + mongo_cursor_set_query( cursor, query ); + mongo_cursor_set_fields( cursor, fields ); + mongo_cursor_set_limit( cursor, 10 ); + mongo_cursor_set_skip( cursor, 10 ); + + while( mongo_cursor_next( cursor ) == MONGO_OK ) + bson_print( mongo_cursor_bson( cursor ) ); + +* bson_iterator_init now takes a (bson*) instead of a (const char*). This is consistent + with bson_find, which also takes a (bson*). If you want to initiate a bson iterator + with a buffer, use the new function bson_iterator_from_buffer. +* With the addition of the mongo_cursor_bson function, it's now no + longer necessary to know how bson and mongo_cursor objects are implemented. + + Example: + + bson b[1]; + bson_iterator i[1]; + + bson_iterator_init( i, b ); + + /* With a cursor */ + bson_iterator_init( i, mongo_cursor_bson( cursor ) ); + +* Added mongo_cursor_data and bson_data functions, which return the + raw bson buffer as a (const char *). +* All constants that were once lower case are now + upper case. These include: MONGO_OP_MSG, MONGO_OP_UPDATE, MONGO_OP_INSERT, + MONGO_OP_QUERY, MONGO_OP_GET_MORE, MONGO_OP_DELETE, MONGO_OP_KILL_CURSORS + BSON_EOO, BSON_DOUBLE, BSON_STRING, BSON_OBJECT, BSON_ARRAY, BSON_BINDATA, + BSON_UNDEFINED, BSON_OID, BSON_BOOL, BSON_DATE, BSON_NULL, BSON_REGEX, BSON_DBREF, + BSON_CODE, BSON_SYMBOL, BSON_CODEWSCOPE, BSON_INT, BSON_TIMESTAMP, BSON_LONG, + MONGO_CONN_SUCCESS, MONGO_CONN_BAD_ARG, MONGO_CONN_NO_SOCKET, MONGO_CONN_FAIL, + MONGO_CONN_NOT_MASTER, MONGO_CONN_BAD_SET_NAME, MONGO_CONN_CANNOT_FIND_PRIMARY + If your programs use any of these constants, you must convert them to their + upper case forms, or you will see compile errors. +* The error handling strategy has been changed. Exceptions are not longer being used. +* Functions taking a mongo_connection object now return either MONGO_OK or MONGO_ERROR. + In case of an error, an error code of type mongo_error_t will be indicated on the + mongo_connection->err field. +* Functions taking a bson object now return either BSON_OK or BSON_ERROR. + In case of an error, an error code of type bson_validity_t will be indicated on the + bson->err or bson_buffer->err field. +* Calls to mongo_cmd_get_last_error store the error status on the + mongo->lasterrcode and mongo->lasterrstr fields. +* bson_print now prints all types. +* Users may now set custom malloc, realloc, free, printf, sprintf, and fprintf fields. +* Groundwork for modules for supporting platform-specific features (e.g., socket timeouts). +* Added mongo_set_op_timeout for setting socket timeout. To take advantage of this, you must + compile with --use-platform=LINUX. The compiles with platform/linux/net.h instead of the + top-level net.h. +* Fixed tailable cursors. +* GridFS API is now in-line with the new driver API. In particular, all of the + following functions now return MONGO_OK or MONGO_ERROR: gridfs_init, + gridfile_init, gridfile_writer_done, gridfs_store_buffer, gridfs_store_file, + and gridfs_find_query. +* Fixed a few memory leaks. + +## 0.3 +2011-4-14 + +* Support replica sets. +* Better standard connection API. +* GridFS write buffers iteratively. +* Fixes for working with large GridFS files (> 3GB) +* bson_append_string_n and family (Gergely Nagy) + +## 0.2 +2011-2-11 + +* GridFS support (Chris Triolo). +* BSON Timestamp type support. + +## 0.1 +2009-11-30 + +* Initial release. diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/README.md b/src/mod/event_handlers/mod_cdr_mongodb/driver/README.md new file mode 100644 index 0000000000..1afe39e69c --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/README.md @@ -0,0 +1,60 @@ +# MongoDB C Driver + +This is then 10gen-supported MongoDB C driver. There are two goals for this driver. +The first is to provide a strict, default compilation option for ultimate portability, +no dependencies, and generic embeddability. + +The second is to support more advanced, platform-specific features, like socket timeout, +by providing an interface for platform-specific modules. + +Until the 1.0 release, this driver should be considered alpha. Keep in mind that the API will be in flux until then. + +# Building + +First check out the version you want to build. *Always build from a particular tag, since HEAD may be +a work in progress.* For example, to build version 0.4, run: + + git checkout v0.4 + +You can then build the driver with scons: + + scons + +## Running the tests +Make sure that you're running mongod on 127.0.0.1 on the default port (27017). The replica set +test assumes a replica set with at least three nodes running at 127.0.0.1 and starting at port +30000. Note that the driver does not recognize 'localhost' as a valid host name. + +To compile and run the tests: + + scons test + +# Error Handling +Most functions return MONGO_OK or BSON_OK on success and MONGO_ERROR or BSON_ERROR on failure. +Specific error codes and error strings are then stored in the `err` and `errstr` fields of the +`mongo` and `bson` objects. It is the client's responsibility to check for errors and handle +them appropriately. + +# Docs +The docs are built using Sphinx and Doxygen. If you have these tools installed, then +you can build the docs with scons: + + scons docs + +The html docs will appear in docs/html. + +# ISSUES + +You can report bugs, request new features, and view this driver's roadmap +using [JIRA](http://jira.mongodb.org/browse/CDRIVER). + +# CREDITS + +* Gergely Nagy - Non-null-terminated string support. +* Josh Rotenberg - Initial Doxygen setup and a significant chunk of documentation. + +# LICENSE + +Unless otherwise specified in a source file, sources in this +repository are published under the terms of the Apache License version +2.0, a copy of which is in this repository as APACHE-2.0.txt. diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/SConstruct b/src/mod/event_handlers/mod_cdr_mongodb/driver/SConstruct new file mode 100644 index 0000000000..d3be2d89a6 --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/SConstruct @@ -0,0 +1,178 @@ +# -*- mode: python; -*- + +VERSION = "0.4" + +# --- options ---- +AddOption('--test-server', + dest='test_server', + default='127.0.0.1', + type='string', + nargs=1, + action='store', + help='IP address of server to use for testing') + +AddOption('--seed-start-port', + dest='seed_start_port', + default=30000, + type='int', + nargs=1, + action='store', + help='IP address of server to use for testing') + +AddOption('--c99', + dest='use_c99', + default=False, + action='store_true', + help='Compile with c99 (recommended for gcc)') + +AddOption('--d', + dest='optimize', + default=True, + action='store_false', + help='disable optimizations') + +AddOption('--use-platform', + dest='compile_platform', + default='GENERIC', + type='string', + nargs=1, + action='store', + help='Compile for a specific platform to take advantage ' + ' of particular system features. For the moment, this include timeouts only.' + ' Current options include LINUX, ' + ' GENERIC, and CUSTOM. If you specific CUSTOM, you must place a' + ' system-specific implementation of net.h and net.c in src/platform/custom/') + +import os, sys + +env = Environment( ENV=os.environ ) + +# ---- Docs ---- +def build_docs(env, target, source): + buildscript_path = os.path.join(os.path.abspath("docs")) + sys.path.insert(0, buildscript_path) + import buildscripts + from buildscripts import docs + docs.main() + +env.Alias("docs", [], [build_docs]) +env.AlwaysBuild("docs") + +# ---- Platforms ---- +PLATFORM_TEST_DIR = None +if "LINUX" == GetOption('compile_platform'): + env.Append( CPPFLAGS=" -D_MONGO_USE_LINUX_SYSTEM" ) + NET_LIB = "src/platform/linux/net.c" + PLATFORM_TEST_DIR = "test/platform/linux/" + PLATFORM_TESTS = [ "timeouts" ] +elif "CUSTOM" == GetOption('compile_platform'): + env.Append( CPPFLAGS=" -D_MONGO_USE_CUSTOM_SYSTEM" ) + NET_LIB = "src/platform/custom/net.c" +else: + NET_LIB = "src/net.c" + +# ---- Libraries ---- +if os.sys.platform in ["darwin", "linux2"]: + env.Append( CPPFLAGS=" -pedantic -Wall -ggdb -DMONGO_HAVE_STDINT" ) + env.Append( CPPPATH=["/opt/local/include/"] ) + env.Append( LIBPATH=["/opt/local/lib/"] ) + + if GetOption('use_c99'): + env.Append( CFLAGS=" -std=c99 " ) + env.Append( CXXDEFINES="MONGO_HAVE_STDINT" ) + else: + env.Append( CFLAGS=" -ansi " ) + + if GetOption('optimize'): + env.Append( CPPFLAGS=" -O3 " ) + # -O3 benchmarks *significantly* faster than -O2 when disabling networking +elif 'win32' == os.sys.platform: + env.Append( LIBS='ws2_32' ) + +#we shouldn't need these options in c99 mode +if not GetOption('use_c99'): + conf = Configure(env) + + if not conf.CheckType('int64_t'): + if conf.CheckType('int64_t', '#include \n'): + conf.env.Append( CPPDEFINES="MONGO_HAVE_STDINT" ) + elif conf.CheckType('int64_t', '#include \n'): + conf.env.Append( CPPDEFINES="MONGO_HAVE_UNISTD" ) + elif conf.CheckType('__int64'): + conf.env.Append( CPPDEFINES="MONGO_USE__INT64" ) + elif conf.CheckType('long long int'): + conf.env.Append( CPPDEFINES="MONGO_USE_LONG_LONG_INT" ) + else: + print "*** what is your 64 bit int type? ****" + Exit(1) + + env = conf.Finish() + +have_libjson = False +conf = Configure(env) +if conf.CheckLib('json'): + have_libjson = True +env = conf.Finish() + +if sys.byteorder == 'big': + env.Append( CPPDEFINES="MONGO_BIG_ENDIAN" ) + +env.Append( CPPPATH=["src/"] ) + +coreFiles = ["src/md5.c" ] +mFiles = [ "src/mongo.c", NET_LIB, "src/gridfs.c"] +bFiles = [ "src/bson.c", "src/numbers.c", "src/encoding.c"] +mLibFiles = coreFiles + mFiles + bFiles +bLibFiles = coreFiles + bFiles +m = env.Library( "mongoc" , mLibFiles ) +b = env.Library( "bson" , bLibFiles ) +env.Default( env.Alias( "lib" , [ m[0] , b[0] ] ) ) + +if os.sys.platform == "linux2": + env.Append( SHLINKFLAGS="-shared -Wl,-soname,libmongoc.so." + VERSION ) + env.Append( SHLINKFLAGS = "-shared -Wl,-soname,libbson.so." + VERSION ) + +dynm = env.SharedLibrary( "mongoc" , mLibFiles ) +dynb = env.SharedLibrary( "bson" , bLibFiles ) +env.Default( env.Alias( "sharedlib" , [ dynm[0] , dynb[0] ] ) ) + + + +# ---- Benchmarking ---- +benchmarkEnv = env.Clone() +benchmarkEnv.Append( CPPDEFINES=[('TEST_SERVER', r'\"%s\"'%GetOption('test_server')), +('SEED_START_PORT', r'%d'%GetOption('seed_start_port'))] ) +benchmarkEnv.Append( LIBS=[m, b] ) +benchmarkEnv.Prepend( LIBPATH=["."] ) +benchmarkEnv.Program( "benchmark" , [ "test/benchmark.c"] ) + +# ---- Tests ---- +testEnv = benchmarkEnv.Clone() +testCoreFiles = [ ] + +def run_tests( root, tests ): + for name in tests: + filename = "%s/%s.c" % (root, name) + exe = "test_" + name + test = testEnv.Program( exe , testCoreFiles + [filename] ) + test_alias = testEnv.Alias('test', [test], test[0].abspath + ' 2> ' + os.path.devnull) + AlwaysBuild(test_alias) + +tests = Split("sizes resize endian_swap bson bson_subobject simple update errors " +"count_delete auth gridfs validate examples helpers oid functions cursors replica_set") + +# Run standard tests +run_tests("test", tests) + +# Run platform tests +if not PLATFORM_TEST_DIR is None: + run_tests( PLATFORM_TEST_DIR, PLATFORM_TESTS ) + +if have_libjson: + tests.append('json') + testEnv.Append( LIBS=["json"] ) + +# special case for cpptest +test = testEnv.Program( 'test_cpp' , testCoreFiles + ['test/cpptest.cpp'] ) +test_alias = testEnv.Alias('test', [test], test[0].abspath + ' 2> '+ os.path.devnull) +AlwaysBuild(test_alias) diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/bson.c b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/bson.c new file mode 100644 index 0000000000..349f42284c --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/bson.c @@ -0,0 +1,978 @@ +/* bson.c */ + +/* Copyright 2009, 2010 10gen Inc. + * + * 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 +#include +#include +#include +#include + +#include "bson.h" +#include "encoding.h" + +const int initialBufferSize = 128; + +/* only need one of these */ +static const int zero = 0; + +/* Custom standard function pointers. */ +void *( *bson_malloc_func )( size_t ) = malloc; +void *( *bson_realloc_func )( void *, size_t ) = realloc; +void ( *bson_free )( void * ) = free; +bson_printf_func bson_printf = printf; +bson_fprintf_func bson_fprintf = fprintf; +bson_sprintf_func bson_sprintf = sprintf; + +static int _bson_errprintf( const char *, ... ); +bson_printf_func bson_errprintf = _bson_errprintf; + +/* ObjectId fuzz functions. */ +static int ( *oid_fuzz_func )( void ) = NULL; +static int ( *oid_inc_func )( void ) = NULL; + +/* ---------------------------- + READING + ------------------------------ */ + +bson *bson_empty( bson *obj ) { + static char *data = "\005\0\0\0\0"; + bson_init_data( obj, data ); + obj->finished = 1; + obj->err = 0; + obj->stackPos = 0; + return obj; +} + +void bson_copy_basic( bson *out, const bson *in ) { + if ( !out ) return; + bson_init_size( out, bson_size( in ) ); + memcpy( out->data, in->data, bson_size( in ) ); +} + +void bson_copy( bson *out, const bson *in ) { + int i; + + if ( !out ) return; + bson_copy_basic( out, in ); + out->cur = out->data + ( in->cur - in->data ); + out->dataSize = in->dataSize; + out->finished = in->finished; + out->stackPos = in->stackPos; + out->err = in->err; + for( i=0; istackPos; i++ ) + out->stack[i] = in->stack[i]; +} + +int bson_init_data( bson *b, char *data ) { + b->data = data; + return BSON_OK; +} + +static void _bson_reset( bson *b ) { + b->finished = 0; + b->stackPos = 0; + b->err = 0; + b->errstr = NULL; +} + +int bson_size( const bson *b ) { + int i; + if ( ! b || ! b->data ) + return 0; + bson_little_endian32( &i, b->data ); + return i; +} + +const char *bson_data( bson *b ) { + return (const char *)b->data; +} + +static char hexbyte( char hex ) { + switch ( hex ) { + case '0': + return 0x0; + case '1': + return 0x1; + case '2': + return 0x2; + case '3': + return 0x3; + case '4': + return 0x4; + case '5': + return 0x5; + case '6': + return 0x6; + case '7': + return 0x7; + case '8': + return 0x8; + case '9': + return 0x9; + case 'a': + case 'A': + return 0xa; + case 'b': + case 'B': + return 0xb; + case 'c': + case 'C': + return 0xc; + case 'd': + case 'D': + return 0xd; + case 'e': + case 'E': + return 0xe; + case 'f': + case 'F': + return 0xf; + default: + return 0x0; /* something smarter? */ + } +} + +void bson_oid_from_string( bson_oid_t *oid, const char *str ) { + int i; + for ( i=0; i<12; i++ ) { + oid->bytes[i] = ( hexbyte( str[2*i] ) << 4 ) | hexbyte( str[2*i + 1] ); + } +} + +void bson_oid_to_string( const bson_oid_t *oid, char *str ) { + static const char hex[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; + int i; + for ( i=0; i<12; i++ ) { + str[2*i] = hex[( oid->bytes[i] & 0xf0 ) >> 4]; + str[2*i + 1] = hex[ oid->bytes[i] & 0x0f ]; + } + str[24] = '\0'; +} + +void bson_set_oid_fuzz( int ( *func )( void ) ) { + oid_fuzz_func = func; +} + +void bson_set_oid_inc( int ( *func )( void ) ) { + oid_inc_func = func; +} + +void bson_oid_gen( bson_oid_t *oid ) { + static int incr = 0; + static int fuzz = 0; + int i; + int t = time( NULL ); + + if( oid_inc_func ) + i = oid_inc_func(); + else + i = incr++; + + if ( !fuzz ) { + if ( oid_fuzz_func ) + fuzz = oid_fuzz_func(); + else { + srand( t ); + fuzz = rand(); + } + } + + bson_big_endian32( &oid->ints[0], &t ); + oid->ints[1] = fuzz; + bson_big_endian32( &oid->ints[2], &i ); +} + +time_t bson_oid_generated_time( bson_oid_t *oid ) { + time_t out; + bson_big_endian32( &out, &oid->ints[0] ); + + return out; +} + +void bson_print( bson *b ) { + bson_print_raw( b->data , 0 ); +} + +void bson_print_raw( const char *data , int depth ) { + bson_iterator i; + const char *key; + int temp; + bson_timestamp_t ts; + char oidhex[25]; + bson scope; + bson_iterator_from_buffer( &i, data ); + + while ( bson_iterator_next( &i ) ) { + bson_type t = bson_iterator_type( &i ); + if ( t == 0 ) + break; + key = bson_iterator_key( &i ); + + for ( temp=0; temp<=depth; temp++ ) + printf( "\t" ); + bson_printf( "%s : %d \t " , key , t ); + switch ( t ) { + case BSON_DOUBLE: + printf( "%f" , bson_iterator_double( &i ) ); + break; + case BSON_STRING: + printf( "%s" , bson_iterator_string( &i ) ); + break; + case BSON_SYMBOL: + printf( "SYMBOL: %s" , bson_iterator_string( &i ) ); + break; + case BSON_OID: + bson_oid_to_string( bson_iterator_oid( &i ), oidhex ); + printf( "%s" , oidhex ); + break; + case BSON_BOOL: + printf( "%s" , bson_iterator_bool( &i ) ? "true" : "false" ); + break; + case BSON_DATE: + printf( "%ld" , ( long int )bson_iterator_date( &i ) ); + break; + case BSON_BINDATA: + printf( "BSON_BINDATA" ); + break; + case BSON_UNDEFINED: + printf( "BSON_UNDEFINED" ); + break; + case BSON_NULL: + printf( "BSON_NULL" ); + break; + case BSON_REGEX: + printf( "BSON_REGEX: %s", bson_iterator_regex( &i ) ); + break; + case BSON_CODE: + printf( "BSON_CODE: %s", bson_iterator_code( &i ) ); + break; + case BSON_CODEWSCOPE: + printf( "BSON_CODE_W_SCOPE: %s", bson_iterator_code( &i ) ); + bson_init( &scope ); + bson_iterator_code_scope( &i, &scope ); + printf( "\n\t SCOPE: " ); + bson_print( &scope ); + break; + case BSON_INT: + printf( "%d" , bson_iterator_int( &i ) ); + break; + case BSON_LONG: + printf( "%lld" , ( long long int )bson_iterator_long( &i ) ); + break; + case BSON_TIMESTAMP: + ts = bson_iterator_timestamp( &i ); + printf( "i: %d, t: %d", ts.i, ts.t ); + break; + case BSON_OBJECT: + case BSON_ARRAY: + printf( "\n" ); + bson_print_raw( bson_iterator_value( &i ) , depth + 1 ); + break; + default: + bson_errprintf( "can't print type : %d\n" , t ); + } + printf( "\n" ); + } +} + +/* ---------------------------- + ITERATOR + ------------------------------ */ + +void bson_iterator_init( bson_iterator *i, const bson *b ) { + i->cur = b->data + 4; + i->first = 1; +} + +void bson_iterator_from_buffer( bson_iterator *i, const char *buffer ) { + i->cur = buffer + 4; + i->first = 1; +} + +bson_type bson_find( bson_iterator *it, const bson *obj, const char *name ) { + bson_iterator_init( it, (bson *)obj ); + while( bson_iterator_next( it ) ) { + if ( strcmp( name, bson_iterator_key( it ) ) == 0 ) + break; + } + return bson_iterator_type( it ); +} + +bson_bool_t bson_iterator_more( const bson_iterator *i ) { + return *( i->cur ); +} + +bson_type bson_iterator_next( bson_iterator *i ) { + int ds; + + if ( i->first ) { + i->first = 0; + return ( bson_type )( *i->cur ); + } + + switch ( bson_iterator_type( i ) ) { + case BSON_EOO: + return BSON_EOO; /* don't advance */ + case BSON_UNDEFINED: + case BSON_NULL: + ds = 0; + break; + case BSON_BOOL: + ds = 1; + break; + case BSON_INT: + ds = 4; + break; + case BSON_LONG: + case BSON_DOUBLE: + case BSON_TIMESTAMP: + case BSON_DATE: + ds = 8; + break; + case BSON_OID: + ds = 12; + break; + case BSON_STRING: + case BSON_SYMBOL: + case BSON_CODE: + ds = 4 + bson_iterator_int_raw( i ); + break; + case BSON_BINDATA: + ds = 5 + bson_iterator_int_raw( i ); + break; + case BSON_OBJECT: + case BSON_ARRAY: + case BSON_CODEWSCOPE: + ds = bson_iterator_int_raw( i ); + break; + case BSON_DBREF: + ds = 4+12 + bson_iterator_int_raw( i ); + break; + case BSON_REGEX: { + const char *s = bson_iterator_value( i ); + const char *p = s; + p += strlen( p )+1; + p += strlen( p )+1; + ds = p-s; + break; + } + + default: { + char msg[] = "unknown type: 000000000000"; + bson_numstr( msg+14, ( unsigned )( i->cur[0] ) ); + bson_fatal_msg( 0, msg ); + return 0; + } + } + + i->cur += 1 + strlen( i->cur + 1 ) + 1 + ds; + + return ( bson_type )( *i->cur ); +} + +bson_type bson_iterator_type( const bson_iterator *i ) { + return ( bson_type )i->cur[0]; +} + +const char *bson_iterator_key( const bson_iterator *i ) { + return i->cur + 1; +} + +const char *bson_iterator_value( const bson_iterator *i ) { + const char *t = i->cur + 1; + t += strlen( t ) + 1; + return t; +} + +/* types */ + +int bson_iterator_int_raw( const bson_iterator *i ) { + int out; + bson_little_endian32( &out, bson_iterator_value( i ) ); + return out; +} + +double bson_iterator_double_raw( const bson_iterator *i ) { + double out; + bson_little_endian64( &out, bson_iterator_value( i ) ); + return out; +} + +int64_t bson_iterator_long_raw( const bson_iterator *i ) { + int64_t out; + bson_little_endian64( &out, bson_iterator_value( i ) ); + return out; +} + +bson_bool_t bson_iterator_bool_raw( const bson_iterator *i ) { + return bson_iterator_value( i )[0]; +} + +bson_oid_t *bson_iterator_oid( const bson_iterator *i ) { + return ( bson_oid_t * )bson_iterator_value( i ); +} + +int bson_iterator_int( const bson_iterator *i ) { + switch ( bson_iterator_type( i ) ) { + case BSON_INT: + return bson_iterator_int_raw( i ); + case BSON_LONG: + return bson_iterator_long_raw( i ); + case BSON_DOUBLE: + return bson_iterator_double_raw( i ); + default: + return 0; + } +} + +double bson_iterator_double( const bson_iterator *i ) { + switch ( bson_iterator_type( i ) ) { + case BSON_INT: + return bson_iterator_int_raw( i ); + case BSON_LONG: + return bson_iterator_long_raw( i ); + case BSON_DOUBLE: + return bson_iterator_double_raw( i ); + default: + return 0; + } +} + +int64_t bson_iterator_long( const bson_iterator *i ) { + switch ( bson_iterator_type( i ) ) { + case BSON_INT: + return bson_iterator_int_raw( i ); + case BSON_LONG: + return bson_iterator_long_raw( i ); + case BSON_DOUBLE: + return bson_iterator_double_raw( i ); + default: + return 0; + } +} + +bson_timestamp_t bson_iterator_timestamp( const bson_iterator *i ) { + bson_timestamp_t ts; + bson_little_endian32( &( ts.i ), bson_iterator_value( i ) ); + bson_little_endian32( &( ts.t ), bson_iterator_value( i ) + 4 ); + return ts; +} + +bson_bool_t bson_iterator_bool( const bson_iterator *i ) { + switch ( bson_iterator_type( i ) ) { + case BSON_BOOL: + return bson_iterator_bool_raw( i ); + case BSON_INT: + return bson_iterator_int_raw( i ) != 0; + case BSON_LONG: + return bson_iterator_long_raw( i ) != 0; + case BSON_DOUBLE: + return bson_iterator_double_raw( i ) != 0; + case BSON_EOO: + case BSON_NULL: + return 0; + default: + return 1; + } +} + +const char *bson_iterator_string( const bson_iterator *i ) { + return bson_iterator_value( i ) + 4; +} + +int bson_iterator_string_len( const bson_iterator *i ) { + return bson_iterator_int_raw( i ); +} + +const char *bson_iterator_code( const bson_iterator *i ) { + switch ( bson_iterator_type( i ) ) { + case BSON_STRING: + case BSON_CODE: + return bson_iterator_value( i ) + 4; + case BSON_CODEWSCOPE: + return bson_iterator_value( i ) + 8; + default: + return NULL; + } +} + +void bson_iterator_code_scope( const bson_iterator *i, bson *scope ) { + if ( bson_iterator_type( i ) == BSON_CODEWSCOPE ) { + int code_len; + bson_little_endian32( &code_len, bson_iterator_value( i )+4 ); + bson_init_data( scope, ( void * )( bson_iterator_value( i )+8+code_len ) ); + } else { + bson_empty( scope ); + } +} + +bson_date_t bson_iterator_date( const bson_iterator *i ) { + return bson_iterator_long_raw( i ); +} + +time_t bson_iterator_time_t( const bson_iterator *i ) { + return bson_iterator_date( i ) / 1000; +} + +int bson_iterator_bin_len( const bson_iterator *i ) { + return ( bson_iterator_bin_type( i ) == BSON_BIN_BINARY_OLD ) + ? bson_iterator_int_raw( i ) - 4 + : bson_iterator_int_raw( i ); +} + +char bson_iterator_bin_type( const bson_iterator *i ) { + return bson_iterator_value( i )[4]; +} + +const char *bson_iterator_bin_data( const bson_iterator *i ) { + return ( bson_iterator_bin_type( i ) == BSON_BIN_BINARY_OLD ) + ? bson_iterator_value( i ) + 9 + : bson_iterator_value( i ) + 5; +} + +const char *bson_iterator_regex( const bson_iterator *i ) { + return bson_iterator_value( i ); +} + +const char *bson_iterator_regex_opts( const bson_iterator *i ) { + const char *p = bson_iterator_value( i ); + return p + strlen( p ) + 1; + +} + +void bson_iterator_subobject( const bson_iterator *i, bson *sub ) { + bson_init_data( sub, ( char * )bson_iterator_value( i ) ); + _bson_reset( sub ); + sub->finished = 1; +} + +void bson_iterator_subiterator( const bson_iterator *i, bson_iterator *sub ) { + bson_iterator_from_buffer( sub, bson_iterator_value( i ) ); +} + +/* ---------------------------- + BUILDING + ------------------------------ */ + +static void _bson_init_size( bson *b, int size ) { + if( size == 0 ) + b->data = NULL; + else + b->data = ( char * )bson_malloc( size ); + b->dataSize = size; + b->cur = b->data + 4; + _bson_reset( b ); +} + +void bson_init( bson *b ) { + _bson_init_size( b, initialBufferSize ); +} + +void bson_init_size( bson *b, int size ) { + _bson_init_size( b, size ); +} + +void bson_append_byte( bson *b, char c ) { + b->cur[0] = c; + b->cur++; +} + +void bson_append( bson *b, const void *data, int len ) { + memcpy( b->cur , data , len ); + b->cur += len; +} + +void bson_append32( bson *b, const void *data ) { + bson_little_endian32( b->cur, data ); + b->cur += 4; +} + +void bson_append64( bson *b, const void *data ) { + bson_little_endian64( b->cur, data ); + b->cur += 8; +} + +int bson_ensure_space( bson *b, const int bytesNeeded ) { + int pos = b->cur - b->data; + char *orig = b->data; + int new_size; + + if ( pos + bytesNeeded <= b->dataSize ) + return BSON_OK; + + new_size = 1.5 * ( b->dataSize + bytesNeeded ); + + if( new_size < b->dataSize ) { + if( ( b->dataSize + bytesNeeded ) < INT_MAX ) + new_size = INT_MAX; + else { + b->err = BSON_SIZE_OVERFLOW; + return BSON_ERROR; + } + } + + b->data = bson_realloc( b->data, new_size ); + if ( !b->data ) + bson_fatal_msg( !!b->data, "realloc() failed" ); + + b->dataSize = new_size; + b->cur += b->data - orig; + + return BSON_OK; +} + +int bson_finish( bson *b ) { + int i; + + if( b->err & BSON_NOT_UTF8 ) + return BSON_ERROR; + + if ( ! b->finished ) { + if ( bson_ensure_space( b, 1 ) == BSON_ERROR ) return BSON_ERROR; + bson_append_byte( b, 0 ); + i = b->cur - b->data; + bson_little_endian32( b->data, &i ); + b->finished = 1; + } + + return BSON_OK; +} + +void bson_destroy( bson *b ) { + bson_free( b->data ); + b->err = 0; + b->data = 0; + b->cur = 0; + b->finished = 1; +} + +static int bson_append_estart( bson *b, int type, const char *name, const int dataSize ) { + const int len = strlen( name ) + 1; + + if ( b->finished ) { + b->err |= BSON_ALREADY_FINISHED; + return BSON_ERROR; + } + + if ( bson_ensure_space( b, 1 + len + dataSize ) == BSON_ERROR ) { + return BSON_ERROR; + } + + if( bson_check_field_name( b, ( const char * )name, len - 1 ) == BSON_ERROR ) { + bson_builder_error( b ); + return BSON_ERROR; + } + + bson_append_byte( b, ( char )type ); + bson_append( b, name, len ); + return BSON_OK; +} + +/* ---------------------------- + BUILDING TYPES + ------------------------------ */ + +int bson_append_int( bson *b, const char *name, const int i ) { + if ( bson_append_estart( b, BSON_INT, name, 4 ) == BSON_ERROR ) + return BSON_ERROR; + bson_append32( b , &i ); + return BSON_OK; +} + +int bson_append_long( bson *b, const char *name, const int64_t i ) { + if ( bson_append_estart( b , BSON_LONG, name, 8 ) == BSON_ERROR ) + return BSON_ERROR; + bson_append64( b , &i ); + return BSON_OK; +} + +int bson_append_double( bson *b, const char *name, const double d ) { + if ( bson_append_estart( b, BSON_DOUBLE, name, 8 ) == BSON_ERROR ) + return BSON_ERROR; + bson_append64( b , &d ); + return BSON_OK; +} + +int bson_append_bool( bson *b, const char *name, const bson_bool_t i ) { + if ( bson_append_estart( b, BSON_BOOL, name, 1 ) == BSON_ERROR ) + return BSON_ERROR; + bson_append_byte( b , i != 0 ); + return BSON_OK; +} + +int bson_append_null( bson *b, const char *name ) { + if ( bson_append_estart( b , BSON_NULL, name, 0 ) == BSON_ERROR ) + return BSON_ERROR; + return BSON_OK; +} + +int bson_append_undefined( bson *b, const char *name ) { + if ( bson_append_estart( b, BSON_UNDEFINED, name, 0 ) == BSON_ERROR ) + return BSON_ERROR; + return BSON_OK; +} + +int bson_append_string_base( bson *b, const char *name, + const char *value, int len, bson_type type ) { + + int sl = len + 1; + if ( bson_check_string( b, ( const char * )value, sl - 1 ) == BSON_ERROR ) + return BSON_ERROR; + if ( bson_append_estart( b, type, name, 4 + sl ) == BSON_ERROR ) { + return BSON_ERROR; + } + bson_append32( b , &sl ); + bson_append( b , value , sl - 1 ); + bson_append( b , "\0" , 1 ); + return BSON_OK; +} + +int bson_append_string( bson *b, const char *name, const char *value ) { + return bson_append_string_base( b, name, value, strlen ( value ), BSON_STRING ); +} + +int bson_append_symbol( bson *b, const char *name, const char *value ) { + return bson_append_string_base( b, name, value, strlen ( value ), BSON_SYMBOL ); +} + +int bson_append_code( bson *b, const char *name, const char *value ) { + return bson_append_string_base( b, name, value, strlen ( value ), BSON_CODE ); +} + +int bson_append_string_n( bson *b, const char *name, const char *value, int len ) { + return bson_append_string_base( b, name, value, len, BSON_STRING ); +} + +int bson_append_symbol_n( bson *b, const char *name, const char *value, int len ) { + return bson_append_string_base( b, name, value, len, BSON_SYMBOL ); +} + +int bson_append_code_n( bson *b, const char *name, const char *value, int len ) { + return bson_append_string_base( b, name, value, len, BSON_CODE ); +} + +int bson_append_code_w_scope_n( bson *b, const char *name, + const char *code, int len, const bson *scope ) { + + int sl = len + 1; + int size = 4 + 4 + sl + bson_size( scope ); + if ( bson_append_estart( b, BSON_CODEWSCOPE, name, size ) == BSON_ERROR ) + return BSON_ERROR; + bson_append32( b, &size ); + bson_append32( b, &sl ); + bson_append( b, code, sl ); + bson_append( b, scope->data, bson_size( scope ) ); + return BSON_OK; +} + +int bson_append_code_w_scope( bson *b, const char *name, const char *code, const bson *scope ) { + return bson_append_code_w_scope_n( b, name, code, strlen ( code ), scope ); +} + +int bson_append_binary( bson *b, const char *name, char type, const char *str, int len ) { + if ( type == BSON_BIN_BINARY_OLD ) { + int subtwolen = len + 4; + if ( bson_append_estart( b, BSON_BINDATA, name, 4+1+4+len ) == BSON_ERROR ) + return BSON_ERROR; + bson_append32( b, &subtwolen ); + bson_append_byte( b, type ); + bson_append32( b, &len ); + bson_append( b, str, len ); + } else { + if ( bson_append_estart( b, BSON_BINDATA, name, 4+1+len ) == BSON_ERROR ) + return BSON_ERROR; + bson_append32( b, &len ); + bson_append_byte( b, type ); + bson_append( b, str, len ); + } + return BSON_OK; +} + +int bson_append_oid( bson *b, const char *name, const bson_oid_t *oid ) { + if ( bson_append_estart( b, BSON_OID, name, 12 ) == BSON_ERROR ) + return BSON_ERROR; + bson_append( b , oid , 12 ); + return BSON_OK; +} + +int bson_append_new_oid( bson *b, const char *name ) { + bson_oid_t oid; + bson_oid_gen( &oid ); + return bson_append_oid( b, name, &oid ); +} + +int bson_append_regex( bson *b, const char *name, const char *pattern, const char *opts ) { + const int plen = strlen( pattern )+1; + const int olen = strlen( opts )+1; + if ( bson_append_estart( b, BSON_REGEX, name, plen + olen ) == BSON_ERROR ) + return BSON_ERROR; + if ( bson_check_string( b, pattern, plen - 1 ) == BSON_ERROR ) + return BSON_ERROR; + bson_append( b , pattern , plen ); + bson_append( b , opts , olen ); + return BSON_OK; +} + +int bson_append_bson( bson *b, const char *name, const bson *bson ) { + if ( bson_append_estart( b, BSON_OBJECT, name, bson_size( bson ) ) == BSON_ERROR ) + return BSON_ERROR; + bson_append( b , bson->data , bson_size( bson ) ); + return BSON_OK; +} + +int bson_append_element( bson *b, const char *name_or_null, const bson_iterator *elem ) { + bson_iterator next = *elem; + int size; + + bson_iterator_next( &next ); + size = next.cur - elem->cur; + + if ( name_or_null == NULL ) { + if( bson_ensure_space( b, size ) == BSON_ERROR ) + return BSON_ERROR; + bson_append( b, elem->cur, size ); + } else { + int data_size = size - 2 - strlen( bson_iterator_key( elem ) ); + bson_append_estart( b, elem->cur[0], name_or_null, data_size ); + bson_append( b, bson_iterator_value( elem ), data_size ); + } + + return BSON_OK; +} + +int bson_append_timestamp( bson *b, const char *name, bson_timestamp_t *ts ) { + if ( bson_append_estart( b, BSON_TIMESTAMP, name, 8 ) == BSON_ERROR ) return BSON_ERROR; + + bson_append32( b , &( ts->i ) ); + bson_append32( b , &( ts->t ) ); + + return BSON_OK; +} + +int bson_append_date( bson *b, const char *name, bson_date_t millis ) { + if ( bson_append_estart( b, BSON_DATE, name, 8 ) == BSON_ERROR ) return BSON_ERROR; + bson_append64( b , &millis ); + return BSON_OK; +} + +int bson_append_time_t( bson *b, const char *name, time_t secs ) { + return bson_append_date( b, name, ( bson_date_t )secs * 1000 ); +} + +int bson_append_start_object( bson *b, const char *name ) { + if ( bson_append_estart( b, BSON_OBJECT, name, 5 ) == BSON_ERROR ) return BSON_ERROR; + b->stack[ b->stackPos++ ] = b->cur - b->data; + bson_append32( b , &zero ); + return BSON_OK; +} + +int bson_append_start_array( bson *b, const char *name ) { + if ( bson_append_estart( b, BSON_ARRAY, name, 5 ) == BSON_ERROR ) return BSON_ERROR; + b->stack[ b->stackPos++ ] = b->cur - b->data; + bson_append32( b , &zero ); + return BSON_OK; +} + +int bson_append_finish_object( bson *b ) { + char *start; + int i; + if ( bson_ensure_space( b, 1 ) == BSON_ERROR ) return BSON_ERROR; + bson_append_byte( b , 0 ); + + start = b->data + b->stack[ --b->stackPos ]; + i = b->cur - start; + bson_little_endian32( start, &i ); + + return BSON_OK; +} + +int bson_append_finish_array( bson *b ) { + return bson_append_finish_object( b ); +} + + +/* Error handling and allocators. */ + +static bson_err_handler err_handler = NULL; + +bson_err_handler set_bson_err_handler( bson_err_handler func ) { + bson_err_handler old = err_handler; + err_handler = func; + return old; +} + +void *bson_malloc( int size ) { + void *p; + p = bson_malloc_func( size ); + bson_fatal_msg( !!p, "malloc() failed" ); + return p; +} + +void *bson_realloc( void *ptr, int size ) { + void *p; + p = bson_realloc_func( ptr, size ); + bson_fatal_msg( !!p, "realloc() failed" ); + return p; +} + +int _bson_errprintf( const char *format, ... ) { + va_list ap; + int ret; + va_start( ap, format ); + ret = vfprintf( stderr, format, ap ); + va_end( ap ); + + return ret; +} + +/** + * This method is invoked when a non-fatal bson error is encountered. + * Calls the error handler if available. + * + * @param + */ +void bson_builder_error( bson *b ) { + if( err_handler ) + err_handler( "BSON error." ); +} + +void bson_fatal( int ok ) { + bson_fatal_msg( ok, "" ); +} + +void bson_fatal_msg( int ok , const char *msg ) { + if ( ok ) + return; + + if ( err_handler ) { + err_handler( msg ); + } + + bson_errprintf( "error: %s\n" , msg ); + exit( -5 ); +} + + +/* Efficiently copy an integer to a string. */ +extern const char bson_numstrs[1000][4]; + +void bson_numstr( char *str, int i ) { + if( i < 1000 ) + memcpy( str, bson_numstrs[i], 4 ); + else + bson_sprintf( str,"%d", i ); +} diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/bson.h b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/bson.h new file mode 100644 index 0000000000..2e385b9160 --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/bson.h @@ -0,0 +1,975 @@ +/** + * @file bson.h + * @brief BSON Declarations + */ + +/* Copyright 2009-2011 10gen Inc. + * + * 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 _BSON_H_ +#define _BSON_H_ + +#include "platform.h" +#include +#include +#include +#include +#include + +MONGO_EXTERN_C_START + +#define BSON_OK 0 +#define BSON_ERROR -1 + +enum bson_error_t { + BSON_SIZE_OVERFLOW = 1 /**< Trying to create a BSON object larger than INT_MAX. */ +}; + +enum bson_validity_t { + BSON_VALID = 0, /**< BSON is valid and UTF-8 compliant. */ + BSON_NOT_UTF8 = ( 1<<1 ), /**< A key or a string is not valid UTF-8. */ + BSON_FIELD_HAS_DOT = ( 1<<2 ), /**< Warning: key contains '.' character. */ + BSON_FIELD_INIT_DOLLAR = ( 1<<3 ), /**< Warning: key starts with '$' character. */ + BSON_ALREADY_FINISHED = ( 1<<4 ) /**< Trying to modify a finished BSON object. */ +}; + +enum bson_binary_subtype_t { + BSON_BIN_BINARY = 0, + BSON_BIN_FUNC = 1, + BSON_BIN_BINARY_OLD = 2, + BSON_BIN_UUID = 3, + BSON_BIN_MD5 = 5, + BSON_BIN_USER = 128 +}; + +typedef enum { + BSON_EOO = 0, + BSON_DOUBLE = 1, + BSON_STRING = 2, + BSON_OBJECT = 3, + BSON_ARRAY = 4, + BSON_BINDATA = 5, + BSON_UNDEFINED = 6, + BSON_OID = 7, + BSON_BOOL = 8, + BSON_DATE = 9, + BSON_NULL = 10, + BSON_REGEX = 11, + BSON_DBREF = 12, /**< Deprecated. */ + BSON_CODE = 13, + BSON_SYMBOL = 14, + BSON_CODEWSCOPE = 15, + BSON_INT = 16, + BSON_TIMESTAMP = 17, + BSON_LONG = 18 +} bson_type; + +typedef int bson_bool_t; + +typedef struct { + const char *cur; + bson_bool_t first; +} bson_iterator; + +typedef struct { + char *data; + char *cur; + int dataSize; + bson_bool_t finished; + int stack[32]; + int stackPos; + int err; /**< Bitfield representing errors or warnings on this buffer */ + char *errstr; /**< A string representation of the most recent error or warning. */ +} bson; + +#pragma pack(1) +typedef union { + char bytes[12]; + int ints[3]; +} bson_oid_t; +#pragma pack() + +typedef int64_t bson_date_t; /* milliseconds since epoch UTC */ + +typedef struct { + int i; /* increment */ + int t; /* time in seconds */ +} bson_timestamp_t; + +/* ---------------------------- + READING + ------------------------------ */ + +/** + * Size of a BSON object. + * + * @param b the BSON object. + * + * @return the size. + */ +int bson_size( const bson *b ); + +/** + * Print a string representation of a BSON object. + * + * @param b the BSON object to print. + */ +void bson_print( bson *b ); + +/** + * Return a pointer to the raw buffer stored by this bson object. + * + * @param b a BSON object + */ +const char *bson_data( bson *b ); + +/** + * Print a string representation of a BSON object. + * + * @param bson the raw data to print. + * @param depth the depth to recurse the object.x + */ +void bson_print_raw( const char *bson , int depth ); + +/** + * Advance a bson_iterator to the named field. + * + * @param it the bson_iterator to use. + * @param obj the BSON object to use. + * @param name the name of the field to find. + * + * @return the type of the found object or BSON_EOO if it is not found. + */ +bson_type bson_find( bson_iterator *it, const bson *obj, const char *name ); + +/** + * Initialize a bson_iterator. + * + * @param i the bson_iterator to initialize. + * @param bson the BSON object to associate with the iterator. + */ +void bson_iterator_init( bson_iterator *i , const bson *b ); + +/** + * Initialize a bson iterator from a const char* buffer. Note + * that this is mostly used internally. + * + * @param i the bson_iterator to initialize. + * @param buffer the buffer to point to. + */ +void bson_iterator_from_buffer( bson_iterator *i, const char *buffer ); + +/* more returns true for eoo. best to loop with bson_iterator_next(&it) */ +/** + * Check to see if the bson_iterator has more data. + * + * @param i the iterator. + * + * @return returns true if there is more data. + */ +bson_bool_t bson_iterator_more( const bson_iterator *i ); + +/** + * Point the iterator at the next BSON object. + * + * @param i the bson_iterator. + * + * @return the type of the next BSON object. + */ +bson_type bson_iterator_next( bson_iterator *i ); + +/** + * Get the type of the BSON object currently pointed to by the iterator. + * + * @param i the bson_iterator + * + * @return the type of the current BSON object. + */ +bson_type bson_iterator_type( const bson_iterator *i ); + +/** + * Get the key of the BSON object currently pointed to by the iterator. + * + * @param i the bson_iterator + * + * @return the key of the current BSON object. + */ +const char *bson_iterator_key( const bson_iterator *i ); + +/** + * Get the value of the BSON object currently pointed to by the iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +const char *bson_iterator_value( const bson_iterator *i ); + +/* these convert to the right type (return 0 if non-numeric) */ +/** + * Get the double value of the BSON object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +double bson_iterator_double( const bson_iterator *i ); + +/** + * Get the int value of the BSON object currently pointed to by the iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +int bson_iterator_int( const bson_iterator *i ); + +/** + * Get the long value of the BSON object currently pointed to by the iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +int64_t bson_iterator_long( const bson_iterator *i ); + +/* return the bson timestamp as a whole or in parts */ +/** + * Get the timestamp value of the BSON object currently pointed to by + * the iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +bson_timestamp_t bson_iterator_timestamp( const bson_iterator *i ); + +/** + * Get the boolean value of the BSON object currently pointed to by + * the iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +/* false: boolean false, 0 in any type, or null */ +/* true: anything else (even empty strings and objects) */ +bson_bool_t bson_iterator_bool( const bson_iterator *i ); + +/** + * Get the double value of the BSON object currently pointed to by the + * iterator. Assumes the correct type is used. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +/* these assume you are using the right type */ +double bson_iterator_double_raw( const bson_iterator *i ); + +/** + * Get the int value of the BSON object currently pointed to by the + * iterator. Assumes the correct type is used. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +int bson_iterator_int_raw( const bson_iterator *i ); + +/** + * Get the long value of the BSON object currently pointed to by the + * iterator. Assumes the correct type is used. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +int64_t bson_iterator_long_raw( const bson_iterator *i ); + +/** + * Get the bson_bool_t value of the BSON object currently pointed to by the + * iterator. Assumes the correct type is used. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +bson_bool_t bson_iterator_bool_raw( const bson_iterator *i ); + +/** + * Get the bson_oid_t value of the BSON object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +bson_oid_t *bson_iterator_oid( const bson_iterator *i ); + +/** + * Get the string value of the BSON object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON object. + */ +/* these can also be used with bson_code and bson_symbol*/ +const char *bson_iterator_string( const bson_iterator *i ); + +/** + * Get the string length of the BSON object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the length of the current BSON object. + */ +int bson_iterator_string_len( const bson_iterator *i ); + +/** + * Get the code value of the BSON object currently pointed to by the + * iterator. Works with bson_code, bson_codewscope, and BSON_STRING + * returns NULL for everything else. + * + * @param i the bson_iterator + * + * @return the code value of the current BSON object. + */ +/* works with bson_code, bson_codewscope, and BSON_STRING */ +/* returns NULL for everything else */ +const char *bson_iterator_code( const bson_iterator *i ); + +/** + * Calls bson_empty on scope if not a bson_codewscope + * + * @param i the bson_iterator. + * @param scope the bson scope. + */ +/* calls bson_empty on scope if not a bson_codewscope */ +void bson_iterator_code_scope( const bson_iterator *i, bson *scope ); + +/** + * Get the date value of the BSON object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the date value of the current BSON object. + */ +/* both of these only work with bson_date */ +bson_date_t bson_iterator_date( const bson_iterator *i ); + +/** + * Get the time value of the BSON object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the time value of the current BSON object. + */ +time_t bson_iterator_time_t( const bson_iterator *i ); + +/** + * Get the length of the BSON binary object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the length of the current BSON binary object. + */ +int bson_iterator_bin_len( const bson_iterator *i ); + +/** + * Get the type of the BSON binary object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the type of the current BSON binary object. + */ +char bson_iterator_bin_type( const bson_iterator *i ); + +/** + * Get the value of the BSON binary object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON binary object. + */ +const char *bson_iterator_bin_data( const bson_iterator *i ); + +/** + * Get the value of the BSON regex object currently pointed to by the + * iterator. + * + * @param i the bson_iterator + * + * @return the value of the current BSON regex object. + */ +const char *bson_iterator_regex( const bson_iterator *i ); + +/** + * Get the options of the BSON regex object currently pointed to by the + * iterator. + * + * @param i the bson_iterator. + * + * @return the options of the current BSON regex object. + */ +const char *bson_iterator_regex_opts( const bson_iterator *i ); + +/* these work with BSON_OBJECT and BSON_ARRAY */ +/** + * Get the BSON subobject currently pointed to by the + * iterator. + * + * @param i the bson_iterator. + * @param sub the BSON subobject destination. + */ +void bson_iterator_subobject( const bson_iterator *i, bson *sub ); + +/** + * Get a bson_iterator that on the BSON subobject. + * + * @param i the bson_iterator. + * @param sub the iterator to point at the BSON subobject. + */ +void bson_iterator_subiterator( const bson_iterator *i, bson_iterator *sub ); + +/* str must be at least 24 hex chars + null byte */ +/** + * Create a bson_oid_t from a string. + * + * @param oid the bson_oid_t destination. + * @param str a null terminated string comprised of at least 24 hex chars. + */ +void bson_oid_from_string( bson_oid_t *oid, const char *str ); + +/** + * Create a string representation of the bson_oid_t. + * + * @param oid the bson_oid_t source. + * @param str the string representation destination. + */ +void bson_oid_to_string( const bson_oid_t *oid, char *str ); + +/** + * Create a bson_oid object. + * + * @param oid the destination for the newly created bson_oid_t. + */ +void bson_oid_gen( bson_oid_t *oid ); + +/** + * Set a function to be used to generate the second four bytes + * of an object id. + * + * @param func a pointer to a function that returns an int. + */ +void bson_set_oid_fuzz( int ( *func )( void ) ); + +/** + * Set a function to be used to generate the incrementing part + * of an object id (last four bytes). If you need thread-safety + * in generating object ids, you should set this function. + * + * @param func a pointer to a function that returns an int. + */ +void bson_set_oid_inc( int ( *func )( void ) ); + +/** + * Get the time a bson_oid_t was created. + * + * @param oid the bson_oid_t. + */ +time_t bson_oid_generated_time( bson_oid_t *oid ); /* Gives the time the OID was created */ + +/* ---------------------------- + BUILDING + ------------------------------ */ + +/** + * Initialize a new bson object. If not created + * with bson_new, you must initialize each new bson + * object using this function. + * + * @note When finished, you must pass the bson object to + * bson_destroy( ). + */ +void bson_init( bson *b ); + +/** + * Initialize a BSON object, and point its data + * pointer to the provided char*. + * + * @param b the BSON object to initialize. + * @param data the raw BSON data. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_init_data( bson *b , char *data ); + +/** + * Initialize a BSON object, and set its + * buffer to the given size. + * + * @param b the BSON object to initialize. + * @param size the initial size of the buffer. + * + * @return BSON_OK or BSON_ERROR. + */ +void bson_init_size( bson *b, int size ); + +/** + * Grow a bson object. + * + * @param b the bson to grow. + * @param bytesNeeded the additional number of bytes needed. + * + * @return BSON_OK or BSON_ERROR with the bson error object set. + * Exits if allocation fails. + */ +int bson_ensure_space( bson *b, const int bytesNeeded ); + +/** + * Finalize a bson object. + * + * @param b the bson object to finalize. + * + * @return the standard error code. To deallocate memory, + * call bson_destroy on the bson object. + */ +int bson_finish( bson *b ); + +/** + * Destroy a bson object. + * + * @param b the bson object to destroy. + * + */ +void bson_destroy( bson *b ); + +/** + * Returns a pointer to a static empty BSON object. + * + * @param obj the BSON object to initialize. + * + * @return the empty initialized BSON object. + */ +/* returns pointer to static empty bson object */ +bson *bson_empty( bson *obj ); + +/** + * Copy BSON data only from one object to another. + * + * @param out the copy destination BSON object. + * @param in the copy source BSON object. + */ +void bson_copy_basic( bson *out, const bson *in ); + +/** + * Make a complete copy of the a BSON object. + * + * @param out the copy destination BSON object. + * @param in the copy source BSON object. + */ +void bson_copy( bson *out, const bson *in ); /* puts data in new buffer. NOOP if out==NULL */ + +/** + * Append a previously created bson_oid_t to a bson object. + * + * @param b the bson to append to. + * @param name the key for the bson_oid_t. + * @param oid the bson_oid_t to append. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_oid( bson *b, const char *name, const bson_oid_t *oid ); + +/** + * Append a bson_oid_t to a bson. + * + * @param b the bson to append to. + * @param name the key for the bson_oid_t. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_new_oid( bson *b, const char *name ); + +/** + * Append an int to a bson. + * + * @param b the bson to append to. + * @param name the key for the int. + * @param i the int to append. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_int( bson *b, const char *name, const int i ); + +/** + * Append an long to a bson. + * + * @param b the bson to append to. + * @param name the key for the long. + * @param i the long to append. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_long( bson *b, const char *name, const int64_t i ); + +/** + * Append an double to a bson. + * + * @param b the bson to append to. + * @param name the key for the double. + * @param d the double to append. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_double( bson *b, const char *name, const double d ); + +/** + * Append a string to a bson. + * + * @param b the bson to append to. + * @param name the key for the string. + * @param str the string to append. + * + * @return BSON_OK or BSON_ERROR. +*/ +int bson_append_string( bson *b, const char *name, const char *str ); + +/** + * Append len bytes of a string to a bson. + * + * @param b the bson to append to. + * @param name the key for the string. + * @param str the string to append. + * @param len the number of bytes from str to append. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_string_n( bson *b, const char *name, const char *str, int len ); + +/** + * Append a symbol to a bson. + * + * @param b the bson to append to. + * @param name the key for the symbol. + * @param str the symbol to append. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_symbol( bson *b, const char *name, const char *str ); + +/** + * Append len bytes of a symbol to a bson. + * + * @param b the bson to append to. + * @param name the key for the symbol. + * @param str the symbol to append. + * @param len the number of bytes from str to append. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_symbol_n( bson *b, const char *name, const char *str, int len ); + +/** + * Append code to a bson. + * + * @param b the bson to append to. + * @param name the key for the code. + * @param str the code to append. + * @param len the number of bytes from str to append. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_code( bson *b, const char *name, const char *str ); + +/** + * Append len bytes of code to a bson. + * + * @param b the bson to append to. + * @param name the key for the code. + * @param str the code to append. + * @param len the number of bytes from str to append. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_code_n( bson *b, const char *name, const char *str, int len ); + +/** + * Append code to a bson with scope. + * + * @param b the bson to append to. + * @param name the key for the code. + * @param str the string to append. + * @param scope a BSON object containing the scope. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_code_w_scope( bson *b, const char *name, const char *code, const bson *scope ); + +/** + * Append len bytes of code to a bson with scope. + * + * @param b the bson to append to. + * @param name the key for the code. + * @param str the string to append. + * @param len the number of bytes from str to append. + * @param scope a BSON object containing the scope. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_code_w_scope_n( bson *b, const char *name, const char *code, int size, const bson *scope ); + +/** + * Append binary data to a bson. + * + * @param b the bson to append to. + * @param name the key for the data. + * @param type the binary data type. + * @param str the binary data. + * @param len the length of the data. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_binary( bson *b, const char *name, char type, const char *str, int len ); + +/** + * Append a bson_bool_t to a bson. + * + * @param b the bson to append to. + * @param name the key for the boolean value. + * @param v the bson_bool_t to append. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_bool( bson *b, const char *name, const bson_bool_t v ); + +/** + * Append a null value to a bson. + * + * @param b the bson to append to. + * @param name the key for the null value. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_null( bson *b, const char *name ); + +/** + * Append an undefined value to a bson. + * + * @param b the bson to append to. + * @param name the key for the undefined value. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_undefined( bson *b, const char *name ); + +/** + * Append a regex value to a bson. + * + * @param b the bson to append to. + * @param name the key for the regex value. + * @param pattern the regex pattern to append. + * @param the regex options. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_regex( bson *b, const char *name, const char *pattern, const char *opts ); + +/** + * Append bson data to a bson. + * + * @param b the bson to append to. + * @param name the key for the bson data. + * @param bson the bson object to append. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_bson( bson *b, const char *name, const bson *bson ); + +/** + * Append a BSON element to a bson from the current point of an iterator. + * + * @param b the bson to append to. + * @param name_or_null the key for the BSON element, or NULL. + * @param elem the bson_iterator. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_element( bson *b, const char *name_or_null, const bson_iterator *elem ); + +/** + * Append a bson_timestamp_t value to a bson. + * + * @param b the bson to append to. + * @param name the key for the timestampe value. + * @param ts the bson_timestamp_t value to append. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_timestamp( bson *b, const char *name, bson_timestamp_t *ts ); + +/* these both append a bson_date */ +/** + * Append a bson_date_t value to a bson. + * + * @param b the bson to append to. + * @param name the key for the date value. + * @param millis the bson_date_t to append. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_date( bson *b, const char *name, bson_date_t millis ); + +/** + * Append a time_t value to a bson. + * + * @param b the bson to append to. + * @param name the key for the date value. + * @param secs the time_t to append. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_time_t( bson *b, const char *name, time_t secs ); + +/** + * Start appending a new object to a bson. + * + * @param b the bson to append to. + * @param name the name of the new object. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_start_object( bson *b, const char *name ); + +/** + * Start appending a new array to a bson. + * + * @param b the bson to append to. + * @param name the name of the new array. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_start_array( bson *b, const char *name ); + +/** + * Finish appending a new object or array to a bson. + * + * @param b the bson to append to. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_finish_object( bson *b ); + +/** + * Finish appending a new object or array to a bson. This + * is simply an alias for bson_append_finish_object. + * + * @param b the bson to append to. + * + * @return BSON_OK or BSON_ERROR. + */ +int bson_append_finish_array( bson *b ); + +void bson_numstr( char *str, int i ); + +void bson_incnumstr( char *str ); + +/* Error handling and stadard library function over-riding. */ +/* -------------------------------------------------------- */ + +/* bson_err_handlers shouldn't return!!! */ +typedef void( *bson_err_handler )( const char *errmsg ); + +typedef int (*bson_printf_func)( const char *, ... ); +typedef int (*bson_fprintf_func)( FILE *, const char *, ... ); +typedef int (*bson_sprintf_func)( char *, const char *, ... ); + +extern void *( *bson_malloc_func )( size_t ); +extern void *( *bson_realloc_func )( void *, size_t ); +extern void ( *bson_free )( void * ); + +extern bson_printf_func bson_printf; +extern bson_fprintf_func bson_fprintf; +extern bson_sprintf_func bson_sprintf; + +extern bson_printf_func bson_errprintf; + +/** + * Allocates memory and checks return value, exiting fatally if malloc() fails. + * + * @param size bytes to allocate. + * + * @return a pointer to the allocated memory. + * + * @sa malloc(3) + */ +void *bson_malloc( int size ); + +/** + * Changes the size of allocated memory and checks return value, + * exiting fatally if realloc() fails. + * + * @param ptr pointer to the space to reallocate. + * @param size bytes to allocate. + * + * @return a pointer to the allocated memory. + * + * @sa realloc() + */ +void *bson_realloc( void *ptr, int size ); + +/** + * Set a function for error handling. + * + * @param func a bson_err_handler function. + * + * @return the old error handling function, or NULL. + */ +bson_err_handler set_bson_err_handler( bson_err_handler func ); + +/* does nothing if ok != 0 */ +/** + * Exit fatally. + * + * @param ok exits if ok is equal to 0. + */ +void bson_fatal( int ok ); + +/** + * Exit fatally with an error message. + * + * @param ok exits if ok is equal to 0. + * @param msg prints to stderr before exiting. + */ +void bson_fatal_msg( int ok, const char *msg ); + +/** + * Invoke the error handler, but do not exit. + * + * @param b the buffer object. + */ +void bson_builder_error( bson *b ); + +MONGO_EXTERN_C_END +#endif diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/encoding.c b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/encoding.c new file mode 100644 index 0000000000..8d2da1502f --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/encoding.c @@ -0,0 +1,148 @@ +/* + * Copyright 2009-2011 10gen, Inc. + * + * 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. + */ + +/* + * Portions Copyright 2001 Unicode, Inc. + * + * Disclaimer + * + * This source code is provided as is by Unicode, Inc. No claims are + * made as to fitness for any particular purpose. No warranties of any + * kind are expressed or implied. The recipient agrees to determine + * applicability of information provided. If this file has been + * purchased on magnetic or optical media from Unicode, Inc., the + * sole remedy for any claim will be exchange of defective media + * within 90 days of receipt. + * + * Limitations on Rights to Redistribute This Code + * + * Unicode, Inc. hereby grants the right to freely use the information + * supplied in this file in the creation of products supporting the + * Unicode Standard, and to make copies of this file in any form + * for internal or external distribution as long as this notice + * remains attached. + */ + + +#include "bson.h" +#include "encoding.h" + +/* + * Index into the table below with the first byte of a UTF-8 sequence to + * get the number of trailing bytes that are supposed to follow it. + */ +static const char trailingBytesForUTF8[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 +}; + +/* --------------------------------------------------------------------- */ + +/* + * Utility routine to tell whether a sequence of bytes is legal UTF-8. + * This must be called with the length pre-determined by the first byte. + * The length can be set by: + * length = trailingBytesForUTF8[*source]+1; + * and the sequence is illegal right away if there aren't that many bytes + * available. + * If presented with a length > 4, this returns 0. The Unicode + * definition of UTF-8 goes up to 4-byte sequences. + */ +static int isLegalUTF8( const unsigned char *source, int length ) { + unsigned char a; + const unsigned char *srcptr = source + length; + switch ( length ) { + default: + return 0; + /* Everything else falls through when "true"... */ + case 4: + if ( ( a = ( *--srcptr ) ) < 0x80 || a > 0xBF ) return 0; + case 3: + if ( ( a = ( *--srcptr ) ) < 0x80 || a > 0xBF ) return 0; + case 2: + if ( ( a = ( *--srcptr ) ) > 0xBF ) return 0; + switch ( *source ) { + /* no fall-through in this inner switch */ + case 0xE0: + if ( a < 0xA0 ) return 0; + break; + case 0xF0: + if ( a < 0x90 ) return 0; + break; + case 0xF4: + if ( a > 0x8F ) return 0; + break; + default: + if ( a < 0x80 ) return 0; + } + case 1: + if ( *source >= 0x80 && *source < 0xC2 ) return 0; + if ( *source > 0xF4 ) return 0; + } + return 1; +} + +static int bson_validate_string( bson *b, const unsigned char *string, + const int length, const char check_utf8, const char check_dot, + const char check_dollar ) { + + int position = 0; + int sequence_length = 1; + + if( check_dollar && string[0] == '$' ) { + b->err |= BSON_FIELD_INIT_DOLLAR; + } + + while ( position < length ) { + if ( check_dot && *( string + position ) == '.' ) { + b->err |= BSON_FIELD_HAS_DOT; + } + + if ( check_utf8 ) { + sequence_length = trailingBytesForUTF8[*( string + position )] + 1; + if ( ( position + sequence_length ) > length ) { + b->err |= BSON_NOT_UTF8; + return BSON_ERROR; + } + if ( !isLegalUTF8( string + position, sequence_length ) ) { + b->err |= BSON_NOT_UTF8; + return BSON_ERROR; + } + } + position += sequence_length; + } + + return BSON_OK; +} + + +int bson_check_string( bson *b, const char *string, + const int length ) { + + return bson_validate_string( b, ( const unsigned char * )string, length, 1, 0, 0 ); +} + +int bson_check_field_name( bson *b, const char *string, + const int length ) { + + return bson_validate_string( b, ( const unsigned char * )string, length, 1, 1, 1 ); +} diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/encoding.h b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/encoding.h new file mode 100644 index 0000000000..a2a07c6d5d --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/encoding.h @@ -0,0 +1,54 @@ +/* + * Copyright 2009-2011 10gen, Inc. + * + * 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 _BSON_ENCODING_H_ +#define _BSON_ENCODING_H_ + +MONGO_EXTERN_C_START + +/** + * Check that a field name is valid UTF8, does not start with a '$', + * and contains no '.' characters. Set bson bit field appropriately. + * Note that we don't need to check for '\0' because we're using + * strlen(3), which stops at '\0'. + * + * @param b The bson object to which field name will be appended. + * @param string The field name as char*. + * @param length The length of the field name. + * + * @return BSON_OK if valid UTF8 and BSON_ERROR if not. All BSON strings must be + * valid UTF8. This function will also check whether the string + * contains '.' or starts with '$', since the validity of this depends on context. + * Set the value of b->err appropriately. + */ +int bson_check_field_name( bson *b, const char *string, + const int length ); + +/** + * Check that a string is valid UTF8. Sets the buffer bit field appropriately. + * + * @param b The bson object to which string will be appended. + * @param string The string to check. + * @param length The length of the string. + * + * @return BSON_OK if valid UTF-8; otherwise, BSON_ERROR. + * Sets b->err on error. + */ +bson_bool_t bson_check_string( bson *b, const char *string, + const int length ); + +MONGO_EXTERN_C_END +#endif diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/gridfs.c b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/gridfs.c new file mode 100644 index 0000000000..f51b397d3f --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/gridfs.c @@ -0,0 +1,685 @@ +/* gridfs.c */ + +/* Copyright 2009-2011 10gen Inc. + * + * 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 "gridfs.h" +#include +#include +#include +#include + +static bson *chunk_new( bson_oid_t id, int chunkNumber, + const char *data, int len ) { + bson *b = bson_malloc( sizeof( bson ) ); + + bson_init( b ); + bson_append_oid( b, "files_id", &id ); + bson_append_int( b, "n", chunkNumber ); + bson_append_binary( b, "data", BSON_BIN_BINARY, data, len ); + bson_finish( b ); + return b; +} + +static void chunk_free( bson *oChunk ) { + bson_destroy( oChunk ); + bson_free( oChunk ); +} + +int gridfs_init( mongo *client, const char *dbname, const char *prefix, + gridfs *gfs ) { + + int options; + bson b; + bson_bool_t success; + + gfs->client = client; + + /* Allocate space to own the dbname */ + gfs->dbname = ( const char * )bson_malloc( strlen( dbname )+1 ); + strcpy( ( char * )gfs->dbname, dbname ); + + /* Allocate space to own the prefix */ + if ( prefix == NULL ) prefix = "fs"; + gfs->prefix = ( const char * )bson_malloc( strlen( prefix )+1 ); + strcpy( ( char * )gfs->prefix, prefix ); + + /* Allocate space to own files_ns */ + gfs->files_ns = + ( const char * ) bson_malloc ( strlen( prefix )+strlen( dbname )+strlen( ".files" )+2 ); + strcpy( ( char * )gfs->files_ns, dbname ); + strcat( ( char * )gfs->files_ns, "." ); + strcat( ( char * )gfs->files_ns, prefix ); + strcat( ( char * )gfs->files_ns, ".files" ); + + /* Allocate space to own chunks_ns */ + gfs->chunks_ns = ( const char * ) bson_malloc( strlen( prefix ) + strlen( dbname ) + + strlen( ".chunks" ) + 2 ); + strcpy( ( char * )gfs->chunks_ns, dbname ); + strcat( ( char * )gfs->chunks_ns, "." ); + strcat( ( char * )gfs->chunks_ns, prefix ); + strcat( ( char * )gfs->chunks_ns, ".chunks" ); + + bson_init( &b ); + bson_append_int( &b, "filename", 1 ); + bson_finish( &b ); + options = 0; + success = ( mongo_create_index( gfs->client, gfs->files_ns, &b, options, NULL ) == MONGO_OK ); + bson_destroy( &b ); + if ( !success ) { + bson_free( ( char * )gfs->dbname ); + bson_free( ( char * )gfs->prefix ); + bson_free( ( char * )gfs->files_ns ); + bson_free( ( char * )gfs->chunks_ns ); + return MONGO_ERROR; + } + + bson_init( &b ); + bson_append_int( &b, "files_id", 1 ); + bson_append_int( &b, "n", 1 ); + bson_finish( &b ); + options = MONGO_INDEX_UNIQUE; + success = ( mongo_create_index( gfs->client, gfs->chunks_ns, &b, options, NULL ) == MONGO_OK ); + bson_destroy( &b ); + if ( !success ) { + bson_free( ( char * )gfs->dbname ); + bson_free( ( char * )gfs->prefix ); + bson_free( ( char * )gfs->files_ns ); + bson_free( ( char * )gfs->chunks_ns ); + return MONGO_ERROR; + } + + return MONGO_OK; +} + +void gridfs_destroy( gridfs *gfs ) { + if ( gfs == NULL ) return; + if ( gfs->dbname ) bson_free( ( char * )gfs->dbname ); + if ( gfs->prefix ) bson_free( ( char * )gfs->prefix ); + if ( gfs->files_ns ) bson_free( ( char * )gfs->files_ns ); + if ( gfs->chunks_ns ) bson_free( ( char * )gfs->chunks_ns ); +} + +static int gridfs_insert_file( gridfs *gfs, const char *name, + const bson_oid_t id, gridfs_offset length, + const char *contenttype ) { + bson command; + bson ret; + bson res; + bson_iterator it; + int result; + + /* Check run md5 */ + bson_init( &command ); + bson_append_oid( &command, "filemd5", &id ); + bson_append_string( &command, "root", gfs->prefix ); + bson_finish( &command ); + assert( mongo_run_command( gfs->client, gfs->dbname, &command, &res ) == MONGO_OK ); + bson_destroy( &command ); + + /* Create and insert BSON for file metadata */ + bson_init( &ret ); + bson_append_oid( &ret, "_id", &id ); + if ( name != NULL && *name != '\0' ) { + bson_append_string( &ret, "filename", name ); + } + bson_append_long( &ret, "length", length ); + bson_append_int( &ret, "chunkSize", DEFAULT_CHUNK_SIZE ); + bson_append_date( &ret, "uploadDate", ( bson_date_t )1000*time( NULL ) ); + bson_find( &it, &res, "md5" ); + bson_append_string( &ret, "md5", bson_iterator_string( &it ) ); + bson_destroy( &res ); + if ( contenttype != NULL && *contenttype != '\0' ) { + bson_append_string( &ret, "contentType", contenttype ); + } + bson_finish( &ret ); + result = mongo_insert( gfs->client, gfs->files_ns, &ret ); + bson_destroy( &ret ); + + return result; +} + +int gridfs_store_buffer( gridfs *gfs, const char *data, + gridfs_offset length, const char *remotename, + const char *contenttype ) { + + char const *end = data + length; + const char *data_ptr = data; + bson_oid_t id; + int chunkNumber = 0; + int chunkLen; + bson *oChunk; + + /* Large files Assertion */ + assert( length <= 0xffffffff ); + + /* Generate and append an oid*/ + bson_oid_gen( &id ); + + /* Insert the file's data chunk by chunk */ + while ( data_ptr < end ) { + chunkLen = DEFAULT_CHUNK_SIZE < ( unsigned int )( end - data_ptr ) ? + DEFAULT_CHUNK_SIZE : ( unsigned int )( end - data_ptr ); + oChunk = chunk_new( id, chunkNumber, data_ptr, chunkLen ); + mongo_insert( gfs->client, gfs->chunks_ns, oChunk ); + chunk_free( oChunk ); + chunkNumber++; + data_ptr += chunkLen; + } + + /* Inserts file's metadata */ + return gridfs_insert_file( gfs, remotename, id, length, contenttype ); +} + +void gridfile_writer_init( gridfile *gfile, gridfs *gfs, + const char *remote_name, const char *content_type ) { + gfile->gfs = gfs; + + bson_oid_gen( &( gfile->id ) ); + gfile->chunk_num = 0; + gfile->length = 0; + gfile->pending_len = 0; + gfile->pending_data = NULL; + + gfile->remote_name = ( char * )bson_malloc( strlen( remote_name ) + 1 ); + strcpy( ( char * )gfile->remote_name, remote_name ); + + gfile->content_type = ( char * )bson_malloc( strlen( content_type ) + 1 ); + strcpy( ( char * )gfile->content_type, content_type ); +} + +void gridfile_write_buffer( gridfile *gfile, const char *data, + gridfs_offset length ) { + + int bytes_left = 0; + int data_partial_len = 0; + int chunks_to_write = 0; + char *buffer; + bson *oChunk; + gridfs_offset to_write = length + gfile->pending_len; + + if ( to_write < DEFAULT_CHUNK_SIZE ) { /* Less than one chunk to write */ + if( gfile->pending_data ) { + gfile->pending_data = ( char * )bson_realloc( ( void * )gfile->pending_data, gfile->pending_len + to_write ); + memcpy( gfile->pending_data + gfile->pending_len, data, length ); + } else if ( to_write > 0 ) { + gfile->pending_data = ( char * )bson_malloc( to_write ); + memcpy( gfile->pending_data, data, length ); + } + gfile->pending_len += length; + + } else { /* At least one chunk of data to write */ + + /* If there's a pending chunk to be written, we need to combine + * the buffer provided up to DEFAULT_CHUNK_SIZE. + */ + if ( gfile->pending_len > 0 ) { + chunks_to_write = to_write / DEFAULT_CHUNK_SIZE; + bytes_left = to_write % DEFAULT_CHUNK_SIZE; + + data_partial_len = DEFAULT_CHUNK_SIZE - gfile->pending_len; + buffer = ( char * )bson_malloc( DEFAULT_CHUNK_SIZE ); + memcpy( buffer, gfile->pending_data, gfile->pending_len ); + memcpy( buffer + gfile->pending_len, data, data_partial_len ); + + oChunk = chunk_new( gfile->id, gfile->chunk_num, buffer, DEFAULT_CHUNK_SIZE ); + mongo_insert( gfile->gfs->client, gfile->gfs->chunks_ns, oChunk ); + chunk_free( oChunk ); + gfile->chunk_num++; + gfile->length += DEFAULT_CHUNK_SIZE; + data += data_partial_len; + + chunks_to_write--; + + bson_free( buffer ); + } + + while( chunks_to_write > 0 ) { + oChunk = chunk_new( gfile->id, gfile->chunk_num, data, DEFAULT_CHUNK_SIZE ); + mongo_insert( gfile->gfs->client, gfile->gfs->chunks_ns, oChunk ); + chunk_free( oChunk ); + gfile->chunk_num++; + chunks_to_write--; + gfile->length += DEFAULT_CHUNK_SIZE; + data += DEFAULT_CHUNK_SIZE; + } + + bson_free( gfile->pending_data ); + + /* If there are any leftover bytes, store them as pending data. */ + if( bytes_left == 0 ) + gfile->pending_data = NULL; + else { + gfile->pending_data = ( char * )bson_malloc( bytes_left ); + memcpy( gfile->pending_data, data, bytes_left ); + } + + gfile->pending_len = bytes_left; + } +} + +int gridfile_writer_done( gridfile *gfile ) { + + /* write any remaining pending chunk data. + * pending data will always take up less than one chunk */ + bson *oChunk; + int response; + if( gfile->pending_data ) { + oChunk = chunk_new( gfile->id, gfile->chunk_num, gfile->pending_data, gfile->pending_len ); + mongo_insert( gfile->gfs->client, gfile->gfs->chunks_ns, oChunk ); + chunk_free( oChunk ); + bson_free( gfile->pending_data ); + gfile->length += gfile->pending_len; + } + + /* insert into files collection */ + response = gridfs_insert_file( gfile->gfs, gfile->remote_name, gfile->id, + gfile->length, gfile->content_type ); + + bson_free( gfile->remote_name ); + bson_free( gfile->content_type ); + + return response; +} + +int gridfs_store_file( gridfs *gfs, const char *filename, + const char *remotename, const char *contenttype ) { + + char buffer[DEFAULT_CHUNK_SIZE]; + FILE *fd; + bson_oid_t id; + int chunkNumber = 0; + gridfs_offset length = 0; + gridfs_offset chunkLen = 0; + bson *oChunk; + + /* Open the file and the correct stream */ + if ( strcmp( filename, "-" ) == 0 ) fd = stdin; + else fd = fopen( filename, "rb" ); + assert( fd != NULL ); /* No such file */ + + /* Generate and append an oid*/ + bson_oid_gen( &id ); + + /* Insert the file chunk by chunk */ + chunkLen = fread( buffer, 1, DEFAULT_CHUNK_SIZE, fd ); + do { + oChunk = chunk_new( id, chunkNumber, buffer, chunkLen ); + mongo_insert( gfs->client, gfs->chunks_ns, oChunk ); + chunk_free( oChunk ); + length += chunkLen; + chunkNumber++; + chunkLen = fread( buffer, 1, DEFAULT_CHUNK_SIZE, fd ); + } while ( chunkLen != 0 ); + + /* Close the file stream */ + if ( fd != stdin ) fclose( fd ); + + /* Large files Assertion */ + /* assert(length <= 0xffffffff); */ + + /* Optional Remote Name */ + if ( remotename == NULL || *remotename == '\0' ) { + remotename = filename; + } + + /* Inserts file's metadata */ + return gridfs_insert_file( gfs, remotename, id, length, contenttype ); +} + +void gridfs_remove_filename( gridfs *gfs, const char *filename ) { + bson query; + mongo_cursor *files; + bson file; + bson_iterator it; + bson_oid_t id; + bson b; + + bson_init( &query ); + bson_append_string( &query, "filename", filename ); + bson_finish( &query ); + files = mongo_find( gfs->client, gfs->files_ns, &query, NULL, 0, 0, 0 ); + bson_destroy( &query ); + + /* Remove each file and it's chunks from files named filename */ + while ( mongo_cursor_next( files ) == MONGO_OK ) { + file = files->current; + bson_find( &it, &file, "_id" ); + id = *bson_iterator_oid( &it ); + + /* Remove the file with the specified id */ + bson_init( &b ); + bson_append_oid( &b, "_id", &id ); + bson_finish( &b ); + mongo_remove( gfs->client, gfs->files_ns, &b ); + bson_destroy( &b ); + + /* Remove all chunks from the file with the specified id */ + bson_init( &b ); + bson_append_oid( &b, "files_id", &id ); + bson_finish( &b ); + mongo_remove( gfs->client, gfs->chunks_ns, &b ); + bson_destroy( &b ); + } + + mongo_cursor_destroy( files ); +} + +int gridfs_find_query( gridfs *gfs, bson *query, + gridfile *gfile ) { + + bson uploadDate; + bson finalQuery; + bson out; + int i; + + bson_init( &uploadDate ); + bson_append_int( &uploadDate, "uploadDate", -1 ); + bson_finish( &uploadDate ); + + bson_init( &finalQuery ); + bson_append_bson( &finalQuery, "query", query ); + bson_append_bson( &finalQuery, "orderby", &uploadDate ); + bson_finish( &finalQuery ); + + i = ( mongo_find_one( gfs->client, gfs->files_ns, + &finalQuery, NULL, &out ) == MONGO_OK ); + bson_destroy( &uploadDate ); + bson_destroy( &finalQuery ); + if ( !i ) + return MONGO_ERROR; + else { + gridfile_init( gfs, &out, gfile ); + bson_destroy( &out ); + return MONGO_OK; + } +} + +int gridfs_find_filename( gridfs *gfs, const char *filename, + gridfile *gfile ) + +{ + bson query; + int i; + + bson_init( &query ); + bson_append_string( &query, "filename", filename ); + bson_finish( &query ); + i = gridfs_find_query( gfs, &query, gfile ); + bson_destroy( &query ); + return i; +} + +int gridfile_init( gridfs *gfs, bson *meta, gridfile *gfile ) + +{ + gfile->gfs = gfs; + gfile->pos = 0; + gfile->meta = ( bson * )bson_malloc( sizeof( bson ) ); + if ( gfile->meta == NULL ) return MONGO_ERROR; + bson_copy( gfile->meta, meta ); + return MONGO_OK; +} + +void gridfile_destroy( gridfile *gfile ) + +{ + bson_destroy( gfile->meta ); + bson_free( gfile->meta ); +} + +bson_bool_t gridfile_exists( gridfile *gfile ) { + return ( bson_bool_t )( gfile != NULL || gfile->meta == NULL ); +} + +const char *gridfile_get_filename( gridfile *gfile ) { + bson_iterator it; + + bson_find( &it, gfile->meta, "filename" ); + return bson_iterator_string( &it ); +} + +int gridfile_get_chunksize( gridfile *gfile ) { + bson_iterator it; + + bson_find( &it, gfile->meta, "chunkSize" ); + return bson_iterator_int( &it ); +} + +gridfs_offset gridfile_get_contentlength( gridfile *gfile ) { + bson_iterator it; + + bson_find( &it, gfile->meta, "length" ); + + if( bson_iterator_type( &it ) == BSON_INT ) + return ( gridfs_offset )bson_iterator_int( &it ); + else + return ( gridfs_offset )bson_iterator_long( &it ); +} + +const char *gridfile_get_contenttype( gridfile *gfile ) { + bson_iterator it; + + if ( bson_find( &it, gfile->meta, "contentType" ) ) + return bson_iterator_string( &it ); + else return NULL; +} + +bson_date_t gridfile_get_uploaddate( gridfile *gfile ) { + bson_iterator it; + + bson_find( &it, gfile->meta, "uploadDate" ); + return bson_iterator_date( &it ); +} + +const char *gridfile_get_md5( gridfile *gfile ) { + bson_iterator it; + + bson_find( &it, gfile->meta, "md5" ); + return bson_iterator_string( &it ); +} + +const char *gridfile_get_field( gridfile *gfile, const char *name ) { + bson_iterator it; + + bson_find( &it, gfile->meta, name ); + return bson_iterator_value( &it ); +} + +bson_bool_t gridfile_get_boolean( gridfile *gfile, const char *name ) { + bson_iterator it; + + bson_find( &it, gfile->meta, name ); + return bson_iterator_bool( &it ); +} + +bson gridfile_get_metadata( gridfile *gfile ) { + bson sub; + bson_iterator it; + + if ( bson_find( &it, gfile->meta, "metadata" ) ) { + bson_iterator_subobject( &it, &sub ); + return sub; + } else { + bson_empty( &sub ); + return sub; + } +} + +int gridfile_get_numchunks( gridfile *gfile ) { + bson_iterator it; + gridfs_offset length; + gridfs_offset chunkSize; + double numchunks; + + bson_find( &it, gfile->meta, "length" ); + + if( bson_iterator_type( &it ) == BSON_INT ) + length = ( gridfs_offset )bson_iterator_int( &it ); + else + length = ( gridfs_offset )bson_iterator_long( &it ); + + bson_find( &it, gfile->meta, "chunkSize" ); + chunkSize = bson_iterator_int( &it ); + numchunks = ( ( double )length/( double )chunkSize ); + return ( numchunks - ( int )numchunks > 0 ) + ? ( int )( numchunks+1 ) + : ( int )( numchunks ); +} + +bson gridfile_get_chunk( gridfile *gfile, int n ) { + bson query; + bson out; + bson_iterator it; + bson_oid_t id; + + bson_init( &query ); + bson_find( &it, gfile->meta, "_id" ); + id = *bson_iterator_oid( &it ); + bson_append_oid( &query, "files_id", &id ); + bson_append_int( &query, "n", n ); + bson_finish( &query ); + + assert( mongo_find_one( gfile->gfs->client, + gfile->gfs->chunks_ns, + &query, NULL, &out ) == MONGO_OK ); + + bson_destroy( &query ); + return out; +} + +mongo_cursor *gridfile_get_chunks( gridfile *gfile, int start, int size ) { + bson_iterator it; + bson_oid_t id; + bson gte; + bson query; + bson orderby; + bson command; + mongo_cursor *cursor; + + bson_find( &it, gfile->meta, "_id" ); + id = *bson_iterator_oid( &it ); + + bson_init( &query ); + bson_append_oid( &query, "files_id", &id ); + if ( size == 1 ) { + bson_append_int( &query, "n", start ); + } else { + bson_init( >e ); + bson_append_int( >e, "$gte", start ); + bson_finish( >e ); + bson_append_bson( &query, "n", >e ); + bson_destroy( >e ); + } + bson_finish( &query ); + + bson_init( &orderby ); + bson_append_int( &orderby, "n", 1 ); + bson_finish( &orderby ); + + bson_init( &command ); + bson_append_bson( &command, "query", &query ); + bson_append_bson( &command, "orderby", &orderby ); + bson_finish( &command ); + + cursor = mongo_find( gfile->gfs->client, gfile->gfs->chunks_ns, + &command, NULL, size, 0, 0 ); + + bson_destroy( &command ); + bson_destroy( &query ); + bson_destroy( &orderby ); + + return cursor; +} + +gridfs_offset gridfile_write_file( gridfile *gfile, FILE *stream ) { + int i; + size_t len; + bson chunk; + bson_iterator it; + const char *data; + const int num = gridfile_get_numchunks( gfile ); + + for ( i=0; ipos < size ) + ? contentlength - gfile->pos + : size; + bytes_left = size; + + first_chunk = ( gfile->pos )/chunksize; + last_chunk = ( gfile->pos+size-1 )/chunksize; + total_chunks = last_chunk - first_chunk + 1; + chunks = gridfile_get_chunks( gfile, first_chunk, total_chunks ); + + for ( i = 0; i < total_chunks; i++ ) { + mongo_cursor_next( chunks ); + chunk = chunks->current; + bson_find( &it, &chunk, "data" ); + chunk_len = bson_iterator_bin_len( &it ); + chunk_data = bson_iterator_bin_data( &it ); + if ( i == 0 ) { + chunk_data += ( gfile->pos )%chunksize; + chunk_len -= ( gfile->pos )%chunksize; + } + if ( bytes_left > chunk_len ) { + memcpy( buf, chunk_data, chunk_len ); + bytes_left -= chunk_len; + buf += chunk_len; + } else { + memcpy( buf, chunk_data, bytes_left ); + } + } + + mongo_cursor_destroy( chunks ); + gfile->pos = gfile->pos + size; + + return size; +} + +gridfs_offset gridfile_seek( gridfile *gfile, gridfs_offset offset ) { + gridfs_offset length; + + length = gridfile_get_contentlength( gfile ); + gfile->pos = length < offset ? length : offset; + return gfile->pos; +} diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/gridfs.h b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/gridfs.h new file mode 100644 index 0000000000..36595ee341 --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/gridfs.h @@ -0,0 +1,326 @@ +/** @file gridfs.h + * + * @brief GridFS declarations + * + * */ + +/* Copyright 2009-2011 10gen Inc. + * + * 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 "mongo.h" + +#ifndef GRIDFS_INCLUDED +#define GRIDFS_INCLUDED + +enum {DEFAULT_CHUNK_SIZE = 256 * 1024}; + +typedef uint64_t gridfs_offset; + +/* A GridFS represents a single collection of GridFS files in the database. */ +typedef struct { + mongo *client; /**> The client to db-connection. */ + const char *dbname; /**> The root database name */ + const char *prefix; /**> The prefix of the GridFS's collections, default is NULL */ + const char *files_ns; /**> The namespace where the file's metadata is stored */ + const char *chunks_ns; /**. The namespace where the files's data is stored in chunks */ +} gridfs; + +/* A GridFile is a single GridFS file. */ +typedef struct { + gridfs *gfs; /**> The GridFS where the GridFile is located */ + bson *meta; /**> The GridFile's bson object where all its metadata is located */ + gridfs_offset pos; /**> The position is the offset in the file */ + bson_oid_t id; /**> The files_id of the gridfile */ + char *remote_name; /**> The name of the gridfile as a string */ + char *content_type; /**> The gridfile's content type */ + gridfs_offset length; /**> The length of this gridfile */ + int chunk_num; /**> The number of the current chunk being written to */ + char *pending_data; /**> A buffer storing data still to be written to chunks */ + int pending_len; /**> Length of pending_data buffer */ +} gridfile; + +/** + * Initializes a GridFS object + * @param client - db connection + * @param dbname - database name + * @param prefix - collection prefix, default is fs if NULL or empty + * @param gfs - the GridFS object to initialize + * + * @return - MONGO_OK or MONGO_ERROR. + */ +int gridfs_init( mongo *client, const char *dbname, + const char *prefix, gridfs *gfs ); + +/** + * Destroys a GridFS object. Call this when finished with + * the object.. + * + * @param gfs a grid + */ +void gridfs_destroy( gridfs *gfs ); + +/** + * Initializes a gridfile for writing incrementally with gridfs_write_buffer. + * Once initialized, you can write any number of buffers with gridfs_write_buffer. + * When done, you must call gridfs_writer_done to save the file metadata. + * + */ +void gridfile_writer_init( gridfile *gfile, gridfs *gfs, const char *remote_name, + const char *content_type ); + +/** + * Write to a GridFS file incrementally. You can call this function any number + * of times with a new buffer each time. This allows you to effectively + * stream to a GridFS file. When finished, be sure to call gridfs_writer_done. + * + */ +void gridfile_write_buffer( gridfile *gfile, const char *data, + gridfs_offset length ); + +/** + * Signal that writing of this gridfile is complete by + * writing any buffered chunks along with the entry in the + * files collection. + * + * @return - MONGO_OK or MONGO_ERROR. + */ +int gridfile_writer_done( gridfile *gfile ); + +/** + * Store a buffer as a GridFS file. + * @param gfs - the working GridFS + * @param data - pointer to buffer to store in GridFS + * @param length - length of the buffer + * @param remotename - filename for use in the database + * @param contenttype - optional MIME type for this object + * + * @return - MONGO_OK or MONGO_ERROR. + */ +int gridfs_store_buffer( gridfs *gfs, const char *data, gridfs_offset length, + const char *remotename, + const char *contenttype ); + +/** + * Open the file referenced by filename and store it as a GridFS file. + * @param gfs - the working GridFS + * @param filename - local filename relative to the process + * @param remotename - optional filename for use in the database + * @param contenttype - optional MIME type for this object + * + * @return - MONGO_OK or MONGO_ERROR. + */ +int gridfs_store_file( gridfs *gfs, const char *filename, + const char *remotename, const char *contenttype ); + +/** + * Removes the files referenced by filename from the db + * @param gfs - the working GridFS + * @param filename - the filename of the file/s to be removed + */ +void gridfs_remove_filename( gridfs *gfs, const char *filename ); + +/** + * Find the first file matching the provided query within the + * GridFS files collection, and return the file as a GridFile. + * + * @param gfs - the working GridFS + * @param query - a pointer to the bson with the query data + * @param gfile - the output GridFile to be initialized + * + * @return MONGO_OK if successful, MONGO_ERROR otherwise + */ +int gridfs_find_query( gridfs *gfs, bson *query, gridfile *gfile ); + +/** + * Find the first file referenced by filename within the GridFS + * and return it as a GridFile + * @param gfs - the working GridFS + * @param filename - filename of the file to find + * @param gfile - the output GridFile to be intialized + * + * @return MONGO_OK or MONGO_ERROR. + */ +int gridfs_find_filename( gridfs *gfs, const char *filename, gridfile *gfile ); + +/** + * Initializes a GridFile containing the GridFS and file bson + * @param gfs - the GridFS where the GridFile is located + * @param meta - the file object + * @param gfile - the output GridFile that is being initialized + * + * @return - MONGO_OK or MONGO_ERROR. + */ +int gridfile_init( gridfs *gfs, bson *meta, gridfile *gfile ); + +/** + * Destroys the GridFile + * + * @param oGridFIle - the GridFile being destroyed + */ +void gridfile_destroy( gridfile *gfile ); + +/** + * Returns whether or not the GridFile exists + * @param gfile - the GridFile being examined + */ +bson_bool_t gridfile_exists( gridfile *gfile ); + +/** + * Returns the filename of GridFile + * @param gfile - the working GridFile + * + * @return - the filename of the Gridfile + */ +const char *gridfile_get_filename( gridfile *gfile ); + +/** + * Returns the size of the chunks of the GridFile + * @param gfile - the working GridFile + * + * @return - the size of the chunks of the Gridfile + */ +int gridfile_get_chunksize( gridfile *gfile ); + +/** + * Returns the length of GridFile's data + * + * @param gfile - the working GridFile + * + * @return - the length of the Gridfile's data + */ +gridfs_offset gridfile_get_contentlength( gridfile *gfile ); + +/** + * Returns the MIME type of the GridFile + * + * @param gfile - the working GridFile + * + * @return - the MIME type of the Gridfile + * (NULL if no type specified) + */ +const char *gridfile_get_contenttype( gridfile *gfile ); + +/** + * Returns the upload date of GridFile + * + * @param gfile - the working GridFile + * + * @return - the upload date of the Gridfile + */ +bson_date_t gridfile_get_uploaddate( gridfile *gfile ); + +/** + * Returns the MD5 of GridFile + * + * @param gfile - the working GridFile + * + * @return - the MD5 of the Gridfile + */ +const char *gridfile_get_md5( gridfile *gfile ); + +/** + * Returns the field in GridFile specified by name + * + * @param gfile - the working GridFile + * @param name - the name of the field to be returned + * + * @return - the data of the field specified + * (NULL if none exists) + */ +const char *gridfile_get_field( gridfile *gfile, + const char *name ); + +/** + * Returns a boolean field in GridFile specified by name + * @param gfile - the working GridFile + * @param name - the name of the field to be returned + * + * @return - the boolean of the field specified + * (NULL if none exists) + */ +bson_bool_t gridfile_get_boolean( gridfile *gfile, + const char *name ); + +/** + * Returns the metadata of GridFile + * @param gfile - the working GridFile + * + * @return - the metadata of the Gridfile in a bson object + * (an empty bson is returned if none exists) + */ +bson gridfile_get_metadata( gridfile *gfile ); + +/** + * Returns the number of chunks in the GridFile + * @param gfile - the working GridFile + * + * @return - the number of chunks in the Gridfile + */ +int gridfile_get_numchunks( gridfile *gfile ); + +/** + * Returns chunk n of GridFile + * @param gfile - the working GridFile + * + * @return - the nth chunk of the Gridfile + */ +bson gridfile_get_chunk( gridfile *gfile, int n ); + +/** + * Returns a mongo_cursor of *size* chunks starting with chunk *start* + * + * @param gfile - the working GridFile + * @param start - the first chunk in the cursor + * @param size - the number of chunks to be returned + * + * @return - mongo_cursor of the chunks (must be destroyed after use) + */ +mongo_cursor *gridfile_get_chunks( gridfile *gfile, int start, int size ); + +/** + * Writes the GridFile to a stream + * + * @param gfile - the working GridFile + * @param stream - the file stream to write to + */ +gridfs_offset gridfile_write_file( gridfile *gfile, FILE *stream ); + +/** + * Reads length bytes from the GridFile to a buffer + * and updates the position in the file. + * (assumes the buffer is large enough) + * (if size is greater than EOF gridfile_read reads until EOF) + * + * @param gfile - the working GridFile + * @param size - the amount of bytes to be read + * @param buf - the buffer to read to + * + * @return - the number of bytes read + */ +gridfs_offset gridfile_read( gridfile *gfile, gridfs_offset size, char *buf ); + +/** + * Updates the position in the file + * (If the offset goes beyond the contentlength, + * the position is updated to the end of the file.) + * + * @param gfile - the working GridFile + * @param offset - the position to update to + * + * @return - resulting offset location + */ +gridfs_offset gridfile_seek( gridfile *gfile, gridfs_offset offset ); + +#endif diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/md5.c b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/md5.c new file mode 100644 index 0000000000..d1c1e3ab0b --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/md5.c @@ -0,0 +1,381 @@ +/* + Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. + + 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. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + + The original and principal author of md5.c is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order + either statically or dynamically; added missing #include + in library. + 2002-03-11 lpd Corrected argument list for main(), and added int return + type, in test program and T value program. + 2002-02-21 lpd Added missing #include in test program. + 2000-07-03 lpd Patched to eliminate warnings about "constant is + unsigned in ANSI C, signed in traditional"; made test program + self-checking. + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). + 1999-05-03 lpd Original version. + */ + +#include "md5.h" +#include + +#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ +#ifdef MONGO_BIG_ENDIAN +# define BYTE_ORDER 1 +#else +# define BYTE_ORDER -1 +#endif + +#define T_MASK ((mongo_md5_word_t)~0) +#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) +#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) +#define T3 0x242070db +#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) +#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) +#define T6 0x4787c62a +#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) +#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) +#define T9 0x698098d8 +#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) +#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) +#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) +#define T13 0x6b901122 +#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) +#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) +#define T16 0x49b40821 +#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) +#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) +#define T19 0x265e5a51 +#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) +#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) +#define T22 0x02441453 +#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) +#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) +#define T25 0x21e1cde6 +#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) +#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) +#define T28 0x455a14ed +#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) +#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) +#define T31 0x676f02d9 +#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) +#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) +#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) +#define T35 0x6d9d6122 +#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) +#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) +#define T38 0x4bdecfa9 +#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) +#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) +#define T41 0x289b7ec6 +#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) +#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) +#define T44 0x04881d05 +#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) +#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) +#define T47 0x1fa27cf8 +#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) +#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) +#define T50 0x432aff97 +#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) +#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) +#define T53 0x655b59c3 +#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) +#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) +#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) +#define T57 0x6fa87e4f +#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) +#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) +#define T60 0x4e0811a1 +#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) +#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) +#define T63 0x2ad7d2bb +#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) + + +static void +mongo_md5_process(mongo_md5_state_t *pms, const mongo_md5_byte_t *data /*[64]*/) +{ + mongo_md5_word_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + mongo_md5_word_t t; +#if BYTE_ORDER > 0 + /* Define storage only for big-endian CPUs. */ + mongo_md5_word_t X[16]; +#else + /* Define storage for little-endian or both types of CPUs. */ + mongo_md5_word_t xbuf[16]; + const mongo_md5_word_t *X; +#endif + + { +#if BYTE_ORDER == 0 + /* + * Determine dynamically whether this is a big-endian or + * little-endian machine, since we can use a more efficient + * algorithm on the latter. + */ + static const int w = 1; + + if (*((const mongo_md5_byte_t *)&w)) /* dynamic little-endian */ +#endif +#if BYTE_ORDER <= 0 /* little-endian */ + { + /* + * On little-endian machines, we can process properly aligned + * data without copying it. + */ + if (!((data - (const mongo_md5_byte_t *)0) & 3)) { + /* data are properly aligned */ + X = (const mongo_md5_word_t *)data; + } else { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } + } +#endif +#if BYTE_ORDER == 0 + else /* dynamic big-endian */ +#endif +#if BYTE_ORDER >= 0 /* big-endian */ + { + /* + * On big-endian machines, we must arrange the bytes in the + * right order. + */ + const mongo_md5_byte_t *xp = data; + int i; + +# if BYTE_ORDER == 0 + X = xbuf; /* (dynamic only) */ +# else +# define xbuf X /* (static only) */ +# endif + for (i = 0; i < 16; ++i, xp += 4) + xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + } +#endif + } + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); +#undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ +#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); +#undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); +#undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ +#define I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); +#undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +void +mongo_md5_init(mongo_md5_state_t *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; + pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; + pms->abcd[3] = 0x10325476; +} + +void +mongo_md5_append(mongo_md5_state_t *pms, const mongo_md5_byte_t *data, int nbytes) +{ + const mongo_md5_byte_t *p = data; + int left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + mongo_md5_word_t nbits = (mongo_md5_word_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + pms->count[1]++; + + /* Process an initial partial block. */ + if (offset) { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + mongo_md5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + mongo_md5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); +} + +void +mongo_md5_finish(mongo_md5_state_t *pms, mongo_md5_byte_t digest[16]) +{ + static const mongo_md5_byte_t pad[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + mongo_md5_byte_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (mongo_md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + mongo_md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + mongo_md5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (mongo_md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); +} diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/md5.h b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/md5.h new file mode 100644 index 0000000000..540da3a584 --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/md5.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved. + + 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. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + + The original and principal author of md5.h is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 2002-04-13 lpd Removed support for non-ANSI compilers; removed + references to Ghostscript; clarified derivation from RFC 1321; + now handles byte order either statically or dynamically. + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5); + added conditionalization for C++ compilation from Martin + Purschke . + 1999-05-03 lpd Original version. + */ + +#ifndef md5_INCLUDED +# define md5_INCLUDED + +/* + * This package supports both compile-time and run-time determination of CPU + * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be + * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is + * defined as non-zero, the code will be compiled to run only on big-endian + * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to + * run on either big- or little-endian CPUs, but will run slightly less + * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined. + */ + +typedef unsigned char mongo_md5_byte_t; /* 8-bit byte */ +typedef unsigned int mongo_md5_word_t; /* 32-bit word */ + +/* Define the state of the MD5 Algorithm. */ +typedef struct mongo_md5_state_s { + mongo_md5_word_t count[2]; /* message length in bits, lsw first */ + mongo_md5_word_t abcd[4]; /* digest buffer */ + mongo_md5_byte_t buf[64]; /* accumulate block */ +} mongo_md5_state_t; + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* Initialize the algorithm. */ + void mongo_md5_init(mongo_md5_state_t *pms); + + /* Append a string to the message. */ + void mongo_md5_append(mongo_md5_state_t *pms, const mongo_md5_byte_t *data, int nbytes); + + /* Finish the message and return the digest. */ + void mongo_md5_finish(mongo_md5_state_t *pms, mongo_md5_byte_t digest[16]); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif /* md5_INCLUDED */ diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/mongo.c b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/mongo.c new file mode 100644 index 0000000000..2090e74312 --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/mongo.c @@ -0,0 +1,1217 @@ +/* mongo.c */ + +/* Copyright 2009-2011 10gen Inc. + * + * 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 "mongo.h" +#include "md5.h" + +#include +#include +#include +#include + +#ifdef _USE_LINUX_SYSTEM +#include "platform/linux/net.h" +#elif defined _USE_CUSTOM_SYSTEM +#include "platform/custom/net.h" +#else +#include "net.h" +#endif + +static const int ZERO = 0; +static const int ONE = 1; +mongo_message *mongo_message_create( int len , int id , int responseTo , int op ) { + mongo_message *mm = ( mongo_message * )bson_malloc( len ); + + if ( !id ) + id = rand(); + + /* native endian (converted on send) */ + mm->head.len = len; + mm->head.id = id; + mm->head.responseTo = responseTo; + mm->head.op = op; + + return mm; +} + +/* Always calls bson_free(mm) */ +int mongo_message_send( mongo *conn, mongo_message *mm ) { + mongo_header head; /* little endian */ + int res; + bson_little_endian32( &head.len, &mm->head.len ); + bson_little_endian32( &head.id, &mm->head.id ); + bson_little_endian32( &head.responseTo, &mm->head.responseTo ); + bson_little_endian32( &head.op, &mm->head.op ); + + res = mongo_write_socket( conn, &head, sizeof( head ) ); + if( res != MONGO_OK ) { + bson_free( mm ); + return res; + } + + res = mongo_write_socket( conn, &mm->data, mm->head.len - sizeof( head ) ); + if( res != MONGO_OK ) { + bson_free( mm ); + return res; + } + + bson_free( mm ); + return MONGO_OK; +} + +int mongo_read_response( mongo *conn, mongo_reply **reply ) { + mongo_header head; /* header from network */ + mongo_reply_fields fields; /* header from network */ + mongo_reply *out; /* native endian */ + unsigned int len; + int res; + + mongo_read_socket( conn, &head, sizeof( head ) ); + mongo_read_socket( conn, &fields, sizeof( fields ) ); + + bson_little_endian32( &len, &head.len ); + + if ( len < sizeof( head )+sizeof( fields ) || len > 64*1024*1024 ) + return MONGO_READ_SIZE_ERROR; /* most likely corruption */ + + out = ( mongo_reply * )bson_malloc( len ); + + out->head.len = len; + bson_little_endian32( &out->head.id, &head.id ); + bson_little_endian32( &out->head.responseTo, &head.responseTo ); + bson_little_endian32( &out->head.op, &head.op ); + + bson_little_endian32( &out->fields.flag, &fields.flag ); + bson_little_endian64( &out->fields.cursorID, &fields.cursorID ); + bson_little_endian32( &out->fields.start, &fields.start ); + bson_little_endian32( &out->fields.num, &fields.num ); + + res = mongo_read_socket( conn, &out->objs, len-sizeof( head )-sizeof( fields ) ); + if( res != MONGO_OK ) { + bson_free( out ); + return res; + } + + *reply = out; + + return MONGO_OK; +} + + +char *mongo_data_append( char *start , const void *data , int len ) { + memcpy( start , data , len ); + return start + len; +} + +char *mongo_data_append32( char *start , const void *data ) { + bson_little_endian32( start , data ); + return start + 4; +} + +char *mongo_data_append64( char *start , const void *data ) { + bson_little_endian64( start , data ); + return start + 8; +} + +/* Connection API */ + +static int mongo_check_is_master( mongo *conn ) { + bson out; + bson_iterator it; + bson_bool_t ismaster = 0; + + out.data = NULL; + + if ( mongo_simple_int_command( conn, "admin", "ismaster", 1, &out ) == MONGO_OK ) { + if( bson_find( &it, &out, "ismaster" ) ) + ismaster = bson_iterator_bool( &it ); + } else { + return MONGO_ERROR; + } + + bson_destroy( &out ); + + if( ismaster ) + return MONGO_OK; + else { + conn->err = MONGO_CONN_NOT_MASTER; + return MONGO_ERROR; + } +} + +void mongo_init( mongo *conn ) { + conn->replset = NULL; + conn->err = 0; + conn->errstr = NULL; + conn->lasterrcode = 0; + conn->lasterrstr = NULL; + + conn->conn_timeout_ms = 0; + conn->op_timeout_ms = 0; +} + +int mongo_connect( mongo *conn , const char *host, int port ) { + conn->primary = bson_malloc( sizeof( mongo_host_port ) ); + strncpy( conn->primary->host, host, strlen( host ) + 1 ); + conn->primary->port = port; + conn->primary->next = NULL; + + mongo_init( conn ); + if( mongo_socket_connect( conn, host, port ) != MONGO_OK ) + return MONGO_ERROR; + + if( mongo_check_is_master( conn ) != MONGO_OK ) + return MONGO_ERROR; + else + return MONGO_OK; +} + +void mongo_replset_init( mongo *conn, const char *name ) { + mongo_init( conn ); + + conn->replset = bson_malloc( sizeof( mongo_replset ) ); + conn->replset->primary_connected = 0; + conn->replset->seeds = NULL; + conn->replset->hosts = NULL; + conn->replset->name = ( char * )bson_malloc( strlen( name ) + 1 ); + memcpy( conn->replset->name, name, strlen( name ) + 1 ); + + conn->primary = bson_malloc( sizeof( mongo_host_port ) ); +} + +static void mongo_replset_add_node( mongo_host_port **list, const char *host, int port ) { + mongo_host_port *host_port = bson_malloc( sizeof( mongo_host_port ) ); + host_port->port = port; + host_port->next = NULL; + strncpy( host_port->host, host, strlen( host ) + 1 ); + + if( *list == NULL ) + *list = host_port; + else { + mongo_host_port *p = *list; + while( p->next != NULL ) + p = p->next; + p->next = host_port; + } +} + +static void mongo_replset_free_list( mongo_host_port **list ) { + mongo_host_port *node = *list; + mongo_host_port *prev; + + while( node != NULL ) { + prev = node; + node = node->next; + bson_free( prev ); + } + + *list = NULL; +} + +void mongo_replset_add_seed( mongo *conn, const char *host, int port ) { + mongo_replset_add_node( &conn->replset->seeds, host, port ); +} + +void mongo_parse_host( const char *host_string, mongo_host_port *host_port ) { + int len, idx, split; + len = split = idx = 0; + + /* Split the host_port string at the ':' */ + while( 1 ) { + if( *( host_string + len ) == '\0' ) + break; + if( *( host_string + len ) == ':' ) + split = len; + + len++; + } + + /* If 'split' is set, we know the that port exists; + * Otherwise, we set the default port. */ + idx = split ? split : len; + memcpy( host_port->host, host_string, idx ); + memcpy( host_port->host + idx, "\0", 1 ); + if( split ) + host_port->port = atoi( host_string + idx + 1 ); + else + host_port->port = MONGO_DEFAULT_PORT; +} + +static void mongo_replset_check_seed( mongo *conn ) { + bson out; + bson hosts; + const char *data; + bson_iterator it; + bson_iterator it_sub; + const char *host_string; + mongo_host_port *host_port = NULL; + + out.data = NULL; + + hosts.data = NULL; + + if( mongo_simple_int_command( conn, "admin", "ismaster", 1, &out ) == MONGO_OK ) { + + if( bson_find( &it, &out, "hosts" ) ) { + data = bson_iterator_value( &it ); + bson_iterator_from_buffer( &it_sub, data ); + + /* Iterate over host list, adding each host to the + * connection's host list. */ + while( bson_iterator_next( &it_sub ) ) { + host_string = bson_iterator_string( &it_sub ); + + host_port = bson_malloc( sizeof( mongo_host_port ) ); + mongo_parse_host( host_string, host_port ); + + if( host_port ) { + mongo_replset_add_node( &conn->replset->hosts, + host_port->host, host_port->port ); + + bson_free( host_port ); + host_port = NULL; + } + } + } + } + + bson_destroy( &out ); + bson_destroy( &hosts ); + mongo_close_socket( conn->sock ); + conn->sock = 0; + conn->connected = 0; + +} + +/* Find out whether the current connected node is master, and + * verify that the node's replica set name matched the provided name + */ +static int mongo_replset_check_host( mongo *conn ) { + + bson out; + bson_iterator it; + bson_bool_t ismaster = 0; + const char *set_name; + + out.data = NULL; + + if ( mongo_simple_int_command( conn, "admin", "ismaster", 1, &out ) == MONGO_OK ) { + if( bson_find( &it, &out, "ismaster" ) ) + ismaster = bson_iterator_bool( &it ); + + if( bson_find( &it, &out, "setName" ) ) { + set_name = bson_iterator_string( &it ); + if( strcmp( set_name, conn->replset->name ) != 0 ) { + bson_destroy( &out ); + conn->err = MONGO_CONN_BAD_SET_NAME; + return MONGO_ERROR; + } + } + } + + bson_destroy( &out ); + + if( ismaster ) { + conn->replset->primary_connected = 1; + } else { + mongo_close_socket( conn->sock ); + } + + return MONGO_OK; +} + +int mongo_replset_connect( mongo *conn ) { + + int res = 0; + mongo_host_port *node; + + conn->sock = 0; + conn->connected = 0; + + /* First iterate over the seed nodes to get the canonical list of hosts + * from the replica set. Break out once we have a host list. + */ + node = conn->replset->seeds; + while( node != NULL ) { + res = mongo_socket_connect( conn, ( const char * )&node->host, node->port ); + if( res != MONGO_OK ) + return MONGO_ERROR; + + mongo_replset_check_seed( conn ); + + if( conn->replset->hosts ) + break; + + node = node->next; + } + + /* Iterate over the host list, checking for the primary node. */ + if( !conn->replset->hosts ) { + conn->err = MONGO_CONN_NO_PRIMARY; + return MONGO_ERROR; + } else { + node = conn->replset->hosts; + + while( node != NULL ) { + res = mongo_socket_connect( conn, ( const char * )&node->host, node->port ); + + if( res == MONGO_OK ) { + if( mongo_replset_check_host( conn ) != MONGO_OK ) + return MONGO_ERROR; + + /* Primary found, so return. */ + else if( conn->replset->primary_connected ) + return MONGO_OK; + + /* No primary, so close the connection. */ + else { + mongo_close_socket( conn->sock ); + conn->sock = 0; + conn->connected = 0; + } + } + + node = node->next; + } + } + + + conn->err = MONGO_CONN_NO_PRIMARY; + return MONGO_ERROR; +} + +int mongo_set_op_timeout( mongo *conn, int millis ) { + conn->op_timeout_ms = millis; + if( conn->sock && conn->connected ) + mongo_set_socket_op_timeout( conn, millis ); + + return MONGO_OK; +} + +int mongo_reconnect( mongo *conn ) { + int res; + mongo_disconnect( conn ); + + if( conn->replset ) { + conn->replset->primary_connected = 0; + mongo_replset_free_list( &conn->replset->hosts ); + conn->replset->hosts = NULL; + res = mongo_replset_connect( conn ); + return res; + } else + return mongo_socket_connect( conn, conn->primary->host, conn->primary->port ); +} + +int mongo_check_connection( mongo *conn ) { + if( ! conn->connected ) + return MONGO_ERROR; + + if( mongo_simple_int_command( conn, "admin", "ping", 1, NULL ) == MONGO_OK ) + return MONGO_OK; + else + return MONGO_ERROR; +} + +void mongo_disconnect( mongo *conn ) { + if( ! conn->connected ) + return; + + if( conn->replset ) { + conn->replset->primary_connected = 0; + mongo_replset_free_list( &conn->replset->hosts ); + conn->replset->hosts = NULL; + } + + mongo_close_socket( conn->sock ); + + conn->sock = 0; + conn->connected = 0; +} + +void mongo_destroy( mongo *conn ) { + mongo_disconnect( conn ); + + if( conn->replset ) { + mongo_replset_free_list( &conn->replset->seeds ); + mongo_replset_free_list( &conn->replset->hosts ); + bson_free( conn->replset->name ); + bson_free( conn->replset ); + conn->replset = NULL; + } + + bson_free( conn->primary ); + bson_free( conn->errstr ); + bson_free( conn->lasterrstr ); + + conn->err = 0; + conn->errstr = NULL; + conn->lasterrcode = 0; + conn->lasterrstr = NULL; +} + +/* Determine whether this BSON object is valid for the given operation. */ +static int mongo_bson_valid( mongo *conn, bson *bson, int write ) { + if( ! bson->finished ) { + conn->err = MONGO_BSON_NOT_FINISHED; + return MONGO_ERROR; + } + + if( bson->err & BSON_NOT_UTF8 ) { + conn->err = MONGO_BSON_INVALID; + return MONGO_ERROR; + } + + if( write ) { + if( ( bson->err & BSON_FIELD_HAS_DOT ) || + ( bson->err & BSON_FIELD_INIT_DOLLAR ) ) { + + conn->err = MONGO_BSON_INVALID; + return MONGO_ERROR; + + } + } + + conn->err = 0; + conn->errstr = NULL; + + return MONGO_OK; +} + +/* Determine whether this BSON object is valid for the given operation. */ +static int mongo_cursor_bson_valid( mongo_cursor *cursor, bson *bson ) { + if( ! bson->finished ) { + cursor->err = MONGO_BSON_NOT_FINISHED; + return MONGO_ERROR; + } + + if( bson->err & BSON_NOT_UTF8 ) { + cursor->err = MONGO_BSON_INVALID; + return MONGO_ERROR; + } + + return MONGO_OK; +} + +/* MongoDB CRUD API */ + +int mongo_insert_batch( mongo *conn, const char *ns, + bson **bsons, int count ) { + + int size = 16 + 4 + strlen( ns ) + 1; + int i; + mongo_message *mm; + char *data; + + for( i=0; idata; + data = mongo_data_append32( data, &ZERO ); + data = mongo_data_append( data, ns, strlen( ns ) + 1 ); + + for( i=0; idata, bson_size( bsons[i] ) ); + } + + return mongo_message_send( conn, mm ); +} + +int mongo_insert( mongo *conn , const char *ns , bson *bson ) { + + char *data; + mongo_message *mm; + + /* Make sure that BSON is valid for insert. */ + if( mongo_bson_valid( conn, bson, 1 ) != MONGO_OK ) { + return MONGO_ERROR; + } + + mm = mongo_message_create( 16 /* header */ + + 4 /* ZERO */ + + strlen( ns ) + + 1 + bson_size( bson ) + , 0, 0, MONGO_OP_INSERT ); + + data = &mm->data; + data = mongo_data_append32( data, &ZERO ); + data = mongo_data_append( data, ns, strlen( ns ) + 1 ); + data = mongo_data_append( data, bson->data, bson_size( bson ) ); + + return mongo_message_send( conn, mm ); +} + +int mongo_update( mongo *conn, const char *ns, const bson *cond, + const bson *op, int flags ) { + + char *data; + mongo_message *mm; + + /* Make sure that the op BSON is valid UTF-8. + * TODO: decide whether to check cond as well. + * */ + if( mongo_bson_valid( conn, ( bson * )op, 0 ) != MONGO_OK ) { + return MONGO_ERROR; + } + + mm = mongo_message_create( 16 /* header */ + + 4 /* ZERO */ + + strlen( ns ) + 1 + + 4 /* flags */ + + bson_size( cond ) + + bson_size( op ) + , 0 , 0 , MONGO_OP_UPDATE ); + + data = &mm->data; + data = mongo_data_append32( data, &ZERO ); + data = mongo_data_append( data, ns, strlen( ns ) + 1 ); + data = mongo_data_append32( data, &flags ); + data = mongo_data_append( data, cond->data, bson_size( cond ) ); + data = mongo_data_append( data, op->data, bson_size( op ) ); + + return mongo_message_send( conn, mm ); +} + +int mongo_remove( mongo *conn, const char *ns, const bson *cond ) { + char *data; + mongo_message *mm = mongo_message_create( 16 /* header */ + + 4 /* ZERO */ + + strlen( ns ) + 1 + + 4 /* ZERO */ + + bson_size( cond ) + , 0 , 0 , MONGO_OP_DELETE ); + + /* Make sure that the BSON is valid UTF-8. + * TODO: decide whether to check cond as well. + * */ + if( mongo_bson_valid( conn, ( bson * )cond, 0 ) != MONGO_OK ) { + return MONGO_ERROR; + } + + data = &mm->data; + data = mongo_data_append32( data, &ZERO ); + data = mongo_data_append( data, ns, strlen( ns ) + 1 ); + data = mongo_data_append32( data, &ZERO ); + data = mongo_data_append( data, cond->data, bson_size( cond ) ); + + return mongo_message_send( conn, mm ); +} + + +static int mongo_cursor_op_query( mongo_cursor *cursor ) { + int res; + bson empty; + char *data; + mongo_message *mm; + + /* Set up default values for query and fields, if necessary. */ + if( ! cursor->query ) + cursor->query = bson_empty( &empty ); + else if( mongo_cursor_bson_valid( cursor, cursor->query ) != MONGO_OK ) + return MONGO_ERROR; + + if( ! cursor->fields ) + cursor->fields = bson_empty( &empty ); + else if( mongo_cursor_bson_valid( cursor, cursor->fields ) != MONGO_OK ) + return MONGO_ERROR; + + mm = mongo_message_create( 16 + /* header */ + 4 + /* options */ + strlen( cursor->ns ) + 1 + /* ns */ + 4 + 4 + /* skip,return */ + bson_size( cursor->query ) + + bson_size( cursor->fields ) , + 0 , 0 , MONGO_OP_QUERY ); + + data = &mm->data; + data = mongo_data_append32( data , &cursor->options ); + data = mongo_data_append( data , cursor->ns , strlen( cursor->ns ) + 1 ); + data = mongo_data_append32( data , &cursor->skip ); + data = mongo_data_append32( data , &cursor->limit ); + data = mongo_data_append( data , cursor->query->data , bson_size( cursor->query ) ); + if ( cursor->fields ) + data = mongo_data_append( data , cursor->fields->data , bson_size( cursor->fields ) ); + + bson_fatal_msg( ( data == ( ( char * )mm ) + mm->head.len ), "query building fail!" ); + + res = mongo_message_send( cursor->conn , mm ); + if( res != MONGO_OK ) { + return MONGO_ERROR; + } + + res = mongo_read_response( cursor->conn, ( mongo_reply ** )&( cursor->reply ) ); + if( res != MONGO_OK ) { + return MONGO_ERROR; + } + + cursor->seen += cursor->reply->fields.num; + cursor->flags |= MONGO_CURSOR_QUERY_SENT; + return MONGO_OK; +} + +static int mongo_cursor_get_more( mongo_cursor *cursor ) { + int res; + + if( cursor->limit > 0 && cursor->seen >= cursor->limit ) { + cursor->err = MONGO_CURSOR_EXHAUSTED; + return MONGO_ERROR; + } else if( ! cursor->reply ) { + cursor->err = MONGO_CURSOR_INVALID; + return MONGO_ERROR; + } else if( ! cursor->reply->fields.cursorID ) { + cursor->err = MONGO_CURSOR_EXHAUSTED; + return MONGO_ERROR; + } else { + char *data; + int sl = strlen( cursor->ns )+1; + int limit = 0; + mongo_message *mm; + + if( cursor->limit > 0 ) + limit = cursor->limit - cursor->seen; + + mm = mongo_message_create( 16 /*header*/ + +4 /*ZERO*/ + +sl + +4 /*numToReturn*/ + +8 /*cursorID*/ + , 0, 0, MONGO_OP_GET_MORE ); + data = &mm->data; + data = mongo_data_append32( data, &ZERO ); + data = mongo_data_append( data, cursor->ns, sl ); + data = mongo_data_append32( data, &limit ); + data = mongo_data_append64( data, &cursor->reply->fields.cursorID ); + + bson_free( cursor->reply ); + res = mongo_message_send( cursor->conn, mm ); + if( res != MONGO_OK ) { + mongo_cursor_destroy( cursor ); + return MONGO_ERROR; + } + + res = mongo_read_response( cursor->conn, &( cursor->reply ) ); + if( res != MONGO_OK ) { + mongo_cursor_destroy( cursor ); + return MONGO_ERROR; + } + cursor->current.data = NULL; + cursor->seen += cursor->reply->fields.num; + + return MONGO_OK; + } +} + +mongo_cursor *mongo_find( mongo *conn, const char *ns, bson *query, + bson *fields, int limit, int skip, int options ) { + + mongo_cursor *cursor = ( mongo_cursor * )bson_malloc( sizeof( mongo_cursor ) ); + mongo_cursor_init( cursor, conn, ns ); + cursor->flags |= MONGO_CURSOR_MUST_FREE; + + mongo_cursor_set_query( cursor, query ); + mongo_cursor_set_fields( cursor, fields ); + mongo_cursor_set_limit( cursor, limit ); + mongo_cursor_set_skip( cursor, skip ); + mongo_cursor_set_options( cursor, options ); + + if( mongo_cursor_op_query( cursor ) == MONGO_OK ) + return cursor; + else { + mongo_cursor_destroy( cursor ); + return NULL; + } +} + +int mongo_find_one( mongo *conn, const char *ns, bson *query, + bson *fields, bson *out ) { + + mongo_cursor *cursor = mongo_find( conn, ns, query, fields, 1, 0, 0 ); + + if ( cursor && mongo_cursor_next( cursor ) == MONGO_OK ) { + bson_copy_basic( out, &cursor->current ); + mongo_cursor_destroy( cursor ); + return MONGO_OK; + } else { + mongo_cursor_destroy( cursor ); + return MONGO_ERROR; + } +} + +void mongo_cursor_init( mongo_cursor *cursor, mongo *conn, const char *ns ) { + cursor->conn = conn; + cursor->ns = ( const char * )bson_malloc( strlen( ns ) + 1 ); + strncpy( ( char * )cursor->ns, ns, strlen( ns ) + 1 ); + cursor->current.data = NULL; + cursor->reply = NULL; + cursor->flags = 0; + cursor->seen = 0; + cursor->err = 0; + cursor->options = 0; + cursor->query = NULL; + cursor->fields = NULL; + cursor->skip = 0; + cursor->limit = 0; +} + +void mongo_cursor_set_query( mongo_cursor *cursor, bson *query ) { + cursor->query = query; +} + +void mongo_cursor_set_fields( mongo_cursor *cursor, bson *fields ) { + cursor->fields = fields; +} + +void mongo_cursor_set_skip( mongo_cursor *cursor, int skip ) { + cursor->skip = skip; +} + +void mongo_cursor_set_limit( mongo_cursor *cursor, int limit ) { + cursor->limit = limit; +} + +void mongo_cursor_set_options( mongo_cursor *cursor, int options ) { + cursor->options = options; +} + +const char *mongo_cursor_data( mongo_cursor *cursor ) { + return cursor->current.data; +} + +const bson *mongo_cursor_bson( mongo_cursor *cursor ) { + return (const bson *)&(cursor->current); +} + +int mongo_cursor_next( mongo_cursor *cursor ) { + char *next_object; + char *message_end; + + if( ! ( cursor->flags & MONGO_CURSOR_QUERY_SENT ) ) + mongo_cursor_op_query( cursor ); + + if( !cursor->reply ) + return MONGO_ERROR; + + /* no data */ + if ( cursor->reply->fields.num == 0 ) { + + /* Special case for tailable cursors. */ + if( cursor->reply->fields.cursorID ) { + if( ( mongo_cursor_get_more( cursor ) != MONGO_OK ) || + cursor->reply->fields.num == 0 ) { + return MONGO_ERROR; + } + } + + else + return MONGO_ERROR; + } + + /* first */ + if ( cursor->current.data == NULL ) { + bson_init_data( &cursor->current, &cursor->reply->objs ); + return MONGO_OK; + } + + next_object = cursor->current.data + bson_size( &cursor->current ); + message_end = ( char * )cursor->reply + cursor->reply->head.len; + + if ( next_object >= message_end ) { + if( mongo_cursor_get_more( cursor ) != MONGO_OK ) + return MONGO_ERROR; + + /* If there's still a cursor id, then the message should be pending. */ + if( cursor->reply->fields.num == 0 && cursor->reply->fields.cursorID ) { + cursor->err = MONGO_CURSOR_PENDING; + return MONGO_ERROR; + } + + bson_init_data( &cursor->current, &cursor->reply->objs ); + } else { + bson_init_data( &cursor->current, next_object ); + } + + return MONGO_OK; +} + +int mongo_cursor_destroy( mongo_cursor *cursor ) { + int result = MONGO_OK; + + if ( !cursor ) return result; + + /* Kill cursor if live. */ + if ( cursor->reply && cursor->reply->fields.cursorID ) { + mongo *conn = cursor->conn; + mongo_message *mm = mongo_message_create( 16 /*header*/ + +4 /*ZERO*/ + +4 /*numCursors*/ + +8 /*cursorID*/ + , 0, 0, MONGO_OP_KILL_CURSORS ); + char *data = &mm->data; + data = mongo_data_append32( data, &ZERO ); + data = mongo_data_append32( data, &ONE ); + data = mongo_data_append64( data, &cursor->reply->fields.cursorID ); + + result = mongo_message_send( conn, mm ); + } + + bson_free( cursor->reply ); + bson_free( ( void * )cursor->ns ); + + if( cursor->flags & MONGO_CURSOR_MUST_FREE ) + bson_free( cursor ); + + return result; +} + +/* MongoDB Helper Functions */ + +int mongo_create_index( mongo *conn, const char *ns, bson *key, int options, bson *out ) { + bson b; + bson_iterator it; + char name[255] = {'_'}; + int i = 1; + char idxns[1024]; + + bson_iterator_init( &it, key ); + while( i < 255 && bson_iterator_next( &it ) ) { + strncpy( name + i, bson_iterator_key( &it ), 255 - i ); + i += strlen( bson_iterator_key( &it ) ); + } + name[254] = '\0'; + + bson_init( &b ); + bson_append_bson( &b, "key", key ); + bson_append_string( &b, "ns", ns ); + bson_append_string( &b, "name", name ); + if ( options & MONGO_INDEX_UNIQUE ) + bson_append_bool( &b, "unique", 1 ); + if ( options & MONGO_INDEX_DROP_DUPS ) + bson_append_bool( &b, "dropDups", 1 ); + if ( options & MONGO_INDEX_BACKGROUND ) + bson_append_bool( &b, "background", 1 ); + if ( options & MONGO_INDEX_SPARSE ) + bson_append_bool( &b, "sparse", 1 ); + bson_finish( &b ); + + strncpy( idxns, ns, 1024-16 ); + strcpy( strchr( idxns, '.' ), ".system.indexes" ); + mongo_insert( conn, idxns, &b ); + bson_destroy( &b ); + + *strchr( idxns, '.' ) = '\0'; /* just db not ns */ + return mongo_cmd_get_last_error( conn, idxns, out ); +} + +bson_bool_t mongo_create_simple_index( mongo *conn, const char *ns, const char *field, int options, bson *out ) { + bson b; + bson_bool_t success; + + bson_init( &b ); + bson_append_int( &b, field, 1 ); + bson_finish( &b ); + + success = mongo_create_index( conn, ns, &b, options, out ); + bson_destroy( &b ); + return success; +} + +int64_t mongo_count( mongo *conn, const char *db, const char *ns, bson *query ) { + bson cmd; + bson out = {NULL, 0}; + int64_t count = -1; + + bson_init( &cmd ); + bson_append_string( &cmd, "count", ns ); + if ( query && bson_size( query ) > 5 ) /* not empty */ + bson_append_bson( &cmd, "query", query ); + bson_finish( &cmd ); + + if( mongo_run_command( conn, db, &cmd, &out ) == MONGO_OK ) { + bson_iterator it; + if( bson_find( &it, &out, "n" ) ) + count = bson_iterator_long( &it ); + bson_destroy( &cmd ); + bson_destroy( &out ); + return count; + } else { + bson_destroy( &out ); + bson_destroy( &cmd ); + return MONGO_ERROR; + } +} + +int mongo_run_command( mongo *conn, const char *db, bson *command, + bson *out ) { + + bson fields; + int sl = strlen( db ); + char *ns = bson_malloc( sl + 5 + 1 ); /* ".$cmd" + nul */ + int res; + + strcpy( ns, db ); + strcpy( ns+sl, ".$cmd" ); + + res = mongo_find_one( conn, ns, command, bson_empty( &fields ), out ); + bson_free( ns ); + return res; +} + +int mongo_simple_int_command( mongo *conn, const char *db, + const char *cmdstr, int arg, bson *realout ) { + + bson out = {NULL, 0}; + bson cmd; + bson_bool_t success = 0; + + bson_init( &cmd ); + bson_append_int( &cmd, cmdstr, arg ); + bson_finish( &cmd ); + + if( mongo_run_command( conn, db, &cmd, &out ) == MONGO_OK ) { + bson_iterator it; + if( bson_find( &it, &out, "ok" ) ) + success = bson_iterator_bool( &it ); + } + + bson_destroy( &cmd ); + + if ( realout ) + *realout = out; + else + bson_destroy( &out ); + + if( success ) + return MONGO_OK; + else { + conn->err = MONGO_COMMAND_FAILED; + return MONGO_ERROR; + } +} + +int mongo_simple_str_command( mongo *conn, const char *db, + const char *cmdstr, const char *arg, bson *realout ) { + + bson out = {NULL, 0}; + int success = 0; + + bson cmd; + bson_init( &cmd ); + bson_append_string( &cmd, cmdstr, arg ); + bson_finish( &cmd ); + + if( mongo_run_command( conn, db, &cmd, &out ) == MONGO_OK ) { + bson_iterator it; + if( bson_find( &it, &out, "ok" ) ) + success = bson_iterator_bool( &it ); + } + + bson_destroy( &cmd ); + + if ( realout ) + *realout = out; + else + bson_destroy( &out ); + + if( success ) + return MONGO_OK; + else + return MONGO_ERROR; +} + +int mongo_cmd_drop_db( mongo *conn, const char *db ) { + return mongo_simple_int_command( conn, db, "dropDatabase", 1, NULL ); +} + +int mongo_cmd_drop_collection( mongo *conn, const char *db, const char *collection, bson *out ) { + return mongo_simple_str_command( conn, db, "drop", collection, out ); +} + +void mongo_cmd_reset_error( mongo *conn, const char *db ) { + mongo_simple_int_command( conn, db, "reseterror", 1, NULL ); +} + +static int mongo_cmd_get_error_helper( mongo *conn, const char *db, + bson *realout, const char *cmdtype ) { + + bson out = {NULL,0}; + bson_bool_t haserror = 0; + + /* Reset last error codes. */ + conn->lasterrcode = 0; + bson_free( conn->lasterrstr ); + conn->lasterrstr = NULL; + + /* If there's an error, store its code and string in the connection object. */ + if( mongo_simple_int_command( conn, db, cmdtype, 1, &out ) == MONGO_OK ) { + bson_iterator it; + haserror = ( bson_find( &it, &out, "err" ) != BSON_NULL ); + if( haserror ) { + conn->lasterrstr = ( char * )bson_malloc( bson_iterator_string_len( &it ) ); + if( conn->lasterrstr ) { + strcpy( conn->lasterrstr, bson_iterator_string( &it ) ); + } + + if( bson_find( &it, &out, "code" ) != BSON_NULL ) + conn->lasterrcode = bson_iterator_int( &it ); + } + } + + if( realout ) + *realout = out; /* transfer of ownership */ + else + bson_destroy( &out ); + + if( haserror ) + return MONGO_ERROR; + else + return MONGO_OK; +} + +int mongo_cmd_get_prev_error( mongo *conn, const char *db, bson *out ) { + return mongo_cmd_get_error_helper( conn, db, out, "getpreverror" ); +} + +int mongo_cmd_get_last_error( mongo *conn, const char *db, bson *out ) { + return mongo_cmd_get_error_helper( conn, db, out, "getlasterror" ); +} + +bson_bool_t mongo_cmd_ismaster( mongo *conn, bson *realout ) { + bson out = {NULL,0}; + bson_bool_t ismaster = 0; + + if ( mongo_simple_int_command( conn, "admin", "ismaster", 1, &out ) == MONGO_OK ) { + bson_iterator it; + bson_find( &it, &out, "ismaster" ); + ismaster = bson_iterator_bool( &it ); + } + + if( realout ) + *realout = out; /* transfer of ownership */ + else + bson_destroy( &out ); + + return ismaster; +} + +static void digest2hex( mongo_md5_byte_t digest[16], char hex_digest[33] ) { + static const char hex[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; + int i; + for ( i=0; i<16; i++ ) { + hex_digest[2*i] = hex[( digest[i] & 0xf0 ) >> 4]; + hex_digest[2*i + 1] = hex[ digest[i] & 0x0f ]; + } + hex_digest[32] = '\0'; +} + +static void mongo_pass_digest( const char *user, const char *pass, char hex_digest[33] ) { + mongo_md5_state_t st; + mongo_md5_byte_t digest[16]; + + mongo_md5_init( &st ); + mongo_md5_append( &st, ( const mongo_md5_byte_t * )user, strlen( user ) ); + mongo_md5_append( &st, ( const mongo_md5_byte_t * )":mongo:", 7 ); + mongo_md5_append( &st, ( const mongo_md5_byte_t * )pass, strlen( pass ) ); + mongo_md5_finish( &st, digest ); + digest2hex( digest, hex_digest ); +} + +int mongo_cmd_add_user( mongo *conn, const char *db, const char *user, const char *pass ) { + bson user_obj; + bson pass_obj; + char hex_digest[33]; + char *ns = bson_malloc( strlen( db ) + strlen( ".system.users" ) + 1 ); + int res; + + strcpy( ns, db ); + strcpy( ns+strlen( db ), ".system.users" ); + + mongo_pass_digest( user, pass, hex_digest ); + + bson_init( &user_obj ); + bson_append_string( &user_obj, "user", user ); + bson_finish( &user_obj ); + + bson_init( &pass_obj ); + bson_append_start_object( &pass_obj, "$set" ); + bson_append_string( &pass_obj, "pwd", hex_digest ); + bson_append_finish_object( &pass_obj ); + bson_finish( &pass_obj ); + + res = mongo_update( conn, ns, &user_obj, &pass_obj, MONGO_UPDATE_UPSERT ); + + bson_free( ns ); + bson_destroy( &user_obj ); + bson_destroy( &pass_obj ); + + return res; +} + +bson_bool_t mongo_cmd_authenticate( mongo *conn, const char *db, const char *user, const char *pass ) { + bson from_db; + bson cmd; + bson out; + const char *nonce; + bson_bool_t success = 0; + + mongo_md5_state_t st; + mongo_md5_byte_t digest[16]; + char hex_digest[33]; + + if( mongo_simple_int_command( conn, db, "getnonce", 1, &from_db ) == MONGO_OK ) { + bson_iterator it; + bson_find( &it, &from_db, "nonce" ); + nonce = bson_iterator_string( &it ); + } else { + return MONGO_ERROR; + } + + mongo_pass_digest( user, pass, hex_digest ); + + mongo_md5_init( &st ); + mongo_md5_append( &st, ( const mongo_md5_byte_t * )nonce, strlen( nonce ) ); + mongo_md5_append( &st, ( const mongo_md5_byte_t * )user, strlen( user ) ); + mongo_md5_append( &st, ( const mongo_md5_byte_t * )hex_digest, 32 ); + mongo_md5_finish( &st, digest ); + digest2hex( digest, hex_digest ); + + bson_init( &cmd ); + bson_append_int( &cmd, "authenticate", 1 ); + bson_append_string( &cmd, "user", user ); + bson_append_string( &cmd, "nonce", nonce ); + bson_append_string( &cmd, "key", hex_digest ); + bson_finish( &cmd ); + + bson_destroy( &from_db ); + /*bson_init( &from_db ); */ + if( mongo_run_command( conn, db, &cmd, &out ) == MONGO_OK ) { + bson_iterator it; + if( bson_find( &it, &out, "ok" ) ) + success = bson_iterator_bool( &it ); + } + + bson_destroy( &from_db ); + bson_destroy( &cmd ); + + if( success ) + return MONGO_OK; + else + return MONGO_ERROR; +} diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/mongo.h b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/mongo.h new file mode 100644 index 0000000000..6f86174101 --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/mongo.h @@ -0,0 +1,648 @@ +/** + * @file mongo.h + * @brief Main MongoDB Declarations + */ + +/* Copyright 2009-2011 10gen Inc. + * + * 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 _MONGO_H_ +#define _MONGO_H_ + +#include "bson.h" + +MONGO_EXTERN_C_START + +#define MONGO_MAJOR 0 +#define MONGO_MINOR 4 +#define MONGO_PATCH 0 + +#define MONGO_OK 0 +#define MONGO_ERROR -1 + +#define MONGO_DEFAULT_PORT 27017 + +typedef enum mongo_error_t { + MONGO_CONN_SUCCESS = 0, /**< Connection success! */ + MONGO_CONN_NO_SOCKET, /**< Could not create a socket. */ + MONGO_CONN_FAIL, /**< An error occured while calling connect(). */ + MONGO_CONN_ADDR_FAIL, /**< An error occured while calling getaddrinfo(). */ + MONGO_CONN_NOT_MASTER, /**< Warning: connected to a non-master node (read-only). */ + MONGO_CONN_BAD_SET_NAME, /**< Given rs name doesn't match this replica set. */ + MONGO_CONN_NO_PRIMARY, /**< Can't find primary in replica set. Connection closed. */ + + MONGO_IO_ERROR, /**< An error occurred while reading or writing on socket. */ + MONGO_READ_SIZE_ERROR, /**< The response is not the expected length. */ + MONGO_COMMAND_FAILED, /**< The command returned with 'ok' value of 0. */ + MONGO_CURSOR_EXHAUSTED, /**< The cursor has no more results. */ + MONGO_CURSOR_INVALID, /**< The cursor has timed out or is not recognized. */ + MONGO_CURSOR_PENDING, /**< Tailable cursor still alive but no data. */ + MONGO_BSON_INVALID, /**< BSON not valid for the specified op. */ + MONGO_BSON_NOT_FINISHED /**< BSON object has not been finished. */ +} mongo_error_t; + +enum mongo_cursor_flags { + MONGO_CURSOR_MUST_FREE = 1, /**< mongo_cursor_destroy should free cursor. */ + MONGO_CURSOR_QUERY_SENT = ( 1<<1 ) /**< Initial query has been sent. */ +}; + +enum mongo_index_opts { + MONGO_INDEX_UNIQUE = ( 1<<0 ), + MONGO_INDEX_DROP_DUPS = ( 1<<2 ), + MONGO_INDEX_BACKGROUND = ( 1<<3 ), + MONGO_INDEX_SPARSE = ( 1<<4 ) +}; + +enum mongo_update_opts { + MONGO_UPDATE_UPSERT = 0x1, + MONGO_UPDATE_MULTI = 0x2, + MONGO_UPDATE_BASIC = 0x4 +}; + +enum mongo_cursor_opts { + MONGO_TAILABLE = ( 1<<1 ), /**< Create a tailable cursor. */ + MONGO_SLAVE_OK = ( 1<<2 ), /**< Allow queries on a non-primary node. */ + MONGO_NO_CURSOR_TIMEOUT = ( 1<<4 ), /**< Disable cursor timeouts. */ + MONGO_AWAIT_DATA = ( 1<<5 ), /**< Momentarily block for more data. */ + MONGO_EXHAUST = ( 1<<6 ), /**< Stream in multiple 'more' packages. */ + MONGO_PARTIAL = ( 1<<7 ) /**< Allow reads even if a shard is down. */ +}; + +enum mongo_operations { + MONGO_OP_MSG = 1000, + MONGO_OP_UPDATE = 2001, + MONGO_OP_INSERT = 2002, + MONGO_OP_QUERY = 2004, + MONGO_OP_GET_MORE = 2005, + MONGO_OP_DELETE = 2006, + MONGO_OP_KILL_CURSORS = 2007 +}; + +#pragma pack(1) +typedef struct { + int len; + int id; + int responseTo; + int op; +} mongo_header; + +typedef struct { + mongo_header head; + char data; +} mongo_message; + +typedef struct { + int flag; /* FIX THIS COMMENT non-zero on failure */ + int64_t cursorID; + int start; + int num; +} mongo_reply_fields; + +typedef struct { + mongo_header head; + mongo_reply_fields fields; + char objs; +} mongo_reply; +#pragma pack() + +typedef struct mongo_host_port { + char host[255]; + int port; + struct mongo_host_port *next; +} mongo_host_port; + +typedef struct { + mongo_host_port *seeds; /**< List of seeds provided by the user. */ + mongo_host_port *hosts; /**< List of host/ports given by the replica set */ + char *name; /**< Name of the replica set. */ + bson_bool_t primary_connected; /**< Primary node connection status. */ +} mongo_replset; + +typedef struct mongo { + mongo_host_port *primary; /**< Primary connection info. */ + mongo_replset *replset; /**< replset object if connected to a replica set. */ + int sock; /**< Socket file descriptor. */ + int flags; /**< Flags on this connection object. */ + int conn_timeout_ms; /**< Connection timeout in milliseconds. */ + int op_timeout_ms; /**< Read and write timeout in milliseconds. */ + bson_bool_t connected; /**< Connection status. */ + + mongo_error_t err; /**< Most recent driver error code. */ + char *errstr; /**< String version of most recent driver error code. */ + int lasterrcode; /**< getlasterror given by the server on calls. */ + char *lasterrstr; /**< getlasterror string generated by server. */ +} mongo; + +typedef struct { + mongo_reply *reply; /**< reply is owned by cursor */ + mongo *conn; /**< connection is *not* owned by cursor */ + const char *ns; /**< owned by cursor */ + int flags; /**< Flags used internally by this drivers. */ + int seen; /**< Number returned so far. */ + bson current; /**< This cursor's current bson object. */ + mongo_error_t err; /**< Errors on this cursor. */ + bson *query; /**< Bitfield containing cursor options. */ + bson *fields; /**< Bitfield containing cursor options. */ + int options; /**< Bitfield containing cursor options. */ + int limit; /**< Bitfield containing cursor options. */ + int skip; /**< Bitfield containing cursor options. */ +} mongo_cursor; + +/* Connection API */ + +/** Initialize a new mongo connection object. If not created + * with mongo_new, you must initialize each mongo + * object using this function. + * + * @note When finished, you must pass this object to + * mongo_destroy( ). + * + * @param conn a mongo connection object allocated on the stack + * or heap. + */ +void mongo_init( mongo *conn ); + +/** + * Connect to a single MongoDB server. + * + * @param conn a mongo object. + * @param host a numerical network address or a network hostname. + * @param port the port to connect to. + * + * @return MONGO_OK or MONGO_ERROR on failure. On failure, a constant of type + * mongo_conn_return_t will be set on the conn->err field. + */ +int mongo_connect( mongo *conn , const char *host, int port ); + +/** + * Set up this connection object for connecting to a replica set. + * To connect, pass the object to mongo_replset_connect(). + * + * @param conn a mongo object. + * @param name the name of the replica set to connect to. + * */ +void mongo_replset_init( mongo *conn, const char *name ); + +/** + * Add a seed node to the replica set connection object. + * + * You must specify at least one seed node before connecting to a replica set. + * + * @param conn a mongo object. + * @param host a numerical network address or a network hostname. + * @param port the port to connect to. + */ +void mongo_replset_add_seed( mongo *conn, const char *host, int port ); + +/** + * Utility function for converting a host-port string to a mongo_host_port. + * + * @param host_string a string containing either a host or a host and port separated + * by a colon. + * @param host_port the mongo_host_port object to write the result to. + */ +void mongo_parse_host( const char *host_string, mongo_host_port *host_port ); + +/** + * Connect to a replica set. + * + * Before passing a connection object to this function, you must already have called + * mongo_set_replset and mongo_replset_add_seed. + * + * @param conn a mongo object. + * + * @return MONGO_OK or MONGO_ERROR on failure. On failure, a constant of type + * mongo_conn_return_t will be set on the conn->err field. + */ +int mongo_replset_connect( mongo *conn ); + +/** Set a timeout for operations on this connection. This + * is a platform-specific feature, and only work on *nix + * system. You must also compile for linux to support this. + * + * @param conn a mongo object. + * @param millis timeout time in milliseconds. + * + * @return MONGO_OK. On error, return MONGO_ERROR and + * set the conn->err field. + */ +int mongo_set_op_timeout( mongo *conn, int millis ); + +/** + * Ensure that this connection is healthy by performing + * a round-trip to the server. + * + * @param conn a mongo connection + * + * @return MONGO_OK if connected; otherwise, MONGO_ERROR. + */ +int mongo_check_connection( mongo *conn ); + +/** + * Try reconnecting to the server using the existing connection settings. + * + * This function will disconnect the current socket. If you've authenticated, + * you'll need to re-authenticate after calling this function. + * + * @param conn a mongo object. + * + * @return MONGO_OK or MONGO_ERROR and + * set the conn->err field. + */ +int mongo_reconnect( mongo *conn ); + +/** + * Close the current connection to the server. After calling + * this function, you may call mongo_reconnect with the same + * connection object. + * + * @param conn a mongo object. + */ +void mongo_disconnect( mongo *conn ); + +/** + * Close any existing connection to the server and free all allocated + * memory associated with the conn object. + * + * You must always call this function when finished with the connection object. + * + * @param conn a mongo object. + */ +void mongo_destroy( mongo *conn ); + +/** + * Insert a BSON document into a MongoDB server. This function + * will fail if the supplied BSON struct is not UTF-8 or if + * the keys are invalid for insert (contain '.' or start with '$'). + * + * @param conn a mongo object. + * @param ns the namespace. + * @param data the bson data. + * + * @return MONGO_OK or MONGO_ERROR. If the conn->err + * field is MONGO_BSON_INVALID, check the err field + * on the bson struct for the reason. + */ +int mongo_insert( mongo *conn, const char *ns, bson *data ); + +/** + * Insert a batch of BSON documents into a MongoDB server. This function + * will fail if any of the documents to be inserted is invalid. + * + * @param conn a mongo object. + * @param ns the namespace. + * @param data the bson data. + * @param num the number of documents in data. + * + * @return MONGO_OK or MONGO_ERROR. + * + */ +int mongo_insert_batch( mongo *conn , const char *ns , + bson **data , int num ); + +/** + * Update a document in a MongoDB server. + * + * @param conn a mongo object. + * @param ns the namespace. + * @param cond the bson update query. + * @param op the bson update data. + * @param flags flags for the update. + * + * @return MONGO_OK or MONGO_ERROR with error stored in conn object. + * + */ +int mongo_update( mongo *conn, const char *ns, const bson *cond, + const bson *op, int flags ); + +/** + * Remove a document from a MongoDB server. + * + * @param conn a mongo object. + * @param ns the namespace. + * @param cond the bson query. + * + * @return MONGO_OK or MONGO_ERROR with error stored in conn object. + */ +int mongo_remove( mongo *conn, const char *ns, const bson *cond ); + +/** + * Find documents in a MongoDB server. + * + * @param conn a mongo object. + * @param ns the namespace. + * @param query the bson query. + * @param fields a bson document of fields to be returned. + * @param limit the maximum number of documents to retrun. + * @param skip the number of documents to skip. + * @param options A bitfield containing cursor options. + * + * @return A cursor object allocated on the heap or NULL if + * an error has occurred. For finer-grained error checking, + * use the cursor builder API instead. + */ +mongo_cursor *mongo_find( mongo *conn, const char *ns, bson *query, + bson *fields, int limit, int skip, int options ); + +/** + * Initalize a new cursor object. + * + * @param cursor + * @param ns the namespace, represented as the the database + * name and collection name separated by a dot. e.g., "test.users" + */ +void mongo_cursor_init( mongo_cursor *cursor, mongo *conn, const char *ns ); + +/** + * Set the bson object specifying this cursor's query spec. If + * your query is the empty bson object "{}", then you need not + * set this value. + * + * @param cursor + * @param query a bson object representing the query spec. This may + * be either a simple query spec or a complex spec storing values for + * $query, $orderby, $hint, and/or $explain. See + * http://www.mongodb.org/display/DOCS/Mongo+Wire+Protocol for details. + */ +void mongo_cursor_set_query( mongo_cursor *cursor, bson *query ); + +/** + * Set the fields to return for this cursor. If you want to return + * all fields, you need not set this value. + * + * @param cursor + * @param fields a bson object representing the fields to return. + * See http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields. + */ +void mongo_cursor_set_fields( mongo_cursor *cursor, bson *fields ); + +/** + * Set the number of documents to skip. + * + * @param cursor + * @param skip + */ +void mongo_cursor_set_skip( mongo_cursor *cursor, int skip ); + +/** + * Set the number of documents to return. + * + * @param cursor + * @param limit + */ +void mongo_cursor_set_limit( mongo_cursor *cursor, int limit ); + +/** + * Set any of the available query options (e.g., MONGO_TAILABLE). + * + * @param cursor + * @param options a bitfield storing query options. See + * mongo_cursor_bitfield_t for available constants. + */ +void mongo_cursor_set_options( mongo_cursor *cursor, int options ); + +/** + * Return the current BSON object data as a const char*. This is useful + * for creating bson iterators with bson_iterator_init. + * + * @param cursor + */ +const char *mongo_cursor_data( mongo_cursor *cursor ); + +/** + * Return the current BSON object data as a const char*. This is useful + * for creating bson iterators with bson_iterator_init. + * + * @param cursor + */ +const bson *mongo_cursor_bson( mongo_cursor *cursor ); + +/** + * Iterate the cursor, returning the next item. When successful, + * the returned object will be stored in cursor->current; + * + * @param cursor + * + * @return MONGO_OK. On error, returns MONGO_ERROR and sets + * cursor->err with a value of mongo_error_t. + */ +int mongo_cursor_next( mongo_cursor *cursor ); + +/** + * Destroy a cursor object. When finished with a cursor, you + * must pass it to this function. + * + * @param cursor the cursor to destroy. + * + * @return MONGO_OK or an error code. On error, check cursor->conn->err + * for errors. + */ +int mongo_cursor_destroy( mongo_cursor *cursor ); + +/** + * Find a single document in a MongoDB server. + * + * @param conn a mongo object. + * @param ns the namespace. + * @param query the bson query. + * @param fields a bson document of the fields to be returned. + * @param out a bson document in which to put the query result. + * + */ +/* out can be NULL if you don't care about results. useful for commands */ +bson_bool_t mongo_find_one( mongo *conn, const char *ns, bson *query, + bson *fields, bson *out ); + +/* MongoDB Helper Functions */ + +/** + * Count the number of documents in a collection matching a query. + * + * @param conn a mongo object. + * @param db the db name. + * @param coll the collection name. + * @param query the BSON query. + * + * @return the number of matching documents. If the command fails, + * MONGO_ERROR is returned. + */ +int64_t mongo_count( mongo *conn, const char *db, const char *coll, + bson *query ); + +/** + * Create a compouned index. + * + * @param conn a mongo object. + * @param ns the namespace. + * @param data the bson index data. + * @param options a bitfield for setting index options. Possibilities include + * MONGO_INDEX_UNIQUE, MONGO_INDEX_DROP_DUPS, MONGO_INDEX_BACKGROUND, + * and MONGO_INDEX_SPARSE. + * @param out a bson document containing errors, if any. + * + * @return MONGO_OK if index is created successfully; otherwise, MONGO_ERROR. + */ +int mongo_create_index( mongo *conn, const char *ns, bson *key, int options, bson *out ); + +/** + * Create an index with a single key. + * + * @param conn a mongo object. + * @param ns the namespace. + * @param field the index key. + * @param options index options. + * @param out a BSON document containing errors, if any. + * + * @return true if the index was created. + */ +bson_bool_t mongo_create_simple_index( mongo *conn, const char *ns, const char *field, int options, bson *out ); + +/* ---------------------------- + COMMANDS + ------------------------------ */ + +/** + * Run a command on a MongoDB server. + * + * @param conn a mongo object. + * @param db the name of the database. + * @param command the BSON command to run. + * @param out the BSON result of the command. + * + * @return true if the command ran without error. + */ +bson_bool_t mongo_run_command( mongo *conn, const char *db, bson *command, bson *out ); + +/** + * Run a command that accepts a simple string key and integer value. + * + * @param conn a mongo object. + * @param db the name of the database. + * @param cmd the command to run. + * @param arg the integer argument to the command. + * @param out the BSON result of the command. + * + * @return MONGO_OK or an error code. + * + */ +int mongo_simple_int_command( mongo *conn, const char *db, + const char *cmd, int arg, bson *out ); + +/** + * Run a command that accepts a simple string key and value. + * + * @param conn a mongo object. + * @param db the name of the database. + * @param cmd the command to run. + * @param arg the string argument to the command. + * @param out the BSON result of the command. + * + * @return true if the command ran without error. + * + */ +bson_bool_t mongo_simple_str_command( mongo *conn, const char *db, const char *cmd, const char *arg, bson *out ); + +/** + * Drop a database. + * + * @param conn a mongo object. + * @param db the name of the database to drop. + * + * @return MONGO_OK or an error code. + */ +int mongo_cmd_drop_db( mongo *conn, const char *db ); + +/** + * Drop a collection. + * + * @param conn a mongo object. + * @param db the name of the database. + * @param collection the name of the collection to drop. + * @param out a BSON document containing the result of the command. + * + * @return true if the collection drop was successful. + */ +bson_bool_t mongo_cmd_drop_collection( mongo *conn, const char *db, const char *collection, bson *out ); + +/** + * Add a database user. + * + * @param conn a mongo object. + * @param db the database in which to add the user. + * @param user the user name + * @param pass the user password + * + * @return MONGO_OK or MONGO_ERROR. + */ +int mongo_cmd_add_user( mongo *conn, const char *db, const char *user, const char *pass ); + +/** + * Authenticate a user. + * + * @param conn a mongo object. + * @param db the database to authenticate against. + * @param user the user name to authenticate. + * @param pass the user's password. + * + * @return MONGO_OK on sucess and MONGO_ERROR on failure. + */ +int mongo_cmd_authenticate( mongo *conn, const char *db, const char *user, const char *pass ); + +/** + * Check if the current server is a master. + * + * @param conn a mongo object. + * @param out a BSON result of the command. + * + * @return true if the server is a master. + */ +/* return value is master status */ +bson_bool_t mongo_cmd_ismaster( mongo *conn, bson *out ); + +/** + * Get the error for the last command with the current connection. + * + * @param conn a mongo object. + * @param db the name of the database. + * @param out a BSON object containing the error details. + * + * @return MONGO_OK if no error and MONGO_ERROR on error. On error, check the values + * of conn->lasterrcode and conn->lasterrstr for the error status. + */ +int mongo_cmd_get_last_error( mongo *conn, const char *db, bson *out ); + +/** + * Get the most recent error with the current connection. + * + * @param conn a mongo object. + * @param db the name of the database. + * @param out a BSON object containing the error details. + * + * @return MONGO_OK if no error and MONGO_ERROR on error. On error, check the values + * of conn->lasterrcode and conn->lasterrstr for the error status. + */ +int mongo_cmd_get_prev_error( mongo *conn, const char *db, bson *out ); + +/** + * Reset the error state for the connection. + * + * @param conn a mongo object. + * @param db the name of the database. + */ +void mongo_cmd_reset_error( mongo *conn, const char *db ); + +MONGO_EXTERN_C_END + +#endif diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/net.c b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/net.c new file mode 100644 index 0000000000..5c8ad9ba5e --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/net.c @@ -0,0 +1,98 @@ +/* net.c */ + +/* Copyright 2009-2011 10gen Inc. + * + * 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. + */ + +/* Implementation for generic version of net.h */ +#include "net.h" +#include + +int mongo_write_socket( mongo *conn, const void *buf, int len ) { + const char *cbuf = buf; + while ( len ) { + int sent = send( conn->sock, cbuf, len, 0 ); + if ( sent == -1 ) { + conn->err = MONGO_IO_ERROR; + return MONGO_ERROR; + } + cbuf += sent; + len -= sent; + } + + return MONGO_OK; +} + +int mongo_read_socket( mongo *conn, void *buf, int len ) { + char *cbuf = buf; + while ( len ) { + int sent = recv( conn->sock, cbuf, len, 0 ); + if ( sent == 0 || sent == -1 ) { + conn->err = MONGO_IO_ERROR; + return MONGO_ERROR; + } + cbuf += sent; + len -= sent; + } + + return MONGO_OK; +} + +/* This is a no-op in the generic implementation. */ +int mongo_set_socket_op_timeout( mongo *conn, int millis ) { + return MONGO_OK; +} + +static int mongo_create_socket( mongo *conn ) { + int fd; + + if( ( fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 ) { + conn->err = MONGO_CONN_NO_SOCKET; + return MONGO_ERROR; + } + conn->sock = fd; + + return MONGO_OK; +} + +int mongo_socket_connect( mongo *conn, const char *host, int port ) { + struct sockaddr_in sa; + socklen_t addressSize; + int flag = 1; + + if( mongo_create_socket( conn ) != MONGO_OK ) + return MONGO_ERROR; + + memset( sa.sin_zero , 0 , sizeof( sa.sin_zero ) ); + sa.sin_family = AF_INET; + sa.sin_port = htons( port ); + sa.sin_addr.s_addr = inet_addr( host ); + addressSize = sizeof( sa ); + + if ( connect( conn->sock, ( struct sockaddr * )&sa, addressSize ) == -1 ) { + mongo_close_socket( conn->sock ); + conn->connected = 0; + conn->sock = 0; + conn->err = MONGO_CONN_FAIL; + return MONGO_ERROR; + } + + setsockopt( conn->sock, IPPROTO_TCP, TCP_NODELAY, ( char * ) &flag, sizeof( flag ) ); + if( conn->op_timeout_ms > 0 ) + mongo_set_socket_op_timeout( conn, conn->op_timeout_ms ); + + conn->connected = 1; + + return MONGO_OK; +} diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/net.h b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/net.h new file mode 100644 index 0000000000..49190877c8 --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/net.h @@ -0,0 +1,57 @@ +/** @file net.h */ + +/* Copyright 2009-2011 10gen Inc. + * + * 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. + */ + +/* Header for generic net.h */ +#ifndef _MONGO_NET_H_ +#define _MONGO_NET_H_ + +#include "mongo.h" + +#ifdef _WIN32 +#include +#include +#define mongo_close_socket(sock) ( closesocket(sock) ) +typedef int socklen_t; +#else +#include +#include +#include +#include +#include +#include +#include +#define mongo_close_socket(sock) ( close(sock) ) +#endif + +#ifndef _WIN32 +#include +#endif + +#if defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE) || _POSIX_C_SOURCE >= 1 +#define _MONGO_USE_GETADDRINFO +#endif + +MONGO_EXTERN_C_START + +/* This is a no-op in the generic implementation. */ +int mongo_set_socket_op_timeout( mongo *conn, int millis ); +int mongo_read_socket( mongo *conn, void *buf, int len ); +int mongo_write_socket( mongo *conn, const void *buf, int len ); +int mongo_socket_connect( mongo *conn, const char *host, int port ); + +MONGO_EXTERN_C_END +#endif diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/numbers.c b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/numbers.c new file mode 100644 index 0000000000..a63e3d73f9 --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/numbers.c @@ -0,0 +1,127 @@ +/* Copyright 2009-2011 10gen Inc. + * + * 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. + */ + +/* all the numbers that fit in a 4 byte string */ +const char bson_numstrs[1000][4] = { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", + "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", + "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", + "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", + "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", + "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", + "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", + "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", + "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", + "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", + + "100", "101", "102", "103", "104", "105", "106", "107", "108", "109", + "110", "111", "112", "113", "114", "115", "116", "117", "118", "119", + "120", "121", "122", "123", "124", "125", "126", "127", "128", "129", + "130", "131", "132", "133", "134", "135", "136", "137", "138", "139", + "140", "141", "142", "143", "144", "145", "146", "147", "148", "149", + "150", "151", "152", "153", "154", "155", "156", "157", "158", "159", + "160", "161", "162", "163", "164", "165", "166", "167", "168", "169", + "170", "171", "172", "173", "174", "175", "176", "177", "178", "179", + "180", "181", "182", "183", "184", "185", "186", "187", "188", "189", + "190", "191", "192", "193", "194", "195", "196", "197", "198", "199", + + "200", "201", "202", "203", "204", "205", "206", "207", "208", "209", + "210", "211", "212", "213", "214", "215", "216", "217", "218", "219", + "220", "221", "222", "223", "224", "225", "226", "227", "228", "229", + "230", "231", "232", "233", "234", "235", "236", "237", "238", "239", + "240", "241", "242", "243", "244", "245", "246", "247", "248", "249", + "250", "251", "252", "253", "254", "255", "256", "257", "258", "259", + "260", "261", "262", "263", "264", "265", "266", "267", "268", "269", + "270", "271", "272", "273", "274", "275", "276", "277", "278", "279", + "280", "281", "282", "283", "284", "285", "286", "287", "288", "289", + "290", "291", "292", "293", "294", "295", "296", "297", "298", "299", + + "300", "301", "302", "303", "304", "305", "306", "307", "308", "309", + "310", "311", "312", "313", "314", "315", "316", "317", "318", "319", + "320", "321", "322", "323", "324", "325", "326", "327", "328", "329", + "330", "331", "332", "333", "334", "335", "336", "337", "338", "339", + "340", "341", "342", "343", "344", "345", "346", "347", "348", "349", + "350", "351", "352", "353", "354", "355", "356", "357", "358", "359", + "360", "361", "362", "363", "364", "365", "366", "367", "368", "369", + "370", "371", "372", "373", "374", "375", "376", "377", "378", "379", + "380", "381", "382", "383", "384", "385", "386", "387", "388", "389", + "390", "391", "392", "393", "394", "395", "396", "397", "398", "399", + + "400", "401", "402", "403", "404", "405", "406", "407", "408", "409", + "410", "411", "412", "413", "414", "415", "416", "417", "418", "419", + "420", "421", "422", "423", "424", "425", "426", "427", "428", "429", + "430", "431", "432", "433", "434", "435", "436", "437", "438", "439", + "440", "441", "442", "443", "444", "445", "446", "447", "448", "449", + "450", "451", "452", "453", "454", "455", "456", "457", "458", "459", + "460", "461", "462", "463", "464", "465", "466", "467", "468", "469", + "470", "471", "472", "473", "474", "475", "476", "477", "478", "479", + "480", "481", "482", "483", "484", "485", "486", "487", "488", "489", + "490", "491", "492", "493", "494", "495", "496", "497", "498", "499", + + "500", "501", "502", "503", "504", "505", "506", "507", "508", "509", + "510", "511", "512", "513", "514", "515", "516", "517", "518", "519", + "520", "521", "522", "523", "524", "525", "526", "527", "528", "529", + "530", "531", "532", "533", "534", "535", "536", "537", "538", "539", + "540", "541", "542", "543", "544", "545", "546", "547", "548", "549", + "550", "551", "552", "553", "554", "555", "556", "557", "558", "559", + "560", "561", "562", "563", "564", "565", "566", "567", "568", "569", + "570", "571", "572", "573", "574", "575", "576", "577", "578", "579", + "580", "581", "582", "583", "584", "585", "586", "587", "588", "589", + "590", "591", "592", "593", "594", "595", "596", "597", "598", "599", + + "600", "601", "602", "603", "604", "605", "606", "607", "608", "609", + "610", "611", "612", "613", "614", "615", "616", "617", "618", "619", + "620", "621", "622", "623", "624", "625", "626", "627", "628", "629", + "630", "631", "632", "633", "634", "635", "636", "637", "638", "639", + "640", "641", "642", "643", "644", "645", "646", "647", "648", "649", + "650", "651", "652", "653", "654", "655", "656", "657", "658", "659", + "660", "661", "662", "663", "664", "665", "666", "667", "668", "669", + "670", "671", "672", "673", "674", "675", "676", "677", "678", "679", + "680", "681", "682", "683", "684", "685", "686", "687", "688", "689", + "690", "691", "692", "693", "694", "695", "696", "697", "698", "699", + + "700", "701", "702", "703", "704", "705", "706", "707", "708", "709", + "710", "711", "712", "713", "714", "715", "716", "717", "718", "719", + "720", "721", "722", "723", "724", "725", "726", "727", "728", "729", + "730", "731", "732", "733", "734", "735", "736", "737", "738", "739", + "740", "741", "742", "743", "744", "745", "746", "747", "748", "749", + "750", "751", "752", "753", "754", "755", "756", "757", "758", "759", + "760", "761", "762", "763", "764", "765", "766", "767", "768", "769", + "770", "771", "772", "773", "774", "775", "776", "777", "778", "779", + "780", "781", "782", "783", "784", "785", "786", "787", "788", "789", + "790", "791", "792", "793", "794", "795", "796", "797", "798", "799", + + "800", "801", "802", "803", "804", "805", "806", "807", "808", "809", + "810", "811", "812", "813", "814", "815", "816", "817", "818", "819", + "820", "821", "822", "823", "824", "825", "826", "827", "828", "829", + "830", "831", "832", "833", "834", "835", "836", "837", "838", "839", + "840", "841", "842", "843", "844", "845", "846", "847", "848", "849", + "850", "851", "852", "853", "854", "855", "856", "857", "858", "859", + "860", "861", "862", "863", "864", "865", "866", "867", "868", "869", + "870", "871", "872", "873", "874", "875", "876", "877", "878", "879", + "880", "881", "882", "883", "884", "885", "886", "887", "888", "889", + "890", "891", "892", "893", "894", "895", "896", "897", "898", "899", + + "900", "901", "902", "903", "904", "905", "906", "907", "908", "909", + "910", "911", "912", "913", "914", "915", "916", "917", "918", "919", + "920", "921", "922", "923", "924", "925", "926", "927", "928", "929", + "930", "931", "932", "933", "934", "935", "936", "937", "938", "939", + "940", "941", "942", "943", "944", "945", "946", "947", "948", "949", + "950", "951", "952", "953", "954", "955", "956", "957", "958", "959", + "960", "961", "962", "963", "964", "965", "966", "967", "968", "969", + "970", "971", "972", "973", "974", "975", "976", "977", "978", "979", + "980", "981", "982", "983", "984", "985", "986", "987", "988", "989", + "990", "991", "992", "993", "994", "995", "996", "997", "998", "999", +}; diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/platform.h b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/platform.h new file mode 100644 index 0000000000..4a96af77e3 --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/platform.h @@ -0,0 +1,94 @@ +/** @file platform.h */ + +/** Copyright 2009-2011 10gen Inc. + * + * 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. + */ + + +/* all platform-specific ifdefs should go here */ + +#ifndef _PLATFORM_HACKS_H_ +#define _PLATFORM_HACKS_H_ + +#ifdef __GNUC__ +#define MONGO_INLINE static __inline__ +#else +#define MONGO_INLINE static +#endif + +#ifdef __cplusplus +#define MONGO_EXTERN_C_START extern "C" { +#define MONGO_EXTERN_C_END } +#else +#define MONGO_EXTERN_C_START +#define MONGO_EXTERN_C_END +#endif + + +#if defined(MONGO_HAVE_STDINT) || __STDC_VERSION__ >= 199901L +#include +#elif defined(MONGO_HAVE_UNISTD) +#include +#elif defined(MONGO_USE__INT64) +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#elif defined(MONGO_USE_LONG_LONG_INT) +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#else +#error must have a 64bit int type +#endif + +/* big endian is only used for OID generation. little is used everywhere else */ +#ifdef MONGO_BIG_ENDIAN +#define bson_little_endian64(out, in) ( bson_swap_endian64(out, in) ) +#define bson_little_endian32(out, in) ( bson_swap_endian32(out, in) ) +#define bson_big_endian64(out, in) ( memcpy(out, in, 8) ) +#define bson_big_endian32(out, in) ( memcpy(out, in, 4) ) +#else +#define bson_little_endian64(out, in) ( memcpy(out, in, 8) ) +#define bson_little_endian32(out, in) ( memcpy(out, in, 4) ) +#define bson_big_endian64(out, in) ( bson_swap_endian64(out, in) ) +#define bson_big_endian32(out, in) ( bson_swap_endian32(out, in) ) +#endif + +MONGO_EXTERN_C_START + +MONGO_INLINE void bson_swap_endian64( void *outp, const void *inp ) { + const char *in = ( const char * )inp; + char *out = ( char * )outp; + + out[0] = in[7]; + out[1] = in[6]; + out[2] = in[5]; + out[3] = in[4]; + out[4] = in[3]; + out[5] = in[2]; + out[6] = in[1]; + out[7] = in[0]; + +} +MONGO_INLINE void bson_swap_endian32( void *outp, const void *inp ) { + const char *in = ( const char * )inp; + char *out = ( char * )outp; + + out[0] = in[3]; + out[1] = in[2]; + out[2] = in[1]; + out[3] = in[0]; +} + +MONGO_EXTERN_C_END + +#endif diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/platform/linux/net.c b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/platform/linux/net.c new file mode 100644 index 0000000000..b2f7c22898 --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/platform/linux/net.c @@ -0,0 +1,183 @@ +/* net.c */ + +/* Copyright 2009-2011 10gen Inc. + * + * 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. + */ + +/* Implementation for Linux version of net.h */ +#include "net.h" +#include + +int mongo_write_socket( mongo *conn, const void *buf, int len ) { + const char *cbuf = buf; + while ( len ) { + int sent = send( conn->sock, cbuf, len, 0 ); + if ( sent == -1 ) { + conn->err = MONGO_IO_ERROR; + return MONGO_ERROR; + } + cbuf += sent; + len -= sent; + } + + return MONGO_OK; +} + +int mongo_read_socket( mongo *conn, void *buf, int len ) { + char *cbuf = buf; + while ( len ) { + int sent = recv( conn->sock, cbuf, len, 0 ); + if ( sent == 0 || sent == -1 ) { + conn->err = MONGO_IO_ERROR; + return MONGO_ERROR; + } + cbuf += sent; + len -= sent; + } + + return MONGO_OK; +} + +static int mongo_create_socket( mongo *conn ) { + int fd; + + if( ( fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 ) { + conn->err = MONGO_CONN_NO_SOCKET; + return MONGO_ERROR; + } + conn->sock = fd; + + return MONGO_OK; +} + +static int mongo_set_blocking_status( mongo *conn ) { + int flags; + int blocking; + + blocking = ( conn->conn_timeout_ms == 0 ); + if( blocking ) + return MONGO_OK; + else { + if( ( flags = fcntl( conn->sock, F_GETFL ) ) == -1 ) { + conn->err = MONGO_IO_ERROR; + mongo_close_socket( conn->sock ); + return MONGO_ERROR; + } + + flags |= O_NONBLOCK; + + if( ( flags = fcntl( conn->sock, F_SETFL, flags ) ) == -1 ) { + conn->err = MONGO_IO_ERROR; + mongo_close_socket( conn->sock ); + return MONGO_ERROR; + } + } + + return MONGO_OK; +} + +int mongo_set_socket_op_timeout( mongo *conn, int millis ) { + struct timeval tv; + tv.tv_sec = millis / 1000; + tv.tv_usec = ( millis % 1000 ) * 1000; + + if ( setsockopt( conn->sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof( tv ) ) == -1 ) { + conn->err = MONGO_IO_ERROR; + return MONGO_ERROR; + } + + if ( setsockopt( conn->sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof( tv ) ) == -1 ) { + conn->err = MONGO_IO_ERROR; + return MONGO_ERROR; + } + + return MONGO_OK; +} + +#ifdef _MONGO_USE_GETADDRINFO +int mongo_socket_connect( mongo *conn, const char *host, int port ) { + + struct addrinfo *addrs = NULL; + struct addrinfo hints; + int flag = 1; + char port_str[12]; + int ret; + + conn->sock = 0; + conn->connected = 0; + + memset( &hints, 0, sizeof( hints ) ); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + + sprintf( port_str, "%d", port ); + + if( mongo_create_socket( conn ) != MONGO_OK ) + return MONGO_ERROR; + + if( getaddrinfo( host, port_str, &hints, &addrs ) != 0 ) { + bson_errprintf( "getaddrinfo failed: %s", gai_strerror( ret ) ); + conn->err = MONGO_CONN_ADDR_FAIL; + return MONGO_ERROR; + } + + if ( connect( conn->sock, addrs->ai_addr, addrs->ai_addrlen ) == -1 ) { + mongo_close_socket( conn->sock ); + freeaddrinfo( addrs ); + conn->err = MONGO_CONN_FAIL; + return MONGO_ERROR; + } + + setsockopt( conn->sock, IPPROTO_TCP, TCP_NODELAY, ( char * )&flag, sizeof( flag ) ); + if( conn->op_timeout_ms > 0 ) + mongo_set_socket_op_timeout( conn, conn->op_timeout_ms ); + + conn->connected = 1; + freeaddrinfo( addrs ); + + return MONGO_OK; +} +#else +int mongo_socket_connect( mongo *conn, const char *host, int port ) { + struct sockaddr_in sa; + socklen_t addressSize; + int flag = 1; + + if( mongo_create_socket( conn ) != MONGO_OK ) + return MONGO_ERROR; + + memset( sa.sin_zero , 0 , sizeof( sa.sin_zero ) ); + sa.sin_family = AF_INET; + sa.sin_port = htons( port ); + sa.sin_addr.s_addr = inet_addr( host ); + addressSize = sizeof( sa ); + + if ( connect( conn->sock, ( struct sockaddr * )&sa, addressSize ) == -1 ) { + mongo_close_socket( conn->sock ); + conn->connected = 0; + conn->sock = 0; + conn->err = MONGO_CONN_FAIL; + return MONGO_ERROR; + } + + setsockopt( conn->sock, IPPROTO_TCP, TCP_NODELAY, ( char * ) &flag, sizeof( flag ) ); + + if( conn->op_timeout_ms > 0 ) + mongo_set_socket_op_timeout( conn, conn->op_timeout_ms ); + + conn->connected = 1; + + return MONGO_OK; +} +#endif diff --git a/src/mod/event_handlers/mod_cdr_mongodb/driver/src/platform/linux/net.h b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/platform/linux/net.h new file mode 100644 index 0000000000..054247c1e8 --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/driver/src/platform/linux/net.h @@ -0,0 +1,51 @@ +/** + * @file net.h + * @brief Networking. + */ + +/* Copyright 2009-2011 10gen Inc. + * + * 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. + */ + +/* Header for Linux net.h */ +#ifndef _MONGO_NET_H_ +#define _MONGO_NET_H_ + +#include "mongo.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define mongo_close_socket(sock) ( close(sock) ) + +#if defined(_XOPEN_SOURCE) || defined(_POSIX_SOURCE) || _POSIX_C_SOURCE >= 1 +#define _MONGO_USE_GETADDRINFO +#endif + +MONGO_EXTERN_C_START + +int mongo_set_socket_op_timeout( mongo *conn, int millis ); +int mongo_read_socket( mongo *conn, void *buf, int len ); +int mongo_write_socket( mongo *conn, const void *buf, int len ); +int mongo_socket_connect( mongo *conn, const char *host, int port ); + +MONGO_EXTERN_C_END +#endif diff --git a/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c b/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c new file mode 100644 index 0000000000..d721bed8a5 --- /dev/null +++ b/src/mod/event_handlers/mod_cdr_mongodb/mod_cdr_mongodb.c @@ -0,0 +1,413 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2011, Anthony Minessale II + * + * 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 FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Daniel Swarbrick + * + * mod_cdr_mongodb.c -- MongoDB CDR Module + * + * Derived from: + * mod_xml_cdr.c -- XML CDR Module to files or curl + * + */ +#include +#include + +static struct { + switch_memory_pool_t *pool; + int shutdown; + char *mongo_host; + uint32_t mongo_port; + char *mongo_namespace; + mongo mongo_conn[1]; + switch_mutex_t *mongo_mutex; + switch_bool_t log_b; +} globals; + +static switch_xml_config_item_t config_settings[] = { + /* key, flags, ptr, default_value, syntax, helptext */ + SWITCH_CONFIG_ITEM_STRING_STRDUP("host", CONFIG_REQUIRED, &globals.mongo_host, "127.0.0.1", NULL, "MongoDB server host address"), + SWITCH_CONFIG_ITEM_STRING_STRDUP("namespace", CONFIG_REQUIRED, &globals.mongo_namespace, NULL, "database.collection", "MongoDB namespace"), + + /* key, type, flags, ptr, default_value, data, syntax, helptext */ + SWITCH_CONFIG_ITEM("port", SWITCH_CONFIG_INT, CONFIG_REQUIRED, &globals.mongo_port, 27017, NULL, NULL, "MongoDB server TCP port"), + SWITCH_CONFIG_ITEM("log-b-leg", SWITCH_CONFIG_BOOL, CONFIG_RELOADABLE, &globals.log_b, SWITCH_TRUE, NULL, NULL, "Log B-leg in addition to A-leg"), + + SWITCH_CONFIG_ITEM_END() +}; + + +SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_mongodb_load); +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_cdr_mongodb_shutdown); +SWITCH_MODULE_DEFINITION(mod_cdr_mongodb, mod_cdr_mongodb_load, mod_cdr_mongodb_shutdown, NULL); + +static void set_bson_profile_data(bson *b, switch_caller_profile_t *caller_profile) +{ + bson_append_string(b, "username", caller_profile->username); + bson_append_string(b, "dialplan", caller_profile->dialplan); + bson_append_string(b, "caller_id_name", caller_profile->caller_id_name); + bson_append_string(b, "ani", caller_profile->ani); + bson_append_string(b, "aniii", caller_profile->aniii); + bson_append_string(b, "caller_id_number", caller_profile->caller_id_number); + bson_append_string(b, "network_addr", caller_profile->network_addr); + bson_append_string(b, "rdnis", caller_profile->rdnis); + bson_append_string(b, "destination_number", caller_profile->destination_number); + bson_append_string(b, "uuid", caller_profile->uuid); + bson_append_string(b, "source", caller_profile->source); + bson_append_string(b, "context", caller_profile->context); + bson_append_string(b, "chan_name", caller_profile->chan_name); +} + + +static switch_status_t my_on_reporting(switch_core_session_t *session) +{ + switch_status_t status = SWITCH_STATUS_SUCCESS; + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_event_header_t *hi; + switch_caller_profile_t *caller_profile; + switch_app_log_t *app_log; + bson cdr; + int is_b; + char *tmp; + + if (globals.shutdown) { + return SWITCH_STATUS_SUCCESS; + } + + is_b = channel && switch_channel_get_originator_caller_profile(channel); + if (!globals.log_b && is_b) { + const char *force_cdr = switch_channel_get_variable(channel, SWITCH_FORCE_PROCESS_CDR_VARIABLE); + if (!switch_true(force_cdr)) { + return SWITCH_STATUS_SUCCESS; + } + } + + bson_init(&cdr); + + /* Channel data */ + bson_append_start_object(&cdr, "channel_data"); + bson_append_string(&cdr, "state", switch_channel_state_name(switch_channel_get_state(channel))); + bson_append_string(&cdr, "direction", switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound"); + bson_append_int(&cdr, "state_number", switch_channel_get_state(channel)); + + if ((tmp = switch_channel_get_flag_string(channel))) { + bson_append_string(&cdr, "flags", tmp); + free(tmp); + } + + if ((tmp = switch_channel_get_cap_string(channel))) { + bson_append_string(&cdr, "caps", tmp); + free(tmp); + } + bson_append_finish_object(&cdr); /* channel_data */ + + + /* Channel variables */ + bson_append_start_object(&cdr, "variables"); + for (hi = switch_channel_variable_first(channel); hi; hi = hi->next) { + if (!zstr(hi->name) && !zstr(hi->value)) { + bson_append_string(&cdr, hi->name, hi->value); + } + } + bson_append_finish_object(&cdr); /* variables */ + + + /* App log */ + if ((app_log = switch_core_session_get_app_log(session))) { + switch_app_log_t *ap; + + bson_append_start_object(&cdr, "app_log"); + for (ap = app_log; ap; ap = ap->next) { + bson_append_start_object(&cdr, "application"); + bson_append_string(&cdr, "app_name", ap->app); + bson_append_string(&cdr, "app_data", ap->arg); + bson_append_long(&cdr, "app_stamp", ap->stamp); + bson_append_finish_object(&cdr); /* application */ + } + + bson_append_finish_object(&cdr); /* app_log */ + } + + + /* Callflow */ + caller_profile = switch_channel_get_caller_profile(channel); + + while (caller_profile) { + bson_append_start_object(&cdr, "callflow"); + + if (!zstr(caller_profile->dialplan)) { + bson_append_string(&cdr, "dialplan", caller_profile->dialplan); + } + + if (!zstr(caller_profile->profile_index)) { + bson_append_string(&cdr, "profile_index", caller_profile->profile_index); + } + + if (caller_profile->caller_extension) { + switch_caller_application_t *ap; + + bson_append_start_object(&cdr, "extension"); + + bson_append_string(&cdr, "name", caller_profile->caller_extension->extension_name); + bson_append_string(&cdr, "number", caller_profile->caller_extension->extension_number); + + if (caller_profile->caller_extension->current_application) { + bson_append_string(&cdr, "current_app", caller_profile->caller_extension->current_application->application_name); + } + + for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) { + bson_append_start_object(&cdr, "application"); + if (ap == caller_profile->caller_extension->current_application) { + bson_append_bool(&cdr, "last_executed", 1); + } + bson_append_string(&cdr, "app_name", ap->application_name); + bson_append_string(&cdr, "app_data", ap->application_data); + bson_append_finish_object(&cdr); + } + + if (caller_profile->caller_extension->children) { + switch_caller_profile_t *cp = NULL; + + for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) { + + if (!cp->caller_extension) { + continue; + } + + bson_append_start_object(&cdr, "sub_extensions"); + bson_append_start_object(&cdr, "extension"); + + bson_append_string(&cdr, "name", cp->caller_extension->extension_name); + bson_append_string(&cdr, "number", cp->caller_extension->extension_number); + bson_append_string(&cdr, "dialplan", cp->dialplan); + if (cp->caller_extension->current_application) { + bson_append_string(&cdr, "current_app", cp->caller_extension->current_application->application_name); + } + + for (ap = cp->caller_extension->applications; ap; ap = ap->next) { + bson_append_start_object(&cdr, "application"); + if (ap == cp->caller_extension->current_application) { + bson_append_bool(&cdr, "last_executed", 1); + } + bson_append_string(&cdr, "app_name", ap->application_name); + bson_append_string(&cdr, "app_data", ap->application_data); + bson_append_finish_object(&cdr); + } + + bson_append_finish_object(&cdr); /* extension */ + bson_append_finish_object(&cdr); /* sub_extensions */ + } + } + + bson_append_finish_object(&cdr); /* extension */ + } + + bson_append_start_object(&cdr, "caller_profile"); + set_bson_profile_data(&cdr, caller_profile); + + if (caller_profile->origination_caller_profile) { + switch_caller_profile_t *cp = NULL; + + bson_append_start_object(&cdr, "origination"); + for (cp = caller_profile->origination_caller_profile; cp; cp = cp->next) { + bson_append_start_object(&cdr, "origination_caller_profile"); + set_bson_profile_data(&cdr, cp); + bson_append_finish_object(&cdr); + } + bson_append_finish_object(&cdr); /* origination */ + } + + if (caller_profile->originator_caller_profile) { + switch_caller_profile_t *cp = NULL; + + bson_append_start_object(&cdr, "originator"); + for (cp = caller_profile->originator_caller_profile; cp; cp = cp->next) { + bson_append_start_object(&cdr, "originator_caller_profile"); + set_bson_profile_data(&cdr, cp); + bson_append_finish_object(&cdr); + } + bson_append_finish_object(&cdr); /* originator */ + } + + if (caller_profile->originatee_caller_profile) { + switch_caller_profile_t *cp = NULL; + + bson_append_start_object(&cdr, "originatee"); + for (cp = caller_profile->originatee_caller_profile; cp; cp = cp->next) { + bson_append_start_object(&cdr, "originatee_caller_profile"); + set_bson_profile_data(&cdr, cp); + bson_append_finish_object(&cdr); + } + bson_append_finish_object(&cdr); /* originatee */ + } + + bson_append_finish_object(&cdr); /* caller_profile */ + + /* Timestamps */ + if (caller_profile->times) { + bson_append_start_object(&cdr, "times"); + + /* Insert timestamps as long ints (microseconds) to preserve accuracy */ + bson_append_long(&cdr, "created_time", caller_profile->times->created); + bson_append_long(&cdr, "profile_created_time", caller_profile->times->profile_created); + bson_append_long(&cdr, "progress_time", caller_profile->times->progress); + bson_append_long(&cdr, "progress_media_time", caller_profile->times->progress_media); + bson_append_long(&cdr, "answered_time", caller_profile->times->answered); + bson_append_long(&cdr, "bridged_time", caller_profile->times->bridged); + bson_append_long(&cdr, "last_hold_time", caller_profile->times->last_hold); + bson_append_long(&cdr, "hold_accum_time", caller_profile->times->hold_accum); + bson_append_long(&cdr, "hangup_time", caller_profile->times->hungup); + bson_append_long(&cdr, "resurrect_time", caller_profile->times->resurrected); + bson_append_long(&cdr, "transfer_time", caller_profile->times->transferred); + bson_append_finish_object(&cdr); /* times */ + } + + bson_append_finish_object(&cdr); /* callflow */ + caller_profile = caller_profile->next; + } + + bson_finish(&cdr); + + switch_mutex_lock(globals.mongo_mutex); + + if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr) != MONGO_OK) { + if (globals.mongo_conn->err == MONGO_IO_ERROR) { + mongo_error_t db_status; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "MongoDB connection failed; attempting reconnect...\n"); + db_status = mongo_reconnect(globals.mongo_conn); + + if (db_status != MONGO_OK) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "MongoDB reconnect failed with error code %d\n", db_status); + status = SWITCH_STATUS_FALSE; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "MongoDB connection re-established.\n"); + if (mongo_insert(globals.mongo_conn, globals.mongo_namespace, &cdr) != MONGO_OK) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: error code %d\n", globals.mongo_conn->err); + status = SWITCH_STATUS_FALSE; + } + } + + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_insert: error code %d\n", globals.mongo_conn->err); + status = SWITCH_STATUS_FALSE; + } + } + + switch_mutex_unlock(globals.mongo_mutex); + bson_destroy(&cdr); + + return status; +} + + +static switch_state_handler_table_t state_handlers = { + /*.on_init */ NULL, + /*.on_routing */ NULL, + /*.on_execute */ NULL, + /*.on_hangup */ NULL, + /*.on_exchange_media */ NULL, + /*.on_soft_execute */ NULL, + /*.on_consume_media */ NULL, + /*.on_hibernate */ NULL, + /*.on_reset */ NULL, + /*.on_park */ NULL, + /*.on_reporting */ my_on_reporting +}; + + +static switch_status_t load_config(switch_memory_pool_t *pool) +{ + switch_status_t status = SWITCH_STATUS_SUCCESS; + + if (switch_xml_config_parse_module_settings("cdr_mongodb.conf", SWITCH_FALSE, config_settings) != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_FALSE; + } + + return status; +} + + +SWITCH_MODULE_LOAD_FUNCTION(mod_cdr_mongodb_load) +{ + switch_status_t status = SWITCH_STATUS_SUCCESS; + mongo_error_t db_status; + + memset(&globals, 0, sizeof(globals)); + globals.pool = pool; + if (load_config(pool) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Unable to load or parse config!\n"); + } + + db_status = mongo_connect(globals.mongo_conn, globals.mongo_host, globals.mongo_port); + + if (db_status != MONGO_OK) { + switch (globals.mongo_conn->err) { + case MONGO_CONN_NO_SOCKET: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_connect: no socket\n"); + break; + case MONGO_CONN_FAIL: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_connect: connection failed\n"); + break; + case MONGO_CONN_NOT_MASTER: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_connect: not master\n"); + break; + default: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mongo_connect: unknown error %d\n", db_status); + } + return SWITCH_STATUS_FALSE; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected to MongoDB server %s:%d\n", globals.mongo_host, globals.mongo_port); + } + + switch_mutex_init(&globals.mongo_mutex, SWITCH_MUTEX_NESTED, pool); + + switch_core_add_state_handler(&state_handlers); + *module_interface = switch_loadable_module_create_module_interface(pool, modname); + + return status; +} + + +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_cdr_mongodb_shutdown) +{ + globals.shutdown = 1; + switch_core_remove_state_handler(&state_handlers); + switch_mutex_destroy(globals.mongo_mutex); + + mongo_destroy(globals.mongo_conn); + + 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: + */ From b31ebc9a69ac166223efaafb067b6e9387f35e89 Mon Sep 17 00:00:00 2001 From: Daniel Swarbrick Date: Wed, 7 Sep 2011 23:57:44 +0200 Subject: [PATCH 043/204] add config file and tweak modules.conf.in for mod_cdr_mongodb --- build/modules.conf.in | 1 + conf/autoload_configs/cdr_mongodb.conf.xml | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 conf/autoload_configs/cdr_mongodb.conf.xml diff --git a/build/modules.conf.in b/build/modules.conf.in index ef3e7eb5bd..9f5cfa5eb7 100644 --- a/build/modules.conf.in +++ b/build/modules.conf.in @@ -81,6 +81,7 @@ event_handlers/mod_event_socket #event_handlers/mod_event_zmq event_handlers/mod_cdr_csv event_handlers/mod_cdr_sqlite +#event_handlers/mod_cdr_mongodb #event_handlers/mod_cdr_pg_csv #event_handlers/mod_radius_cdr #event_handlers/mod_erlang_event diff --git a/conf/autoload_configs/cdr_mongodb.conf.xml b/conf/autoload_configs/cdr_mongodb.conf.xml new file mode 100644 index 0000000000..ce366d1bd0 --- /dev/null +++ b/conf/autoload_configs/cdr_mongodb.conf.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + From 09a61f5025b1c7dee05259db0e169f39a565b62d Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Wed, 7 Sep 2011 22:51:29 +0200 Subject: [PATCH 044/204] [FreeTDM] Add (experimental) ftmod_misdn Add I/O plugin for mISDN stack that is included in the linux kernel since version 2.6.27. The in-kernel mISDN stack uses a socket based interface (AF_ISDN), data and control commands are exchanged via datagram messages. This makes writing a driver that doesn't use a separate (per-span) thread to handle all incoming events a bit tricky, because responses to control messages and incoming data are mixed and interfacing with the synchronous FreeTDM I/O API is problematic. B(*)/D-channel handling: The current version uses misdn_wait() to poll() for activity on the non-blocking channel sockets and misdn_read() to receive and handle all pending events up to the first PH_DATA_IND (data) message (which is what the caller of the read method is actually after). In case no data has been received, misdn_read() returns FTDM_SUCCESS with *datalen = 0, which is OK for all the signalling modules tested (ftmod_libpri and (out-of-tree) ftmod_isdn). To send data, misdn_write() is called, which just sends a PH_DATA_REQ message to the mISDN channel socket. (*) B-channels use a per-channel timerfd as a timing reference for 'ready-for-write' poll()ing in misdn_wait(). This is a workaround for a limitation of mISDN sockets, which do not support POLLOUT waiting on b-channel sockets (in a useful way). Sending/receiving of data works the same way as on d-channels, otherwise. The module has received some minimal testing using a beronet single-port HFC E1 and a HFC4-S quad-port BRI card on linux-3.0.x. --- Limitations --- - Only the most basic features have been implemented (alarms, sending/receiving data/audio). - Spans are limited to E1 and BRI/BRI_PTMP trunk types. - D-Channels only work on 16 for PRI and 3 for BRI. - NT/TE mode information is not available from freetdm.conf / at configure_span()-time so the module assumes TE mode, which should be only a problem for cards that can change the port configuration (pin-out) from software. - Current design (b-channel timerfd / misdn_wait()/_read()/_write()) should be fine for most SoHo use-cases (scalability / cpu usage / timing precision). --- Requirements --- - mISDNif.h header (/usr/include/mISDN/mISDNif.h), provided by mISDNuser (http://isdn.eversberg.eu/download/lcr-1.7/mISDNuser-20100525.tar.gz). - Linux kernel with mISDN and timerfd enabled (>= 2.6.27) and libc with timerfd support. mISDN options can be found in the: "Device Drivers" -> "ISDN support" -> "Modular ISDN driver" section of make menuconfig. Timerfd is usually enabled by default. The FreeTDM configure script will check for missing mISDNif.h header and timerfd support and print a message. You should see the following in the summary screen on success: ftmod_misdn........................ yes NOTE: Forcing mISDN support using the "--with-misdn" configure option, will cause the configure script to fail on the first missing dependency. --- Usage --- To use the module, make sure you have mISDN support in the kernel (kernel modules loaded or kernel with built-in mISDN running), the "misdn_info" application shipped with mISDNuser will output a list of available mISDN ports on your system, e.g.: Found 5 ports Port 0 'hfc-4s.1-1': TE/NT-mode BRI S/T (for phone lines & phones) 2 B-channels: 1-2 B-protocols: RAW HDLC X75slp ... Port 4 'hfc-e1.2': TE/NT-mode PRI E1 (for phone lines & E1 devices) 30 B-channels: 1-15 17-31 B-protocols: RAW HDLC X75slp NOTE: ftmod_misdn will print an error message if mISDN support is not available, or if there are no ports installed. - Example freetdm.conf settings [span misdn BRI_1] trunk_type => BRI_PTMP b-channel => 0:1,2 d-channel => 0:3 [span misdn PRI_1] trunk_type => E1 b-channel => hfc-e1.2:1-15,17-31 d-channel => hfc-e1.2:16 Signed-off-by: Stefan Knoblich --- libs/freetdm/Makefile.am | 8 + libs/freetdm/configure.ac | 37 + .../src/ftmod/ftmod_misdn/ftmod_misdn.c | 1807 +++++++++++++++++ 3 files changed, 1852 insertions(+) create mode 100644 libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c diff --git a/libs/freetdm/Makefile.am b/libs/freetdm/Makefile.am index b4eb76d6fd..3a88b5f521 100644 --- a/libs/freetdm/Makefile.am +++ b/libs/freetdm/Makefile.am @@ -248,6 +248,14 @@ ftmod_r2_la_LDFLAGS = -shared -module -avoid-version -lopenr2 ftmod_r2_la_LIBADD = libfreetdm.la endif +if HAVE_MISDN +mod_LTLIBRARIES += ftmod_misdn.la +ftmod_misdn_la_SOURCES = $(SRC)/ftmod/ftmod_misdn/ftmod_misdn.c +ftmod_misdn_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) $(MISDN_CFLAGS) +ftmod_misdn_la_LDFLAGS = -shared -module -avoid-version +ftmod_misdn_la_LIBADD = libfreetdm.la +endif + dox doxygen: doxygen $(FT_SRCDIR)/docs/Doxygen.conf diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac index 493f0da3b0..70033a7a0a 100644 --- a/libs/freetdm/configure.ac +++ b/libs/freetdm/configure.ac @@ -364,6 +364,42 @@ then fi AM_CONDITIONAL([HAVE_LIBISDN], [test "${HAVE_LIBISDN}" = "yes"]) + +## +# mISDN dependencies +# +HAVE_MISDN="no" +AC_ARG_WITH([misdn], + [AS_HELP_STRING([--with-misdn], [Install ftmod_misdn (mISDN I/O plugin)])], + [case "${withval}" in + no|yes) with_misdn="${withval}" ;; + *) AC_MSG_ERROR([Invalid value \"${with_misdn}\" for --with-misdn option]) ;; + esac], + [with_misdn="auto"] +) +AS_IF([test "${with_misdn}" != "no"], + [AC_MSG_RESULT([${as_nl}<<>> ftmod_misdn (Linux mISDN I/O plugin)]) + AC_CHECK_FUNCS([timerfd_create],, + [AS_IF([test "${with_misdn}" = "yes"], + [AC_MSG_ERROR([no timerfd support in libc])], + [AC_MSG_NOTICE([no timerfd support in libc])] + )] + ) + AC_CHECK_HEADER([mISDN/mISDNif.h],, + [AS_IF([test "${with_misdn}" = "yes"], + [AC_MSG_ERROR([mISDN/mISDNif.h not found])], + [AC_MSG_NOTICE([mISDN/mISDNif.h not found])] + )], + [#include ] + ) + AS_IF([test "${ac_cv_func_timerfd_create}" = "yes" -a "${ac_cv_header_mISDN_mISDNif_h}" = "yes"], + [HAVE_MISDN="yes"], + [AC_MSG_NOTICE([Some required dependencies are missing, module disabled])] + )] +) +AM_CONDITIONAL([HAVE_MISDN], [test "${HAVE_MISDN}" = "yes"]) + + AC_MSG_RESULT([${as_nl}<<>> Creating output files]) AC_CONFIG_FILES([ Makefile @@ -389,6 +425,7 @@ AC_MSG_RESULT([ ftmod_pritap....................... ${HAVE_PRITAP} I/O: ftmod_wanpipe...................... ${HAVE_LIBSANGOMA} + ftmod_misdn........................ ${HAVE_MISDN} =============================================================================== ]) diff --git a/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c b/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c new file mode 100644 index 0000000000..9673549f79 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_misdn/ftmod_misdn.c @@ -0,0 +1,1807 @@ +/** + * mISDN HW interface + * + * Copyright (c) 2011, Stefan Knoblich + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * NOTE: This is intended as a Layer 1 interface only, signaling + * is handled by other modules (e.g. ftmod_libpri or ftmod_isdn). + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* this is how it should have been... +#ifdef HAVE_FREETDM_FREETDM_H +#include +#else +#include +#endif +*/ +/* ... and this is how it is */ +#include + +#include + +/* + * mISDNcompat.h replaces these with references to an extern int, + * which is exported by libmisdn... unset them and use the official + * AF ID "34" + */ +#undef PF_ISDN +#undef AF_ISDN +#define AF_ISDN 34 +#define PF_ISDN AF_ISDN + +//#define MISDN_DEBUG_EVENTS +//#define MISDN_DEBUG_IO + +#ifndef MIN +#define MIN(x,y) (((x) < (y)) ? (x) : (y)) +#endif + +typedef enum { + MISDN_CAPS_NONE = 0, + + /* D-Channel */ + MISDN_CAPS_PRI = (1 << 0), + MISDN_CAPS_BRI = (1 << 1), + MISDN_CAPS_UP0 = (1 << 2), + MISDN_CAPS_NT = (1 << 3), + MISDN_CAPS_TE = (1 << 4), + + /* B-Channel */ + MISDN_CAPS_RAW = (1 << 10), + MISDN_CAPS_HDLC = (1 << 11), +} misdn_capability_flags_t; + +#define MISDN_IS_BRI(x) (x & MISDN_CAPS_BRI) +#define MISDN_IS_PRI(x) (x & MISDN_CAPS_PRI) + +#define MISDN_IS_TE(x) (x & MISDN_CAPS_TE) +#define MISDN_IS_NT(x) (x & MISDN_CAPS_NT) + +#define MISDN_IS_RAW(x) (x & MISDN_CAPS_RAW) +#define MISDN_IS_HDLC(x) (x & MISDN_CAPS_HDLC) + + +const static struct { + const int id; + const char *name; +} misdn_event_types[] = { + { PH_DATA_REQ, "PH_DATA_REQ" }, + { PH_DATA_IND, "PH_DATA_IND" }, + { PH_DATA_CNF, "PH_DATA_CNF" }, + { PH_CONTROL_REQ, "PH_CONTROL_REQ" }, + { PH_CONTROL_IND, "PH_CONTROL_IND" }, + { PH_CONTROL_CNF, "PH_CONTROL_CNF" }, + { PH_ACTIVATE_REQ, "PH_ACTIVATE_REQ" }, + { PH_ACTIVATE_IND, "PH_ACTIVATE_IND" }, + { PH_ACTIVATE_CNF, "PH_ACTIVATE_CNF" }, + { PH_DEACTIVATE_REQ, "PH_DEACTIVATE_REQ" }, + { PH_DEACTIVATE_IND, "PH_DEACTIVATE_IND" }, + { PH_DEACTIVATE_CNF, "PH_DEACTIVATE_CNF" }, +}; + +static const char *misdn_event2str(const int event) +{ + int x; + + for (x = 0; x < ftdm_array_len(misdn_event_types); x++) { + if (event == misdn_event_types[x].id) + return misdn_event_types[x].name; + } + return "unknown"; +} + + +const static struct { + const int id; + const char *name; +} misdn_control_types[] = { +#define MISDN_CONTROL_TYPE(x) { x, #x } + MISDN_CONTROL_TYPE(DTMF_HFC_COEF), +}; + +#if 0 /* unused for now */ +static const char *misdn_control2str(const int ctrl) +{ + int x; + + for (x = 0; x < ftdm_array_len(misdn_control_types); x++) { + if (ctrl == misdn_control_types[x].id) + return misdn_control_types[x].name; + } + return "unknown"; +} +#endif + +/*********************************************************************************** + * mISDN <-> FreeTDM data structures + ***********************************************************************************/ + +enum { + MISDN_SPAN_NONE = 0, + MISDN_SPAN_RUNNING = (1 << 0), + MISDN_SPAN_STOPPED = (1 << 1) +}; + +struct misdn_span_private { + int flags; + + /* event conditional */ + pthread_mutex_t event_cond_mutex; + pthread_cond_t event_cond; +}; + +#define MISDN_CHAN_STATE_CLOSED 0 +#define MISDN_CHAN_STATE_OPEN 1 + +struct misdn_event_queue; + +struct misdn_chan_private { + /* */ + int state; + int debugfd; + int timerfd; + + /* hw addr of channel */ + struct sockaddr_mISDN addr; + + /* counters */ + unsigned long tx_cnt; + unsigned long tx_ack_cnt; + unsigned long rx_cnt; + unsigned long slip_rx_cnt; + unsigned long slip_tx_cnt; + + struct misdn_event_queue *events; +}; + +#define ftdm_chan_io_private(x) ((x)->io_data) +#define ftdm_span_io_private(x) ((x)->io_data) + +static ftdm_status_t misdn_handle_incoming(ftdm_channel_t *ftdmchan, const char *rbuf, const int size); + +/*********************************************************************************** + * mISDN interface functions + ***********************************************************************************/ + +/* + * Event Queue + */ +#define MISDN_EVENTS_MAX 8 + +struct misdn_event { + int id; +}; + +struct misdn_event_queue { + int read_pos; + int write_pos; + pthread_mutex_t mutex; + + struct misdn_event events[MISDN_EVENTS_MAX]; +}; + +/** + * Initialize event queue + */ +static ftdm_status_t misdn_event_queue_create(struct misdn_event_queue **queue) +{ + struct misdn_event_queue *tmp = NULL; + + if (!queue) + return FTDM_FAIL; + + tmp = calloc(1, sizeof(*tmp)); + if (!tmp) + return FTDM_FAIL; + + pthread_mutex_init(&tmp->mutex, NULL); + + *queue = tmp; + return FTDM_SUCCESS; +} + +/** + * Destroy event queue + */ +static ftdm_status_t misdn_event_queue_destroy(struct misdn_event_queue **queue) +{ + if (!queue || !*queue) + return FTDM_FAIL; + + pthread_mutex_destroy(&(*queue)->mutex); + ftdm_safe_free(*queue); + *queue = NULL; + + return FTDM_SUCCESS; +} + +static ftdm_status_t misdn_event_queue_reset(struct misdn_event_queue *queue) +{ + if (!queue) + return FTDM_FAIL; + pthread_mutex_lock(&queue->mutex); + + memset(queue->events, 0, sizeof(queue->events)); + queue->read_pos = queue->write_pos = 0; + + pthread_mutex_unlock(&queue->mutex); + return FTDM_SUCCESS; +} + +static ftdm_status_t misdn_event_queue_has_data(const struct misdn_event_queue *queue) +{ + if (!queue) + return FTDM_FALSE; + + return (queue->read_pos == queue->write_pos) ? FTDM_FALSE : FTDM_TRUE; +} + +static struct misdn_event *misdn_event_queue_pop(struct misdn_event_queue *queue) +{ + struct misdn_event *evt = NULL; + int next_idx = 0; + + if (!queue) + return NULL; + + pthread_mutex_lock(&queue->mutex); + + next_idx = (queue->read_pos + 1) % MISDN_EVENTS_MAX; + + if (queue->read_pos == queue->write_pos) { +#ifdef MISDN_DEBUG_EVENTS + ftdm_log(FTDM_LOG_DEBUG, "mISDN queue %p: empty\n", queue); +#endif + pthread_mutex_unlock(&queue->mutex); + return NULL; + } + +#ifdef MISDN_DEBUG_EVENTS + ftdm_log(FTDM_LOG_DEBUG, "mISDN queue %p: read event (read_pos: %d, write_pos: %d, next_write_pos: %d)\n", + queue, queue->read_pos, queue->write_pos, next_idx); +#endif + /* update read pos */ + evt = &queue->events[queue->read_pos]; + queue->read_pos = next_idx; + + pthread_mutex_unlock(&queue->mutex); + return evt; +} + +static ftdm_status_t misdn_event_queue_push(struct misdn_event_queue *queue, struct misdn_event *evt) +{ + int next_idx = 0; + + if (!queue || !evt) + return FTDM_FAIL; + + pthread_mutex_lock(&queue->mutex); + + next_idx = (queue->write_pos + 1) % MISDN_EVENTS_MAX; + + if (next_idx == queue->read_pos) { +#ifdef MISDN_DEBUG_EVENTS + ftdm_log(FTDM_LOG_DEBUG, "mISDN queue %p: full\n", queue); +#endif + pthread_mutex_unlock(&queue->mutex); + return FTDM_FAIL; + } + +#ifdef MISDN_DEBUG_EVENTS + ftdm_log(FTDM_LOG_DEBUG, "mISDN queue %p: wrote event (read_pos: %d, write_pos: %d, next_write_pos: %d)\n", + queue, queue->read_pos, queue->write_pos, next_idx); +#endif + memcpy(&queue->events[queue->write_pos], evt, sizeof(*evt)); + queue->write_pos = next_idx; + + pthread_mutex_unlock(&queue->mutex); + return FTDM_SUCCESS; +} + +#if 0 /* unused for now */ +static void misdn_event_queue_print_info(const struct misdn_event_queue *queue) +{ + ftdm_log(FTDM_LOG_DEBUG, "Queue %p\n\tread idx: %d\n\twrite idx: %d\n", queue, + queue->read_pos, queue->write_pos); +} +#endif + +/*********************************************************************************** + * mISDN helper functions + ***********************************************************************************/ + +#define MISDN_PH_ACTIVATE_TIMEOUT_MS 10000 +#define MISDN_MPH_INFORMATION_TIMEOUT_MS 3000 + +static inline void ts_add_msec(struct timespec *a, int msec) +{ + a->tv_sec += (msec / 1000); + a->tv_nsec += (msec % 1000) * 1000000; + if (a->tv_nsec >= 1000000000) { + a->tv_sec++; + a->tv_nsec -= 1000000000; + } +} + +static inline int ts_sub_msec(struct timespec *a, struct timespec *b) +{ + int msec = 0; + msec += (a->tv_sec - b->tv_sec) * 1000; + msec += (a->tv_nsec - b->tv_nsec) / 1000000; + return msec; +} + +static inline int ts_after(struct timespec *a, struct timespec *b) +{ + if (a->tv_sec > b->tv_sec) return 1; + if (a->tv_sec == b->tv_sec && a->tv_nsec > b->tv_nsec) return 1; + return 0; +} + +static inline int ts_before(struct timespec *a, struct timespec *b) +{ + if (a->tv_sec < b->tv_sec) return 1; + if (a->tv_sec == b->tv_sec && a->tv_nsec < b->tv_nsec) return 1; + return 0; +} + +static ftdm_status_t misdn_activate_channel(ftdm_channel_t *chan, int activate) +{ + char buf[MAX_DATA_MEM] = { 0 }; + struct mISDNhead *hh = (struct mISDNhead *) buf; + struct timespec abstimeout; + int req = 0, resp = 0, ms_left = MISDN_PH_ACTIVATE_TIMEOUT_MS; + int retval; + + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN sending %s request\n", + (activate) ? "activation" : "deactivation"); + + /* prepare + send request primitive */ + req = (activate) ? PH_ACTIVATE_REQ : PH_DEACTIVATE_REQ; + hh->prim = req; + hh->id = MISDN_ID_ANY; + + if ((retval = sendto(chan->sockfd, hh, sizeof(*hh), 0, NULL, 0)) < sizeof(*hh)) { + ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN failed to send activation request: %s\n", + strerror(errno)); + return FTDM_FAIL; + } + + clock_gettime(CLOCK_MONOTONIC, &abstimeout); + ts_add_msec(&abstimeout, ms_left); + + /* wait for answer */ + while (1) { + struct timespec now; + struct pollfd pfd; + + pfd.fd = chan->sockfd; + pfd.events = POLLIN /* | POLLPRI */; + pfd.revents = 0; + + switch ((retval = poll(&pfd, 1, ms_left))) { + case 0: /* timeout */ + goto out; + case -1: /* error */ + if (!(retval == EAGAIN || retval == EINTR)) { + ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN polling for activation confirmation failed: %s\n", + strerror(errno)); + return FTDM_FAIL; + } + break; + default: /* read data */ + break; + } + + if (pfd.revents & (POLLIN | POLLPRI)) { + /* handle incoming message */ + if ((retval = recvfrom(chan->sockfd, buf, sizeof(buf), 0, NULL, NULL)) <= 0) { + ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN failed to receive possible answer for %s request: %s\n", + (activate) ? "activation" : "deactivation", strerror(errno)); + return FTDM_FAIL; + } +//#ifdef MISDN_DEBUG_EVENTS + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN got event '%s' while waiting for %s confirmation\n", + misdn_event2str(hh->prim), (activate) ? "activation" : "deactivation"); +//#endif + switch (hh->prim) { + case PH_ACTIVATE_IND: /* success (or not): save last response, */ + case PH_DEACTIVATE_IND: /* stop looping if it's the one we've been waiting for */ + resp = hh->prim; + if (hh->prim == (activate) ? PH_ACTIVATE_IND : PH_DEACTIVATE_IND) goto out; + break; + case PH_ACTIVATE_CNF: + case PH_DEACTIVATE_CNF: + resp = hh->prim; + if (hh->prim == (activate) ? PH_ACTIVATE_CNF : PH_DEACTIVATE_CNF) goto out; + break; + case PH_ACTIVATE_REQ: /* REQ echo, ignore */ + case PH_DEACTIVATE_REQ: + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN got '%s' echo while waiting for %s confirmation (id: %#x)\n", + misdn_event2str(hh->prim), (activate) ? "activation" : "deactivation", hh->id); + break; + default: /* other messages, ignore */ + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN ignoring event '%s' while waiting for %s confirmation\n", + misdn_event2str(hh->prim), (activate) ? "activation" : "deactivation"); + break; + } + } + + /* check timeout */ + clock_gettime(CLOCK_MONOTONIC, &now); + + if (ts_after(&now, &abstimeout) || (ms_left = ts_sub_msec(&abstimeout, &now)) <= 0) + goto out; + } +out: + if (resp == 0) { + ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN timeout waiting for %s confirmation\n", + (activate) ? "activation" : "deactivation"); + return FTDM_TIMEOUT; + } + if ((req == PH_ACTIVATE_IND && !(resp == PH_ACTIVATE_CNF || resp == PH_ACTIVATE_IND)) || + (req == PH_DEACTIVATE_IND && !(resp == PH_DEACTIVATE_CNF || resp == PH_DEACTIVATE_CNF))) { + ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN received '%s' while waiting for %s\n", + misdn_event2str(resp), (activate) ? "activation" : "deactivation"); + return FTDM_FAIL; + } + + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN received %s confirmation\n", + (activate) ? "activation" : "deactivation"); + return FTDM_SUCCESS; +} + + +#if 0 /* unused for now */ +static ftdm_status_t misdn_get_ph_info(ftdm_channel_t *chan, struct ph_info *info) +{ + char buf[MAX_DATA_MEM] = { 0 }; + struct mISDNhead *hh; + struct timespec abstimeout; + int req = 0, resp = 0, ms_left = MISDN_MPH_INFORMATION_TIMEOUT_MS; + int retval; + + /* prepare + send request primitive */ + req = MPH_INFORMATION_REQ; + hh = (struct mISDNhead *)buf; + hh->prim = req; + hh->id = MISDN_ID_ANY; + + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN sending %s request\n", + misdn_event2str(req)); + + if ((retval = sendto(chan->sockfd, &hh, sizeof(hh), 0, NULL, 0)) < sizeof(hh)) { + ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN failed to send %s request: %s\n", + misdn_event2str(req), strerror(errno)); + return FTDM_FAIL; + } + + clock_gettime(CLOCK_MONOTONIC, &abstimeout); + ts_add_msec(&abstimeout, ms_left); + + /* wait for answer */ + while (1) { + struct timespec now; + struct pollfd pfd; + + pfd.fd = chan->sockfd; + pfd.events = POLLIN /* | POLLPRI */; + pfd.revents = 0; + + switch ((retval = poll(&pfd, 1, ms_left))) { + case 0: /* timeout */ + goto out; + case -1: /* error */ + if (!(retval == EAGAIN || retval == EINTR)) { + ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN polling for %s answer failed: %s\n", + misdn_event2str(req), strerror(errno)); + return FTDM_FAIL; + } + break; + default: /* read data */ + break; + } + + if (pfd.revents & (POLLIN | POLLPRI)) { + /* handle incoming message */ + if ((retval = recvfrom(chan->sockfd, buf, sizeof(buf), 0, NULL, NULL)) <= 0) { + ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN failed to receive possible answer for %s request: %s\n", + misdn_event2str(req), strerror(errno)); + return FTDM_FAIL; + } +//#ifdef MISDN_DEBUG_EVENTS + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN got event '%s' while waiting for %s answer\n", + misdn_event2str(hh->prim), misdn_event2str(req)); +//#endif + switch (hh->prim) { + case MPH_INFORMATION_IND: /* success */ + if (retval < MISDN_HEADER_LEN + sizeof(*info)) { + ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN answer for %s is too short\n", + misdn_event2str(req)); + return FTDM_FAIL; + } + resp = hh->prim; + /* TODO */ + goto out; + case MPH_INFORMATION_REQ: /* REQ echo, ignore */ + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN got '%s' echo while waiting for %s answer\n", + misdn_event2str(hh->prim), misdn_event2str(req)); + break; + default: /* other messages, ignore */ + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN ignoring event '%s' while waiting for %s answer\n", + misdn_event2str(hh->prim), misdn_event2str(req)); + break; + } + } + + /* check timeout */ + clock_gettime(CLOCK_MONOTONIC, &now); + + if (ts_after(&now, &abstimeout) || (ms_left = ts_sub_msec(&abstimeout, &now)) <= 0) + goto out; + } +out: + if (resp == 0) { + ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN timeout waiting for %s answer\n", + misdn_event2str(req)); + return FTDM_TIMEOUT; + } + + return FTDM_SUCCESS; +} +#endif + +static int misdn_handle_ph_control_ind(ftdm_channel_t *chan, const struct mISDNhead *hh, const void *data, const int data_len) +{ +#ifdef MISDN_DEBUG_EVENTS + ftdm_log_chan(chan, FTDM_LOG_DEBUG, + "PH_CONTROL_IND:\n" + "\tMessage:\t%s\n" + "\tPayload:\t%d\n", + misdn_control2str(hh->id), data_len); +#endif + + switch (hh->id) { + case DTMF_HFC_COEF: + break; + default: + break; + } + + return FTDM_SUCCESS; +} + +static int misdn_handle_mph_information_ind(ftdm_channel_t *chan, const struct mISDNhead *hh, const void *data, const int data_len) +{ + struct misdn_chan_private *priv = ftdm_chan_io_private(chan); + int alarm_flags, value; + + if (data_len < sizeof(value)) { + ftdm_log_chan_msg(chan, FTDM_LOG_ERROR, "mISDN MPH_INFORMATION_IND message is too short\n"); + return FTDM_FAIL; + } + value = *(int *)data; + alarm_flags = chan->alarm_flags; + + switch (value) { + case L1_SIGNAL_LOS_ON: + alarm_flags |= FTDM_ALARM_RED; + break; + case L1_SIGNAL_LOS_OFF: + alarm_flags &= ~FTDM_ALARM_RED; + break; + case L1_SIGNAL_AIS_ON: + alarm_flags |= FTDM_ALARM_AIS; + break; + case L1_SIGNAL_AIS_OFF: + alarm_flags &= ~FTDM_ALARM_AIS; + break; + case L1_SIGNAL_RDI_ON: + alarm_flags |= FTDM_ALARM_YELLOW; + break; + case L1_SIGNAL_RDI_OFF: + alarm_flags &= ~FTDM_ALARM_YELLOW; + break; + case L1_SIGNAL_SLIP_RX: + priv->slip_rx_cnt++; + break; + case L1_SIGNAL_SLIP_TX: + priv->slip_tx_cnt++; + break; + default: + ftdm_log_chan(chan, FTDM_LOG_ERROR, "mISDN unknown MPH_INFORMATION_IND message: %d\n", + value); + return FTDM_FAIL; + } + if ((value = (alarm_flags ^ chan->alarm_flags))) { + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "mISDN alarm flags have changed %#x -> %#x\n", + chan->alarm_flags, alarm_flags); + chan->alarm_flags ^= value; + } + return FTDM_SUCCESS; +} + +/*********************************************************************************** + * mISDN <-> FreeTDM interface functions + ***********************************************************************************/ + +struct misdn_globals { + int sockfd; +} globals; + +/** + * \brief Open channel + * \param ftdmchan FreeTDM channel to open + */ +static FIO_OPEN_FUNCTION(misdn_open) +{ + struct misdn_chan_private *chan_priv = ftdm_chan_io_private(ftdmchan); + ftdm_span_t *span = ftdm_channel_get_span(ftdmchan); + struct misdn_span_private *span_priv = ftdm_span_io_private(span); + ftdm_status_t ret = 0; + + assert(chan_priv); + assert(span_priv); + + if (chan_priv->state == MISDN_CHAN_STATE_OPEN) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "mISDN channel is already open, skipping activation\n"); + return FTDM_SUCCESS; + } + + /* flush all events */ + misdn_event_queue_reset(chan_priv->events); + + /* + * Send activation request + */ + ret = misdn_activate_channel(ftdmchan, 1); + if (ret != FTDM_SUCCESS) { + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to activate channel (socket: %d)\n", + ftdmchan->sockfd); + return FTDM_FAIL; + } + + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "mISDN channel activation request sent\n"); + + switch (ftdmchan->type) { + case FTDM_CHAN_TYPE_B: { + struct itimerspec its = { + .it_interval = { 0, 0 }, + .it_value = { 0, 0 }, + }; + + its.it_interval.tv_nsec = (ftdmchan->effective_interval * 1000000); + its.it_value.tv_nsec = (ftdmchan->effective_interval * 1000000); + + /* create tx timerfd */ + chan_priv->timerfd = timerfd_create(CLOCK_MONOTONIC, O_NONBLOCK); + if (chan_priv->timerfd < 0) { + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "mISDN failed to create b-channel tx interval timer: %s\n", + strerror(errno)); + return FTDM_FAIL; + } + + /* start tx timerfd */ + ret = timerfd_settime(chan_priv->timerfd, 0, &its, NULL); + if (ret < 0) { + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "mISDN failed to start b-channel tx interval timer: %s\n", + strerror(errno)); + return FTDM_FAIL; + } + + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "mISDN created tx interval (%d ms) timer\n", + ftdmchan->effective_interval); + } + case FTDM_CHAN_TYPE_DQ921: + chan_priv->state = MISDN_CHAN_STATE_OPEN; + break; + default: + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "mISDN invalid channel type '%s'\n", + ftdm_channel_get_type(ftdmchan)); + break; + } + return FTDM_SUCCESS; +} + +/** + * \brief Close channel + * \param ftdmchan FreeTDM channel to close + */ +static FIO_CLOSE_FUNCTION(misdn_close) +{ + struct misdn_chan_private *chan_priv = ftdm_chan_io_private(ftdmchan); + ftdm_status_t ret = 0; + + assert(chan_priv); + + /* deactivate b-channels on close */ + if (ftdm_channel_get_type(ftdmchan) == FTDM_CHAN_TYPE_B) { + /* + * Stop tx timerfd + */ + if (chan_priv->timerfd >= 0) { + close(chan_priv->timerfd); + chan_priv->timerfd = -1; + } + + /* + * Send deactivation request (don't wait for answer) + */ + ret = misdn_activate_channel(ftdmchan, 0); + if (ret != FTDM_SUCCESS) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to deactivate channel\n"); + return FTDM_FAIL; + } + + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "mISDN channel deactivated\n"); + chan_priv->state = MISDN_CHAN_STATE_CLOSED; + } + + return FTDM_SUCCESS; +} + +/** + * \brief Execute command + * \param ftdmchan FreeTDM channel + * \param command Command to execute + * \param obj Additional command data + */ +static FIO_COMMAND_FUNCTION(misdn_command) +{ + switch (command) { + case FTDM_COMMAND_NOOP: + break; + case FTDM_COMMAND_SET_INTERVAL: +// case FTDM_COMMAND_GET_INTERVAL: + case FTDM_COMMAND_SET_CODEC: + case FTDM_COMMAND_GET_CODEC: + case FTDM_COMMAND_SET_NATIVE_CODEC: + case FTDM_COMMAND_GET_NATIVE_CODEC: + case FTDM_COMMAND_ENABLE_DTMF_DETECT: + case FTDM_COMMAND_DISABLE_DTMF_DETECT: + case FTDM_COMMAND_SEND_DTMF: + case FTDM_COMMAND_SET_DTMF_ON_PERIOD: + case FTDM_COMMAND_GET_DTMF_ON_PERIOD: + case FTDM_COMMAND_SET_DTMF_OFF_PERIOD: + case FTDM_COMMAND_GET_DTMF_OFF_PERIOD: + case FTDM_COMMAND_SET_RX_GAIN: /* DSP_VOL_CHANGE_RX / HFC_VOL_CHANGE_RX */ + case FTDM_COMMAND_GET_RX_GAIN: + case FTDM_COMMAND_SET_TX_GAIN: /* DSP_VOL_CHANGE_TX / HFC_VOL_CHANGE_TX */ + case FTDM_COMMAND_GET_TX_GAIN: + case FTDM_COMMAND_FLUSH_TX_BUFFERS: + case FTDM_COMMAND_FLUSH_RX_BUFFERS: + case FTDM_COMMAND_FLUSH_BUFFERS: + case FTDM_COMMAND_FLUSH_IOSTATS: + case FTDM_COMMAND_SET_PRE_BUFFER_SIZE: + case FTDM_COMMAND_SET_LINK_STATUS: + case FTDM_COMMAND_GET_LINK_STATUS: + case FTDM_COMMAND_SET_RX_QUEUE_SIZE: + case FTDM_COMMAND_SET_TX_QUEUE_SIZE: + case FTDM_COMMAND_START_MF_PLAYBACK: + case FTDM_COMMAND_STOP_MF_PLAYBACK: + case FTDM_COMMAND_GET_IOSTATS: + case FTDM_COMMAND_SWITCH_IOSTATS: + /* Supported by mISDN */ + case FTDM_COMMAND_ENABLE_ECHOCANCEL: /* DSP_ECHO_ON */ + case FTDM_COMMAND_DISABLE_ECHOCANCEL: /* DSP_ECHO_OFF */ + case FTDM_COMMAND_ENABLE_LOOP: + case FTDM_COMMAND_DISABLE_LOOP: + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Received unimplemented command: %d\n", + command); + break; + + case FTDM_COMMAND_GET_INTERVAL: + FTDM_COMMAND_OBJ_INT = ftdm_channel_get_io_interval(ftdmchan); + ftdm_log(FTDM_LOG_NOTICE, "Interval %d ms [%d:%d]\n", + ftdm_channel_get_io_interval(ftdmchan), ftdm_channel_get_span_id(ftdmchan), ftdm_channel_get_id(ftdmchan)); + break; + + default: + ftdm_log(FTDM_LOG_ERROR, "Unknown command %d\n", command); + } + return FTDM_SUCCESS; +} + + +/** + * \brief Wait for new data + * \param ftdmchan FreeTDM channel to wait on + * \param flags Wait flags + * \param to Timeout + */ +static FIO_WAIT_FUNCTION(misdn_wait) +{ + struct misdn_chan_private *chan_priv = ftdm_chan_io_private(ftdmchan); + struct pollfd pfds[2]; + int nr_fds = 0; + int retval; + + memset(pfds, 0, sizeof(pfds)); + + switch (ftdm_channel_get_type(ftdmchan)) { + case FTDM_CHAN_TYPE_B: + if (*flags & FTDM_WRITE) { + pfds[nr_fds].fd = chan_priv->timerfd; + pfds[nr_fds].events = POLLIN; + nr_fds++; + } + if (*flags & (FTDM_READ | FTDM_EVENTS)) { + pfds[nr_fds].fd = ftdmchan->sockfd; + pfds[nr_fds].events |= (*flags & FTDM_READ) ? POLLIN : 0; + pfds[nr_fds].events |= (*flags & FTDM_EVENTS) ? POLLPRI : 0; + nr_fds++; + } + break; + default: + if (*flags & FTDM_READ) + pfds[0].events |= POLLIN; + if (*flags & FTDM_WRITE) + pfds[0].events |= POLLOUT; + if (*flags & FTDM_EVENTS) + pfds[0].events |= POLLPRI; + pfds[0].fd = ftdmchan->sockfd; + nr_fds++; + break; + } + + *flags = FTDM_NO_FLAGS; + + if (!(pfds[0].events || pfds[1].events)) + return FTDM_SUCCESS; + if ((retval = poll(pfds, nr_fds, to)) < 0) { + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "mISDN poll() failed: %s\n", + strerror(errno)); + return FTDM_FAIL; + } + if (retval == 0) + return FTDM_TIMEOUT; + + switch (ftdm_channel_get_type(ftdmchan)) { + case FTDM_CHAN_TYPE_B: + if (pfds[0].fd == chan_priv->timerfd) { + if (pfds[0].revents & POLLIN) { + uint64_t tmp = 0; /* clear pending events on timerfd */ + retval = read(pfds[0].fd, &tmp, sizeof(tmp)); + *flags |= FTDM_WRITE; + } + if (pfds[1].revents & POLLIN) + *flags |= FTDM_READ; + if (pfds[1].revents & POLLPRI) + *flags |= FTDM_EVENTS; + break; + } + default: + if (pfds[0].revents & POLLIN) + *flags |= FTDM_READ; + if (pfds[0].revents & POLLOUT) + *flags |= FTDM_WRITE; + if (pfds[0].revents & POLLPRI) + *flags |= FTDM_EVENTS; + break; + } + return FTDM_SUCCESS; +} + +/** + * \brief Read data + * \param ftdmchan FreeTDM channel + * \param data Buffer for data + * \param datalen Number of bytes to read (contains bytes read after return) + */ +static FIO_READ_FUNCTION(misdn_read) +{ + struct misdn_chan_private *priv = ftdm_chan_io_private(ftdmchan); + char rbuf[MAX_DATA_MEM] = { 0 }; + struct mISDNhead *hh = (struct mISDNhead *)rbuf; + int bytes = *datalen; + int retval; + + if (priv->state == MISDN_CHAN_STATE_CLOSED) { + /* ignore */ + *datalen = 0; + return FTDM_SUCCESS; + } + + /* + * try to read all messages, as long as we haven't received a PH_DATA_IND one + * we'll get a lot of "mISDN_send: error -12" message in dmesg otherwise + * (= b-channel receive queue overflowing) + */ + while (1) { + if ((retval = recvfrom(ftdmchan->sockfd, rbuf, sizeof(rbuf), 0, NULL, NULL)) < 0) { + if (errno == EWOULDBLOCK) break; + if (errno == EAGAIN) continue; + ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "mISDN failed to receive incoming message: %s\n", + strerror(errno)); + return FTDM_FAIL; + } + + if (retval < MISDN_HEADER_LEN) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "mISDN received message too small\n"); + return FTDM_FAIL; + } + + if (hh->prim == PH_DATA_IND) { + *datalen = MIN(bytes, retval - MISDN_HEADER_LEN); + memcpy(data, rbuf + MISDN_HEADER_LEN, *datalen); +#ifdef MISDN_DEBUG_IO + if (*datalen > 0) { + char hbuf[MAX_DATA_MEM] = { 0 }; + print_hex_bytes(data, *datalen, hbuf, sizeof(hbuf)); + ftdm_log(FTDM_LOG_DEBUG, "mISDN read data: %s\n", hbuf); + } +#endif + return FTDM_SUCCESS; + } else { + *datalen = 0; + /* event */ + misdn_handle_incoming(ftdmchan, rbuf, retval); + } + } + return FTDM_SUCCESS; +} + +/** + * \brief Write data + * \param ftdmchan FreeTDM channel + * \param data Buffer for data + * \param datalen Number of bytes to write (contains bytes written after return) + */ +static FIO_WRITE_FUNCTION(misdn_write) +{ + struct misdn_chan_private *priv = ftdm_chan_io_private(ftdmchan); + char wbuf[MAX_DATA_MEM]; + struct mISDNhead *hh = (struct mISDNhead *)wbuf; + int size = *datalen; + int retval = 0; + + assert(priv); + + /* ignore empty writes */ + if (*datalen <= 0) + return FTDM_SUCCESS; + +#ifdef MISDN_DEBUG_IO + { + char hbuf[MAX_DATA_MEM] = { 0 }; + print_hex_bytes(data, *datalen, hbuf, sizeof(hbuf)); + ftdm_log(FTDM_LOG_DEBUG, "mISDN write data: %s\n", hbuf); + } +#endif + hh->prim = PH_DATA_REQ; + hh->id = MISDN_ID_ANY; + + /* avoid buffer overflow */ + size = MIN(size, MAX_DATA_MEM); + + memcpy(wbuf + MISDN_HEADER_LEN, data, size); + size += MISDN_HEADER_LEN; + +#ifdef MISDN_DEBUG_IO + ftdm_log(FTDM_LOG_DEBUG, "mISDN writing %d bytes to channel %d:%d socket %d\n", + size, ftdm_channel_get_span_id(ftdmchan), ftdm_channel_get_id(ftdmchan), ftdmchan->sockfd); +#endif + if ((retval = sendto(ftdmchan->sockfd, wbuf, size, 0, NULL, 0)) != size) { + ftdm_log(FTDM_LOG_ERROR, "mISDN channel %d:%d socket write error: %s\n", + ftdm_channel_get_span_id(ftdmchan), ftdm_channel_get_id(ftdmchan), + strerror(errno)); + return FTDM_FAIL; + } + *datalen = retval; + +// if (priv->debugfd >= 0) { +// write(priv->debugfd, wbuf + MISDN_HEADER_LEN, size - MISDN_HEADER_LEN); +// } + + priv->tx_cnt++; + return FTDM_SUCCESS; +} + + +static ftdm_status_t misdn_open_range(ftdm_span_t *span, ftdm_chan_type_t type, struct mISDN_devinfo *devinfo, int start, int end) +{ + int num_configured = 0; + int d_protocol, d_channel; + int x; + + ftdm_log(FTDM_LOG_DEBUG, "mISDN configuring card:range %d:%d->%d\n", + devinfo->id, start, end); + + switch (ftdm_span_get_trunk_type(span)) { + case FTDM_TRUNK_E1: + d_protocol = ISDN_P_TE_E1; + d_channel = 16; + break; + case FTDM_TRUNK_BRI: + case FTDM_TRUNK_BRI_PTMP: + d_protocol = ISDN_P_TE_S0; + d_channel = 0; + break; + default: + ftdm_log(FTDM_LOG_ERROR, "Unsupported span type %s\n", + ftdm_span_get_trunk_type_str(span)); + return FTDM_FAIL; + } + + for (x = start; x <= end; x++) { + struct misdn_chan_private *priv; + struct sockaddr_mISDN addr; + ftdm_channel_t *ftdmchan = NULL; + ftdm_socket_t sockfd = -1; + + ftdm_log(FTDM_LOG_DEBUG, "mISDN configuring card:channel => %d:%d\n", + devinfo->id, x); + + memset(&addr, 0, sizeof(addr)); + addr.family = AF_ISDN; + addr.dev = devinfo->id; + + switch (type) { + case FTDM_CHAN_TYPE_DQ931: /* unsupported */ + ftdm_log(FTDM_LOG_ERROR, "Unsupported channel type '%s'\n", + ftdm_chan_type2str(type)); + return FTDM_FAIL; + + case FTDM_CHAN_TYPE_DQ921: + /* No NT-mode support, since we have no idea which mode we should run in at this point */ + sockfd = socket(PF_ISDN, SOCK_DGRAM, d_protocol); + addr.channel = d_channel; /* 0 for S0 and 16 for E1 */ + break; + + case FTDM_CHAN_TYPE_B: + if (!test_channelmap(x, devinfo->channelmap)) { + ftdm_log(FTDM_LOG_ERROR, "Invalid B-Channel specified: %d\n", x); + return FTDM_FAIL; + } + sockfd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW); + addr.channel = x; + break; + + default: + ftdm_log(FTDM_LOG_ERROR, "Invalid/unsupported channel type '%s' (%d)\n", + ftdm_chan_type2str(type), type); + return FTDM_FAIL; + } + + if (sockfd < 0) { + ftdm_log(FTDM_LOG_ERROR, "Failed to open socket: %s\n", strerror(errno)); + return FTDM_FAIL; + } + + ftdm_log(FTDM_LOG_DEBUG, "mISDN opened socket (on chan:dev => %d:%d): %d\n", + addr.dev, addr.channel, sockfd); + + /* set non-blocking */ + if (fcntl(sockfd, F_SETFL, O_NONBLOCK) < 0) { + ftdm_log(FTDM_LOG_ERROR, "mISDN Failed to set socket fd to non-blocking: %s\n", strerror(errno)); + return FTDM_FAIL; + } + + /* + * Bind socket to card:channel + */ + if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + ftdm_log(FTDM_LOG_ERROR, "Failed to bind mISDN socket [%d:%d]: %s\n", + addr.dev, x, strerror(errno)); + close(sockfd); + return FTDM_FAIL; + } + + /* + * Add channel to span + */ + if (ftdm_span_add_channel(span, sockfd, type, &ftdmchan) != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_ERROR, "Failed to add mISDN ftdmchan to span\n"); + close(sockfd); + return FTDM_FAIL; + } + + priv = calloc(1, sizeof(*priv)); + if (!priv) { + ftdm_log(FTDM_LOG_ERROR, "mISDN failed to allocate channel private data\n"); + close(sockfd); + return FTDM_FAIL; + } + ftdm_chan_io_private(ftdmchan) = priv; + + priv->addr = addr; + priv->debugfd = -1; + priv->timerfd = -1; + + /* + * Create event queue + */ + misdn_event_queue_create(&priv->events); + + ftdmchan->rate = 8000; + ftdmchan->physical_span_id = devinfo->id; + ftdmchan->physical_chan_id = x; + + if (ftdmchan->type == FTDM_CHAN_TYPE_B) { + ftdmchan->packet_len = 10 /* ms */ * (ftdmchan->rate / 1000); + ftdmchan->effective_interval = ftdmchan->native_interval = ftdmchan->packet_len / 8; + ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_ALAW; + + ftdm_channel_set_feature(ftdmchan, FTDM_CHANNEL_FEATURE_INTERVAL); + } else { + ftdmchan->native_codec = ftdmchan->effective_codec = FTDM_CODEC_NONE; + } + num_configured++; + } + + return num_configured; +} + +static int misdn_find_device(const char *name, int nr_devices, struct mISDN_devinfo *info) +{ + struct mISDN_devinfo devinfo; + char *endp = NULL; + int port_id = -1; + int i; + + port_id = strtoul(name, &endp, 10); + if (endp == name || errno == EINVAL) + port_id = -1; + if (port_id < 0 || port_id >= nr_devices) + port_id = -1; + + for (i = 0; i < nr_devices; i++) { + memset(&devinfo, 0, sizeof(devinfo)); + devinfo.id = i; + + if (ioctl(globals.sockfd, IMGETDEVINFO, &devinfo) < 0) { + ftdm_log(FTDM_LOG_ERROR, "mISDN unable to get device %d info: %s\n", + devinfo.id, strerror(errno)); + return FTDM_FAIL; + } + if (devinfo.id == port_id) + break; + if (strlen(devinfo.name) <= 0) + continue; + if (!strcasecmp(devinfo.name, name)) + break; + } + if (i == nr_devices) + return FTDM_FAIL; + + if (info) *info = devinfo; + return FTDM_SUCCESS; +} + +#define MISDN_PH_TE_PROTOCOLS(x) \ + ((x) & ((1 << ISDN_P_TE_S0) | (1 << ISDN_P_TE_E1) | (1 << ISDN_P_TE_UP0))) +#define MISDN_PH_NT_PROTOCOLS(x) \ + ((x) & ((1 << ISDN_P_NT_S0) | (1 << ISDN_P_NT_E1) | (1 << ISDN_P_NT_UP0))) + +/** + * \brief Configure/open span ftmod_misdn settings + */ +static FIO_CONFIGURE_SPAN_FUNCTION(misdn_configure_span) +{ + struct misdn_span_private *span_priv = ftdm_span_io_private(span); + struct mISDN_devinfo devinfo; + int range_start = 0, range_end = 0; + int nr_ports = 0, nr_items = 0; + int res = 0, i; + char *chan_str, *ptr; + char *data = strdup(str); + char *item_list[10]; + + /* only these are supported */ + switch (ftdm_span_get_trunk_type(span)) { + case FTDM_TRUNK_E1: + case FTDM_TRUNK_BRI: + case FTDM_TRUNK_BRI_PTMP: + break; + default: + ftdm_log(FTDM_LOG_ERROR, "Unsupported span type %s\n", + ftdm_span_get_trunk_type_str(span)); + return FTDM_FAIL; + } + + /* get port count */ + if (ioctl(globals.sockfd, IMGETCOUNT, &nr_ports) < 0) { + ftdm_log(FTDM_LOG_ERROR, "mISDN unable to get port count: %s\n", + strerror(errno)); + goto error; + } + if (nr_ports <= 0) { + ftdm_log(FTDM_LOG_ERROR, "No mISDN devices found\n"); + goto error; + } + + /* split configuration string into port ID and channel list */ + if (!(chan_str = strchr(data, ':'))) { + ftdm_log(FTDM_LOG_ERROR, "Invalid configuration string: %s\nExpected format :[-]\n", str); + goto error; + } + *chan_str++ = '\0'; + + /* lookup port id, by number first, then by name */ + if (misdn_find_device(data, nr_ports, &devinfo) != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_ERROR, "No such mISDN device/port: %s\n", + data); + goto error; + } + if (devinfo.nrbchan == 0 || devinfo.channelmap == 0) { + ftdm_log(FTDM_LOG_ERROR, "mISDN device '%s' has no b-channels\n", + data); + goto error; + } + if (!MISDN_PH_TE_PROTOCOLS(devinfo.Dprotocols)) { + ftdm_log(FTDM_LOG_ERROR, "mISDN device '%s' does not support any ISDN TE modes\n", + data); + goto error; + } + + /* allocate span private */ + if (!span_priv) { + /* + * Not perfect, there should be something like span_create too + */ + span_priv = calloc(1, sizeof(*span_priv)); + if (!span_priv) { + ftdm_log(FTDM_LOG_ERROR, "mISDN failed to allocate span private data\n"); + return FTDM_FAIL; + } + ftdm_span_io_private(span) = span_priv; + + /* init event condition */ + pthread_cond_init(&span_priv->event_cond, NULL); + pthread_mutex_init(&span_priv->event_cond_mutex, NULL); + } + + /* split channel list by ',' */ + nr_items = ftdm_separate_string(chan_str, ',', item_list, ftdm_array_len(item_list)); + + for (i = 0; i < nr_items; i++) { + /* */ + if (!(ptr = strchr(item_list[i], '-'))) { + /* single channel */ + range_start = atoi(item_list[i]); + range_end = range_start; + } else { + *ptr++ = '\0'; + /* channel range */ + range_start = atoi(item_list[i]); + range_end = atoi(ptr); + } + + /* check if channel range/id is valid */ + if (range_start <= 0 || range_end <= 0 || range_end < range_start) { + ftdm_log(FTDM_LOG_ERROR, "Invalid configuration string: %s\n", + item_list[i]); + goto error; + } + + /* add range to span */ + res = misdn_open_range(span, type, &devinfo, range_start, range_end); + if (res <= 0) { + ftdm_log(FTDM_LOG_ERROR, "mISDN failed to configure channel(s)\n"); + goto error; + } + } + + ftdm_safe_free(data); + return res; +error: + ftdm_span_io_private(span) = NULL; + ftdm_safe_free(span_priv); + ftdm_safe_free(data); + return res; +} + +/** + * \brief Configure global ftmod_misdn settings + */ +static FIO_CONFIGURE_FUNCTION(misdn_configure) +{ + return FTDM_SUCCESS; +} + +/** + * \brief Retrieve alarm event information (if any) + * \param ftdmchan FreeTDM channel + */ +static FIO_GET_ALARMS_FUNCTION(misdn_get_alarms) +{ +#if 0 +/* + Nope, this won't work... + + There's no way to create a separate "control" socket for a device + that can be used to send / receive MPH_INFORMATION_REQ/_IND without + having to care about PH_* messages in between... + + ... well, unless we use our own event loop (= thread) and + add event queues and data fifos, so we can sift all the + messages we get to forward them to the right receiver +*/ + ftdm_span_t *span = ftdm_channel_get_span(ftdmchan); + struct misdn_span_private *span_priv = ftdm_span_io_private(span); + char buf[MAX_DATA_MEM] = { 0 }; + struct sockaddr_mISDN addr; + struct mISDNhead *hh; + struct ph_info *phi = NULL; + struct pollfd pfd; + socklen_t addrlen = sizeof(addr); + int retval; + + /* use the global socket to query alarms */ + ftdm_log(FTDM_LOG_DEBUG, "mISDN getting alarms for channel %d:%d [%d:%d]\n", + ftdm_channel_get_span_id(ftdmchan), ftdm_channel_get_id(ftdmchan), + ftdm_channel_get_ph_span_id(ftdmchan), ftdm_channel_get_ph_id(ftdmchan)); + + memset(&addr, 0, sizeof(addr)); + addr.family = AF_ISDN; + addr.dev = ftdm_channel_get_ph_span_id(ftdmchan) - 1; + addr.channel = ftdm_channel_get_ph_id(ftdmchan) - 1; + + hh = (struct mISDNhead *)buf; + hh->prim = MPH_INFORMATION_REQ; + hh->id = MISDN_ID_ANY; + + /* */ + if ((retval = sendto(span_priv->ctrlsock, hh, sizeof(*hh), 0, (struct sockaddr *)&addr, addrlen)) <= 0) { + ftdm_log(FTDM_LOG_ERROR, "mISDN failed to send '%s' to channel %d:%d: %s\n", + misdn_event2str(hh->prim), ftdm_channel_get_span_id(ftdmchan), + ftdm_channel_get_id(ftdmchan), strerror(errno)); + return FTDM_FAIL; + } + + pfd.fd = span_priv->ctrlsock; + pfd.events = POLLIN /*| POLLPRI*/; + pfd.revents = 0; + + if ((retval = poll(&pfd, 1, -1)) <= 0) { + ftdm_log(FTDM_LOG_ERROR, "mISDN failed to poll for '%s' answer on channel %d:%d: %s\n", + misdn_event2str(hh->prim), ftdm_channel_get_span_id(ftdmchan), + ftdm_channel_get_id(ftdmchan), strerror(errno)); + return FTDM_FAIL; + } + + if (!(pfd.revents & (POLLIN | POLLPRI))) { + ftdm_log(FTDM_LOG_ERROR, "mISDN failed to poll for '%s' answer on channel %d:%d: %s\n", + misdn_event2str(hh->prim), ftdm_channel_get_span_id(ftdmchan), + ftdm_channel_get_id(ftdmchan), "No read/pri flag"); + return FTDM_FAIL; + } + + if ((retval = recvfrom(span_priv->ctrlsock, buf, sizeof(buf), 0, (struct sockaddr *)&addr, &addrlen)) < 0) { + ftdm_log(FTDM_LOG_ERROR, "mISDN failed to receive answer for '%s' on channel %d:%d: %s\n", + misdn_event2str(hh->prim), ftdm_channel_get_span_id(ftdmchan), + ftdm_channel_get_id(ftdmchan), strerror(errno)); + return FTDM_FAIL; + } + if (retval < MISDN_HEADER_LEN) { + ftdm_log(FTDM_LOG_ERROR, "mISDN short read on channel %d:%d\n", + ftdm_channel_get_span_id(ftdmchan), ftdm_channel_get_id(ftdmchan)); + return FTDM_FAIL; + } + + switch (hh->prim) { + case MPH_INFORMATION_IND: + ftdm_log(FTDM_LOG_DEBUG, "mISDN received '%s' on channel %d:%d, size %d bytes\n", + misdn_event2str(hh->prim), ftdm_channel_get_span_id(ftdmchan), + ftdm_channel_get_id(ftdmchan), retval); + break; + default: + ftdm_log(FTDM_LOG_ERROR, "mISDN received unexpected answer '%s' on channel %d:%d: %s\n", + misdn_event2str(hh->prim), ftdm_channel_get_span_id(ftdmchan), + ftdm_channel_get_id(ftdmchan), strerror(errno)); + return FTDM_FAIL; + } +#endif + return FTDM_SUCCESS; +} + + +/** + * \brief Poll for new events + * \param span FreeTDM span + * \param ms Timeout (in ms) + */ +static FIO_SPAN_POLL_EVENT_FUNCTION(misdn_poll_event) +{ + struct misdn_span_private *span_priv = ftdm_span_io_private(span); + struct timespec ts; + int retval = 0, nr_events = 0; + int i; + + clock_gettime(CLOCK_REALTIME, &ts); + ts_add_msec(&ts, ms); + + for (i = 1; i <= ftdm_span_get_chan_count(span); i++) { + ftdm_channel_t *chan = ftdm_span_get_channel(span, i); + struct misdn_chan_private *chan_priv = ftdm_chan_io_private(chan); + + if (misdn_event_queue_has_data(chan_priv->events)) { +#ifdef MISDN_DEBUG_EVENTS + ftdm_log(FTDM_LOG_DEBUG, "mISDN channel %d:%d has event(s)\n", + ftdm_channel_get_span_id(chan), ftdm_channel_get_id(chan)); +#endif + ftdm_set_flag(chan, FTDM_CHANNEL_IO_EVENT); + chan->last_event_time = ftdm_current_time_in_ms(); + nr_events++; + } + } + if (nr_events) + return FTDM_SUCCESS; + + if ((retval = pthread_cond_timedwait(&span_priv->event_cond, &span_priv->event_cond_mutex, &ts))) { + switch (retval) { + case ETIMEDOUT: +// ftdm_log(FTDM_LOG_DEBUG, "mISDN span %d: No events within %d ms\n", +// ftdm_span_get_id(span), ms); + return FTDM_TIMEOUT; + default: + ftdm_log(FTDM_LOG_DEBUG, "mISDN failed to poll for events on span %d: %s\n", + ftdm_span_get_id(span), strerror(retval)); + return FTDM_FAIL; + } + } + + for (i = 1; i <= ftdm_span_get_chan_count(span); i++) { + ftdm_channel_t *chan = ftdm_span_get_channel(span, i); + struct misdn_chan_private *chan_priv = ftdm_chan_io_private(chan); + + if (misdn_event_queue_has_data(chan_priv->events)) { + ftdm_set_flag(chan, FTDM_CHANNEL_IO_EVENT); + chan->last_event_time = ftdm_current_time_in_ms(); + nr_events++; + } + } + return (nr_events) ? FTDM_SUCCESS : FTDM_TIMEOUT; /* no events? => timeout */ +} + +/** + * \brief Retrieve event + * \param span FreeTDM span + * \param event FreeTDM event + */ +static FIO_SPAN_NEXT_EVENT_FUNCTION(misdn_next_event) +{ + int32_t event_id = FTDM_OOB_INVALID; + int i; + + ftdm_log(FTDM_LOG_DEBUG, "Reading next event from span %d\n", + ftdm_span_get_id(span)); + + for (i = 1; i <= ftdm_span_get_chan_count(span); i++) { + ftdm_channel_t *chan = ftdm_span_get_channel(span, i); + struct misdn_chan_private *chan_priv = ftdm_chan_io_private(chan); + struct misdn_event *evt = NULL; + + if (!(evt = misdn_event_queue_pop(chan_priv->events))) { +#ifdef MISDN_DEBUG_EVENTS + ftdm_log_chan_msg(chan, FTDM_LOG_DEBUG, "mISDN channel event queue has no events\n"); +#endif + ftdm_clear_io_flag(chan, FTDM_CHANNEL_IO_EVENT); + continue; + } + +#ifdef MISDN_DEBUG_EVENTS + ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Got event '%s' from channel event queue\n", + misdn_event2str(evt->id)); +#endif + switch (evt->id) { + case PH_DEACTIVATE_IND: + event_id = FTDM_OOB_ALARM_TRAP; + chan->alarm_flags |= FTDM_ALARM_RED; + break; + case PH_ACTIVATE_IND: + event_id = FTDM_OOB_ALARM_CLEAR; + chan->alarm_flags &= ~FTDM_ALARM_RED; + break; + default: + ftdm_log(FTDM_LOG_ERROR, "Unhandled event id %d (0x%x) %s\n", + evt->id, evt->id, misdn_event2str(evt->id)); + continue; + } + + chan->last_event_time = 0; + span->event_header.e_type = FTDM_EVENT_OOB; + span->event_header.enum_id = event_id; + span->event_header.channel = chan; + *event = &span->event_header; + return FTDM_SUCCESS; + } + return FTDM_FAIL; +} + +/** + * \brief Shutdown ftmod_misdn channel + * \param ftdmchan FreeTDM channel + */ +static FIO_CHANNEL_DESTROY_FUNCTION(misdn_channel_destroy) +{ + struct misdn_chan_private *chan_priv = ftdm_chan_io_private(ftdmchan); + assert(chan_priv); + + ftdm_log(FTDM_LOG_DEBUG, "Destroying channel %d:%d\n", + ftdm_channel_get_span_id(ftdmchan), + ftdm_channel_get_id(ftdmchan)); + + if (ftdmchan->sockfd >= 0) { + close(ftdmchan->sockfd); + ftdmchan->sockfd = -1; + } + + /* + * Destroy fifo + event queue + */ + if (chan_priv->events) + misdn_event_queue_destroy(&chan_priv->events); + + ftdm_chan_io_private(ftdmchan) = NULL; + ftdm_safe_free(chan_priv); + + ftdm_log(FTDM_LOG_DEBUG, "mISDN channel %d:%d destroyed\n", + ftdm_channel_get_span_id(ftdmchan), ftdm_channel_get_id(ftdmchan)); + return FTDM_SUCCESS; +} + +/** + * \brief Shutdown ftmod_misdn span + * \param span FreeTDM span + */ +static FIO_SPAN_DESTROY_FUNCTION(misdn_span_destroy) +{ + struct misdn_span_private *span_priv = ftdm_span_io_private(span); + + ftdm_span_io_private(span) = NULL; + ftdm_safe_free(span_priv); + + ftdm_log(FTDM_LOG_DEBUG, "mISDN span %d (%s) destroyed\n", + ftdm_span_get_id(span), ftdm_span_get_name(span)); + return FTDM_SUCCESS; +} + + +static ftdm_status_t misdn_handle_incoming(ftdm_channel_t *ftdmchan, const char *rbuf, const int size) +{ + struct mISDNhead *hh = (struct mISDNhead *)rbuf; + struct misdn_chan_private *priv = ftdm_chan_io_private(ftdmchan); + const char *data = rbuf + sizeof(*hh); + int data_len = size - sizeof(*hh); + + assert(priv); + +#ifdef MISDN_DEBUG_EVENTS + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "mISDN channel received '%s' message (additional data: %d bytes)\n", + misdn_event2str(hh->prim), data_len); +#endif + + switch (hh->prim) { + /* data events */ + case PH_DATA_CNF: /* TX ack */ + priv->tx_ack_cnt++; + break; + case PH_DATA_REQ: /* request echo? */ + break; + case PH_DATA_E_IND: /* TX/RX ERR(?) */ + break; + + /* control events */ + case PH_ACTIVATE_REQ: + case PH_DEACTIVATE_REQ: + /* + * Echoed(?) L2->L1 requests, ignore... + * (something broken in mISDN or the way we setup the channel?) + */ + break; + case PH_CONTROL_IND: + return misdn_handle_ph_control_ind(ftdmchan, hh, data, data_len); + case PH_CONTROL_REQ: + case PH_CONTROL_CNF: + break; + + case MPH_INFORMATION_IND: + return misdn_handle_mph_information_ind(ftdmchan, hh, data, data_len); + + case PH_ACTIVATE_IND: + case PH_DEACTIVATE_IND: + { + /* other events, enqueue and let misdn_event_next handle it */ + struct misdn_span_private *span_priv = ftdm_span_io_private(ftdmchan->span); + struct misdn_event evt = { 0 }; + evt.id = hh->prim; + + misdn_event_queue_push(priv->events, &evt); + + /* wake possible readers */ + pthread_cond_signal(&span_priv->event_cond); + } + break; + + default: /* error? */ + ftdm_log(FTDM_LOG_DEBUG, "mISDN channel %d:%d received unknown event %d\n", + ftdm_channel_get_span_id(ftdmchan), ftdm_channel_get_id(ftdmchan), hh->prim); + break; + } + return FTDM_SUCCESS; +} + + +/** + * \brief ftmod_misdn interface + */ +//static const ftdm_io_interface_t misdn_interface = { +static const ftdm_io_interface_t misdn_interface = { + .name = "misdn", + + .open = misdn_open, + .close = misdn_close, + .wait = misdn_wait, + .read = misdn_read, + .write = misdn_write, + + .poll_event = misdn_poll_event, + .next_event = misdn_next_event, + + .command = misdn_command, + .get_alarms = misdn_get_alarms, + .configure = misdn_configure, /* configure global parameters */ + .configure_span = misdn_configure_span, /* assign channels to span */ + .channel_destroy = misdn_channel_destroy, /* clean up channel */ + .span_destroy = misdn_span_destroy, /* clean up span */ +}; + + +/** + * \brief ftmod_misdn module init function + */ +static FIO_IO_LOAD_FUNCTION(misdn_load) +{ + struct mISDNversion ver; + struct mISDN_devinfo devinfo; + int devcnt, usecnt; + int i; + + /* */ + globals.sockfd = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE); + if (globals.sockfd < 0) { + ftdm_log(FTDM_LOG_CRIT, "Unable to create mISDN base socket (are you sure this kernel has mISDN support?)\n"); + return FTDM_FAIL; + } + + if (ioctl(globals.sockfd, IMGETVERSION, &ver) < 0) { + ftdm_log(FTDM_LOG_CRIT, "Unable to retrieve mISDN version\n"); + goto error; + } + + ftdm_log(FTDM_LOG_INFO, "mISDN Interface version %hhd.%hhd.%hd\n", ver.major, ver.minor, ver.release); + + devcnt = 0; + if (ioctl(globals.sockfd, IMGETCOUNT, &devcnt) < 0) { + ftdm_log(FTDM_LOG_CRIT, "Unable to retrieve number of mISDN devices\n"); + goto error; + + } + + if (!devcnt) { + ftdm_log(FTDM_LOG_CRIT, "No mISDN devices found\n"); + goto error; + } + usecnt = devcnt; + + ftdm_log(FTDM_LOG_INFO, "Found %d mISDN devices:\n", devcnt); + + /* Output most important device information */ + for (i = 0; i < devcnt; i++) { + int caps = MISDN_CAPS_NONE; + + devinfo.id = i; + if (ioctl(globals.sockfd, IMGETDEVINFO, &devinfo) < 0) { + ftdm_log(FTDM_LOG_ERROR, "Failed to retrieve information for device %d\n", i); + continue; + } + + /* print */ + ftdm_log(FTDM_LOG_INFO, "<%d> Name: %s, B-Channels: %d\n", + devinfo.id, + ftdm_strlen_zero_buf(devinfo.name) ? "Unknown" : devinfo.name, + devinfo.nrbchan); + + /* D-Channels capabilities */ + if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1)) + caps |= MISDN_CAPS_TE | MISDN_CAPS_PRI; + if (devinfo.Dprotocols & (1 << ISDN_P_NT_E1)) + caps |= MISDN_CAPS_NT | MISDN_CAPS_PRI; + if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0)) + caps |= MISDN_CAPS_TE | MISDN_CAPS_BRI; + if (devinfo.Dprotocols & (1 << ISDN_P_NT_S0)) + caps |= MISDN_CAPS_NT | MISDN_CAPS_BRI; +#ifdef ISDN_P_TE_UP0 + if (devinfo.Dprotocols & (1 << ISDN_P_TE_UP0)) + caps |= MISDN_CAPS_TE | MISDN_CAPS_UP0 | MISDN_CAPS_BRI; +#endif +#ifdef ISDN_P_NT_UP0 + if (devinfo.Dprotocols & (1 << ISDN_P_NT_UP0)) + caps |= MISDN_CAPS_NT | MISDN_CAPS_UP0 | MISDN_CAPS_BRI; +#endif + /* B-Channel capabilities */ + if (devinfo.Bprotocols & (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK))) + caps |= MISDN_CAPS_RAW; + if (devinfo.Bprotocols & (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK))) + caps |= MISDN_CAPS_HDLC; + + ftdm_log(FTDM_LOG_INFO, " Type: %s, Modes: %s %s\n", + MISDN_IS_PRI(caps) ? "PRI" : "BRI", + MISDN_IS_NT(caps) ? "NT" : "", + MISDN_IS_TE(caps) ? "TE" : ""); + + ftdm_log(FTDM_LOG_INFO, " B-Channel modes: %s %s\n", + MISDN_IS_RAW(caps) ? "RAW" : "", + MISDN_IS_HDLC(caps) ? "HDLC" : ""); + + if (!(MISDN_IS_NT(caps) || MISDN_IS_TE(caps)) && !MISDN_IS_RAW(caps)) { + ftdm_log(FTDM_LOG_ERROR, " This device is unusable!\n"); + usecnt--; + } + } + if (!usecnt) { + ftdm_log(FTDM_LOG_CRIT, "No useable devices found!\n"); + goto error; + } + + ftdm_log(FTDM_LOG_INFO, "Found %d useable mISDN devices\n", usecnt); + + /* assign interface struct */ + *fio = (ftdm_io_interface_t *)&misdn_interface; + return FTDM_SUCCESS; +error: + if (globals.sockfd >= 0) + close(globals.sockfd); + return FTDM_FAIL; +} + +/** + * \brief ftmod_misdn module shutdown + */ +static FIO_IO_UNLOAD_FUNCTION(misdn_unload) +{ + if (globals.sockfd >= 0) + close(globals.sockfd); + return FTDM_SUCCESS; +} + +/** + * \brief ftmod_misdn module + */ +ftdm_module_t ftdm_module = { + .name = "misdn", + .io_load = misdn_load, + .io_unload = misdn_unload +}; From f2099bf999fae87962fcd8f4902e7729ebc6e54f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 8 Sep 2011 08:12:07 -0500 Subject: [PATCH 045/204] FS-3529 please try this revision I suspect its related to some uninitilized memory causing flags to be set that are not in the dtmf structure in certian cases --- src/mod/applications/mod_fax/mod_fax.c | 2 +- src/mod/applications/mod_spandsp/mod_spandsp_dsp.c | 2 +- src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp | 2 +- src/mod/endpoints/mod_skypopen/mod_skypopen.c | 2 +- src/switch_ivr.c | 2 +- src/switch_ivr_async.c | 6 +++--- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/mod/applications/mod_fax/mod_fax.c b/src/mod/applications/mod_fax/mod_fax.c index a899d270fc..340a497a23 100644 --- a/src/mod/applications/mod_fax/mod_fax.c +++ b/src/mod/applications/mod_fax/mod_fax.c @@ -1329,7 +1329,7 @@ static switch_bool_t inband_dtmf_callback(switch_media_bug_t *bug, void *user_da if (digit_str[0]) { char *p = digit_str; while (p && *p) { - switch_dtmf_t dtmf; + switch_dtmf_t dtmf = {0}; dtmf.digit = *p; dtmf.duration = switch_core_default_dtmf_duration(0); switch_channel_queue_dtmf(channel, &dtmf); diff --git a/src/mod/applications/mod_spandsp/mod_spandsp_dsp.c b/src/mod/applications/mod_spandsp/mod_spandsp_dsp.c index 8a31a9272d..bed6c1021b 100644 --- a/src/mod/applications/mod_spandsp/mod_spandsp_dsp.c +++ b/src/mod/applications/mod_spandsp/mod_spandsp_dsp.c @@ -52,7 +52,7 @@ static void spandsp_dtmf_rx_realtime_callback(void *user_data, int code, int lev if (digit) { /* prevent duplicate DTMF */ if (digit != pvt->last_digit || (pvt->samples - pvt->last_digit_end) > pvt->min_dup_digit_spacing) { - switch_dtmf_t dtmf; + switch_dtmf_t dtmf = {0}; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(pvt->session), SWITCH_LOG_DEBUG, "DTMF BEGIN DETECTED: [%c]\n", digit); pvt->last_digit = digit; dtmf.digit = digit; diff --git a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp index fe1f7cb8c0..4033577f7c 100644 --- a/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp +++ b/src/mod/endpoints/mod_gsmopen/mod_gsmopen.cpp @@ -928,7 +928,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch switch_channel_t *channel = switch_core_session_get_channel(session); while (p && *p) { - switch_dtmf_t dtmf; + switch_dtmf_t dtmf = {0}; dtmf.digit = *p; dtmf.duration = SWITCH_DEFAULT_DTMF_DURATION; switch_channel_queue_dtmf(channel, &dtmf); diff --git a/src/mod/endpoints/mod_skypopen/mod_skypopen.c b/src/mod/endpoints/mod_skypopen/mod_skypopen.c index 4f095ff886..a5d90d0c50 100644 --- a/src/mod/endpoints/mod_skypopen/mod_skypopen.c +++ b/src/mod/endpoints/mod_skypopen/mod_skypopen.c @@ -943,7 +943,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch if(channel){ while (p && *p) { - switch_dtmf_t dtmf; + switch_dtmf_t dtmf = {0}; dtmf.digit = *p; dtmf.duration = SWITCH_DEFAULT_DTMF_DURATION; switch_channel_queue_dtmf(channel, &dtmf); diff --git a/src/switch_ivr.c b/src/switch_ivr.c index 56397ede5c..b7f4a38b71 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -241,7 +241,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_sleep(switch_core_session_t *session, if (args) { - switch_dtmf_t dtmf; + switch_dtmf_t dtmf = {0}; /* dtmf handler function you can hook up to be executed when a digit is dialed during playback diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index c99d332c7f..b5d0591ec5 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -566,7 +566,7 @@ SWITCH_DECLARE(void) switch_ivr_session_echo(switch_core_session_t *session, swi switch_ivr_parse_all_events(session); if (args && (args->input_callback || args->buf || args->buflen)) { - switch_dtmf_t dtmf; + switch_dtmf_t dtmf = {0}; /* dtmf handler function you can hook up to be executed when a digit is dialed during playback @@ -2154,7 +2154,7 @@ static switch_bool_t inband_dtmf_callback(switch_media_bug_t *bug, void *user_da if (digit_str[0]) { char *p = digit_str; while (p && *p) { - switch_dtmf_t dtmf; + switch_dtmf_t dtmf = {0}; dtmf.digit = *p; dtmf.duration = switch_core_default_dtmf_duration(0); dtmf.source = SWITCH_DTMF_INBAND_AUDIO; @@ -3188,7 +3188,7 @@ static void *SWITCH_THREAD_FUNC speech_thread(switch_thread_t *thread, void *obj } if (is_dtmf(c)) { - switch_dtmf_t dtmf; + switch_dtmf_t dtmf = {0}; dtmf.digit = c; dtmf.duration = switch_core_default_dtmf_duration(0); dtmf.source = SWITCH_DTMF_INBAND_AUDIO; From aea22cd4b745140de947eeac46e79edc67d6ff6c Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 8 Sep 2011 08:57:28 -0500 Subject: [PATCH 046/204] add RTP_BUG_ACCEPT_ANY_PACKETS to disable dropping invalid packets for interop with Oracle CCA --- src/include/switch_types.h | 10 ++++++++++ src/mod/endpoints/mod_sofia/sofia_glue.c | 8 ++++++++ src/switch_rtp.c | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 312e0bd342..eb4de9ade7 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -680,6 +680,16 @@ typedef enum { This flag will treat every dtmf as if it were 50ms and queue it on recipt of the leading packet rather than at the end. */ + + RTP_BUG_ACCEPT_ANY_PACKETS = (1 << 7) + + /* + Oracle's Contact Center Anywhere (CCA) likes to use a single RTP socket to send all its outbound audio. + This messes up our ability to auto adjust to NATTED RTP and causes us to ignore its audio packets. + This flag will allow compatibility with this dying product. + */ + + } switch_rtp_bug_flag_t; #ifdef _MSC_VER diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index adc0c5347f..77c1842832 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -6553,6 +6553,14 @@ void sofia_glue_parse_rtp_bugs(switch_rtp_bug_flag_t *flag_pole, const char *str if (switch_stristr("~IGNORE_DTMF_DURATION", str)) { *flag_pole &= ~RTP_BUG_IGNORE_DTMF_DURATION; } + + if (switch_stristr("ACCEPT_ANY_PACKETS", str)) { + *flag_pole |= RTP_BUG_ACCEPT_ANY_PACKETS; + } + + if (switch_stristr("~ACCEPT_ANY_PACKETS", str)) { + *flag_pole &= ~RTP_BUG_ACCEPT_ANY_PACKETS; + } } char *sofia_glue_gen_contact_str(sofia_profile_t *profile, sip_t const *sip, sofia_dispatch_event_t *de, sofia_nat_parse_t *np) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 6d51bf2963..02c440ca6f 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -3135,7 +3135,7 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ goto recvfrom; } - } else if (!switch_cmp_addr(rtp_session->from_addr, rtp_session->remote_addr)) { + } else if (!(rtp_session->rtp_bugs & RTP_BUG_ACCEPT_ANY_PACKETS) && !switch_cmp_addr(rtp_session->from_addr, rtp_session->remote_addr)) { goto recvfrom; } From 83a78fbfa0996527de72bbad229eb13f51a012e2 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 8 Sep 2011 09:48:21 -0500 Subject: [PATCH 047/204] FS-3545 --resolve no, that was not the intention, I missed a few more spots to hack in the exception for iLBC, (thanks for marring my code iLBC ppl) it should work as expected now even with the m_per_ptime on --- src/mod/endpoints/mod_sofia/sofia_glue.c | 28 ++++++++++++++++-------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 77c1842832..1116d21235 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -201,7 +201,12 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen, for (i = 0; i < tech_pvt->num_codecs; i++) { const switch_codec_implementation_t *imp = tech_pvt->codecs[i]; - + int this_ptime = (imp->microseconds_per_packet / 1000); + + if (!strcasecmp(imp->iananame, "ilbc")) { + this_ptime = 20; + } + if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) { continue; } @@ -210,12 +215,12 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen, if (!cur_ptime) { #if 0 if (ptime) { - if (ptime != imp->microseconds_per_packet / 1000) { + if (ptime != this_ptime) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Codec %s payload %d added to sdp wanting ptime %d but it's already %d (%s:%d:%d), disabling ptime.\n", imp->iananame, tech_pvt->ianacodes[i], - imp->microseconds_per_packet / 1000, + this_ptime, ptime, tech_pvt->codecs[0]->iananame, tech_pvt->codecs[0]->ianacode, @@ -224,15 +229,15 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen, noptime = 1; } } else { - ptime = imp->microseconds_per_packet / 1000; + ptime = this_ptime; } #else if (!ptime) { - ptime = imp->microseconds_per_packet / 1000; + ptime = this_ptime; } #endif } else { - if ((imp->microseconds_per_packet / 1000) != cur_ptime) { + if (this_ptime != cur_ptime) { continue; } } @@ -266,18 +271,23 @@ static void generate_m(private_object_t *tech_pvt, char *buf, size_t buflen, for (i = 0; i < tech_pvt->num_codecs; i++) { const switch_codec_implementation_t *imp = tech_pvt->codecs[i]; char *fmtp = imp->fmtp; - + int this_ptime = imp->microseconds_per_packet / 1000; + if (imp->codec_type != SWITCH_CODEC_TYPE_AUDIO) { continue; } + if (!strcasecmp(imp->iananame, "ilbc")) { + this_ptime = 20; + } + if (!noptime) { if (!cur_ptime) { if (!ptime) { - ptime = imp->microseconds_per_packet / 1000; + ptime = this_ptime; } } else { - if ((imp->microseconds_per_packet / 1000) != cur_ptime) { + if (this_ptime != cur_ptime) { continue; } } From fb69d37592770a6d1d2f918d602826b4df8f77bd Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 8 Sep 2011 12:50:34 -0400 Subject: [PATCH 048/204] freetdm: fix small bug reported in freeswitch-dev where the call_id member of sigmsg is not being set for SIGEVENT_START event --- libs/freetdm/src/ftdm_io.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index e190becd35..95626299bb 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -5465,10 +5465,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t if (sigmsg->channel) { fchan = sigmsg->channel; ftdm_channel_lock(fchan); - sigmsg->chan_id = fchan->chan_id; - sigmsg->span_id = fchan->span_id; - sigmsg->call_id = fchan->caller_data.call_id; - sigmsg->call_priv = fchan->caller_data.priv; } /* some core things to do on special events */ @@ -5558,6 +5554,14 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t } + if (fchan) { + /* set members of the sigmsg that must be present for all events */ + sigmsg->chan_id = fchan->chan_id; + sigmsg->span_id = fchan->span_id; + sigmsg->call_id = fchan->caller_data.call_id; + sigmsg->call_priv = fchan->caller_data.priv; + } + /* if the signaling module uses a queue for signaling notifications, then enqueue it */ if (ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE)) { ftdm_span_queue_signal(span, sigmsg); From 7d399cce96bd01a35e351b81b20f9792d5ee9ff0 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 8 Sep 2011 10:01:52 -0500 Subject: [PATCH 049/204] don't turn X-FS- headers into variables, they are reserved for FS specific communication and should not be passed on --- src/mod/endpoints/mod_sofia/sofia_glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 1116d21235..f57c2ab350 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -1924,7 +1924,7 @@ void sofia_glue_set_extra_headers(switch_channel_t *channel, sip_t const *sip, c } for (un = sip->sip_unknown; un; un = un->un_next) { - if (!strncasecmp(un->un_name, "X-", 2) || !strncasecmp(un->un_name, "P-", 2)) { + if ((!strncasecmp(un->un_name, "X-", 2) && strncasecmp(un->un_name, "X-FS-", 5)) || !strncasecmp(un->un_name, "P-", 2)) { if (!zstr(un->un_value)) { switch_snprintf(name, sizeof(name), "%s%s", prefix, un->un_name); switch_channel_set_variable(channel, name, un->un_value); From 361b6239371917a2f952d223fb81ab6d08665d99 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 8 Sep 2011 10:22:46 -0500 Subject: [PATCH 050/204] This patch will probably make it work but the bug is actually in the phone, the patch is simply tolerating the bad behaviour. You are correct about the a=sendonly missing, this was fixed in a later revision of the polycom firmware. I suggest that even if this patch works, that you update your phones to a newer firmware, preferably the most recent. --- src/mod/endpoints/mod_sofia/sofia_glue.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index f57c2ab350..0c44cf3439 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -4345,7 +4345,9 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s } } - if ((m = sdp->sdp_media) && (m->m_mode == sdp_sendonly || m->m_mode == sdp_inactive)) { + if ((m = sdp->sdp_media) && + (m->m_mode == sdp_sendonly || m->m_mode == sdp_inactive || + (m->m_connections && m->m_connections->c_address && !strcmp(m->m_connections->c_address, "0.0.0.0")))) { sendonly = 2; /* global sendonly always wins */ } From 74d5a593af7b4d54adbf4defd02b8e4b373ae263 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 8 Sep 2011 10:23:40 -0500 Subject: [PATCH 051/204] revert forgot jira info --- src/mod/endpoints/mod_sofia/sofia_glue.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 0c44cf3439..f57c2ab350 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -4345,9 +4345,7 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s } } - if ((m = sdp->sdp_media) && - (m->m_mode == sdp_sendonly || m->m_mode == sdp_inactive || - (m->m_connections && m->m_connections->c_address && !strcmp(m->m_connections->c_address, "0.0.0.0")))) { + if ((m = sdp->sdp_media) && (m->m_mode == sdp_sendonly || m->m_mode == sdp_inactive)) { sendonly = 2; /* global sendonly always wins */ } From 7acddfac95a97e737c95fa7c68e0249f163f9975 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 8 Sep 2011 10:24:05 -0500 Subject: [PATCH 052/204] FS-3549 --resolve This patch will probably make it work but the bug is actually in the phone, the patch is simply tolerating the bad behaviour. You are correct about the a=sendonly missing, this was fixed in a later revision of the polycom firmware. I suggest that even if this patch works, that you update your phones to a newer firmware, preferably the most recent. --- src/mod/endpoints/mod_sofia/sofia_glue.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index f57c2ab350..0c44cf3439 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -4345,7 +4345,9 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s } } - if ((m = sdp->sdp_media) && (m->m_mode == sdp_sendonly || m->m_mode == sdp_inactive)) { + if ((m = sdp->sdp_media) && + (m->m_mode == sdp_sendonly || m->m_mode == sdp_inactive || + (m->m_connections && m->m_connections->c_address && !strcmp(m->m_connections->c_address, "0.0.0.0")))) { sendonly = 2; /* global sendonly always wins */ } From 26039c57c27e0085aadd18a8f6b8a3f1c2cbf3a9 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 8 Sep 2011 10:44:44 -0500 Subject: [PATCH 053/204] FS-3548 --resolve --- src/mod/applications/mod_fifo/mod_fifo.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 007ee221a3..9e263056c9 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -1264,8 +1264,9 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void if (timeout < h->timeout) timeout = h->timeout; if (use_ent) { - stream.write_function(&stream, "{ignore_early_media=true,outbound_redirect_fatal=true,leg_timeout=%d,fifo_outbound_uuid=%s,fifo_name=%s}%s:_:", - h->timeout, h->uuid, node->name, parsed ? parsed : h->originate_string); + stream.write_function(&stream, "{ignore_early_media=true,outbound_redirect_fatal=true,leg_timeout=%d,fifo_outbound_uuid=%s,fifo_name=%s}%s%s", + h->timeout, h->uuid, node->name, + parsed ? parsed : h->originate_string, (i == cbh->rowcount - 1) ? "" : SWITCH_ENT_ORIGINATE_DELIM); } else { stream.write_function(&stream, "[leg_timeout=%d,fifo_outbound_uuid=%s,fifo_name=%s]%s,", h->timeout, h->uuid, node->name, parsed ? parsed : h->originate_string); @@ -1278,10 +1279,6 @@ static void *SWITCH_THREAD_FUNC ringall_thread_run(switch_thread_t *thread, void originate_string = (char *) stream.data; - if (originate_string) { - end_of(originate_string) = '\0'; - } - uuid_list = (char *) stream2.data; if (uuid_list) { From 1b9b3456ad01e93bcefe8f5f67a19307c3bad808 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Thu, 8 Sep 2011 17:57:07 -0400 Subject: [PATCH 054/204] add auth username to unreg event --- src/mod/endpoints/mod_sofia/sofia_reg.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index 1c9715d5a1..c591e9393d 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1708,10 +1708,16 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand } } } else { + const char *username = "unknown"; + if (auth_params) { + username = switch_event_get_header(auth_params, "sip_auth_username"); + } + switch_core_del_registration(to_user, reg_host, call_id); if (switch_event_create_subclass(&s_event, SWITCH_EVENT_CUSTOM, MY_EVENT_UNREGISTER) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "profile-name", profile->name); + switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "username", username); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-user", to_user); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "from-host", reg_host); switch_event_add_header_string(s_event, SWITCH_STACK_BOTTOM, "contact", contact_str); From 2e6ce02462863bca2b6b48306e8ac12311ddab5a Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 8 Sep 2011 16:44:57 -0500 Subject: [PATCH 055/204] fix unlikely failure condition --- src/switch_utils.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/switch_utils.c b/src/switch_utils.c index 158c5d540f..7d6fc21f55 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -654,8 +654,10 @@ SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, } if (write(fd, &out, bytes) != bytes) { rval = -1; - } else + break; + } else { bytes = 0; + } } From 7d612da4405276f26e1bf86c867219a96d7b3c43 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 8 Sep 2011 16:46:10 -0500 Subject: [PATCH 056/204] yield when doing b64 encode to avoid stealing the cpu on single proc crappy hardware --- src/switch_utils.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/switch_utils.c b/src/switch_utils.c index 7d6fc21f55..3b9ad79c2f 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -465,6 +465,10 @@ SWITCH_DECLARE(switch_status_t) switch_b64_encode(unsigned char *in, switch_size for (x = 0; x < ilen; x++) { b = (b << 8) + in[x]; l += 8; + + if ((X % 1024) == 0) { + switch_cond_next(); /* give other processes/threads a chance */ + } while (l >= 6) { out[bytes++] = switch_b64_table[(b >> (l -= 6)) % 64]; if (++y != 72) { @@ -641,6 +645,7 @@ SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, } while ((ilen = read(ifd, in, B64BUFFLEN))) { + switch_cond_next(); /* give other processes/threads a chance */ for (x = 0; x < ilen; x++) { b = (b << 8) + in[x]; l += 8; From 329e29f69d8f71ef4d5f98724bc6dcb8d72899aa Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 8 Sep 2011 16:55:40 -0500 Subject: [PATCH 057/204] doh --- src/switch_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_utils.c b/src/switch_utils.c index 3b9ad79c2f..ea6a0a2dfa 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -466,7 +466,7 @@ SWITCH_DECLARE(switch_status_t) switch_b64_encode(unsigned char *in, switch_size b = (b << 8) + in[x]; l += 8; - if ((X % 1024) == 0) { + if ((x % 1024) == 0) { switch_cond_next(); /* give other processes/threads a chance */ } while (l >= 6) { From 5154b8819d3dd3602c22a7d37ab21bc148c04d0e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 8 Sep 2011 17:13:28 -0500 Subject: [PATCH 058/204] fix wrong media ip in recover data issue --- src/mod/endpoints/mod_sofia/sofia_glue.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 0c44cf3439..76c5e8a421 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -1072,7 +1072,7 @@ switch_status_t sofia_glue_tech_choose_port(private_object_t *tech_pvt, int forc tech_pvt->adv_sdp_audio_port = sdp_port; tech_pvt->adv_sdp_audio_ip = tech_pvt->extrtpip = switch_core_session_strdup(tech_pvt->session, use_ip); - switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE, tech_pvt->adv_sdp_audio_ip); + switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE, tech_pvt->local_sdp_audio_ip); switch_channel_set_variable_printf(tech_pvt->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE, "%d", sdp_port); return SWITCH_STATUS_SUCCESS; @@ -5495,8 +5495,8 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName tech_pvt->adv_sdp_audio_ip = tech_pvt->extrtpip = (char *) ip; tech_pvt->adv_sdp_audio_port = tech_pvt->local_sdp_audio_port = (switch_port_t)atoi(port); - if ((tmp = switch_channel_get_variable(channel, "local_media_ip"))) { - tech_pvt->local_sdp_audio_ip = switch_core_session_strdup(session, tmp); + if (!zstr(ip)) { + tech_pvt->local_sdp_audio_ip = switch_core_session_strdup(session, ip); tech_pvt->rtpip = tech_pvt->local_sdp_audio_ip; } From 0f9b2cebfb3495f3f288c81ad1b2a6fa9db0c22f Mon Sep 17 00:00:00 2001 From: Brian West Date: Fri, 9 Sep 2011 00:34:41 -0500 Subject: [PATCH 059/204] swigall --- src/mod/languages/mod_managed/managed/swig.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index e782107007..e838e77c7f 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -29319,7 +29319,8 @@ public enum switch_rtp_bug_flag_t { RTP_BUG_SEND_LINEAR_TIMESTAMPS = (1 << 3), RTP_BUG_START_SEQ_AT_ZERO = (1 << 4), RTP_BUG_NEVER_SEND_MARKER = (1 << 5), - RTP_BUG_IGNORE_DTMF_DURATION = (1 << 6) + RTP_BUG_IGNORE_DTMF_DURATION = (1 << 6), + RTP_BUG_ACCEPT_ANY_PACKETS = (1 << 7) } } From 06eb4b6ab3e2f0e30726bab883a5da26b6d89422 Mon Sep 17 00:00:00 2001 From: Brian West Date: Fri, 9 Sep 2011 02:47:56 -0500 Subject: [PATCH 060/204] Fix recovery when nat is involved --- src/include/switch_types.h | 1 + src/mod/endpoints/mod_sofia/sofia_glue.c | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index eb4de9ade7..5a8d49ab41 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -182,6 +182,7 @@ SWITCH_BEGIN_EXTERN_C #define SWITCH_ORIGINATOR_VIDEO_CODEC_VARIABLE "originator_video_codec" #define SWITCH_LOCAL_MEDIA_IP_VARIABLE "local_media_ip" #define SWITCH_LOCAL_MEDIA_PORT_VARIABLE "local_media_port" +#define SWITCH_ADVERTISED_MEDIA_IP_VARIABLE "advertised_media_ip" #define SWITCH_REMOTE_MEDIA_IP_VARIABLE "remote_media_ip" #define SWITCH_REMOTE_MEDIA_PORT_VARIABLE "remote_media_port" #define SWITCH_REMOTE_VIDEO_IP_VARIABLE "remote_video_ip" diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 76c5e8a421..0e4b5ab870 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -1074,6 +1074,7 @@ switch_status_t sofia_glue_tech_choose_port(private_object_t *tech_pvt, int forc switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE, tech_pvt->local_sdp_audio_ip); switch_channel_set_variable_printf(tech_pvt->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE, "%d", sdp_port); + switch_channel_set_variable(tech_pvt->channel, SWITCH_ADVERTISED_MEDIA_IP_VARIABLE, tech_pvt->adv_sdp_audio_ip); return SWITCH_STATUS_SUCCESS; } @@ -3128,8 +3129,9 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f } switch_snprintf(tmp, sizeof(tmp), "%d", tech_pvt->local_sdp_audio_port); - switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE, tech_pvt->adv_sdp_audio_ip); + switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE, tech_pvt->local_sdp_audio_ip); switch_channel_set_variable(tech_pvt->channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE, tmp); + switch_channel_set_variable(tech_pvt->channel, SWITCH_ADVERTISED_MEDIA_IP_VARIABLE, tech_pvt->adv_sdp_audio_ip); if (tech_pvt->rtp_session && sofia_test_flag(tech_pvt, TFLAG_REINVITE)) { const char *rport = NULL; @@ -5456,6 +5458,7 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName if (session) { switch_caller_extension_t *extension = NULL; const char *ip = switch_channel_get_variable(channel, SWITCH_LOCAL_MEDIA_IP_VARIABLE); + const char *a_ip = switch_channel_get_variable(channel, SWITCH_ADVERTISED_MEDIA_IP_VARIABLE); const char *port = switch_channel_get_variable(channel, SWITCH_LOCAL_MEDIA_PORT_VARIABLE); const char *r_ip = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_IP_VARIABLE); const char *r_port = switch_channel_get_variable(channel, SWITCH_REMOTE_MEDIA_PORT_VARIABLE); @@ -5500,6 +5503,10 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName tech_pvt->rtpip = tech_pvt->local_sdp_audio_ip; } + if (!zstr(a_ip)) { + tech_pvt->adv_sdp_audio_ip = switch_core_session_strdup(session, a_ip); + } + if (r_ip && r_port) { tech_pvt->remote_sdp_audio_ip = (char *) r_ip; tech_pvt->remote_sdp_audio_port = (switch_port_t)atoi(r_port); From 10d2e808197b730dc73171724507a9bca53eb775 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 8 Sep 2011 22:35:20 -0500 Subject: [PATCH 061/204] FS-3454 --resolve --- src/mod/applications/mod_dptools/mod_dptools.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 40a68ec471..0e89b9049b 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -1375,6 +1375,7 @@ SWITCH_STANDARD_APP(event_function) switch_assert(new); memcpy(new, val, len); event->subclass_name = new; + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, var, val); } else { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, var, val); } From d62679df18315652fb33848ccee9549992379d90 Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Fri, 9 Sep 2011 10:02:52 -0700 Subject: [PATCH 062/204] Add phrase macros for ' has joined/left the conference' --- conf/lang/en/ivr/sounds.xml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/conf/lang/en/ivr/sounds.xml b/conf/lang/en/ivr/sounds.xml index e436e294a3..b5ccead13a 100644 --- a/conf/lang/en/ivr/sounds.xml +++ b/conf/lang/en/ivr/sounds.xml @@ -9,6 +9,26 @@ + + + + + + + + + + + + + + + + + + + + From be4d36e3c6cec6ea6e21b1b7527a440b7190b5c9 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 9 Sep 2011 11:34:34 -0500 Subject: [PATCH 063/204] OMFG one annoying bang --- src/switch_rtp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 02c440ca6f..f893e17a45 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -2255,7 +2255,7 @@ static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session) switch_frame_flag_t flags = 0; uint32_t samples = rtp_session->samples_per_interval; - if (!rtp_session->sending_dtmf > 1) { + if (rtp_session->sending_dtmf > 1) { rtp_session->sending_dtmf--; return; } From 0c066f063c11c7a4ee908afa58d03b8920e7a59f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 9 Sep 2011 12:02:15 -0500 Subject: [PATCH 064/204] DTMF stands for Devil Took My Fone --- src/switch_rtp.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index f893e17a45..1fbe5aeebe 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -33,6 +33,9 @@ //#define DEBUG_2833 //#define RTP_DEBUG_WRITE_DELTA //#define DEBUG_MISSED_SEQ + +#define RTP_TS_RESET 1 + #include #include #undef PACKAGE_NAME @@ -2316,7 +2319,7 @@ static void do_2833(switch_rtp_t *rtp_session, switch_core_session_t *session) rtp_session->dtmf_data.out_digit_dur = 0; set_dtmf_delay(rtp_session, 40, 500); - + return; } } @@ -2405,7 +2408,7 @@ SWITCH_DECLARE(void) rtp_flush_read_buffer(switch_rtp_t *rtp_session, switch_rtp { if (switch_rtp_ready(rtp_session)) { - rtp_session->last_write_ts = 0; + rtp_session->last_write_ts = RTP_TS_RESET; if (!switch_test_flag(rtp_session, SWITCH_RTP_FLAG_PROXY_MEDIA) && !switch_test_flag(rtp_session, SWITCH_RTP_FLAG_VIDEO)) { @@ -3800,10 +3803,11 @@ static int rtp_common_write(switch_rtp_t *rtp_session, this_ts = ntohl(send_msg->header.ts); if ((this_ts < rtp_session->last_write_ts) && ((rtp_session->last_write_ts - this_ts) > 16000)) { - rtp_session->last_write_ts = 0; + rtp_session->last_write_ts = RTP_TS_RESET; } - if (!switch_rtp_ready(rtp_session) || rtp_session->sending_dtmf || !this_ts || this_ts < rtp_session->last_write_ts) { + if (!switch_rtp_ready(rtp_session) || rtp_session->sending_dtmf || !this_ts || + (rtp_session->last_write_ts > RTP_TS_RESET && this_ts < rtp_session->last_write_ts)) { send = 0; } From 4872e6fff042e5fe36db0bafbde73c6ecf85c2c6 Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Fri, 9 Sep 2011 12:09:05 -0700 Subject: [PATCH 065/204] mod_commands: Add 'presence_data' field to 'show channels like xxx' list of fields. This makes anthm's trick mentioned on the mailing list even more handy. --- src/mod/applications/mod_commands/mod_commands.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index 8d28e3bea2..c1f5fe5940 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -4020,12 +4020,12 @@ SWITCH_STANDARD_API(show_function) } if (strchr(argv[2], '%')) { sprintf(sql, - "select * from channels where hostname='%s' and uuid like '%s' or name like '%s' or cid_name like '%s' or cid_num like '%s' order by created_epoch", - hostname, argv[2], argv[2], argv[2], argv[2]); + "select * from channels where hostname='%s' and uuid like '%s' or name like '%s' or cid_name like '%s' or cid_num like '%s' or presence_data like '%s' order by created_epoch", + hostname, argv[2], argv[2], argv[2], argv[2], argv[2]); } else { sprintf(sql, - "select * from channels where hostname='%s' and uuid like '%%%s%%' or name like '%%%s%%' or cid_name like '%%%s%%' or cid_num like '%%%s%%' order by created_epoch", - hostname, argv[2], argv[2], argv[2], argv[2]); + "select * from channels where hostname='%s' and uuid like '%%%s%%' or name like '%%%s%%' or cid_name like '%%%s%%' or cid_num like '%%%s%%' or presence_data like '%%%s%%' order by created_epoch", + hostname, argv[2], argv[2], argv[2], argv[2], argv[2]); } From bcd1e14711b56fc5b8a5bb629e5b0bd9779be96e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 9 Sep 2011 13:01:04 -0500 Subject: [PATCH 066/204] add callee_id name/number to xml_cdr --- src/switch_ivr.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/switch_ivr.c b/src/switch_ivr.c index b7f4a38b71..45b582b715 100644 --- a/src/switch_ivr.c +++ b/src/switch_ivr.c @@ -2000,6 +2000,21 @@ SWITCH_DECLARE(int) switch_ivr_set_xml_profile_data(switch_xml_t xml, switch_cal } switch_xml_set_txt_d(param, caller_profile->caller_id_name); + if (!(param = switch_xml_add_child_d(xml, "caller_id_number", off++))) { + return -1; + } + switch_xml_set_txt_d(param, caller_profile->caller_id_number); + + if (!(param = switch_xml_add_child_d(xml, "callee_id_name", off++))) { + return -1; + } + switch_xml_set_txt_d(param, caller_profile->callee_id_name); + + if (!(param = switch_xml_add_child_d(xml, "callee_id_number", off++))) { + return -1; + } + switch_xml_set_txt_d(param, caller_profile->callee_id_number); + if (!(param = switch_xml_add_child_d(xml, "ani", off++))) { return -1; } @@ -2010,10 +2025,6 @@ SWITCH_DECLARE(int) switch_ivr_set_xml_profile_data(switch_xml_t xml, switch_cal } switch_xml_set_txt_d(param, caller_profile->aniii); - if (!(param = switch_xml_add_child_d(xml, "caller_id_number", off++))) { - return -1; - } - switch_xml_set_txt_d(param, caller_profile->caller_id_number); if (!(param = switch_xml_add_child_d(xml, "network_addr", off++))) { return -1; From cb9abe0268150819b7351a58fe73aff757bcc589 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 9 Sep 2011 13:56:04 -0500 Subject: [PATCH 067/204] add new flag to frames to denote pass thru frames that are not audio --- src/include/switch_types.h | 3 ++- src/switch_core_io.c | 14 ++++++++++++++ src/switch_rtp.c | 5 +++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 5a8d49ab41..51ed3587e5 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1203,7 +1203,8 @@ typedef enum { SFF_PROXY_PACKET = (1 << 5), SFF_DYNAMIC = (1 << 6), SFF_ZRTP = (1 << 7), - SFF_UDPTL_PACKET = (1 << 8) + SFF_UDPTL_PACKET = (1 << 8), + SFF_NOT_AUDIO = (1 << 9) } switch_frame_flag_enum_t; typedef uint32_t switch_frame_flag_t; diff --git a/src/switch_core_io.c b/src/switch_core_io.c index c2b8c4608f..587218339a 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -265,6 +265,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_read_frame(switch_core_sessi do_bugs = 1; need_codec = 1; } + + if (((*frame)->flags & SFF_NOT_AUDIO)) { + do_resample = 0; + do_bugs = 0; + need_codec = 0; + } + if (switch_test_flag(session, SSF_READ_TRANSCODE) && !need_codec && switch_core_codec_ready(session->read_codec)) { switch_core_session_t *other_session; @@ -792,6 +799,13 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_write_frame(switch_core_sess do_resample = TRUE; } + + if ((frame->flags & SFF_NOT_AUDIO)) { + do_resample = 0; + do_bugs = 0; + need_codec = 0; + } + if (switch_test_flag(session, SSF_WRITE_TRANSCODE) && !need_codec && switch_core_codec_ready(session->write_codec)) { switch_core_session_t *other_session; const char *uuid = switch_channel_get_variable(switch_core_session_get_channel(session), SWITCH_SIGNAL_BOND_VARIABLE); diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 1fbe5aeebe..6d6c59b84b 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -3131,6 +3131,11 @@ static int rtp_common_read(switch_rtp_t *rtp_session, switch_payload_t *payload_ } } + if (((rtp_session->cng_pt && rtp_session->recv_msg.header.pt == rtp_session->cng_pt) || rtp_session->recv_msg.header.pt == 13)) { + *flags |= SFF_NOT_AUDIO; + } + + /* ignore packets not meant for us unless the auto-adjust window is open */ if (bytes) { if (switch_test_flag(rtp_session, SWITCH_RTP_FLAG_AUTOADJ)) { From ef2f87deb244e488b5074a81e5cf9dd4a42f7e50 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Fri, 9 Sep 2011 16:08:47 -0500 Subject: [PATCH 068/204] fix trivial build error on windows --- src/switch_rtp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/switch_rtp.c b/src/switch_rtp.c index 6d6c59b84b..24e8c3346d 100644 --- a/src/switch_rtp.c +++ b/src/switch_rtp.c @@ -34,8 +34,6 @@ //#define RTP_DEBUG_WRITE_DELTA //#define DEBUG_MISSED_SEQ -#define RTP_TS_RESET 1 - #include #include #undef PACKAGE_NAME @@ -62,6 +60,7 @@ #define MASTER_KEY_LEN 30 #define RTP_MAGIC_NUMBER 42 #define MAX_SRTP_ERRS 10 +#define RTP_TS_RESET 1 static switch_port_t START_PORT = RTP_START_PORT; static switch_port_t END_PORT = RTP_END_PORT; From 7ed7f539b0283ab848c2fdecb5c2d844ed9e6ff5 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 9 Sep 2011 14:31:02 -0500 Subject: [PATCH 069/204] add optional format string after myevent --- .../mod_event_socket/mod_event_socket.c | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c index 37c238852c..aaf270cb26 100644 --- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c +++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c @@ -1883,11 +1883,30 @@ static switch_status_t parse_command(listener_t *listener, switch_event_t **even char *uuid; if ((uuid = cmd + 9)) { + char *fmt; strip_cr(uuid); - + + if ((fmt = strchr(uuid, ' '))) { + *fmt++ = '\0'; + } + if (!(listener->session = switch_core_session_locate(uuid))) { - switch_snprintf(reply, reply_len, "-ERR invalid uuid"); - goto done; + if (fmt) { + switch_snprintf(reply, reply_len, "-ERR invalid uuid"); + goto done; + } else { + fmt = uuid; + } + } + + if ((fmt = strchr(uuid, ' '))) { + if (!strcasecmp(fmt, "xml")) { + listener->format = EVENT_FORMAT_XML; + } else if (!strcasecmp(fmt, "plain")) { + listener->format = EVENT_FORMAT_PLAIN; + } else if (!strcasecmp(fmt, "json")) { + listener->format = EVENT_FORMAT_JSON; + } } switch_set_flag_locked(listener, LFLAG_SESSION); From 2fa8f11002ed1d5fcc13934522d2054f83ed707d Mon Sep 17 00:00:00 2001 From: Michael S Collins Date: Fri, 9 Sep 2011 14:50:54 -0700 Subject: [PATCH 070/204] Update tab-complete for show cmd to include bridged_calls, detailed_calls, detailed_bridged_calls and removed distinct_channels --- src/mod/applications/mod_commands/mod_commands.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index c1f5fe5940..dba27031b1 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -5389,7 +5389,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) switch_console_set_complete("add show codec"); switch_console_set_complete("add show complete"); switch_console_set_complete("add show dialplan"); - switch_console_set_complete("add show distinct_channels"); + switch_console_set_complete("add show detailed_calls"); + switch_console_set_complete("add show bridged_calls"); + switch_console_set_complete("add show detailed_bridged_calls"); switch_console_set_complete("add show endpoint"); switch_console_set_complete("add show file"); switch_console_set_complete("add show interfaces"); From 8547c5c9957e7b395569a2222a020f80727d4792 Mon Sep 17 00:00:00 2001 From: Tamas Cseke Date: Mon, 12 Sep 2011 09:16:56 +0200 Subject: [PATCH 071/204] more general way to connect to mongo --- conf/autoload_configs/mongo.conf.xml | 8 +++- src/mod/applications/mod_mongo/mod_mongo.cpp | 15 ++++--- src/mod/applications/mod_mongo/mod_mongo.h | 13 +++---- src/mod/applications/mod_mongo/mongo_conn.cpp | 39 +++++++++++-------- 4 files changed, 45 insertions(+), 30 deletions(-) diff --git a/conf/autoload_configs/mongo.conf.xml b/conf/autoload_configs/mongo.conf.xml index ff8daed72a..8423645e95 100644 --- a/conf/autoload_configs/mongo.conf.xml +++ b/conf/autoload_configs/mongo.conf.xml @@ -1,6 +1,12 @@ - + + diff --git a/src/mod/applications/mod_mongo/mod_mongo.cpp b/src/mod/applications/mod_mongo/mod_mongo.cpp index 52e1eadf31..e0b93d85b4 100644 --- a/src/mod/applications/mod_mongo/mod_mongo.cpp +++ b/src/mod/applications/mod_mongo/mod_mongo.cpp @@ -15,7 +15,7 @@ static struct { SWITCH_STANDARD_API(mongo_mapreduce_function) { switch_status_t status = SWITCH_STATUS_SUCCESS; - DBClientConnection *conn = NULL; + DBClientBase *conn = NULL; char *ns = NULL, *json_query = NULL; ns = strdup(cmd); @@ -88,7 +88,7 @@ SWITCH_STANDARD_API(mongo_find_one_function) if (!zstr(ns) && !zstr(json_query) && !zstr(json_fields)) { - DBClientConnection *conn = NULL; + DBClientBase *conn = NULL; try { BSONObj query = fromjson(json_query); @@ -124,7 +124,7 @@ static switch_status_t config(void) const char *cf = "mongo.conf"; switch_xml_t cfg, xml, settings, param; switch_status_t status = SWITCH_STATUS_SUCCESS; - const char *host = "127.0.0.1"; + const char *conn_str = "127.0.0.1"; switch_size_t min_connections = 1, max_connections = 1; if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { @@ -139,7 +139,10 @@ static switch_status_t config(void) int tmp; if (!strcmp(var, "host")) { - host = val; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "'host' is deprecated. use 'connection-string'\n"); + conn_str = val; + } else if (!strcmp(var, "connection-string")) { + conn_str = val; } else if (!strcmp(var, "min-connections")) { if ((tmp = atoi(val)) > 0) { min_connections = tmp; @@ -158,11 +161,11 @@ static switch_status_t config(void) } } - if (mongo_connection_pool_create(&globals.conn_pool, min_connections, max_connections, host) != SWITCH_STATUS_SUCCESS) { + if (mongo_connection_pool_create(&globals.conn_pool, min_connections, max_connections, conn_str) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Can't create connection pool\n"); status = SWITCH_STATUS_GENERR; } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Mongo connection pool created [%s %d/%d]\n", host, (int)min_connections, (int)max_connections); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Mongo connection pool created [%s %d/%d]\n", conn_str, (int)min_connections, (int)max_connections); } switch_xml_free(xml); diff --git a/src/mod/applications/mod_mongo/mod_mongo.h b/src/mod/applications/mod_mongo/mod_mongo.h index 91c14bb29b..d264464294 100644 --- a/src/mod/applications/mod_mongo/mod_mongo.h +++ b/src/mod/applications/mod_mongo/mod_mongo.h @@ -1,7 +1,6 @@ #ifndef MOD_MONGO_H #define MOD_MONGO_H - #include #include #include @@ -10,7 +9,7 @@ using namespace mongo; typedef struct { - char *host; + char *conn_str; switch_size_t min_connections; switch_size_t max_connections; @@ -22,16 +21,16 @@ typedef struct { } mongo_connection_pool_t; -switch_status_t mongo_connection_create(DBClientConnection **connection, const char *host); -void mongo_connection_destroy(DBClientConnection **conn); +switch_status_t mongo_connection_create(DBClientBase **connection, const char *conn_str); +void mongo_connection_destroy(DBClientBase **conn); switch_status_t mongo_connection_pool_create(mongo_connection_pool_t **conn_pool, switch_size_t min_connections, switch_size_t max_connections, - const char *host); + const char *conn_str); void mongo_connection_pool_destroy(mongo_connection_pool_t **conn_pool); -DBClientConnection *mongo_connection_pool_get(mongo_connection_pool_t *conn_pool); -switch_status_t mongo_connection_pool_put(mongo_connection_pool_t *conn_pool, DBClientConnection *conn); +DBClientBase *mongo_connection_pool_get(mongo_connection_pool_t *conn_pool); +switch_status_t mongo_connection_pool_put(mongo_connection_pool_t *conn_pool, DBClientBase *conn); #endif diff --git a/src/mod/applications/mod_mongo/mongo_conn.cpp b/src/mod/applications/mod_mongo/mongo_conn.cpp index ee702b8470..ffcf1200d0 100644 --- a/src/mod/applications/mod_mongo/mongo_conn.cpp +++ b/src/mod/applications/mod_mongo/mongo_conn.cpp @@ -10,24 +10,31 @@ scoped_conn.done(); */ -switch_status_t mongo_connection_create(DBClientConnection **connection, const char *host) +switch_status_t mongo_connection_create(DBClientBase **connection, const char *conn_str) { - DBClientConnection *conn = new DBClientConnection(); + DBClientBase *conn = NULL; + string conn_string(conn_str), err_msg; + ConnectionString cs = ConnectionString::parse(conn_string, err_msg); + + if (!cs.isValid()) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't parse url: %s\n", err_msg.c_str()); + return SWITCH_STATUS_GENERR; + } try { - conn->connect(host); + conn = cs.connect(err_msg); } catch (DBException &e) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't connect to mongo [%s]\n", host); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't connect to mongo [%s]: %s\n", conn_str, err_msg.c_str()); return SWITCH_STATUS_GENERR; } *connection = conn; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected to mongo [%s]\n", host); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Connected to mongo [%s]\n", conn_str); return SWITCH_STATUS_SUCCESS; } -void mongo_connection_destroy(DBClientConnection **conn) +void mongo_connection_destroy(DBClientBase **conn) { switch_assert(*conn != NULL); delete *conn; @@ -36,12 +43,12 @@ void mongo_connection_destroy(DBClientConnection **conn) } switch_status_t mongo_connection_pool_create(mongo_connection_pool_t **conn_pool, switch_size_t min_connections, switch_size_t max_connections, - const char *host) + const char *conn_str) { switch_memory_pool_t *pool = NULL; switch_status_t status = SWITCH_STATUS_SUCCESS; mongo_connection_pool_t *cpool = NULL; - DBClientConnection *conn = NULL; + DBClientBase *conn = NULL; if ((status = switch_core_new_memory_pool(&pool)) != SWITCH_STATUS_SUCCESS) { return status; @@ -61,13 +68,13 @@ switch_status_t mongo_connection_pool_create(mongo_connection_pool_t **conn_pool cpool->min_connections = min_connections; cpool->max_connections = max_connections; - cpool->host = switch_core_strdup(pool, host); + cpool->conn_str = switch_core_strdup(pool, conn_str); cpool->pool = pool; for (cpool->size = 0; cpool->size < min_connections; cpool->size++) { - if (mongo_connection_create(&conn, host) == SWITCH_STATUS_SUCCESS) { + if (mongo_connection_create(&conn, conn_str) == SWITCH_STATUS_SUCCESS) { mongo_connection_pool_put(cpool, conn); } else { break; @@ -94,7 +101,7 @@ void mongo_connection_pool_destroy(mongo_connection_pool_t **conn_pool) switch_assert(cpool != NULL); while (switch_queue_trypop(cpool->connections, &data) == SWITCH_STATUS_SUCCESS) { - mongo_connection_destroy((DBClientConnection **)&data); + mongo_connection_destroy((DBClientBase **)&data); } switch_mutex_destroy(cpool->mutex); @@ -104,9 +111,9 @@ void mongo_connection_pool_destroy(mongo_connection_pool_t **conn_pool) } -DBClientConnection *mongo_connection_pool_get(mongo_connection_pool_t *conn_pool) +DBClientBase *mongo_connection_pool_get(mongo_connection_pool_t *conn_pool) { - DBClientConnection *conn = NULL; + DBClientBase *conn = NULL; void *data = NULL; switch_assert(conn_pool != NULL); @@ -114,8 +121,8 @@ DBClientConnection *mongo_connection_pool_get(mongo_connection_pool_t *conn_pool switch_mutex_lock(conn_pool->mutex); if (switch_queue_trypop(conn_pool->connections, &data) == SWITCH_STATUS_SUCCESS) { - conn = (DBClientConnection *) data; - } else if (mongo_connection_create(&conn, conn_pool->host) == SWITCH_STATUS_SUCCESS) { + conn = (DBClientBase *) data; + } else if (mongo_connection_create(&conn, conn_pool->conn_str) == SWITCH_STATUS_SUCCESS) { if (++conn_pool->size > conn_pool->max_connections) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Connection pool is empty. You may want to increase 'max-connections'\n"); } @@ -130,7 +137,7 @@ DBClientConnection *mongo_connection_pool_get(mongo_connection_pool_t *conn_pool return conn; } -switch_status_t mongo_connection_pool_put(mongo_connection_pool_t *conn_pool, DBClientConnection *conn) +switch_status_t mongo_connection_pool_put(mongo_connection_pool_t *conn_pool, DBClientBase *conn) { switch_status_t status = SWITCH_STATUS_SUCCESS; From ea7f051ee30c357c713203b214a9e24c8afe4670 Mon Sep 17 00:00:00 2001 From: Michal Bielicki - cypromis Date: Mon, 12 Sep 2011 11:10:57 +0200 Subject: [PATCH 072/204] added mongodb cdr config file to spec file --- freeswitch.spec | 1 + 1 file changed, 1 insertion(+) diff --git a/freeswitch.spec b/freeswitch.spec index 8fa7dedab6..c6226aaa9e 100644 --- a/freeswitch.spec +++ b/freeswitch.spec @@ -753,6 +753,7 @@ fi %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/alsa.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/callcenter.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/cdr_csv.conf.xml +%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/cdr_mongodb.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/cdr_pg_csv.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/cdr_sqlite.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/cepstral.conf.xml From f4facb0f6531fd469453e990a2268ae80751eab9 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Mon, 12 Sep 2011 13:07:34 +0200 Subject: [PATCH 073/204] [FreeTDM] Add missing newline in "Failed to configure span" error message in ftdm_configure_span_channels(). Signed-off-by: Stefan Knoblich --- libs/freetdm/src/ftdm_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 95626299bb..5f6e4391db 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -4565,7 +4565,7 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const *configured = 0; *configured = span->fio->configure_span(span, str, chan_config->type, chan_config->name, chan_config->number); if (!*configured) { - ftdm_log(FTDM_LOG_ERROR, "%d:Failed to configure span", span->span_id); + ftdm_log(FTDM_LOG_ERROR, "%d:Failed to configure span\n", span->span_id); return FTDM_FAIL; } From 6c5132a5076f676ed8235e328ded1bff5ae3d346 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Mon, 12 Sep 2011 15:21:23 -0400 Subject: [PATCH 074/204] freetdm: - Clear the IO flag when FreeSWITCH hangs up before notifying freetdm - Misc fixes to log messages to aid debugging - Added ftdm ioread command to read media from the channel - Modified the ftdm_channel_open() API to return FTDM_EBUSY if the channel is already open --- libs/freetdm/mod_freetdm/mod_freetdm.c | 203 +++++++++++++++++++++---- libs/freetdm/src/ftdm_io.c | 11 +- 2 files changed, 179 insertions(+), 35 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index c17b28cb77..a26dd1e257 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -503,13 +503,16 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) tech_pvt = switch_core_session_get_private(session); assert(tech_pvt != NULL); + /* ignore any further I/O requests, we're hanging up already! */ + switch_clear_flag_locked(tech_pvt, TFLAG_IO); + if (!tech_pvt->ftdmchan) { goto end; } ftdm_channel_clear_token(tech_pvt->ftdmchan, switch_core_session_get_uuid(session)); - chantype = ftdm_channel_get_type(tech_pvt->ftdmchan); + chantype = ftdm_channel_get_type(tech_pvt->ftdmchan); switch (chantype) { case FTDM_CHAN_TYPE_FXO: case FTDM_CHAN_TYPE_EM: @@ -548,8 +551,6 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) end: - switch_clear_flag_locked(tech_pvt, TFLAG_IO); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel)); switch_mutex_lock(globals.mutex); globals.calls--; @@ -629,6 +630,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch int total_to; int chunk, do_break = 0; uint32_t span_id, chan_id; + const char *name = NULL; channel = switch_core_session_get_channel(session); assert(channel != NULL); @@ -636,17 +638,18 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch tech_pvt = switch_core_session_get_private(session); assert(tech_pvt != NULL); - if (switch_test_flag(tech_pvt, TFLAG_DEAD)) { - ftdm_log(FTDM_LOG_DEBUG, "TFLAG_DEAD is set\n"); - return SWITCH_STATUS_FALSE; - } - + name = switch_channel_get_name(channel); if (!tech_pvt->ftdmchan) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "no ftdmchan set in channel %s!\n", name); 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(tech_pvt, TFLAG_DEAD)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TFLAG_DEAD is set in channel %s device %d:%d!\n", name, span_id, chan_id); + return SWITCH_STATUS_FALSE; + } /* Digium Cards sometimes timeout several times in a row here. Yes, we support digium cards, ain't we nice....... @@ -678,7 +681,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch } if (!switch_test_flag(tech_pvt, TFLAG_IO)) { - ftdm_log(FTDM_LOG_DEBUG, "TFLAG_IO is not set\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TFLAG_IO is not set in channel %s device %d:%d!\n", name, span_id, chan_id); goto fail; } @@ -686,7 +689,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch status = ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, chunk); if (status == FTDM_FAIL) { - ftdm_log(FTDM_LOG_ERROR, "Failed to wait for I/O\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id); goto fail; } @@ -694,7 +697,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch if (!switch_test_flag(tech_pvt, TFLAG_HOLD)) { total_to -= chunk; if (total_to <= 0) { - ftdm_log(FTDM_LOG_WARNING, "Too many timeouts while waiting for I/O\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Too many timeouts while waiting I/O in channel %s device %d:%d!\n", name, span_id, chan_id); goto fail; } } @@ -707,9 +710,9 @@ 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 %d:%d\n", span_id, chan_id); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to read from channel %s device %d:%d!\n", name, 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); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "too many I/O read errors on channel %s device %d:%d!\n", name, span_id, chan_id); goto fail; } } else { @@ -730,18 +733,18 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch for (p = dtmf; p && *p; p++) { if (is_dtmf(*p)) { _dtmf.digit = *p; - ftdm_log(FTDM_LOG_DEBUG, "Queuing DTMF [%c] in channel %s\n", *p, switch_channel_get_name(channel)); + ftdm_log(FTDM_LOG_DEBUG, "Queuing DTMF [%c] in channel %s device %d:%d\n", *p, name, span_id, chan_id); switch_channel_queue_dtmf(channel, &_dtmf); } } } + return SWITCH_STATUS_SUCCESS; - fail: +fail: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "clearing IO in channel %s device %d:%d!\n", name, span_id, chan_id); switch_clear_flag_locked(tech_pvt, TFLAG_IO); return SWITCH_STATUS_GENERR; - - } static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id) @@ -750,8 +753,9 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc private_t *tech_pvt = NULL; ftdm_size_t len; unsigned char data[SWITCH_RECOMMENDED_BUFFER_SIZE] = {0}; + const char *name = "(none)"; ftdm_wait_flag_t wflags = FTDM_WRITE; - uint32_t span_id, chan_id; + uint32_t span_id = 0, chan_id = 0; channel = switch_core_session_get_channel(session); assert(channel != NULL); @@ -759,7 +763,17 @@ 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); + name = switch_channel_get_name(channel); + if (!tech_pvt->ftdmchan) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "no ftdmchan set in channel %s!\n", name); + 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(tech_pvt, TFLAG_DEAD)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TFLAG_DEAD is set in channel %s device %d:%d!\n", name, span_id, chan_id); return SWITCH_STATUS_FALSE; } @@ -768,17 +782,10 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc } if (!switch_test_flag(tech_pvt, TFLAG_IO)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TFLAG_IO is not set in channel %s device %d:%d!\n", name, span_id, chan_id); 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; frame->buflen = sizeof(data); @@ -793,16 +800,16 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, ftdm_channel_get_io_interval(tech_pvt->ftdmchan) * 10); if (!(wflags & FTDM_WRITE)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Dropping frame! (write not ready)\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Dropping frame! (write note ready) in channel %s device %d:%d!\n", name, span_id, chan_id); return SWITCH_STATUS_SUCCESS; } len = frame->datalen; if (ftdm_channel_write(tech_pvt->ftdmchan, frame->data, frame->buflen, &len) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_WARNING, "failed to write to device %d:%d\n", span_id, chan_id); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Failed to write to channel %s device %d:%d!\n", name, 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); + SWITCH_LOG_ERROR, "Too many I/O write errors on channel %s device %d:%d!\n", name, span_id, chan_id); goto fail; } } else { @@ -812,7 +819,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc return SWITCH_STATUS_SUCCESS; fail: - + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error writing to channel %s device %d:%d!\n", name, span_id, chan_id); switch_clear_flag_locked(tech_pvt, TFLAG_IO); return SWITCH_STATUS_GENERR; @@ -3802,9 +3809,139 @@ typedef switch_status_t (*ftdm_cli_function_t)(ftdm_cli_entry_t *cli, const char int argc, char *argv[]) static void print_usage(switch_stream_handle_t *stream, ftdm_cli_entry_t *cli); -FTDM_CLI_DECLARE(ftdm_cmd_voice_detect) + +typedef struct cmd_ioread_data { + int num_times; + uint32_t interval; + ftdm_span_t *span; + ftdm_channel_t *fchan; + switch_memory_pool_t *pool; + int already_open; +} cmd_ioread_data_t; + +static void *SWITCH_THREAD_FUNC ioread_thread(switch_thread_t *thread, void *obj) { - print_usage(stream, cli); + ftdm_wait_flag_t wflags = FTDM_READ; + ftdm_status_t status = FTDM_FAIL; + unsigned char iobuf[SWITCH_RECOMMENDED_BUFFER_SIZE]; + cmd_ioread_data_t *data = obj; + int span_id = ftdm_span_get_id(data->span); + int chan_id = ftdm_channel_get_id(data->fchan); + uint32_t len = ftdm_channel_get_io_packet_len(data->fchan); + uint32_t origlen = len; + unsigned int pbuf[5]; + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, + "Started ioread thread (times = %d, interval = %ums, len = %u, span = %d, chan = %d\n", + data->num_times, data->interval, len, span_id, chan_id); + + while (ftdm_running() && data->num_times > 0) { + data->num_times--; + + wflags = FTDM_READ; + + status = ftdm_channel_wait(data->fchan, &wflags, (data->interval * 10)); + + if (status == FTDM_FAIL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to wait for IO in device %d:%d!\n", span_id, chan_id); + continue; + } + + if (status == FTDM_TIMEOUT) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Timed out while waiting I/O in device %d:%d!\n", span_id, chan_id); + continue; + } + + len = origlen; + if (ftdm_channel_read(data->fchan, iobuf, &len) != FTDM_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to read from device %d:%d!\n", span_id, chan_id); + continue; + } + pbuf[0] = iobuf[0]; + pbuf[1] = iobuf[1]; + pbuf[2] = iobuf[2]; + pbuf[3] = iobuf[3]; + pbuf[4] = iobuf[4]; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Read 0x%1X 0x%1X 0x%1X 0x%1X 0x%1X\n", + pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4]); + } + + if (!data->already_open) { + ftdm_channel_close(&data->fchan); + } + + switch_core_destroy_memory_pool(&data->pool); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, + "Done ioread thread (times = %d, interval = %ums, len = %u, span = %d, chan = %d\n", + data->num_times, data->interval, origlen, span_id, chan_id); + return NULL; +} + +FTDM_CLI_DECLARE(ftdm_cmd_ioread) +{ + char *span_name = NULL; + int channo = 0; + ftdm_status_t status = FTDM_SUCCESS; + switch_threadattr_t *attr = NULL; + switch_thread_t *thread = NULL; + + cmd_ioread_data_t *thdata; + cmd_ioread_data_t data; + + memset(&data, 0, sizeof(data)); + data.num_times = 1; + + if (argc < 3) { + print_usage(stream, cli); + goto end; + } + + span_name = argv[1]; + + ftdm_span_find_by_name(span_name, &data.span); + if (!data.span) { + stream->write_function(stream, "-ERR span %s not found\n", span_name); + goto end; + } + + channo = atoi(argv[2]); + + status = ftdm_channel_open(ftdm_span_get_id(data.span), channo, &data.fchan); + if (!data.fchan || (status != FTDM_SUCCESS && status != FTDM_EBUSY)) { + stream->write_function(stream, "-ERR Failed to open channel %d in span %s\n", channo, span_name); + goto end; + } + + if (status == FTDM_EBUSY) { + data.already_open = 1; + } + + if (argc > 3) { + data.num_times = atoi(argv[3]); + if (data.num_times < 1) { + data.num_times = 1; + } + } + + if (argc > 4) { + data.interval = atoi(argv[4]); + } + + if (data.interval <= 0 || data.interval > 10000) { + data.interval = ftdm_channel_get_io_interval(data.fchan); + } + + switch_core_new_memory_pool(&data.pool); + + thdata = switch_core_alloc(data.pool, sizeof(data)); + memcpy(thdata, &data, sizeof(*thdata)); + + switch_threadattr_create(&attr, data.pool); + switch_threadattr_detach_set(attr, 1); + switch_threadattr_stacksize_set(attr, SWITCH_THREAD_STACKSIZE); + switch_thread_create(&thread, attr, ioread_thread, thdata, data.pool); + +end: return SWITCH_STATUS_SUCCESS; } @@ -4452,7 +4589,7 @@ static ftdm_cli_entry_t ftdm_cli_options[] = { "dtmf", "on|off []", "::[on:off", ftdm_cmd_dtmf }, { "queuesize", " []", "", ftdm_cmd_queuesize }, { "iostats", "enable|disable|flush|print ", "::[enable:disable:flush:print", ftdm_cmd_iostats }, - { "voice_detect", "[on|off] []", "::[on:off", ftdm_cmd_voice_detect }, + { "ioread", " [num_times] [interval]", "", ftdm_cmd_ioread }, /* Fake handlers as they are handled within freetdm library, * we should provide a way inside freetdm to query for completions from signaling modules */ diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 5f6e4391db..0d0fdb655f 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -1855,7 +1855,14 @@ static ftdm_status_t _ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm goto done; } - ftdm_mutex_lock(check->mutex); + ftdm_channel_lock(check); + + if (ftdm_test_flag(check, FTDM_CHANNEL_OPEN)) { + /* let them know is already open, but return the channel anyway */ + status = FTDM_EBUSY; + *ftdmchan = check; + goto unlockchan; + } /* The following if's and gotos replace a big if (this || this || this || this) else { nothing; } */ @@ -1902,7 +1909,7 @@ openchan: goto done; unlockchan: - ftdm_mutex_unlock(check->mutex); + ftdm_channel_unlock(check); done: ftdm_mutex_unlock(globals.mutex); From 4cdf9f24912a3cc3d9d624a89c71eefc7860548a Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Mon, 12 Sep 2011 15:23:21 -0400 Subject: [PATCH 075/204] freetdm: ftmod_wanpipe - Added misc IO debugging code (define WP_DEBUG_IO to use) --- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 90 ++++++++++++++++--- 1 file changed, 79 insertions(+), 11 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index 6c945e1512..81e2405606 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -39,6 +39,11 @@ * */ +#ifdef WP_DEBUG_IO +#define _BSD_SOURCE +#include +#endif + #ifdef __sun #include #include @@ -99,6 +104,17 @@ static struct { uint32_t ring_off_ms; } wp_globals; +typedef struct { + sangoma_wait_obj_t *waitobj; +#ifdef WP_DEBUG_IO + /* record the last reader threads */ + pid_t readers[10]; + int rindex; + ftdm_time_t last_read; +#endif +} wp_channel_t; +#define WP_GET_WAITABLE(fchan) ((wp_channel_t *)((fchan)->io_data))->waitobj + /* a bunch of this stuff should go into the wanpipe_tdm_api_iface.h */ FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event); @@ -123,7 +139,7 @@ static __inline__ int tdmv_api_wait_socket(ftdm_channel_t *ftdmchan, int timeout int err; uint32_t inflags = *flags; uint32_t outflags = 0; - sangoma_wait_obj_t *sangoma_wait_obj = ftdmchan->io_data; + sangoma_wait_obj_t *sangoma_wait_obj = WP_GET_WAITABLE(ftdmchan); if (timeout == -1) { timeout = SANGOMA_WAIT_INFINITE; @@ -254,9 +270,13 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start } if (ftdm_span_add_channel(span, sockfd, type, &chan) == FTDM_SUCCESS) { + wp_channel_t *wpchan = NULL; wanpipe_tdm_api_t tdm_api; memset(&tdm_api, 0, sizeof(tdm_api)); #ifdef LIBSANGOMA_VERSION + wpchan = ftdm_calloc(1, sizeof(*wpchan)); + ftdm_assert(wpchan != NULL, "wpchan alloc failed\n"); + chan->io_data = wpchan; /* we need SANGOMA_DEVICE_WAIT_OBJ_SIG and not SANGOMA_DEVICE_WAIT_OBJ alone because we need to call * sangoma_wait_obj_sig to wake up any I/O waiters when closing the channel (typically on ftdm shutdown) * this adds an extra pair of file descriptors to the waitable object @@ -266,7 +286,7 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start ftdm_log(FTDM_LOG_ERROR, "failure create waitable object for s%dc%d\n", spanno, x); continue; } - chan->io_data = sangoma_wait_obj; + WP_GET_WAITABLE(chan) = sangoma_wait_obj; #endif chan->physical_span_id = spanno; @@ -580,9 +600,16 @@ static FIO_OPEN_FUNCTION(wanpipe_open) static FIO_CLOSE_FUNCTION(wanpipe_close) { #ifdef LIBSANGOMA_VERSION - sangoma_wait_obj_t *waitobj = ftdmchan->io_data; + sangoma_wait_obj_t *waitobj = WP_GET_WAITABLE(ftdmchan); /* kick any I/O waiters */ sangoma_wait_obj_signal(waitobj); +#ifdef WP_DEBUG_IO + { + wp_channel_t *wchan = ftdmchan->io_data; + memset(wchan->readers, 0, sizeof(wchan->readers)); + wchan->rindex = 0; + } +#endif #endif return FTDM_SUCCESS; } @@ -950,10 +977,44 @@ static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx static FIO_READ_FUNCTION(wanpipe_read) { int rx_len = 0; + int rq_len = (int)*datalen; wp_tdm_api_rx_hdr_t hdrframe; - memset(&hdrframe, 0, sizeof(hdrframe)); +#ifdef WP_DEBUG_IO + wp_channel_t *wchan = ftdmchan->io_data; + ftdm_time_t time_diff = 0; + pid_t previous_thread = 1; + pid_t current_thread = 0; + int previous_thread_index = 0; + previous_thread_index = wchan->rindex == 0 ? (ftdm_array_len(wchan->readers) - 1) : wchan->rindex - 1; + previous_thread = wchan->readers[previous_thread_index]; + current_thread = syscall(SYS_gettid); + if (current_thread && current_thread != wchan->readers[wchan->rindex]) { + if (!wchan->readers[wchan->rindex]) { + wchan->readers[wchan->rindex] = current_thread; + /* first read */ + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Initial reader thread is %d\n", current_thread); + previous_thread = current_thread; + } else { + previous_thread = wchan->readers[wchan->rindex]; + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Changed reader thread from %d to %d (rindex = %d)\n", + previous_thread, current_thread, wchan->rindex); + if (wchan->rindex == (ftdm_array_len(wchan->readers) - 1)) { + wchan->rindex = 0; + } else { + wchan->rindex++; + } + wchan->readers[wchan->rindex] = current_thread; + } + } + ftdm_time_t curr = ftdm_current_time_in_ms(); + if (wchan->last_read) { + time_diff = curr - wchan->last_read; + } +#endif + + memset(&hdrframe, 0, sizeof(hdrframe)); rx_len = sangoma_readmsg_tdm(ftdmchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (int)*datalen, 0); *datalen = rx_len; @@ -963,14 +1024,20 @@ static FIO_READ_FUNCTION(wanpipe_read) } if (rx_len < 0) { - snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno)); - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read from sangoma device: %s (%d)\n", strerror(errno), rx_len); +#ifdef WP_DEBUG_IO + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read %d bytes from sangoma device: %s (%d) " + "(read time diff = %llums, prev thread = %d, curr thread = %d)\n", rq_len, strerror(errno), rx_len, + time_diff, previous_thread, current_thread); +#else + ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read %d bytes from sangoma device: %s (%d)\n", rq_len, strerror(errno), rx_len); +#endif return FTDM_FAIL; } if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS)) { wanpipe_read_stats(ftdmchan, &hdrframe); } + return FTDM_SUCCESS; } @@ -1116,7 +1183,7 @@ FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event) if (!ftdmchan->io_data) { continue; /* should never happen but happens when shutting down */ } - pfds[j] = ftdmchan->io_data; + pfds[j] = WP_GET_WAITABLE(ftdmchan); inflags[j] = chan_events; #else memset(&pfds[j], 0, sizeof(pfds[j])); @@ -1578,10 +1645,10 @@ static FIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy) { #ifdef LIBSANGOMA_VERSION if (ftdmchan->io_data) { - sangoma_wait_obj_t *sangoma_wait_obj; - sangoma_wait_obj = ftdmchan->io_data; - ftdmchan->io_data = NULL; + sangoma_wait_obj_t *sangoma_wait_obj = WP_GET_WAITABLE(ftdmchan); sangoma_wait_obj_delete(&sangoma_wait_obj); + ftdm_safe_free(ftdmchan->io_data); + ftdmchan->io_data = NULL; } #endif @@ -1612,7 +1679,8 @@ static FIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy) */ static FIO_IO_LOAD_FUNCTION(wanpipe_init) { - assert(fio != NULL); + ftdm_assert(fio != NULL, "fio should not be null\n"); + memset(&wanpipe_interface, 0, sizeof(wanpipe_interface)); wp_globals.codec_ms = 20; From 23aba09f1bf2102fd359a0b332fbfe1701152d27 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Mon, 12 Sep 2011 15:48:28 -0400 Subject: [PATCH 076/204] freetdm: mod_freetdm - fix len data type for 64bit systems --- libs/freetdm/mod_freetdm/mod_freetdm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index a26dd1e257..805e581399 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -3827,12 +3827,12 @@ static void *SWITCH_THREAD_FUNC ioread_thread(switch_thread_t *thread, void *obj cmd_ioread_data_t *data = obj; int span_id = ftdm_span_get_id(data->span); int chan_id = ftdm_channel_get_id(data->fchan); - uint32_t len = ftdm_channel_get_io_packet_len(data->fchan); - uint32_t origlen = len; + ftdm_size_t len = ftdm_channel_get_io_packet_len(data->fchan); + ftdm_size_t origlen = len; unsigned int pbuf[5]; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, - "Started ioread thread (times = %d, interval = %ums, len = %u, span = %d, chan = %d\n", + "Started ioread thread (times = %d, interval = %ums, len = %"FTDM_SIZE_FMT", span = %d, chan = %d\n", data->num_times, data->interval, len, span_id, chan_id); while (ftdm_running() && data->num_times > 0) { @@ -3872,7 +3872,7 @@ static void *SWITCH_THREAD_FUNC ioread_thread(switch_thread_t *thread, void *obj switch_core_destroy_memory_pool(&data->pool); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, - "Done ioread thread (times = %d, interval = %ums, len = %u, span = %d, chan = %d\n", + "Done ioread thread (times = %d, interval = %ums, len = %"FTDM_SIZE_FMT", span = %d, chan = %d\n", data->num_times, data->interval, origlen, span_id, chan_id); return NULL; } From dd6996cd3f44b6be8272357a77a56b5e34312adf Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 9 Sep 2011 15:13:13 -0500 Subject: [PATCH 077/204] revert --- src/switch_utils.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/switch_utils.c b/src/switch_utils.c index ea6a0a2dfa..50f1725f5e 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -466,9 +466,6 @@ SWITCH_DECLARE(switch_status_t) switch_b64_encode(unsigned char *in, switch_size b = (b << 8) + in[x]; l += 8; - if ((x % 1024) == 0) { - switch_cond_next(); /* give other processes/threads a chance */ - } while (l >= 6) { out[bytes++] = switch_b64_table[(b >> (l -= 6)) % 64]; if (++y != 72) { @@ -645,7 +642,6 @@ SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, } while ((ilen = read(ifd, in, B64BUFFLEN))) { - switch_cond_next(); /* give other processes/threads a chance */ for (x = 0; x < ilen; x++) { b = (b << 8) + in[x]; l += 8; From 910f5364a4a81d05ad801a84d0b595b2de3b48b1 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 12 Sep 2011 14:24:58 -0500 Subject: [PATCH 078/204] add threaded-system-exec param and fsctl (set it to false to use fork) --- configure.in | 2 +- src/include/switch_types.h | 6 +- .../applications/mod_commands/mod_commands.c | 9 ++ src/switch.c | 1 + src/switch_core.c | 146 +++++++++++++++++- 5 files changed, 159 insertions(+), 5 deletions(-) diff --git a/configure.in b/configure.in index 6a7d7dec4d..b74e973a4a 100644 --- a/configure.in +++ b/configure.in @@ -474,7 +474,7 @@ AC_PROG_GCC_TRADITIONAL AC_FUNC_MALLOC AC_TYPE_SIGNAL AC_FUNC_STRFTIME -AC_CHECK_FUNCS([gethostname vasprintf mmap mlock mlockall usleep getifaddrs timerfd_create]) +AC_CHECK_FUNCS([gethostname vasprintf mmap mlock mlockall usleep getifaddrs timerfd_create getdtablesize]) AC_CHECK_FUNCS([sched_setscheduler setpriority setrlimit setgroups initgroups]) AC_CHECK_FUNCS([wcsncmp setgroups asprintf setenv pselect gettimeofday localtime_r gmtime_r strcasecmp stricmp _stricmp]) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 51ed3587e5..97fbc942af 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -306,7 +306,8 @@ typedef enum { SCF_AUTO_SCHEMAS = (1 << 13), SCF_MINIMAL = (1 << 14), SCF_USE_NAT_MAPPING = (1 << 15), - SCF_CLEAR_SQL = (1 << 16) + SCF_CLEAR_SQL = (1 << 16), + SCF_THREADED_SYSTEM_EXEC = (1 << 17) } switch_core_flag_enum_t; typedef uint32_t switch_core_flag_t; @@ -1677,7 +1678,8 @@ typedef enum { SCSC_VERBOSE_EVENTS, SCSC_SHUTDOWN_CHECK, SCSC_PAUSE_CHECK, - SCSC_READY_CHECK + SCSC_READY_CHECK, + SCSC_THREADED_SYSTEM_EXEC } switch_session_ctl_t; typedef enum { diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index dba27031b1..a5175299be 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -1840,6 +1840,15 @@ SWITCH_STANDARD_API(ctl_function) switch_core_session_ctl(SCSC_VERBOSE_EVENTS, &arg); stream->write_function(stream, "+OK verbose_events is %s \n", arg ? "on" : "off"); + } else if (!strcasecmp(argv[0], "threaded_system_exec")) { + arg = -1; + if (argv[1]) { + arg = switch_true(argv[1]); + } + + switch_core_session_ctl(SCSC_THREADED_SYSTEM_EXEC, &arg); + + stream->write_function(stream, "+OK threaded_system_exec is %s \n", arg ? "true" : "false"); } else if (!strcasecmp(argv[0], "save_history")) { switch_core_session_ctl(SCSC_SAVE_HISTORY, NULL); diff --git a/src/switch.c b/src/switch.c index 401829cf82..4ef38111f2 100644 --- a/src/switch.c +++ b/src/switch.c @@ -102,6 +102,7 @@ static void handle_SIGCHLD(int sig) pid = wait(&status); if (pid > 0) { + printf("ASS %d\n", pid); system_ready = -1; } diff --git a/src/switch_core.c b/src/switch_core.c index e9e5b3871c..ba0350a7fe 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -647,6 +647,41 @@ SWITCH_DECLARE(void) switch_core_set_globals(void) switch_assert(SWITCH_GLOBAL_dirs.temp_dir); } + +static int32_t set_low_priority(void) +{ +#ifdef WIN32 + SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS); +#else +#ifdef USE_SCHED_SETSCHEDULER + /* + * Try to use a normal scheduler + */ + struct sched_param sched = { 0 }; + sched.sched_priority = 0; + if (sched_setscheduler(0, SCHED_OTHER, &sched)) { + return -1; + } +#endif + +#ifdef HAVE_SETPRIORITY + /* + * setpriority() works on FreeBSD (6.2), nice() doesn't + */ + if (setpriority(PRIO_PROCESS, getpid(), 19) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); + return -1; + } +#else + if (nice(19) != 19) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Could not set nice level\n"); + return -1; + } +#endif +#endif + return 0; +} + static int32_t set_priority(void) { #ifdef WIN32 @@ -1359,6 +1394,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc switch_set_flag((&runtime.dummy_cng_frame), SFF_CNG); switch_set_flag((&runtime), SCF_AUTO_SCHEMAS); switch_set_flag((&runtime), SCF_CLEAR_SQL); + switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); switch_set_flag((&runtime), SCF_NO_NEW_SESSIONS); runtime.hard_log_level = SWITCH_LOG_DEBUG; @@ -1483,6 +1519,24 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc } +#ifndef WIN32 +static void handle_SIGCHLD(int sig) +{ + int status = 0; + int pid = 0; + + if (sig); + + pid = wait(&status); + + if (pid > 0) { + printf("ASS %d\n", pid); + } + + return; +} +#endif + #ifdef TRAP_BUS static void handle_SIGBUS(int sig) { @@ -1690,6 +1744,17 @@ static void switch_load_core_config(const char *file) } else { switch_clear_flag((&runtime), SCF_VERBOSE_EVENTS); } + } else if (!strcasecmp(var, "threaded-system-exec") && !zstr(val)) { +#ifdef WIN32 + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "threaded-system-exec is not implemented on this platform\n"); +#else + int v = switch_true(val); + if (v) { + switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } else { + switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } +#endif } else if (!strcasecmp(var, "min-idle-cpu") && !zstr(val)) { switch_core_min_idle_cpu(atof(val)); } else if (!strcasecmp(var, "tipping-point") && !zstr(val)) { @@ -1870,7 +1935,9 @@ SWITCH_DECLARE(void) switch_core_set_signal_handlers(void) { /* set signal handlers */ signal(SIGINT, SIG_IGN); - +#ifndef WIN32 + signal(SIGCHLD, handle_SIGCHLD); +#endif #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif @@ -1924,6 +1991,18 @@ SWITCH_DECLARE(int32_t) switch_core_session_ctl(switch_session_ctl_t cmd, void * newintval = switch_test_flag((&runtime), SCF_VERBOSE_EVENTS); } break; + case SCSC_THREADED_SYSTEM_EXEC: + if (intval) { + if (oldintval > -1) { + if (oldintval) { + switch_set_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } else { + switch_clear_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } + } + newintval = switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC); + } + break; case SCSC_CALIBRATE_CLOCK: switch_time_calibrate_clock(); break; @@ -2256,7 +2335,8 @@ static void *SWITCH_THREAD_FUNC system_thread(switch_thread_t *thread, void *obj return NULL; } -SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait) + +static int switch_system_thread(const char *cmd, switch_bool_t wait) { switch_thread_t *thread; switch_threadattr_t *thd_attr; @@ -2296,6 +2376,68 @@ SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait) } +#ifdef WIN32 +static int switch_system_fork(const char *cmd, switch_bool_t wait) +{ + return switch_system_thread(cmd, wait); +} + +#else +static int max_open(void) +{ + int max; + +#if defined(HAVE_GETDTABLESIZE) + max = getdtablesize(); +#else + max = sysconf(_SC_OPEN_MAX); +#endif + + return max; + +} + +static int switch_system_fork(const char *cmd, switch_bool_t wait) +{ + int pid; + + switch_core_set_signal_handlers(); + + pid = fork(); + + if (pid) { + if (wait) { + waitpid(pid, NULL, 0); + } + } else { + int open_max = max_open(); + int i; + + for (i = 3; i < open_max; i++) { + close(i); + } + + set_low_priority(); + system(cmd); + exit(0); + } + + return 0; +} +#endif + + + +SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait) +{ + int (*sys_p)(const char *cmd, switch_bool_t wait); + + sys_p = switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC) ? switch_system_thread : switch_system_fork; + + return sys_p(cmd, wait); + +} + /* For Emacs: * Local Variables: From 408adb8d0c8b6585481338e72510f21d1aeb6cd9 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 12 Sep 2011 14:26:42 -0500 Subject: [PATCH 079/204] FS-3558 --resolve --- src/mod/endpoints/mod_sofia/sofia.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia.c b/src/mod/endpoints/mod_sofia/sofia.c index 6b5e18ec58..ef65a7ce95 100644 --- a/src/mod/endpoints/mod_sofia/sofia.c +++ b/src/mod/endpoints/mod_sofia/sofia.c @@ -5281,6 +5281,9 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, break; case nua_callstate_completing: { + const char *invite_full_from = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_from"); + const char *invite_full_to = switch_channel_get_variable(tech_pvt->channel, "sip_invite_full_to"); + if (r_sdp && sofia_test_flag(tech_pvt, TFLAG_3PCC_INVITE) && !sofia_test_flag(tech_pvt, TFLAG_SDP)) { sofia_set_flag(tech_pvt, TFLAG_SDP); @@ -5304,12 +5307,18 @@ static void sofia_handle_sip_i_state(switch_core_session_t *session, int status, const char *invite_route_uri = switch_channel_get_variable(tech_pvt->channel, "sip_invite_route_uri"); nua_ack(nh, - TAG_IF(!zstr(invite_full_via), SIPTAG_VIA_STR(invite_full_via)), - TAG_IF(!zstr(invite_route_uri), SIPTAG_ROUTE_STR(invite_route_uri)), - TAG_END()); + TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)), + TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)), + TAG_IF(!zstr(invite_full_via), SIPTAG_VIA_STR(invite_full_via)), + TAG_IF(!zstr(invite_route_uri), SIPTAG_ROUTE_STR(invite_route_uri)), + TAG_END()); } else { - nua_ack(nh, TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), TAG_END()); + nua_ack(nh, + TAG_IF(invite_full_from, SIPTAG_FROM_STR(invite_full_from)), + TAG_IF(invite_full_to, SIPTAG_TO_STR(invite_full_to)), + TAG_IF(!zstr(tech_pvt->user_via), SIPTAG_VIA_STR(tech_pvt->user_via)), + TAG_END()); } } goto done; From 4ed900eb92095e62691384553c687d5263dd765c Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Mon, 12 Sep 2011 18:12:12 -0400 Subject: [PATCH 080/204] freetdm: add debug stacktrace to track spurious channel_on_hangup call --- libs/freetdm/mod_freetdm/mod_freetdm.c | 34 ++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 805e581399..7e0bb55a1b 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -34,6 +34,15 @@ #include #include "freetdm.h" +//#define CUDATEL_DEBUG +#ifdef CUDATEL_DEBUG +#ifndef _BSD_SOURCE +#define _BSD_SOURCE +#endif +#include +#include +#endif + #ifndef __FUNCTION__ #define __FUNCTION__ __SWITCH_FUNC__ #endif @@ -495,6 +504,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) switch_channel_t *channel = NULL; private_t *tech_pvt = NULL; ftdm_chan_type_t chantype; + const char *name = NULL; uint32_t tokencnt; channel = switch_core_session_get_channel(session); @@ -506,9 +516,29 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) /* ignore any further I/O requests, we're hanging up already! */ switch_clear_flag_locked(tech_pvt, TFLAG_IO); + name = switch_channel_get_name(channel); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP ENTER\n", name); + if (!tech_pvt->ftdmchan) { goto end; - } + } + +#ifdef CUDATEL_DEBUG + { + pid_t tid = 0; + size_t size = 0; + char **symbols = NULL; + void *stacktrace[50]; + int si = 0; + size = backtrace(stacktrace, ftdm_array_len(stacktrace)); + symbols = backtrace_symbols(stacktrace, size); + tid = syscall(SYS_gettid); + for (si = 0; si < size; si++) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%d] %s -> %s\n", tid, name, symbols[si]); + } + free(symbols); + } +#endif ftdm_channel_clear_token(tech_pvt->ftdmchan, switch_core_session_get_uuid(session)); @@ -551,7 +581,6 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) end: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel)); switch_mutex_lock(globals.mutex); globals.calls--; if (globals.calls < 0) { @@ -559,6 +588,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) } switch_mutex_unlock(globals.mutex); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP EXIT\n", name); return SWITCH_STATUS_SUCCESS; } From c1dd008b1dd5a5020763476306f365dc18f7b4b1 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 12 Sep 2011 16:13:19 -0500 Subject: [PATCH 081/204] change -hp to -rp, add -lp and -np, no priority flags means auto which will do -rp if you have > 1 cpu --- src/include/private/switch_core_pvt.h | 1 + src/include/switch_core.h | 5 ++- src/switch.c | 38 +++++++++++++++----- src/switch_core.c | 50 ++++++++------------------- 4 files changed, 48 insertions(+), 46 deletions(-) diff --git a/src/include/private/switch_core_pvt.h b/src/include/private/switch_core_pvt.h index af82f1e88d..31da5a9bf1 100644 --- a/src/include/private/switch_core_pvt.h +++ b/src/include/private/switch_core_pvt.h @@ -255,6 +255,7 @@ struct switch_runtime { uint32_t db_handle_timeout; int curl_count; int ssl_count; + int cpu_count; }; extern struct switch_runtime runtime; diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 562262c82d..da6a2e6ada 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -1978,8 +1978,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_management_exec(char *relative_oid, \brief Set the maximum priority the process can obtain \return 0 on success */ -SWITCH_DECLARE(int32_t) set_high_priority(void); + SWITCH_DECLARE(int32_t) set_normal_priority(void); +SWITCH_DECLARE(int32_t) set_auto_priority(void); +SWITCH_DECLARE(int32_t) set_realtime_priority(void); +SWITCH_DECLARE(int32_t) set_low_priority(void); /*! \brief Change user and/or group of the running process diff --git a/src/switch.c b/src/switch.c index 4ef38111f2..4d4208ebdb 100644 --- a/src/switch.c +++ b/src/switch.c @@ -358,7 +358,7 @@ int main(int argc, char *argv[]) char *usageDesc; int alt_dirs = 0, log_set = 0, run_set = 0, do_kill = 0; int known_opt; - int high_prio = 0; + int priority = 0; #ifndef WIN32 int do_wait = 0; #endif @@ -408,7 +408,9 @@ int main(int argc, char *argv[]) "\t-waste -- allow memory waste\n" "\t-core -- dump cores\n" #endif - "\t-hp -- enable high priority settings\n" + "\t-rp -- enable high(realtime) priority settings\n" + "\t-lp -- enable low priority settings\n" + "\t-np -- enable normal priority settings (system defaults)\n" "\t-vg -- run under valgrind\n" "\t-nosql -- disable internal sql scoreboard\n" "\t-heavy-timer -- Heavy Timer, possibly more accurate but at a cost\n" @@ -567,8 +569,18 @@ int main(int argc, char *argv[]) } #endif - if (local_argv[x] && !strcmp(local_argv[x], "-hp")) { - high_prio++; + if (local_argv[x] && (!strcmp(local_argv[x], "-hp") || !strcmp(local_argv[x], "-rp"))) { + priority = 2; + known_opt++; + } + + if (local_argv[x] && !strcmp(local_argv[x], "-lp")) { + priority = -1; + known_opt++; + } + + if (local_argv[x] && !strcmp(local_argv[x], "-np")) { + priority = 1; known_opt++; } @@ -828,13 +840,21 @@ int main(int argc, char *argv[]) } - - if (high_prio) { - set_high_priority(); - } else { + switch(priority) { + case 2: + set_realtime_priority(); + break; + case 1: set_normal_priority(); + break; + case -1: + set_low_priority(); + break; + default: + set_auto_priority(); + break; } - + switch_core_setrlimits(); diff --git a/src/switch_core.c b/src/switch_core.c index ba0350a7fe..4edf0dc576 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -648,8 +648,10 @@ SWITCH_DECLARE(void) switch_core_set_globals(void) } -static int32_t set_low_priority(void) +SWITCH_DECLARE(int32_t) set_low_priority(void) { + + #ifdef WIN32 SetPriorityClass(GetCurrentProcess(), BELOW_NORMAL_PRIORITY_CLASS); #else @@ -679,13 +681,14 @@ static int32_t set_low_priority(void) } #endif #endif + return 0; } -static int32_t set_priority(void) +SWITCH_DECLARE(int32_t) set_realtime_priority(void) { #ifdef WIN32 - SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); + SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); #else #ifdef USE_SCHED_SETSCHEDULER /* @@ -720,47 +723,20 @@ static int32_t set_priority(void) return 0; } - SWITCH_DECLARE(int32_t) set_normal_priority(void) { - return set_priority(); + return 0; } -SWITCH_DECLARE(int32_t) set_high_priority(void) +SWITCH_DECLARE(int32_t) set_auto_priority(void) { -#ifdef WIN32 - SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); -#else - int pri; + runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN); -#ifdef USE_SETRLIMIT - struct rlimit lim = { RLIM_INFINITY, RLIM_INFINITY }; -#endif - - if ((pri = set_priority())) { - return pri; + /* If we have more than 1 cpu, we should use realtime priority so we can have priority threads */ + if (runtime.cpu_count > 1) { + return set_realtime_priority(); } -#ifdef USE_SETRLIMIT - /* - * The amount of memory which can be mlocked is limited for non-root users. - * FS will segfault (= hitting the limit) soon after mlockall has been called - * and we've switched to a different user. - * So let's try to remove the mlock limit here... - */ - if (setrlimit(RLIMIT_MEMLOCK, &lim) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Failed to disable memlock limit, application may crash if run as non-root user!\n"); - } -#endif - -#ifdef USE_MLOCKALL - /* - * Pin memory pages to RAM to prevent being swapped to disk - */ - mlockall(MCL_CURRENT | MCL_FUTURE); -#endif - -#endif return 0; } @@ -1405,6 +1381,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc runtime.min_dtmf_duration = SWITCH_MIN_DTMF_DURATION; runtime.odbc_dbtype = DBTYPE_DEFAULT; runtime.dbname = NULL; + runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN); + /* INIT APR and Create the pool context */ if (apr_initialize() != SWITCH_STATUS_SUCCESS) { From 1e712c7e0320d48080cf39c6aa328492da98a83e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 12 Sep 2011 16:14:30 -0500 Subject: [PATCH 082/204] only reap sigchld when in fork mode for system --- src/switch_core.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/switch_core.c b/src/switch_core.c index 4edf0dc576..c4ce502721 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1914,7 +1914,11 @@ SWITCH_DECLARE(void) switch_core_set_signal_handlers(void) /* set signal handlers */ signal(SIGINT, SIG_IGN); #ifndef WIN32 - signal(SIGCHLD, handle_SIGCHLD); + if (switch_test_flag((&runtime), SCF_THREADED_SYSTEM_EXEC)) { + signal(SIGCHLD, SIG_DFL); + } else { + signal(SIGCHLD, handle_SIGCHLD); + } #endif #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); @@ -2293,6 +2297,7 @@ static void *SWITCH_THREAD_FUNC system_thread(switch_thread_t *thread, void *obj #endif sth->ret = system(sth->cmd); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "WTF %d %s\n", sth->ret, strerror(errno)); #if 0 #if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__) From 35f81e117a03cb6c708f15fe446b3d6c23e85969 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 12 Sep 2011 17:52:02 -0500 Subject: [PATCH 083/204] swigall --- .../languages/mod_managed/freeswitch_wrap.cxx | 51 +++++++++++++++---- src/mod/languages/mod_managed/managed/swig.cs | 43 ++++++++++++---- src/mod/languages/mod_perl/mod_perl_wrap.cpp | 6 +-- 3 files changed, 77 insertions(+), 23 deletions(-) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index a6ec671a52..f89b749c12 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -1664,6 +1664,17 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_LOCAL_MEDIA_PORT_VARIABLE_get() { } +SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_ADVERTISED_MEDIA_IP_VARIABLE_get() { + char * jresult ; + char *result = 0 ; + + result = (char *) "advertised_media_ip"; + + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_REMOTE_MEDIA_IP_VARIABLE_get() { char * jresult ; char *result = 0 ; @@ -9981,16 +9992,6 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_management_exec(char * jarg1, int } -SWIGEXPORT int SWIGSTDCALL CSharp_set_high_priority() { - int jresult ; - int32_t result; - - result = (int32_t)set_high_priority(); - jresult = result; - return jresult; -} - - SWIGEXPORT int SWIGSTDCALL CSharp_set_normal_priority() { int jresult ; int32_t result; @@ -10001,6 +10002,36 @@ SWIGEXPORT int SWIGSTDCALL CSharp_set_normal_priority() { } +SWIGEXPORT int SWIGSTDCALL CSharp_set_auto_priority() { + int jresult ; + int32_t result; + + result = (int32_t)set_auto_priority(); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_set_realtime_priority() { + int jresult ; + int32_t result; + + result = (int32_t)set_realtime_priority(); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_set_low_priority() { + int jresult ; + int32_t result; + + result = (int32_t)set_low_priority(); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_change_user_group(char * jarg1, char * jarg2) { int jresult ; char *arg1 = (char *) 0 ; diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index e838e77c7f..1b8f7fd816 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -2188,13 +2188,23 @@ public class freeswitch { return ret; } - public static int set_high_priority() { - int ret = freeswitchPINVOKE.set_high_priority(); + public static int set_normal_priority() { + int ret = freeswitchPINVOKE.set_normal_priority(); return ret; } - public static int set_normal_priority() { - int ret = freeswitchPINVOKE.set_normal_priority(); + public static int set_auto_priority() { + int ret = freeswitchPINVOKE.set_auto_priority(); + return ret; + } + + public static int set_realtime_priority() { + int ret = freeswitchPINVOKE.set_realtime_priority(); + return ret; + } + + public static int set_low_priority() { + int ret = freeswitchPINVOKE.set_low_priority(); return ret; } @@ -5784,6 +5794,7 @@ public class freeswitch { public static readonly string SWITCH_ORIGINATOR_VIDEO_CODEC_VARIABLE = freeswitchPINVOKE.SWITCH_ORIGINATOR_VIDEO_CODEC_VARIABLE_get(); public static readonly string SWITCH_LOCAL_MEDIA_IP_VARIABLE = freeswitchPINVOKE.SWITCH_LOCAL_MEDIA_IP_VARIABLE_get(); public static readonly string SWITCH_LOCAL_MEDIA_PORT_VARIABLE = freeswitchPINVOKE.SWITCH_LOCAL_MEDIA_PORT_VARIABLE_get(); + public static readonly string SWITCH_ADVERTISED_MEDIA_IP_VARIABLE = freeswitchPINVOKE.SWITCH_ADVERTISED_MEDIA_IP_VARIABLE_get(); public static readonly string SWITCH_REMOTE_MEDIA_IP_VARIABLE = freeswitchPINVOKE.SWITCH_REMOTE_MEDIA_IP_VARIABLE_get(); public static readonly string SWITCH_REMOTE_MEDIA_PORT_VARIABLE = freeswitchPINVOKE.SWITCH_REMOTE_MEDIA_PORT_VARIABLE_get(); public static readonly string SWITCH_REMOTE_VIDEO_IP_VARIABLE = freeswitchPINVOKE.SWITCH_REMOTE_VIDEO_IP_VARIABLE_get(); @@ -6424,6 +6435,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_LOCAL_MEDIA_PORT_VARIABLE_get")] public static extern string SWITCH_LOCAL_MEDIA_PORT_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_ADVERTISED_MEDIA_IP_VARIABLE_get")] + public static extern string SWITCH_ADVERTISED_MEDIA_IP_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_REMOTE_MEDIA_IP_VARIABLE_get")] public static extern string SWITCH_REMOTE_MEDIA_IP_VARIABLE_get(); @@ -8374,12 +8388,18 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_management_exec")] public static extern int switch_core_management_exec(string jarg1, int jarg2, string jarg3, HandleRef jarg4); - [DllImport("mod_managed", EntryPoint="CSharp_set_high_priority")] - public static extern int set_high_priority(); - [DllImport("mod_managed", EntryPoint="CSharp_set_normal_priority")] public static extern int set_normal_priority(); + [DllImport("mod_managed", EntryPoint="CSharp_set_auto_priority")] + public static extern int set_auto_priority(); + + [DllImport("mod_managed", EntryPoint="CSharp_set_realtime_priority")] + public static extern int set_realtime_priority(); + + [DllImport("mod_managed", EntryPoint="CSharp_set_low_priority")] + public static extern int set_low_priority(); + [DllImport("mod_managed", EntryPoint="CSharp_change_user_group")] public static extern int change_user_group(string jarg1, string jarg2); @@ -23817,7 +23837,8 @@ namespace FreeSWITCH.Native { SCF_AUTO_SCHEMAS = (1 << 13), SCF_MINIMAL = (1 << 14), SCF_USE_NAT_MAPPING = (1 << 15), - SCF_CLEAR_SQL = (1 << 16) + SCF_CLEAR_SQL = (1 << 16), + SCF_THREADED_SYSTEM_EXEC = (1 << 17) } } @@ -26537,7 +26558,8 @@ namespace FreeSWITCH.Native { SFF_PROXY_PACKET = (1 << 5), SFF_DYNAMIC = (1 << 6), SFF_ZRTP = (1 << 7), - SFF_UDPTL_PACKET = (1 << 8) + SFF_UDPTL_PACKET = (1 << 8), + SFF_NOT_AUDIO = (1 << 9) } } @@ -30358,7 +30380,8 @@ public enum switch_session_ctl_t { SCSC_VERBOSE_EVENTS, SCSC_SHUTDOWN_CHECK, SCSC_PAUSE_CHECK, - SCSC_READY_CHECK + SCSC_READY_CHECK, + SCSC_THREADED_SYSTEM_EXEC } } diff --git a/src/mod/languages/mod_perl/mod_perl_wrap.cpp b/src/mod/languages/mod_perl/mod_perl_wrap.cpp index 19700c2bcd..3957f52448 100644 --- a/src/mod/languages/mod_perl/mod_perl_wrap.cpp +++ b/src/mod/languages/mod_perl/mod_perl_wrap.cpp @@ -9912,17 +9912,17 @@ XS(SWIG_init) { SWIG_TypeClientData(SWIGTYPE_p_IVRMenu, (void*) "freeswitch::IVRMenu"); SWIG_TypeClientData(SWIGTYPE_p_API, (void*) "freeswitch::API"); SWIG_TypeClientData(SWIGTYPE_p_input_callback_state, (void*) "freeswitch::input_callback_state_t"); - /*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { + /*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { SV *sv = get_sv((char*) SWIG_prefix "S_HUP", TRUE | 0x2 | GV_ADDMULTI); sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_HUP))); SvREADONLY_on(sv); } while(0) /*@SWIG@*/; - /*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { + /*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { SV *sv = get_sv((char*) SWIG_prefix "S_FREE", TRUE | 0x2 | GV_ADDMULTI); sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_FREE))); SvREADONLY_on(sv); } while(0) /*@SWIG@*/; - /*@SWIG:/usr/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { + /*@SWIG:/usr/local/share/swig/1.3.35/perl5/perltypemaps.swg,64,%set_constant@*/ do { SV *sv = get_sv((char*) SWIG_prefix "S_RDLOCK", TRUE | 0x2 | GV_ADDMULTI); sv_setsv(sv, SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(S_RDLOCK))); SvREADONLY_on(sv); From d354399c8ad8780ef1bbc4303276c0a17cd9cba3 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 12 Sep 2011 17:54:07 -0500 Subject: [PATCH 084/204] wtf --- src/switch_core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/switch_core.c b/src/switch_core.c index c4ce502721..89b683c02d 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -2297,7 +2297,6 @@ static void *SWITCH_THREAD_FUNC system_thread(switch_thread_t *thread, void *obj #endif sth->ret = system(sth->cmd); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "WTF %d %s\n", sth->ret, strerror(errno)); #if 0 #if defined(HAVE_SETRLIMIT) && !defined(__FreeBSD__) From 2fb0f8e24f9b1619579e6a752db24ec33401da76 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 12 Sep 2011 16:38:48 -0500 Subject: [PATCH 085/204] only unlink if file exists --- src/mod/applications/mod_voicemail/mod_voicemail.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index aa06fb6300..0b88532874 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -2848,7 +2848,7 @@ static switch_status_t deliver_vm(vm_profile_t *profile, failed: - if (del_file && file_path) { + if (del_file && file_path && switch_file_exists(file_path, pool)) { if (unlink(file_path) != 0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to delete file [%s]\n", file_path); } From 722f10606a1fdf8358598bc2082c6eedff1075ca Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 12 Sep 2011 21:05:15 -0500 Subject: [PATCH 086/204] fix windows build for now --- src/switch_core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/switch_core.c b/src/switch_core.c index 89b683c02d..b64e185dd1 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -730,13 +730,14 @@ SWITCH_DECLARE(int32_t) set_normal_priority(void) SWITCH_DECLARE(int32_t) set_auto_priority(void) { +#ifndef WIN32 runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN); /* If we have more than 1 cpu, we should use realtime priority so we can have priority threads */ if (runtime.cpu_count > 1) { return set_realtime_priority(); } - +#endif return 0; } @@ -1381,8 +1382,9 @@ SWITCH_DECLARE(switch_status_t) switch_core_init(switch_core_flag_t flags, switc runtime.min_dtmf_duration = SWITCH_MIN_DTMF_DURATION; runtime.odbc_dbtype = DBTYPE_DEFAULT; runtime.dbname = NULL; +#ifndef WIN32 runtime.cpu_count = sysconf (_SC_NPROCESSORS_ONLN); - +#endif /* INIT APR and Create the pool context */ if (apr_initialize() != SWITCH_STATUS_SUCCESS) { From 114f05789a8da6ba72e9cc6324230c9ba2032821 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Mon, 12 Sep 2011 21:07:19 -0500 Subject: [PATCH 087/204] vs2010 reswig --- .../mod_managed/freeswitch_wrap.2010.cxx | 50 +++++++++++++++---- .../mod_managed/managed/swig.2010.cs | 46 +++++++++++++---- 2 files changed, 75 insertions(+), 21 deletions(-) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx index 8c341715ef..0935ec7d17 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx @@ -1551,6 +1551,16 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_LOCAL_MEDIA_PORT_VARIABLE_get() { } +SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_ADVERTISED_MEDIA_IP_VARIABLE_get() { + char * jresult ; + char *result = 0 ; + + result = (char *)("advertised_media_ip"); + jresult = SWIG_csharp_string_callback((const char *)result); + return jresult; +} + + SWIGEXPORT char * SWIGSTDCALL CSharp_SWITCH_REMOTE_MEDIA_IP_VARIABLE_get() { char * jresult ; char *result = 0 ; @@ -9680,16 +9690,6 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_management_exec(char * jarg1, int } -SWIGEXPORT int SWIGSTDCALL CSharp_set_high_priority() { - int jresult ; - int32_t result; - - result = (int32_t)set_high_priority(); - jresult = result; - return jresult; -} - - SWIGEXPORT int SWIGSTDCALL CSharp_set_normal_priority() { int jresult ; int32_t result; @@ -9700,6 +9700,36 @@ SWIGEXPORT int SWIGSTDCALL CSharp_set_normal_priority() { } +SWIGEXPORT int SWIGSTDCALL CSharp_set_auto_priority() { + int jresult ; + int32_t result; + + result = (int32_t)set_auto_priority(); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_set_realtime_priority() { + int jresult ; + int32_t result; + + result = (int32_t)set_realtime_priority(); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_set_low_priority() { + int jresult ; + int32_t result; + + result = (int32_t)set_low_priority(); + jresult = result; + return jresult; +} + + SWIGEXPORT int SWIGSTDCALL CSharp_change_user_group(char * jarg1, char * jarg2) { int jresult ; char *arg1 = (char *) 0 ; diff --git a/src/mod/languages/mod_managed/managed/swig.2010.cs b/src/mod/languages/mod_managed/managed/swig.2010.cs index 62440a3970..72231bd0dc 100644 --- a/src/mod/languages/mod_managed/managed/swig.2010.cs +++ b/src/mod/languages/mod_managed/managed/swig.2010.cs @@ -2198,13 +2198,23 @@ public class freeswitch { return ret; } - public static int set_high_priority() { - int ret = freeswitchPINVOKE.set_high_priority(); + public static int set_normal_priority() { + int ret = freeswitchPINVOKE.set_normal_priority(); return ret; } - public static int set_normal_priority() { - int ret = freeswitchPINVOKE.set_normal_priority(); + public static int set_auto_priority() { + int ret = freeswitchPINVOKE.set_auto_priority(); + return ret; + } + + public static int set_realtime_priority() { + int ret = freeswitchPINVOKE.set_realtime_priority(); + return ret; + } + + public static int set_low_priority() { + int ret = freeswitchPINVOKE.set_low_priority(); return ret; } @@ -5794,6 +5804,7 @@ public class freeswitch { public static readonly string SWITCH_ORIGINATOR_VIDEO_CODEC_VARIABLE = freeswitchPINVOKE.SWITCH_ORIGINATOR_VIDEO_CODEC_VARIABLE_get(); public static readonly string SWITCH_LOCAL_MEDIA_IP_VARIABLE = freeswitchPINVOKE.SWITCH_LOCAL_MEDIA_IP_VARIABLE_get(); public static readonly string SWITCH_LOCAL_MEDIA_PORT_VARIABLE = freeswitchPINVOKE.SWITCH_LOCAL_MEDIA_PORT_VARIABLE_get(); + public static readonly string SWITCH_ADVERTISED_MEDIA_IP_VARIABLE = freeswitchPINVOKE.SWITCH_ADVERTISED_MEDIA_IP_VARIABLE_get(); public static readonly string SWITCH_REMOTE_MEDIA_IP_VARIABLE = freeswitchPINVOKE.SWITCH_REMOTE_MEDIA_IP_VARIABLE_get(); public static readonly string SWITCH_REMOTE_MEDIA_PORT_VARIABLE = freeswitchPINVOKE.SWITCH_REMOTE_MEDIA_PORT_VARIABLE_get(); public static readonly string SWITCH_REMOTE_VIDEO_IP_VARIABLE = freeswitchPINVOKE.SWITCH_REMOTE_VIDEO_IP_VARIABLE_get(); @@ -6438,6 +6449,9 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_LOCAL_MEDIA_PORT_VARIABLE_get")] public static extern string SWITCH_LOCAL_MEDIA_PORT_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_ADVERTISED_MEDIA_IP_VARIABLE_get")] + public static extern string SWITCH_ADVERTISED_MEDIA_IP_VARIABLE_get(); + [DllImport("mod_managed", EntryPoint="CSharp_SWITCH_REMOTE_MEDIA_IP_VARIABLE_get")] public static extern string SWITCH_REMOTE_MEDIA_IP_VARIABLE_get(); @@ -8388,12 +8402,18 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_core_management_exec")] public static extern int switch_core_management_exec(string jarg1, int jarg2, string jarg3, HandleRef jarg4); - [DllImport("mod_managed", EntryPoint="CSharp_set_high_priority")] - public static extern int set_high_priority(); - [DllImport("mod_managed", EntryPoint="CSharp_set_normal_priority")] public static extern int set_normal_priority(); + [DllImport("mod_managed", EntryPoint="CSharp_set_auto_priority")] + public static extern int set_auto_priority(); + + [DllImport("mod_managed", EntryPoint="CSharp_set_realtime_priority")] + public static extern int set_realtime_priority(); + + [DllImport("mod_managed", EntryPoint="CSharp_set_low_priority")] + public static extern int set_low_priority(); + [DllImport("mod_managed", EntryPoint="CSharp_change_user_group")] public static extern int change_user_group(string jarg1, string jarg2); @@ -23891,7 +23911,8 @@ namespace FreeSWITCH.Native { SCF_AUTO_SCHEMAS = (1 << 13), SCF_MINIMAL = (1 << 14), SCF_USE_NAT_MAPPING = (1 << 15), - SCF_CLEAR_SQL = (1 << 16) + SCF_CLEAR_SQL = (1 << 16), + SCF_THREADED_SYSTEM_EXEC = (1 << 17) } } @@ -26639,7 +26660,8 @@ namespace FreeSWITCH.Native { SFF_PROXY_PACKET = (1 << 5), SFF_DYNAMIC = (1 << 6), SFF_ZRTP = (1 << 7), - SFF_UDPTL_PACKET = (1 << 8) + SFF_UDPTL_PACKET = (1 << 8), + SFF_NOT_AUDIO = (1 << 9) } } @@ -29469,7 +29491,8 @@ public enum switch_rtp_bug_flag_t { RTP_BUG_SEND_LINEAR_TIMESTAMPS = (1 << 3), RTP_BUG_START_SEQ_AT_ZERO = (1 << 4), RTP_BUG_NEVER_SEND_MARKER = (1 << 5), - RTP_BUG_IGNORE_DTMF_DURATION = (1 << 6) + RTP_BUG_IGNORE_DTMF_DURATION = (1 << 6), + RTP_BUG_ACCEPT_ANY_PACKETS = (1 << 7) } } @@ -30521,7 +30544,8 @@ public enum switch_session_ctl_t { SCSC_VERBOSE_EVENTS, SCSC_SHUTDOWN_CHECK, SCSC_PAUSE_CHECK, - SCSC_READY_CHECK + SCSC_READY_CHECK, + SCSC_THREADED_SYSTEM_EXEC } } From 0651b01abf9b5fb30a6e825cd0820ddfcc3fa343 Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Tue, 13 Sep 2011 10:40:33 -0500 Subject: [PATCH 088/204] correct sofia_count_reg_function behavior reported from user list --- src/mod/endpoints/mod_sofia/mod_sofia.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 147dc279be..8ef3b92663 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -3616,12 +3616,12 @@ SWITCH_STANDARD_API(sofia_count_reg_function) if (zstr(user)) { sql = switch_mprintf("select count(*) " "from sip_registrations where (sip_host='%q' or presence_hosts like '%%%q%%')", - (concat != NULL) ? concat : "", domain, domain); + domain, domain); } else { sql = switch_mprintf("select count(*) " - "from sip_registrations where (sip_user='%q' or dir_user='%q') and (sip_host='%q' or presence_hosts like '%%%q%%')", - (concat != NULL) ? concat : "", user, user, domain, domain); + "from sip_registrations where sip_user='%q' and (sip_host='%q' or presence_hosts like '%%%q%%')", + user, domain, domain); } switch_assert(sql); sofia_glue_execute_sql_callback(profile, profile->ireg_mutex, sql, sql2str_callback, &cb); From 4c3a0eb35702ac4ceae5db24dda85f67b84b23d8 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 13 Sep 2011 08:37:40 -0500 Subject: [PATCH 089/204] fix build for n00buntu --- src/switch_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/switch_core.c b/src/switch_core.c index b64e185dd1..045ff3978c 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -2402,7 +2402,7 @@ static int switch_system_fork(const char *cmd, switch_bool_t wait) } set_low_priority(); - system(cmd); + i = system(cmd); exit(0); } From 637a5ed83d73fbe215fd7b30eabb917784786baf Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 13 Sep 2011 09:35:41 -0500 Subject: [PATCH 090/204] Add application flag zombie_exec so registered applications can apply to be executed on channels that are already hungup, like the inline exec this is only limited to a small family of apps that do not use the channel for audio. --- src/include/switch_types.h | 3 +- src/mod/applications/mod_db/mod_db.c | 4 +-- .../applications/mod_dptools/mod_dptools.c | 24 ++++++------- src/mod/applications/mod_hash/mod_hash.c | 2 +- src/switch_core_session.c | 34 ++++++++++++++++--- src/switch_core_state_machine.c | 19 +++++++++++ 6 files changed, 65 insertions(+), 21 deletions(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 97fbc942af..8bcf9b6b53 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1214,7 +1214,8 @@ typedef enum { SAF_NONE = 0, SAF_SUPPORT_NOMEDIA = (1 << 0), SAF_ROUTING_EXEC = (1 << 1), - SAF_MEDIA_TAP = (1 << 2) + SAF_MEDIA_TAP = (1 << 2), + SAF_ZOMBIE_EXEC = (1 << 3) } switch_application_flag_enum_t; typedef uint32_t switch_application_flag_t; diff --git a/src/mod/applications/mod_db/mod_db.c b/src/mod/applications/mod_db/mod_db.c index 165e02e949..dccc6c9a2f 100644 --- a/src/mod/applications/mod_db/mod_db.c +++ b/src/mod/applications/mod_db/mod_db.c @@ -622,8 +622,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_db_load) /* register limit interfaces */ SWITCH_ADD_LIMIT(limit_interface, "db", limit_incr_db, limit_release_db, limit_usage_db, limit_reset_db, limit_status_db, NULL); - SWITCH_ADD_APP(app_interface, "db", "Insert to the db", DB_DESC, db_function, DB_USAGE, SAF_SUPPORT_NOMEDIA); - SWITCH_ADD_APP(app_interface, "group", "Manage a group", GROUP_DESC, group_function, GROUP_USAGE, SAF_SUPPORT_NOMEDIA); + SWITCH_ADD_APP(app_interface, "db", "Insert to the db", DB_DESC, db_function, DB_USAGE, SAF_SUPPORT_NOMEDIA | SAF_ZOMBIE_EXEC); + SWITCH_ADD_APP(app_interface, "group", "Manage a group", GROUP_DESC, group_function, GROUP_USAGE, SAF_SUPPORT_NOMEDIA | SAF_ZOMBIE_EXEC); SWITCH_ADD_API(commands_api_interface, "db", "db get/set", db_api_function, "[insert|delete|select]///"); switch_console_set_complete("add db insert"); switch_console_set_complete("add db delete"); diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 0e89b9049b..c8366f05c8 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -3916,7 +3916,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "delay_echo", "echo audio at a specified delay", "Delay n ms", delay_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "strftime", "strftime", "strftime", strftime_function, "[|]", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "phrase", "Say a Phrase", "Say a Phrase", phrase_function, ",", SAF_NONE); - SWITCH_ADD_APP(app_interface, "eval", "Do Nothing", "Do Nothing", eval_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + SWITCH_ADD_APP(app_interface, "eval", "Do Nothing", "Do Nothing", eval_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); SWITCH_ADD_APP(app_interface, "pre_answer", "Pre-Answer the call", "Pre-Answer the call for a channel.", pre_answer_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "answer", "Answer the call", "Answer the call for a channel.", answer_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "hangup", "Hangup the call", "Hangup the call for a channel.", hangup_function, "[]", SAF_SUPPORT_NOMEDIA); @@ -3924,29 +3924,29 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "presence", "Send Presence", "Send Presence.", presence_function, " []", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); SWITCH_ADD_APP(app_interface, "log", "Logs to the logger", LOG_LONG_DESC, log_function, " ", - SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); - SWITCH_ADD_APP(app_interface, "info", "Display Call Info", "Display Call Info", info_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); - SWITCH_ADD_APP(app_interface, "event", "Fire an event", "Fire an event", event_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC | SAF_ZOMBIE_EXEC); + SWITCH_ADD_APP(app_interface, "info", "Display Call Info", "Display Call Info", info_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); + SWITCH_ADD_APP(app_interface, "event", "Fire an event", "Fire an event", event_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); SWITCH_ADD_APP(app_interface, "sound_test", "Analyze Audio", "Analyze Audio", sound_test_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "export", "Export a channel variable across a bridge", EXPORT_LONG_DESC, export_function, "=", - SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); SWITCH_ADD_APP(app_interface, "bridge_export", "Export a channel variable across a bridge", EXPORT_LONG_DESC, bridge_export_function, "=", - SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); SWITCH_ADD_APP(app_interface, "set", "Set a channel variable", SET_LONG_DESC, set_function, "=", - SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); SWITCH_ADD_APP(app_interface, "push", "Set a channel variable", SET_LONG_DESC, push_function, "=", - SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); SWITCH_ADD_APP(app_interface, "unshift", "Set a channel variable", SET_LONG_DESC, unshift_function, "=", - SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); SWITCH_ADD_APP(app_interface, "set_global", "Set a global variable", SET_GLOBAL_LONG_DESC, set_global_function, "=", - SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); SWITCH_ADD_APP(app_interface, "set_profile_var", "Set a caller profile variable", SET_PROFILE_VAR_LONG_DESC, set_profile_var_function, - "=", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + "=", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); SWITCH_ADD_APP(app_interface, "unset", "Unset a channel variable", UNSET_LONG_DESC, unset_function, "", - SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); SWITCH_ADD_APP(app_interface, "ring_ready", "Indicate Ring_Ready", "Indicate Ring_Ready on a channel.", ring_ready_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "remove_bugs", "Remove media bugs", "Remove all media bugs from a channel.", remove_bugs_function, "", SAF_NONE); SWITCH_ADD_APP(app_interface, "break", "Break", "Set the break flag.", break_function, "", SAF_SUPPORT_NOMEDIA); diff --git a/src/mod/applications/mod_hash/mod_hash.c b/src/mod/applications/mod_hash/mod_hash.c index f9b808fad1..25b3c8abfc 100644 --- a/src/mod/applications/mod_hash/mod_hash.c +++ b/src/mod/applications/mod_hash/mod_hash.c @@ -945,7 +945,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_hash_load) switch_scheduler_add_task(switch_epoch_time_now(NULL) + LIMIT_HASH_CLEANUP_INTERVAL, limit_hash_cleanup_callback, "limit_hash_cleanup", "mod_hash", 0, NULL, SSHF_NONE); - SWITCH_ADD_APP(app_interface, "hash", "Insert into the hashtable", HASH_DESC, hash_function, HASH_USAGE, SAF_SUPPORT_NOMEDIA) + SWITCH_ADD_APP(app_interface, "hash", "Insert into the hashtable", HASH_DESC, hash_function, HASH_USAGE, SAF_SUPPORT_NOMEDIA | SAF_ZOMBIE_EXEC) SWITCH_ADD_API(commands_api_interface, "hash", "hash get/set", hash_api_function, "[insert|delete|select]///"); SWITCH_ADD_API(commands_api_interface, "hash_dump", "dump hash/limit_hash data (used for synchronization)", hash_dump_function, HASH_DUMP_SYNTAX); SWITCH_ADD_API(commands_api_interface, "hash_remote", "hash remote", hash_remote_function, HASH_REMOTE_SYNTAX); diff --git a/src/switch_core_session.c b/src/switch_core_session.c index b3f6d15eb8..cfeeab028c 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -2025,13 +2025,35 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flag switch_application_interface_t *application_interface; switch_status_t status = SWITCH_STATUS_SUCCESS; - if (!arg && strstr(app, "::")) { - return switch_core_session_execute_application_async(session, app, arg); + if (switch_channel_down(session->channel)) { + char *p; + if (!arg && (p = strstr(app, "::"))) { + *p++ = '0'; + *p++ = '0'; + arg = p; + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s ASYNC CALL CONVERTED TO INLINE %s(%s)\n", + switch_channel_get_name(session->channel), app, switch_str_nil(arg)); + } + + if ((application_interface = switch_loadable_module_get_application_interface(app)) == 0) { + return SWITCH_STATUS_FALSE; + } + + if (switch_test_flag(application_interface, SAF_ZOMBIE_EXEC)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s ZOMBIE EXEC %s(%s)\n", + switch_channel_get_name(session->channel), app, switch_str_nil(arg)); + goto exec; + } + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, + "%s Channel is hungup and application '%s' does not have the zombie_exec flag.\n", + switch_channel_get_name(session->channel), app); + return SWITCH_STATUS_FALSE; } - if (switch_channel_down(session->channel)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Channel is hungup, aborting execution of application: %s\n", app); - return SWITCH_STATUS_FALSE; + if (!arg && strstr(app, "::")) { + return switch_core_session_execute_application_async(session, app, arg); } if ((application_interface = switch_loadable_module_get_application_interface(app)) == 0) { @@ -2079,6 +2101,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flag } } + exec: + switch_core_session_exec(session, application_interface, arg); done: diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index 4c191249df..2136de30c2 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -42,9 +42,28 @@ static void switch_core_standard_on_init(switch_core_session_t *session) static void switch_core_standard_on_hangup(switch_core_session_t *session) { + switch_caller_extension_t *extension; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard HANGUP, cause: %s\n", switch_channel_get_name(session->channel), switch_channel_cause2str(switch_channel_get_cause(session->channel))); + + if ((extension = switch_channel_get_caller_extension(session->channel)) == 0) { + return; + } + + while(extension->current_application) { + switch_caller_application_t *current_application = extension->current_application; + + extension->current_application = extension->current_application->next; + + if (switch_core_session_execute_application(session, + current_application->application_name, + current_application->application_data) != SWITCH_STATUS_SUCCESS) { + return; + } + } + + } static void switch_core_standard_on_reporting(switch_core_session_t *session) From 4cb49fbaa09b865d01ae8b0dd86954327d63dec7 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 13 Sep 2011 16:19:00 -0500 Subject: [PATCH 091/204] fix some minor internal dtmf issues --- .../applications/mod_dptools/mod_dptools.c | 7 +-- src/switch_channel.c | 29 ++++++------ src/switch_core_io.c | 45 ++++++++++--------- 3 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index c8366f05c8..1c8fe1262e 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -110,7 +110,6 @@ static switch_status_t digit_nomatch_action_callback(switch_ivr_dmachine_match_t { switch_core_session_t *session = (switch_core_session_t *) match->user_data; switch_channel_t *channel; - char str[DMACHINE_MAX_DIGIT_LEN + 2]; switch_event_t *event; switch_status_t status; switch_core_session_t *use_session = session; @@ -139,10 +138,8 @@ static switch_status_t digit_nomatch_action_callback(switch_ivr_dmachine_match_t } } - /* send it back around flagged to skip the dmachine */ - switch_snprintf(str, sizeof(str), "!%s", match->match_digits); - - switch_channel_queue_dtmf_string(channel, str); + /* send it back around and skip the dmachine */ + switch_channel_queue_dtmf_string(channel, match->match_digits); if (use_session != session) { switch_core_session_rwunlock(use_session); diff --git a/src/switch_channel.c b/src/switch_channel.c index 5650b1ef3b..2055e8fc07 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -430,9 +430,12 @@ SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf_string(switch_channel_ return SWITCH_STATUS_FALSE; } - if (*dtmf_string == '!') { + + dtmf.flags = DTMF_FLAG_SKIP_PROCESS; + + if (*dtmf_string == '~') { dtmf_string++; - dtmf.flags = DTMF_FLAG_SKIP_PROCESS; + dtmf.flags = 0; } string = switch_core_session_strdup(channel->session, dtmf_string); @@ -448,20 +451,20 @@ SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf_string(switch_channel_ } } - if (dtmf.duration > switch_core_max_dtmf_duration(0)) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "EXCESSIVE DTMF DIGIT LEN %c %d\n", dtmf.digit, dtmf.duration); - dtmf.duration = switch_core_max_dtmf_duration(0); - } else if (dtmf.duration < switch_core_min_dtmf_duration(0)) { - switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "SHORT DTMF DIGIT LEN %c %d\n", dtmf.digit, dtmf.duration); - dtmf.duration = switch_core_min_dtmf_duration(0); - } else if (!dtmf.duration) { - dtmf.duration = switch_core_default_dtmf_duration(0); - } - - for (p = argv[i]; p && *p; p++) { if (is_dtmf(*p)) { dtmf.digit = *p; + + if (dtmf.duration > switch_core_max_dtmf_duration(0)) { + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "EXCESSIVE DTMF DIGIT LEN %c %d\n", dtmf.digit, dtmf.duration); + dtmf.duration = switch_core_max_dtmf_duration(0); + } else if (dtmf.duration < switch_core_min_dtmf_duration(0)) { + switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_WARNING, "SHORT DTMF DIGIT LEN %c %d\n", dtmf.digit, dtmf.duration); + dtmf.duration = switch_core_min_dtmf_duration(0); + } else if (!dtmf.duration) { + dtmf.duration = switch_core_default_dtmf_duration(0); + } + if (switch_channel_queue_dtmf(channel, &dtmf) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_CHANNEL_LOG(channel), SWITCH_LOG_DEBUG, "%s Queue dtmf\ndigit=%c ms=%u samples=%u\n", switch_channel_get_name(channel), dtmf.digit, dur, dtmf.duration); diff --git a/src/switch_core_io.c b/src/switch_core_io.c index 587218339a..a36d55776b 100644 --- a/src/switch_core_io.c +++ b/src/switch_core_io.c @@ -1354,14 +1354,14 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_sessio new_dtmf.duration = switch_core_default_dtmf_duration(0); } - - for (ptr = session->event_hooks.send_dtmf; ptr; ptr = ptr->next) { - if ((status = ptr->send_dtmf(session, dtmf, SWITCH_DTMF_SEND)) != SWITCH_STATUS_SUCCESS) { - return SWITCH_STATUS_SUCCESS; - } - } - if (!switch_test_flag(dtmf, DTMF_FLAG_SKIP_PROCESS)) { + if (!switch_test_flag(dtmf, DTMF_FLAG_SKIP_PROCESS)) { + for (ptr = session->event_hooks.send_dtmf; ptr; ptr = ptr->next) { + if ((status = ptr->send_dtmf(session, dtmf, SWITCH_DTMF_SEND)) != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_SUCCESS; + } + } + if (session->dmachine[1] && !switch_channel_test_flag(session->channel, CF_BROADCAST)) { char str[2] = { new_dtmf.digit, '\0' }; switch_ivr_dmachine_feed(session->dmachine[1], str, NULL); @@ -1396,7 +1396,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf(switch_core_sessio SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf_string(switch_core_session_t *session, const char *dtmf_string) { char *p; - switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0) }; + switch_dtmf_t dtmf = { 0, switch_core_default_dtmf_duration(0), DTMF_FLAG_SKIP_PROCESS, 0}; int sent = 0, dur; char *string; int i, argc; @@ -1405,6 +1405,10 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf_string(switch_core switch_assert(session != NULL); + if (*dtmf_string == '~') { + dtmf_string++; + dtmf.flags = 0; + } if (switch_channel_down(session->channel)) { return SWITCH_STATUS_FALSE; @@ -1437,21 +1441,22 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_send_dtmf_string(switch_core } - if (dtmf.duration > switch_core_max_dtmf_duration(0)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s EXCESSIVE DTMF DIGIT [%c] LEN [%d]\n", - switch_channel_get_name(session->channel), dtmf.digit, dtmf.duration); - dtmf.duration = switch_core_max_dtmf_duration(0); - } else if (dtmf.duration < switch_core_min_dtmf_duration(0)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s SHORT DTMF DIGIT [%c] LEN [%d]\n", - switch_channel_get_name(session->channel), dtmf.digit, dtmf.duration); - dtmf.duration = switch_core_min_dtmf_duration(0); - } else if (!dtmf.duration) { - dtmf.duration = switch_core_default_dtmf_duration(0); - } - for (p = argv[i]; p && *p; p++) { if (is_dtmf(*p)) { dtmf.digit = *p; + + if (dtmf.duration > switch_core_max_dtmf_duration(0)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s EXCESSIVE DTMF DIGIT [%c] LEN [%d]\n", + switch_channel_get_name(session->channel), dtmf.digit, dtmf.duration); + dtmf.duration = switch_core_max_dtmf_duration(0); + } else if (dtmf.duration < switch_core_min_dtmf_duration(0)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "%s SHORT DTMF DIGIT [%c] LEN [%d]\n", + switch_channel_get_name(session->channel), dtmf.digit, dtmf.duration); + dtmf.duration = switch_core_min_dtmf_duration(0); + } else if (!dtmf.duration) { + dtmf.duration = switch_core_default_dtmf_duration(0); + } + if (switch_core_session_send_dtmf(session, &dtmf) == SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s send dtmf\ndigit=%c ms=%u samples=%u\n", switch_channel_get_name(session->channel), dtmf.digit, dur, dtmf.duration); From b4b99c410d742b09ec11c97b359d7e69eafcf7d8 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 13 Sep 2011 16:50:05 -0500 Subject: [PATCH 092/204] do not escape strings inside single quotes unless we can find a closing quote too --- src/switch_utils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/switch_utils.c b/src/switch_utils.c index 50f1725f5e..1c49fb4104 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -1871,7 +1871,7 @@ static char *cleanup_separated_string(char *str, char delim) } } if (!esc) { - if (*ptr == '\'') { + if (*ptr == '\'' && (inside_quotes || ((ptr+1) && strchr(ptr+1, '\'')))) { if ((inside_quotes = (1 - inside_quotes))) { end = dest; } @@ -1934,7 +1934,7 @@ static unsigned int separate_string_char_delim(char *buf, char delim, char **arr /* escaped characters are copied verbatim to the destination string */ if (*ptr == ESCAPE_META) { ++ptr; - } else if (*ptr == '\'') { + } else if (*ptr == '\'' && (inside_quotes || ((ptr+1) && strchr(ptr+1, '\'')))) { inside_quotes = (1 - inside_quotes); } else if (*ptr == delim && !inside_quotes) { *ptr = '\0'; From 9125a96c6da2ba4bd40783dd473c6fb4ec67cbe3 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 13 Sep 2011 16:51:30 -0500 Subject: [PATCH 093/204] convert chat interface to use events instead of a bunch of args --- src/include/switch_core.h | 6 +- src/include/switch_module_interfaces.h | 4 +- .../mod_conference/mod_conference.c | 39 +++++++---- .../applications/mod_dptools/mod_dptools.c | 67 ++++++++++-------- .../endpoints/mod_dingaling/mod_dingaling.c | 58 ++++++++++++--- src/mod/endpoints/mod_skypopen/mod_skypopen.c | 61 +++++++++++++--- src/mod/endpoints/mod_sofia/mod_sofia.c | 2 + src/mod/endpoints/mod_sofia/mod_sofia.h | 4 +- src/mod/endpoints/mod_sofia/sofia_presence.c | 66 ++++++++++------- src/switch_loadable_module.c | 70 ++++++++++++++++--- 10 files changed, 273 insertions(+), 104 deletions(-) diff --git a/src/include/switch_core.h b/src/include/switch_core.h index da6a2e6ada..1591cf18cc 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -2107,8 +2107,10 @@ SWITCH_DECLARE(switch_status_t) switch_console_set_alias(const char *string); SWITCH_DECLARE(int) switch_system(const char *cmd, switch_bool_t wait); SWITCH_DECLARE(void) switch_cond_yield(switch_interval_time_t t); SWITCH_DECLARE(void) switch_cond_next(void); -SWITCH_DECLARE(switch_status_t) switch_core_chat_send(const char *name, const char *proto, const char *from, const char *to, - const char *subject, const char *body, const char *type, const char *hint); +SWITCH_DECLARE(switch_status_t) switch_core_chat_send_args(const char *dest_proto, const char *proto, const char *from, const char *to, + const char *subject, const char *body, const char *type, const char *hint); +SWITCH_DECLARE(switch_status_t) switch_core_chat_send(const char *dest_proto, switch_event_t *message_event); + SWITCH_DECLARE(switch_status_t) switch_ivr_preprocess_session(switch_core_session_t *session, const char *cmds); diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index 33c4c22bac..7c666ab9f4 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -483,8 +483,8 @@ struct switch_chat_interface { /*! the name of the interface */ const char *interface_name; /*! function to open the directory interface */ - switch_status_t (*chat_send) (const char *proto, const char *from, const char *to, - const char *subject, const char *body, const char *type, const char *hint); + switch_status_t (*chat_send) (switch_event_t *message_event); + switch_thread_rwlock_t *rwlock; int refs; switch_mutex_t *reflock; diff --git a/src/mod/applications/mod_conference/mod_conference.c b/src/mod/applications/mod_conference/mod_conference.c index b99ee84160..53d2f3f34a 100644 --- a/src/mod/applications/mod_conference/mod_conference.c +++ b/src/mod/applications/mod_conference/mod_conference.c @@ -436,8 +436,8 @@ static switch_status_t conference_member_play_file(conference_member_t *member, static switch_status_t conference_member_say(conference_member_t *member, char *text, uint32_t leadin); static uint32_t conference_member_stop_file(conference_member_t *member, file_stop_t stop); static conference_obj_t *conference_new(char *name, conf_xml_cfg_t cfg, switch_core_session_t *session, switch_memory_pool_t *pool); -static switch_status_t chat_send(const char *proto, const char *from, const char *to, const char *subject, - const char *body, const char *type, const char *hint); +static switch_status_t chat_send(switch_event_t *message_event); + static void launch_conference_record_thread(conference_obj_t *conference, char *path); static void launch_conference_video_bridge_thread(conference_member_t *member_a, conference_member_t *member_b); @@ -2705,19 +2705,16 @@ static void conference_loop_output(conference_member_t *member) if (event->event_id == SWITCH_EVENT_MESSAGE) { char *from = switch_event_get_header(event, "from"); char *to = switch_event_get_header(event, "to"); - char *proto = switch_event_get_header(event, "proto"); - char *subject = switch_event_get_header(event, "subject"); - char *hint = switch_event_get_header(event, "hint"); char *body = switch_event_get_body(event); - char *p, *freeme = NULL; + char *p; if (to && from && body) { if ((p = strchr(to, '+')) && strncmp(to, CONF_CHAT_PROTO, strlen(CONF_CHAT_PROTO))) { - freeme = switch_mprintf("%s+%s@%s", CONF_CHAT_PROTO, member->conference->name, member->conference->domain); - to = freeme; + switch_event_del_header(event, "to"); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, + "to", "%s+%s@%s", CONF_CHAT_PROTO, member->conference->name, member->conference->domain); } - chat_send(proto, from, to, subject, body, NULL, hint); - switch_safe_free(freeme); + chat_send(event); } } switch_event_destroy(&event); @@ -6379,12 +6376,26 @@ static void launch_conference_record_thread(conference_obj_t *conference, char * switch_thread_create(&thread, thd_attr, conference_record_thread_run, rec, rec->pool); } -static switch_status_t chat_send(const char *proto, const char *from, const char *to, const char *subject, - const char *body, const char *type, const char *hint) +static switch_status_t chat_send(switch_event_t *message_event) { char name[512] = "", *p, *lbuf = NULL; conference_obj_t *conference = NULL; switch_stream_handle_t stream = { 0 }; + const char *proto; + const char *from; + const char *to; + //const char *subject; + const char *body; + //const char *type; + const char *hint; + + proto = switch_event_get_header(message_event, "proto"); + from = switch_event_get_header(message_event, "from"); + to = switch_event_get_header(message_event, "to"); + //subject = switch_event_get_header(message_event, "subject"); + body = switch_event_get_body(message_event); + //type = switch_event_get_header(message_event, "type"); + hint = switch_event_get_header(message_event, "hint"); if ((p = strchr(to, '+'))) { to = ++p; @@ -6401,7 +6412,7 @@ static switch_status_t chat_send(const char *proto, const char *from, const char } if (!(conference = conference_find(name))) { - switch_core_chat_send(proto, CONF_CHAT_PROTO, to, hint && strchr(hint, '/') ? hint : from, "", "Conference not active.", NULL, NULL); + switch_core_chat_send_args(proto, CONF_CHAT_PROTO, to, hint && strchr(hint, '/') ? hint : from, "", "Conference not active.", NULL, NULL); return SWITCH_STATUS_FALSE; } @@ -6419,7 +6430,7 @@ static switch_status_t chat_send(const char *proto, const char *from, const char switch_safe_free(lbuf); - switch_core_chat_send(proto, CONF_CHAT_PROTO, to, hint && strchr(hint, '/') ? hint : from, "", stream.data, NULL, NULL); + switch_core_chat_send_args(proto, CONF_CHAT_PROTO, to, hint && strchr(hint, '/') ? hint : from, "", stream.data, NULL, NULL); switch_safe_free(stream.data); return SWITCH_STATUS_SUCCESS; diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 1c8fe1262e..4d21a6d681 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -1549,7 +1549,7 @@ SWITCH_STANDARD_API(chat_api_function) if (!zstr(cmd) && (lbuf = strdup(cmd)) && (argc = switch_separate_string(lbuf, '|', argv, (sizeof(argv) / sizeof(argv[0])))) >= 4) { - if (switch_core_chat_send(argv[0], "dp", argv[1], argv[2], "", argv[3], !zstr(argv[4]) ? argv[4] : NULL, "") == SWITCH_STATUS_SUCCESS) { + if (switch_core_chat_send_args(argv[0], "dp", argv[1], argv[2], "", argv[3], !zstr(argv[4]) ? argv[4] : NULL, "") == SWITCH_STATUS_SUCCESS) { stream->write_function(stream, "Sent"); } else { stream->write_function(stream, "Error! Message Not Sent"); @@ -3372,44 +3372,51 @@ SWITCH_STANDARD_APP(wait_for_silence_function) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Usage: %s\n", WAIT_FOR_SILENCE_SYNTAX); } -static switch_status_t event_chat_send(const char *proto, const char *from, const char *to, const char *subject, - const char *body, const char *type, const char *hint) +static switch_status_t event_chat_send(switch_event_t *message_event) + { switch_event_t *event; + const char *to; - if (switch_event_create(&event, SWITCH_EVENT_RECV_MESSAGE) == SWITCH_STATUS_SUCCESS) { - if (proto) - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Proto", proto); - if (from) - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "From", from); - if (subject) - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Subject", subject); - if (hint) - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Hint", hint); - if (body) - switch_event_add_body(event, "%s", body); - if (to) { - char *v; - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "To", to); - if ((v = switch_core_get_variable_dup(to))) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Command", v); - free(v); - } + switch_event_dup(&event, message_event); + event->event_id = SWITCH_EVENT_RECV_MESSAGE; + + if ((to = switch_event_get_header(event, "to"))) { + char *v; + if ((v = switch_core_get_variable_dup(to))) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Command", v); + free(v); } - - if (switch_event_fire(&event) == SWITCH_STATUS_SUCCESS) { - return SWITCH_STATUS_SUCCESS; - } - - switch_event_destroy(&event); } + if (switch_event_fire(&event) == SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_SUCCESS; + } + + switch_event_destroy(&event); + return SWITCH_STATUS_MEMERR; } -static switch_status_t api_chat_send(const char *proto, const char *from, const char *to, const char *subject, - const char *body, const char *type, const char *hint) +static switch_status_t api_chat_send(switch_event_t *message_event) { + const char *proto; + const char *from; + const char *to; + //const char *subject; + //const char *body; + const char *type; + const char *hint; + + proto = switch_event_get_header(message_event, "proto"); + from = switch_event_get_header(message_event, "from"); + to = switch_event_get_header(message_event, "to"); + //subject = switch_event_get_header(message_event, "subject"); + //body = switch_event_get_body(message_event); + type = switch_event_get_header(message_event, "type"); + hint = switch_event_get_header(message_event, "hint"); + + if (to) { char *v = NULL; switch_stream_handle_t stream = { 0 }; @@ -3432,7 +3439,7 @@ static switch_status_t api_chat_send(const char *proto, const char *from, const switch_api_execute(cmd, arg, NULL, &stream); if (proto) { - switch_core_chat_send(proto, "api", to, hint && strchr(hint, '/') ? hint : from, !zstr(type) ? type : NULL, (char *) stream.data, NULL, NULL); + switch_core_chat_send_args(proto, "api", to, hint && strchr(hint, '/') ? hint : from, !zstr(type) ? type : NULL, (char *) stream.data, NULL, NULL); } switch_safe_free(stream.data); diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index a0b9e7da28..a7e8537180 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -489,11 +489,25 @@ static void pres_event_handler(switch_event_t *event) switch_safe_free(sql); } -static switch_status_t chat_send(const char *proto, const char *from, const char *to, const char *subject, - const char *body, const char *type, const char *hint) +static switch_status_t chat_send(switch_event_t *message_event) { char *user, *host, *f_user = NULL, *ffrom = NULL, *f_host = NULL, *f_resource = NULL; mdl_profile_t *profile = NULL; + const char *proto; + const char *from; + const char *to; + const char *subject; + const char *body; + const char *type; + const char *hint; + + proto = switch_event_get_header(message_event, "proto"); + from = switch_event_get_header(message_event, "from"); + to = switch_event_get_header(message_event, "to"); + subject = switch_event_get_header(message_event, "subject"); + body = switch_event_get_body(message_event); + type = switch_event_get_header(message_event, "type"); + hint = switch_event_get_header(message_event, "hint"); switch_assert(proto != NULL); @@ -2876,8 +2890,8 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi char *proto = MDL_CHAT_PROTO; char *pproto = NULL, *ffrom = NULL; char *hint; - int got_proto = 0; - + switch_event_t *event; + char *from_user, *from_host; #ifdef AUTO_REPLY if (profile->auto_reply) { ldl_handle_send_msg(handle, @@ -2892,7 +2906,6 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi *to++ = '\0'; } proto = pproto; - got_proto++; } hint = from; @@ -2905,13 +2918,40 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi from = ffrom; } - if (strcasecmp(proto, MDL_CHAT_PROTO)) { /* yes no ! on purpose */ - switch_core_chat_send(proto, MDL_CHAT_PROTO, from, to, subject, switch_str_nil(msg), NULL, hint); + from_user = strdup(from); + if ((from_host = strchr(from_user, '@'))) { + *from_host++ = '\0'; } - if (!got_proto) { - switch_core_chat_send("GLOBAL", MDL_CHAT_PROTO, from, to, subject, switch_str_nil(msg), NULL, hint); + + if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_PROTO); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", from); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_user", from_user); + if (from_host) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_host", from_host); + } + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to", to); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", subject); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "normal"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", hint); + + if (msg) { + switch_event_add_body(event, "%s", msg); + } + } else { + abort(); } + + switch_safe_free(from_user); + + if (strcasecmp(proto, MDL_CHAT_PROTO)) { /* yes no ! on purpose */ + switch_core_chat_send(proto, event); + } + + switch_core_chat_send("GLOBAL", event); + + switch_event_destroy(&event); switch_safe_free(pproto); switch_safe_free(ffrom); diff --git a/src/mod/endpoints/mod_skypopen/mod_skypopen.c b/src/mod/endpoints/mod_skypopen/mod_skypopen.c index a5d90d0c50..ddb5fe35ab 100644 --- a/src/mod/endpoints/mod_skypopen/mod_skypopen.c +++ b/src/mod/endpoints/mod_skypopen/mod_skypopen.c @@ -35,7 +35,7 @@ */ #include "skypopen.h" -#define MDL_CHAT_PROTO "skype" +#define SKYPE_CHAT_PROTO "skype" #ifdef WIN32 /***************/ @@ -1858,14 +1858,30 @@ static switch_status_t load_config(int reload_type) return SWITCH_STATUS_SUCCESS; } -static switch_status_t chat_send(const char *proto, const char *from, const char *to, const char *subject, const char *body, const char *type, - const char *hint) +static switch_status_t chat_send(switch_event_t *message_event) + { char *user = NULL, *host, *f_user = NULL, *f_host = NULL, *f_resource = NULL; private_t *tech_pvt = NULL; int i = 0, found = 0, tried = 0; char skype_msg[1024]; + const char *proto; + const char *from; + const char *to; + const char *subject; + const char *body; + //const char *type; + const char *hint; + + proto = switch_event_get_header(message_event, "proto"); + from = switch_event_get_header(message_event, "from"); + to = switch_event_get_header(message_event, "to"); + subject = switch_event_get_header(message_event, "subject"); + body = switch_event_get_body(message_event); + //type = switch_event_get_header(message_event, "type"); + hint = switch_event_get_header(message_event, "hint"); + switch_assert(proto != NULL); DEBUGA_SKYPE("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, type=%s, hint=%s)\n", SKYPOPEN_P_LOG, proto, from, to, subject, body, type, @@ -1998,7 +2014,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skypopen_load) SWITCH_ADD_API(commands_api_interface, "skypopen", "Skypopen interface commands", skypopen_function, SKYPOPEN_SYNTAX); SWITCH_ADD_API(commands_api_interface, "skypopen_chat", "Skypopen_chat interface remote_skypename TEXT", skypopen_chat_function, SKYPOPEN_CHAT_SYNTAX); - SWITCH_ADD_CHAT(chat_interface, MDL_CHAT_PROTO, chat_send); + SWITCH_ADD_CHAT(chat_interface, SKYPE_CHAT_PROTO, chat_send); if (switch_event_reserve_subclass(MY_EVENT_INCOMING_CHATMESSAGE) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!\n"); @@ -2944,7 +2960,7 @@ int incoming_chatmessage(private_t *tech_pvt, int which) session = switch_core_session_locate(tech_pvt->session_uuid_str); } if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_PROTO); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SKYPE_CHAT_PROTO); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", tech_pvt->name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", tech_pvt->chatmessages[which].from_dispname); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", tech_pvt->chatmessages[which].from_handle); @@ -2971,7 +2987,7 @@ int incoming_chatmessage(private_t *tech_pvt, int which) if (!event_sent_to_esl) { if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", MDL_CHAT_PROTO); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SKYPE_CHAT_PROTO); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", tech_pvt->name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", tech_pvt->chatmessages[which].from_dispname); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", tech_pvt->chatmessages[which].from_handle); @@ -2997,6 +3013,33 @@ int incoming_chatmessage(private_t *tech_pvt, int which) return 0; } +static switch_status_t compat_chat_send(const char *proto, const char *from, const char *to, + const char *subject, const char *body, const char *type, const char *hint) +{ + switch_event_t *message_event; + switch_status_t status; + + if (switch_event_create(&message_event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "proto", proto); + switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "from", from); + switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "to", to); + switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "subject", subject); + switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "type", type); + switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "hint", hint); + + if (body) { + switch_event_add_body(message_event, "%s", body); + } + } else { + abort(); + } + + status = chat_send(message_event); + switch_event_destroy(&message_event); + + return status; + +} SWITCH_STANDARD_API(skypopen_chat_function) { @@ -3037,11 +3080,11 @@ SWITCH_STANDARD_API(skypopen_chat_function) goto end; } else { - NOTICA("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, type=NULL, hint=%s)\n", SKYPOPEN_P_LOG, MDL_CHAT_PROTO, tech_pvt->skype_user, + NOTICA("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, type=NULL, hint=%s)\n", SKYPOPEN_P_LOG, SKYPE_CHAT_PROTO, tech_pvt->skype_user, argv[1], "SIMPLE MESSAGE", switch_str_nil((char *) &cmd[strlen(argv[0]) + 1 + strlen(argv[1]) + 1]), tech_pvt->name); - chat_send(MDL_CHAT_PROTO, tech_pvt->skype_user, argv[1], "SIMPLE MESSAGE", - switch_str_nil((char *) &cmd[strlen(argv[0]) + 1 + strlen(argv[1]) + 1]), NULL, tech_pvt->name); + compat_chat_send(SKYPE_CHAT_PROTO, tech_pvt->skype_user, argv[1], "SIMPLE MESSAGE", + switch_str_nil((char *) &cmd[strlen(argv[0]) + 1 + strlen(argv[1]) + 1]), NULL, tech_pvt->name); } } else { diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 8ef3b92663..270c6c3e40 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1986,6 +1986,8 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi number = tech_pvt->caller_profile->destination_number; } + printf("WTF [%s][%s]\n", name, number); + if (!sofia_test_flag(tech_pvt, TFLAG_UPDATING_DISPLAY)) { if (zstr(tech_pvt->last_sent_callee_id_name) || strcmp(tech_pvt->last_sent_callee_id_name, name) || zstr(tech_pvt->last_sent_callee_id_number) || strcmp(tech_pvt->last_sent_callee_id_number, number)) { diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.h b/src/mod/endpoints/mod_sofia/mod_sofia.h index 4e8a0585bd..a0f1cac582 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.h +++ b/src/mod/endpoints/mod_sofia/mod_sofia.h @@ -872,8 +872,8 @@ void *SWITCH_THREAD_FUNC sofia_profile_thread_run(switch_thread_t *thread, void void launch_sofia_profile_thread(sofia_profile_t *profile); -switch_status_t sofia_presence_chat_send(const char *proto, const char *from, const char *to, const char *subject, - const char *body, const char *type, const char *hint); +switch_status_t sofia_presence_chat_send(switch_event_t *message_event); + void sofia_glue_tech_absorb_sdp(private_object_t *tech_pvt); /* diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index 33154e73ec..db7aa94a3a 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -72,8 +72,8 @@ struct presence_helper { char last_uuid[512]; }; -switch_status_t sofia_presence_chat_send(const char *proto, const char *from, const char *to, const char *subject, - const char *body, const char *type, const char *hint) +switch_status_t sofia_presence_chat_send(switch_event_t *message_event) + { char *prof = NULL, *user = NULL, *host = NULL; sofia_profile_t *profile = NULL; @@ -93,6 +93,22 @@ switch_status_t sofia_presence_chat_send(const char *proto, const char *from, co char *dup_dest = NULL; char *p = NULL; char *remote_host = NULL; + const char *proto; + const char *from; + const char *to; + //const char *subject; + const char *body; + const char *type; + const char *hint; + + proto = switch_event_get_header(message_event, "proto"); + from = switch_event_get_header(message_event, "from"); + to = switch_event_get_header(message_event, "to"); + //subject = switch_event_get_header(message_event, "subject"); + body = switch_event_get_body(message_event); + type = switch_event_get_header(message_event, "type"); + hint = switch_event_get_header(message_event, "hint"); + if (!to) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing To: header.\n"); @@ -2891,7 +2907,6 @@ void sofia_presence_handle_sip_i_message(int status, char *p; char *full_from; char proto[512] = SOFIA_CHAT_PROTO; - int got_proto = 0; full_from = sip_header_as_string(nh->nh_home, (void *) sip->sip_from); @@ -2905,7 +2920,6 @@ void sofia_presence_handle_sip_i_message(int status, *p = '@'; } } - got_proto++; } else { to_addr = switch_mprintf("%s@%s", to_user, to_host); } @@ -2916,35 +2930,35 @@ void sofia_presence_handle_sip_i_message(int status, sofia_presence_set_hash_key(hash_key, sizeof(hash_key), sip); } - if (sofia_test_pflag(profile, PFLAG_IN_DIALOG_CHAT) && (tech_pvt = (private_object_t *) switch_core_hash_find(profile->chat_hash, hash_key))) { - if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", from_addr); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", full_from); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to", to_addr); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "SIMPLE MESSAGE"); - if (msg) { - switch_event_add_body(event, "%s", msg); - } - - if (switch_core_session_queue_event(tech_pvt->session, &event) != SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "delivery-failure", "true"); - switch_event_fire(&event); - } + if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", profile->url); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", SOFIA_CHAT_PROTO); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", from_addr); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_user", from_user); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_host", from_host); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to", to_addr); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "SIMPLE MESSAGE"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "normal"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", full_from); + + if (msg) { + switch_event_add_body(event, "%s", msg); } } else { - if (strcasecmp(proto, SOFIA_CHAT_PROTO)) { - switch_core_chat_send(proto, SOFIA_CHAT_PROTO, from_addr, to_addr, "", msg, NULL, full_from); - } + abort(); } - - if (!got_proto) { - switch_core_chat_send("GLOBAL", SOFIA_CHAT_PROTO, from_addr, to_addr, "", msg, NULL, full_from); + + if (sofia_test_pflag(profile, PFLAG_IN_DIALOG_CHAT) && (tech_pvt = (private_object_t *) switch_core_hash_find(profile->chat_hash, hash_key))) { + switch_core_session_queue_event(tech_pvt->session, &event); + } else { + switch_core_chat_send(proto, event); + switch_core_chat_send("GLOBAL", event); + switch_event_destroy(&event); } switch_safe_free(to_addr); switch_safe_free(from_addr); + if (full_from) { su_free(nh->nh_home, full_from); } diff --git a/src/switch_loadable_module.c b/src/switch_loadable_module.c index 4e663df6e0..6368863872 100644 --- a/src/switch_loadable_module.c +++ b/src/switch_loadable_module.c @@ -468,28 +468,78 @@ static switch_status_t switch_loadable_module_process(char *key, switch_loadable } -SWITCH_DECLARE(switch_status_t) switch_core_chat_send(const char *name, const char *proto, const char *from, const char *to, - const char *subject, const char *body, const char *type, const char *hint) +SWITCH_DECLARE(switch_status_t) switch_core_chat_send_args(const char *dest_proto, const char *proto, const char *from, const char *to, + const char *subject, const char *body, const char *type, const char *hint) +{ + switch_event_t *message_event; + switch_status_t status; + + if (switch_event_create(&message_event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "proto", proto); + switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "from", from); + switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "to", to); + switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "subject", subject); + switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "type", type); + switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "hint", hint); + + if (body) { + switch_event_add_body(message_event, "%s", body); + } + } else { + abort(); + } + + status = switch_core_chat_send(dest_proto, message_event); + + switch_event_destroy(&message_event); + + return status; + +} + +SWITCH_DECLARE(switch_status_t) switch_core_chat_send(const char *dest_proto, switch_event_t *message_event) + { switch_chat_interface_t *ci; switch_status_t status = SWITCH_STATUS_FALSE; switch_hash_index_t *hi; const void *var; void *val; - - if (!name) { + + /* + const char *proto; + const char *from; + const char *to; + const char *subject; + const char *body; + const char *type; + const char *hint; + */ + + if (!dest_proto) { return SWITCH_STATUS_FALSE; } - if (!strcasecmp(name, "GLOBAL")) { + /* + proto = switch_event_get_header(message_event, "proto"); + from = switch_event_get_header(message_event, "from"); + to = switch_event_get_header(message_event, "to"); + subject = switch_event_get_header(message_event, "subject"); + body = switch_event_get_body(message_event); + type = switch_event_get_header(message_event, "type"); + hint = switch_event_get_header(message_event, "hint"); + */ + + + if (!strcasecmp(dest_proto, "GLOBAL")) { switch_mutex_lock(loadable_modules.mutex); for (hi = switch_hash_first(NULL, loadable_modules.chat_hash); hi; hi = switch_hash_next(hi)) { switch_hash_this(hi, &var, NULL, &val); if ((ci = (switch_chat_interface_t *) val)) { if (ci->chat_send && !strncasecmp(ci->interface_name, "GLOBAL_", 7)) { - if ((status = ci->chat_send(proto, from, to, subject, body, type, hint)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Chat Interface Error [%s]!\n", name); + if ((status = ci->chat_send(message_event)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Chat Interface Error [%s]!\n", dest_proto); break; } } @@ -497,11 +547,11 @@ SWITCH_DECLARE(switch_status_t) switch_core_chat_send(const char *name, const ch } switch_mutex_unlock(loadable_modules.mutex); } else { - if (!(ci = switch_loadable_module_get_chat_interface(name)) || !ci->chat_send) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid chat interface [%s]!\n", name); + if (!(ci = switch_loadable_module_get_chat_interface(dest_proto)) || !ci->chat_send) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid chat interface [%s]!\n", dest_proto); return SWITCH_STATUS_FALSE; } - status = ci->chat_send(proto, from, to, subject, body, type, hint); + status = ci->chat_send(message_event); UNPROTECT_INTERFACE(ci); } From 908c41031db6b1ede058df17bae2532167c69615 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 13 Sep 2011 16:53:12 -0500 Subject: [PATCH 094/204] remove dup --- src/mod/applications/mod_dptools/mod_dptools.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 4d21a6d681..05ac416920 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -3928,7 +3928,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "presence", "Send Presence", "Send Presence.", presence_function, " []", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); SWITCH_ADD_APP(app_interface, "log", "Logs to the logger", LOG_LONG_DESC, log_function, " ", - SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC | SAF_ZOMBIE_EXEC); + SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); SWITCH_ADD_APP(app_interface, "info", "Display Call Info", "Display Call Info", info_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); SWITCH_ADD_APP(app_interface, "event", "Fire an event", "Fire an event", event_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); SWITCH_ADD_APP(app_interface, "sound_test", "Analyze Audio", "Analyze Audio", sound_test_function, "", SAF_NONE); From 3a2f8183877582b00ea5a97502898cabf3685efb Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Tue, 13 Sep 2011 17:12:37 -0500 Subject: [PATCH 095/204] make app to turn on new zombie exec instead of always doing it --- src/include/switch_types.h | 1 + src/mod/applications/mod_commands/mod_commands.c | 16 ++++++++++++++++ src/mod/applications/mod_dptools/mod_dptools.c | 15 +++++++++++++++ src/switch_core_session.c | 2 +- src/switch_core_state_machine.c | 15 +++++++++++---- 5 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 8bcf9b6b53..6a6b0be69c 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -1167,6 +1167,7 @@ typedef enum { CF_LAZY_ATTENDED_TRANSFER, CF_SIGNAL_DATA, CF_SIMPLIFY, + CF_ZOMBIE_EXEC, /* WARNING: DO NOT ADD ANY FLAGS BELOW THIS LINE */ /* IF YOU ADD NEW ONES CHECK IF THEY SHOULD PERSIST OR ZERO THEM IN switch_core_session.c switch_core_session_request_xml() */ CF_FLAG_MAX diff --git a/src/mod/applications/mod_commands/mod_commands.c b/src/mod/applications/mod_commands/mod_commands.c index a5175299be..62fbc0bf59 100644 --- a/src/mod/applications/mod_commands/mod_commands.c +++ b/src/mod/applications/mod_commands/mod_commands.c @@ -4271,6 +4271,21 @@ SWITCH_STANDARD_API(uuid_flush_dtmf_function) return SWITCH_STATUS_SUCCESS; } +SWITCH_STANDARD_API(uuid_zombie_exec_function) +{ + switch_core_session_t *fsession; + + if (!zstr(cmd) && (fsession = switch_core_session_locate(cmd))) { + switch_channel_set_flag(switch_core_session_get_channel(fsession), CF_ZOMBIE_EXEC); + switch_core_session_rwunlock(fsession); + stream->write_function(stream, "+OK MMM Brains...\n"); + } else { + stream->write_function(stream, "-ERR no such session\n"); + } + + return SWITCH_STATUS_SUCCESS; +} + #define SETVAR_SYNTAX " [value]" SWITCH_STANDARD_API(uuid_setvar_function) { @@ -5331,6 +5346,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_commands_load) SWITCH_ADD_API(commands_api_interface, "uuid_simplify", "Try to cut out of a call path / attended xfer", uuid_simplify_function, SIMPLIFY_SYNTAX); SWITCH_ADD_API(commands_api_interface, "uuid_jitterbuffer", "Try to cut out of a call path / attended xfer", uuid_jitterbuffer_function, JITTERBUFFER_SYNTAX); + SWITCH_ADD_API(commands_api_interface, "uuid_zombie_exec", "Set zombie_exec flag on the specified uuid", uuid_zombie_exec_function, ""); SWITCH_ADD_API(commands_api_interface, "xml_flush_cache", "clear xml cache", xml_flush_function, " "); SWITCH_ADD_API(commands_api_interface, "xml_locate", "find some xml", xml_locate_function, "[root |
]"); SWITCH_ADD_API(commands_api_interface, "xml_wrap", "Wrap another api command in xml", xml_wrap_api_function, " "); diff --git a/src/mod/applications/mod_dptools/mod_dptools.c b/src/mod/applications/mod_dptools/mod_dptools.c index 05ac416920..c088d81111 100755 --- a/src/mod/applications/mod_dptools/mod_dptools.c +++ b/src/mod/applications/mod_dptools/mod_dptools.c @@ -1005,6 +1005,18 @@ SWITCH_STANDARD_APP(eval_function) return; } +SWITCH_STANDARD_APP(zombie_function) +{ + switch_channel_t *channel = switch_core_session_get_channel(session); + + if (switch_channel_up(channel)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s MMM Brains....\n", switch_channel_get_name(channel)); + switch_channel_set_flag(channel, CF_ZOMBIE_EXEC); + } + + return; +} + SWITCH_STANDARD_APP(hangup_function) { @@ -3921,6 +3933,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_dptools_load) SWITCH_ADD_APP(app_interface, "strftime", "strftime", "strftime", strftime_function, "[|]", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "phrase", "Say a Phrase", "Say a Phrase", phrase_function, ",", SAF_NONE); SWITCH_ADD_APP(app_interface, "eval", "Do Nothing", "Do Nothing", eval_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); + SWITCH_ADD_APP(app_interface, "stop", "Do Nothing", "Do Nothing", eval_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); + SWITCH_ADD_APP(app_interface, "set_zombie_exec", "Enable Zombie Execution", "Enable Zombie Execution", + zombie_function, "", SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC); SWITCH_ADD_APP(app_interface, "pre_answer", "Pre-Answer the call", "Pre-Answer the call for a channel.", pre_answer_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "answer", "Answer the call", "Answer the call for a channel.", answer_function, "", SAF_SUPPORT_NOMEDIA); SWITCH_ADD_APP(app_interface, "hangup", "Hangup the call", "Hangup the call for a channel.", hangup_function, "[]", SAF_SUPPORT_NOMEDIA); diff --git a/src/switch_core_session.c b/src/switch_core_session.c index cfeeab028c..3bccaf5b0a 100644 --- a/src/switch_core_session.c +++ b/src/switch_core_session.c @@ -2049,7 +2049,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_session_execute_application_get_flag switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Channel is hungup and application '%s' does not have the zombie_exec flag.\n", switch_channel_get_name(session->channel), app); - return SWITCH_STATUS_FALSE; + return SWITCH_STATUS_IGNORE; } if (!arg && strstr(app, "::")) { diff --git a/src/switch_core_state_machine.c b/src/switch_core_state_machine.c index 2136de30c2..1b540c963f 100644 --- a/src/switch_core_state_machine.c +++ b/src/switch_core_state_machine.c @@ -46,6 +46,10 @@ static void switch_core_standard_on_hangup(switch_core_session_t *session) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s Standard HANGUP, cause: %s\n", switch_channel_get_name(session->channel), switch_channel_cause2str(switch_channel_get_cause(session->channel))); + + if (!switch_channel_test_flag(session->channel, CF_ZOMBIE_EXEC)) { + return; + } if ((extension = switch_channel_get_caller_extension(session->channel)) == 0) { return; @@ -53,14 +57,17 @@ static void switch_core_standard_on_hangup(switch_core_session_t *session) while(extension->current_application) { switch_caller_application_t *current_application = extension->current_application; + switch_status_t status; extension->current_application = extension->current_application->next; - if (switch_core_session_execute_application(session, - current_application->application_name, - current_application->application_data) != SWITCH_STATUS_SUCCESS) { + status = switch_core_session_execute_application(session, + current_application->application_name, current_application->application_data); + + + if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_IGNORE) { return; - } + } } From cb1cb69ee489ff40a3121b8143010eaf49391df7 Mon Sep 17 00:00:00 2001 From: Michal Bielicki - cypromis Date: Wed, 14 Sep 2011 14:59:02 +0200 Subject: [PATCH 096/204] let gcc have part in the great solaris building world --- configure.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.in b/configure.in index b74e973a4a..25c0c2a675 100644 --- a/configure.in +++ b/configure.in @@ -428,7 +428,7 @@ case "$host" in fi ;; *-solaris2*) - APR_ADDTO(SWITCH_AM_CFLAGS, -DPATH_MAX=2048) + APR_ADDTO(SWITCH_AM_CFLAGS, -DPATH_MAX=2048 -D__EXTENSIONS__) APR_ADDTO(SWITCH_AM_LDFLAGS, -lsendfile -lresolv -lsocket -lnsl -luuid) APR_ADDTO(ESL_LDFLAGS, -lnsl -lsocket) ;; From d3b9b882f35017e218e337edbc398904b5ceef4a Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 14 Sep 2011 08:29:56 -0500 Subject: [PATCH 097/204] FS-3565 reswig vs2010 --- .../mod_managed/freeswitch_wrap.2010.cxx | 26 ++++-- .../mod_managed/managed/swig.2010.cs | 84 +++++++++++-------- 2 files changed, 67 insertions(+), 43 deletions(-) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx index 0935ec7d17..cc6fa0fe57 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.2010.cxx @@ -10200,7 +10200,7 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_cond_next() { } -SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_chat_send(char * jarg1, char * jarg2, char * jarg3, char * jarg4, char * jarg5, char * jarg6, char * jarg7, char * jarg8) { +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_chat_send_args(char * jarg1, char * jarg2, char * jarg3, char * jarg4, char * jarg5, char * jarg6, char * jarg7, char * jarg8) { int jresult ; char *arg1 = (char *) 0 ; char *arg2 = (char *) 0 ; @@ -10220,7 +10220,21 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_chat_send(char * jarg1, char * jar arg6 = (char *)jarg6; arg7 = (char *)jarg7; arg8 = (char *)jarg8; - result = (switch_status_t)switch_core_chat_send((char const *)arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,(char const *)arg5,(char const *)arg6,(char const *)arg7,(char const *)arg8); + result = (switch_status_t)switch_core_chat_send_args((char const *)arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,(char const *)arg5,(char const *)arg6,(char const *)arg7,(char const *)arg8); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_chat_send(char * jarg1, void * jarg2) { + int jresult ; + char *arg1 = (char *) 0 ; + switch_event_t *arg2 = (switch_event_t *) 0 ; + switch_status_t result; + + arg1 = (char *)jarg1; + arg2 = (switch_event_t *)jarg2; + result = (switch_status_t)switch_core_chat_send((char const *)arg1,arg2); jresult = result; return jresult; } @@ -20178,10 +20192,10 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_chat_interface_interface_name_get(vo SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_interface_chat_send_set(void * jarg1, void * jarg2) { switch_chat_interface *arg1 = (switch_chat_interface *) 0 ; - switch_status_t (*arg2)(char const *,char const *,char const *,char const *,char const *,char const *,char const *) = (switch_status_t (*)(char const *,char const *,char const *,char const *,char const *,char const *,char const *)) 0 ; + switch_status_t (*arg2)(switch_event_t *) = (switch_status_t (*)(switch_event_t *)) 0 ; arg1 = (switch_chat_interface *)jarg1; - arg2 = (switch_status_t (*)(char const *,char const *,char const *,char const *,char const *,char const *,char const *))jarg2; + arg2 = (switch_status_t (*)(switch_event_t *))jarg2; if (arg1) (arg1)->chat_send = arg2; } @@ -20189,10 +20203,10 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_interface_chat_send_set(void * ja SWIGEXPORT void * SWIGSTDCALL CSharp_switch_chat_interface_chat_send_get(void * jarg1) { void * jresult ; switch_chat_interface *arg1 = (switch_chat_interface *) 0 ; - switch_status_t (*result)(char const *,char const *,char const *,char const *,char const *,char const *,char const *) = 0 ; + switch_status_t (*result)(switch_event_t *) = 0 ; arg1 = (switch_chat_interface *)jarg1; - result = (switch_status_t (*)(char const *,char const *,char const *,char const *,char const *,char const *,char const *)) ((arg1)->chat_send); + result = (switch_status_t (*)(switch_event_t *)) ((arg1)->chat_send); jresult = (void *)result; return jresult; } diff --git a/src/mod/languages/mod_managed/managed/swig.2010.cs b/src/mod/languages/mod_managed/managed/swig.2010.cs index 72231bd0dc..e8f921b6f4 100644 --- a/src/mod/languages/mod_managed/managed/swig.2010.cs +++ b/src/mod/languages/mod_managed/managed/swig.2010.cs @@ -2424,8 +2424,13 @@ public class freeswitch { freeswitchPINVOKE.switch_cond_next(); } - public static switch_status_t switch_core_chat_send(string name, string proto, string from, string to, string subject, string body, string type, string hint) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_chat_send(name, proto, from, to, subject, body, type, hint); + public static switch_status_t switch_core_chat_send_args(string dest_proto, string proto, string from, string to, string subject, string body, string type, string hint) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_chat_send_args(dest_proto, proto, from, to, subject, body, type, hint); + return ret; + } + + public static switch_status_t switch_core_chat_send(string dest_proto, switch_event message_event) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_chat_send(dest_proto, switch_event.getCPtr(message_event)); return ret; } @@ -8543,8 +8548,11 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_cond_next")] public static extern void switch_cond_next(); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_chat_send_args")] + public static extern int switch_core_chat_send_args(string jarg1, string jarg2, string jarg3, string jarg4, string jarg5, string jarg6, string jarg7, string jarg8); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_chat_send")] - public static extern int switch_core_chat_send(string jarg1, string jarg2, string jarg3, string jarg4, string jarg5, string jarg6, string jarg7, string jarg8); + public static extern int switch_core_chat_send(string jarg1, HandleRef jarg2); [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_preprocess_session")] public static extern int switch_ivr_preprocess_session(HandleRef jarg1, string jarg2); @@ -15191,36 +15199,6 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; -public class SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char__switch_status_t { - private HandleRef swigCPtr; - - internal SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char__switch_status_t(IntPtr cPtr, bool futureUse) { - swigCPtr = new HandleRef(this, cPtr); - } - - protected SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char__switch_status_t() { - swigCPtr = new HandleRef(null, IntPtr.Zero); - } - - internal static HandleRef getCPtr(SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char__switch_status_t obj) { - return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; - } -} - -} -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 2.0.1 - * - * Do not make changes to this file unless you know what you are doing--modify - * the SWIG interface file instead. - * ----------------------------------------------------------------------------- */ - -namespace FreeSWITCH.Native { - -using System; -using System.Runtime.InteropServices; - public class SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_switch_event_t_p_void__p_switch_xml { private HandleRef swigCPtr; @@ -16571,6 +16549,36 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; +public class SWIGTYPE_p_f_p_switch_event__switch_status_t { + private HandleRef swigCPtr; + + internal SWIGTYPE_p_f_p_switch_event__switch_status_t(IntPtr cPtr, bool futureUse) { + swigCPtr = new HandleRef(this, cPtr); + } + + protected SWIGTYPE_p_f_p_switch_event__switch_status_t() { + swigCPtr = new HandleRef(null, IntPtr.Zero); + } + + internal static HandleRef getCPtr(SWIGTYPE_p_f_p_switch_event__switch_status_t obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 2.0.1 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + +using System; +using System.Runtime.InteropServices; + public class SWIGTYPE_p_f_p_switch_event__void { private HandleRef swigCPtr; @@ -20217,7 +20225,8 @@ namespace FreeSWITCH.Native { SAF_NONE = 0, SAF_SUPPORT_NOMEDIA = (1 << 0), SAF_ROUTING_EXEC = (1 << 1), - SAF_MEDIA_TAP = (1 << 2) + SAF_MEDIA_TAP = (1 << 2), + SAF_ZOMBIE_EXEC = (1 << 3) } } @@ -22490,6 +22499,7 @@ public enum switch_channel_flag_t { CF_LAZY_ATTENDED_TRANSFER, CF_SIGNAL_DATA, CF_SIMPLIFY, + CF_ZOMBIE_EXEC, CF_FLAG_MAX } @@ -22767,13 +22777,13 @@ public class switch_chat_interface : IDisposable { } } - public SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char__switch_status_t chat_send { + public SWIGTYPE_p_f_p_switch_event__switch_status_t chat_send { set { - freeswitchPINVOKE.switch_chat_interface_chat_send_set(swigCPtr, SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char__switch_status_t.getCPtr(value)); + freeswitchPINVOKE.switch_chat_interface_chat_send_set(swigCPtr, SWIGTYPE_p_f_p_switch_event__switch_status_t.getCPtr(value)); } get { IntPtr cPtr = freeswitchPINVOKE.switch_chat_interface_chat_send_get(swigCPtr); - SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char__switch_status_t ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char__switch_status_t(cPtr, false); + SWIGTYPE_p_f_p_switch_event__switch_status_t ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_f_p_switch_event__switch_status_t(cPtr, false); return ret; } } From 406c21ce2b6a895a4ffdfe58a19e3443d89bc45b Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 14 Sep 2011 08:35:40 -0500 Subject: [PATCH 098/204] FS-3564 --resolve Fix build for mod_skypopen, problem occurs after latest changes for chat interface --- src/mod/endpoints/mod_skypopen/mod_skypopen.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_skypopen/mod_skypopen.c b/src/mod/endpoints/mod_skypopen/mod_skypopen.c index ddb5fe35ab..0360913eb0 100644 --- a/src/mod/endpoints/mod_skypopen/mod_skypopen.c +++ b/src/mod/endpoints/mod_skypopen/mod_skypopen.c @@ -1884,7 +1884,9 @@ static switch_status_t chat_send(switch_event_t *message_event) switch_assert(proto != NULL); - DEBUGA_SKYPE("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, type=%s, hint=%s)\n", SKYPOPEN_P_LOG, proto, from, to, subject, body, type, + //DEBUGA_SKYPE("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, type=%s, hint=%s)\n", SKYPOPEN_P_LOG, proto, from, to, subject, body, type, + // hint ? hint : "NULL"); + DEBUGA_SKYPE("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, hint=%s)\n", SKYPOPEN_P_LOG, proto, from, to, subject, body, hint ? hint : "NULL"); if (!to || !strlen(to)) { @@ -1911,7 +1913,9 @@ static switch_status_t chat_send(switch_event_t *message_event) *host++ = '\0'; } - DEBUGA_SKYPE("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, type=%s, hint=%s)\n", SKYPOPEN_P_LOG, proto, from, to, subject, body, type, + //DEBUGA_SKYPE("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, type=%s, hint=%s)\n", SKYPOPEN_P_LOG, proto, from, to, subject, body, type, + // hint ? hint : "NULL"); + DEBUGA_SKYPE("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, hint=%s)\n", SKYPOPEN_P_LOG, proto, from, to, subject, body, hint ? hint : "NULL"); if (hint && strlen(hint)) { //in hint we receive the interface name to use From b06f58a14b29eb8db612a3142579552afaddffbf Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Wed, 14 Sep 2011 10:46:32 -0400 Subject: [PATCH 099/204] freetdm: do not warn on io status changes, leave as debug messages --- libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index 81e2405606..d0d66205a5 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -887,7 +887,7 @@ static void wanpipe_write_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_tx_hdr_t *t /* HDLC channels do not always transmit, so its ok for drivers to fill with idle * also do not report idle warning when we just started transmitting */ if (ftdmchan->iostats.tx.packets && FTDM_IS_VOICE_CHANNEL(ftdmchan)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Tx idle changed from %d to %d\n", + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Tx idle changed from %d to %d\n", ftdmchan->iostats.tx.idle_packets, tx_stats->wp_api_tx_hdr_tx_idle_packets); } ftdmchan->iostats.tx.idle_packets = tx_stats->wp_api_tx_hdr_tx_idle_packets; @@ -940,21 +940,21 @@ static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx } if (ftdmchan->iostats.rx.queue_len >= (0.8 * ftdmchan->iostats.rx.queue_size)) { - ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Rx Queue length exceeded 80% threshold (%d/%d)\n", + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Rx Queue length exceeded 80% threshold (%d/%d)\n", ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); } else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES)){ - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue length reduced 80% threshold (%d/%d)\n", + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Rx Queue length reduced 80% threshold (%d/%d)\n", ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_THRES); } if (ftdmchan->iostats.rx.queue_len >= ftdmchan->iostats.rx.queue_size) { - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Rx Queue Full (%d/%d)\n", + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Rx Queue Full (%d/%d)\n", ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); ftdm_set_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); } else if (ftdm_test_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL)){ - ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Rx Queue no longer full (%d/%d)\n", + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Rx Queue no longer full (%d/%d)\n", ftdmchan->iostats.rx.queue_len, ftdmchan->iostats.rx.queue_size); ftdm_clear_flag(&(ftdmchan->iostats.rx), FTDM_IOSTATS_ERROR_QUEUE_FULL); } From 6310318cadc49e585a87891ad2b9d2e0138f2137 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 14 Sep 2011 11:50:36 -0500 Subject: [PATCH 100/204] wtf --- src/mod/endpoints/mod_sofia/mod_sofia.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 270c6c3e40..8ef3b92663 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1986,8 +1986,6 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi number = tech_pvt->caller_profile->destination_number; } - printf("WTF [%s][%s]\n", name, number); - if (!sofia_test_flag(tech_pvt, TFLAG_UPDATING_DISPLAY)) { if (zstr(tech_pvt->last_sent_callee_id_name) || strcmp(tech_pvt->last_sent_callee_id_name, name) || zstr(tech_pvt->last_sent_callee_id_number) || strcmp(tech_pvt->last_sent_callee_id_number, number)) { From 61dd9c076533045422a73c5e8cd36d05bd381123 Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Thu, 15 Sep 2011 10:48:37 -0400 Subject: [PATCH 101/204] don't delete file if its the same file --- src/switch_utils.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/switch_utils.c b/src/switch_utils.c index 1c49fb4104..3f3f804d77 100644 --- a/src/switch_utils.c +++ b/src/switch_utils.c @@ -570,7 +570,11 @@ SWITCH_DECLARE(switch_bool_t) switch_simple_email(const char *to, char cmd[1024] = ""; switch_snprintf(cmd, sizeof(cmd), "%s %s %s", convert_cmd, file, newfile); switch_system(cmd, SWITCH_TRUE); - file = newfile; + if (strcmp(file, newfile)) { + file = newfile; + } else { + switch_safe_free(newfile); + } } switch_safe_free(dupfile); From f479462026d6d245511ef635ded70c7c645ac5ee Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 14 Sep 2011 12:58:32 -0500 Subject: [PATCH 102/204] use bridge_to instead of signal_bond for recovering bridge --- src/mod/endpoints/mod_sofia/sofia_glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 0e4b5ab870..b098358845 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -5566,7 +5566,7 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName } - if (switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) { + if (switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) { sofia_set_flag(tech_pvt, TFLAG_RECOVERING_BRIDGE); } else { switch_xml_t callflow, param, x_extension; From 51b7445d401a2d04acad63d5fe67f860b49a0fec Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Thu, 15 Sep 2011 10:59:20 -0500 Subject: [PATCH 103/204] FS-3565 --resolve reswig vs2008 --- .../languages/mod_managed/freeswitch_wrap.cxx | 26 +- src/mod/languages/mod_managed/managed/swig.cs | 1018 +++++++++-------- src/mod/languages/mod_managed/runswig.cmd | 2 + 3 files changed, 536 insertions(+), 510 deletions(-) diff --git a/src/mod/languages/mod_managed/freeswitch_wrap.cxx b/src/mod/languages/mod_managed/freeswitch_wrap.cxx index f89b749c12..6e9c56de0e 100644 --- a/src/mod/languages/mod_managed/freeswitch_wrap.cxx +++ b/src/mod/languages/mod_managed/freeswitch_wrap.cxx @@ -10502,7 +10502,7 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_cond_next() { } -SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_chat_send(char * jarg1, char * jarg2, char * jarg3, char * jarg4, char * jarg5, char * jarg6, char * jarg7, char * jarg8) { +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_chat_send_args(char * jarg1, char * jarg2, char * jarg3, char * jarg4, char * jarg5, char * jarg6, char * jarg7, char * jarg8) { int jresult ; char *arg1 = (char *) 0 ; char *arg2 = (char *) 0 ; @@ -10522,7 +10522,21 @@ SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_chat_send(char * jarg1, char * jar arg6 = (char *)jarg6; arg7 = (char *)jarg7; arg8 = (char *)jarg8; - result = (switch_status_t)switch_core_chat_send((char const *)arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,(char const *)arg5,(char const *)arg6,(char const *)arg7,(char const *)arg8); + result = (switch_status_t)switch_core_chat_send_args((char const *)arg1,(char const *)arg2,(char const *)arg3,(char const *)arg4,(char const *)arg5,(char const *)arg6,(char const *)arg7,(char const *)arg8); + jresult = result; + return jresult; +} + + +SWIGEXPORT int SWIGSTDCALL CSharp_switch_core_chat_send(char * jarg1, void * jarg2) { + int jresult ; + char *arg1 = (char *) 0 ; + switch_event_t *arg2 = (switch_event_t *) 0 ; + switch_status_t result; + + arg1 = (char *)jarg1; + arg2 = (switch_event_t *)jarg2; + result = (switch_status_t)switch_core_chat_send((char const *)arg1,arg2); jresult = result; return jresult; } @@ -20745,10 +20759,10 @@ SWIGEXPORT char * SWIGSTDCALL CSharp_switch_chat_interface_interface_name_get(vo SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_interface_chat_send_set(void * jarg1, void * jarg2) { switch_chat_interface *arg1 = (switch_chat_interface *) 0 ; - switch_status_t (*arg2)(char const *,char const *,char const *,char const *,char const *,char const *,char const *) = (switch_status_t (*)(char const *,char const *,char const *,char const *,char const *,char const *,char const *)) 0 ; + switch_status_t (*arg2)(switch_event_t *) = (switch_status_t (*)(switch_event_t *)) 0 ; arg1 = (switch_chat_interface *)jarg1; - arg2 = (switch_status_t (*)(char const *,char const *,char const *,char const *,char const *,char const *,char const *))jarg2; + arg2 = (switch_status_t (*)(switch_event_t *))jarg2; if (arg1) (arg1)->chat_send = arg2; } @@ -20757,10 +20771,10 @@ SWIGEXPORT void SWIGSTDCALL CSharp_switch_chat_interface_chat_send_set(void * ja SWIGEXPORT void * SWIGSTDCALL CSharp_switch_chat_interface_chat_send_get(void * jarg1) { void * jresult ; switch_chat_interface *arg1 = (switch_chat_interface *) 0 ; - switch_status_t (*result)(char const *,char const *,char const *,char const *,char const *,char const *,char const *) = 0 ; + switch_status_t (*result)(switch_event_t *) = 0 ; arg1 = (switch_chat_interface *)jarg1; - result = (switch_status_t (*)(char const *,char const *,char const *,char const *,char const *,char const *,char const *)) ((arg1)->chat_send); + result = (switch_status_t (*)(switch_event_t *)) ((arg1)->chat_send); jresult = (void *)result; return jresult; } diff --git a/src/mod/languages/mod_managed/managed/swig.cs b/src/mod/languages/mod_managed/managed/swig.cs index 1b8f7fd816..8d78c7d735 100644 --- a/src/mod/languages/mod_managed/managed/swig.cs +++ b/src/mod/languages/mod_managed/managed/swig.cs @@ -542,6 +542,132 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; +public partial class Event : IDisposable { + private HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal Event(IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new HandleRef(this, cPtr); + } + + internal static HandleRef getCPtr(Event obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } + + ~Event() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) { + swigCMemOwn = false; + freeswitchPINVOKE.delete_Event(swigCPtr); + } + swigCPtr = new HandleRef(null, IntPtr.Zero); + GC.SuppressFinalize(this); + } + } + + public switch_event InternalEvent { + set { + freeswitchPINVOKE.Event_InternalEvent_set(swigCPtr, switch_event.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.Event_InternalEvent_get(swigCPtr); + switch_event ret = (cPtr == IntPtr.Zero) ? null : new switch_event(cPtr, false); + return ret; + } + } + + public string serialized_string { + set { + freeswitchPINVOKE.Event_serialized_string_set(swigCPtr, value); + } + get { + string ret = freeswitchPINVOKE.Event_serialized_string_get(swigCPtr); + return ret; + } + } + + public int mine { + set { + freeswitchPINVOKE.Event_mine_set(swigCPtr, value); + } + get { + int ret = freeswitchPINVOKE.Event_mine_get(swigCPtr); + return ret; + } + } + + public Event(string type, string subclass_name) : this(freeswitchPINVOKE.new_Event__SWIG_0(type, subclass_name), true) { + } + + public Event(switch_event wrap_me, int free_me) : this(freeswitchPINVOKE.new_Event__SWIG_1(switch_event.getCPtr(wrap_me), free_me), true) { + } + + public string Serialize(string format) { + string ret = freeswitchPINVOKE.Event_Serialize(swigCPtr, format); + return ret; + } + + public bool SetPriority(switch_priority_t priority) { + bool ret = freeswitchPINVOKE.Event_SetPriority(swigCPtr, (int)priority); + return ret; + } + + public string GetHeader(string header_name) { + string ret = freeswitchPINVOKE.Event_GetHeader(swigCPtr, header_name); + return ret; + } + + public string GetBody() { + string ret = freeswitchPINVOKE.Event_GetBody(swigCPtr); + return ret; + } + + public string GetEventType() { + string ret = freeswitchPINVOKE.Event_GetEventType(swigCPtr); + return ret; + } + + public bool AddBody(string value) { + bool ret = freeswitchPINVOKE.Event_AddBody(swigCPtr, value); + return ret; + } + + public bool AddHeader(string header_name, string value) { + bool ret = freeswitchPINVOKE.Event_AddHeader(swigCPtr, header_name, value); + return ret; + } + + public bool DeleteHeader(string header_name) { + bool ret = freeswitchPINVOKE.Event_DeleteHeader(swigCPtr, header_name); + return ret; + } + + public bool Fire() { + bool ret = freeswitchPINVOKE.Event_Fire(swigCPtr); + return ret; + } + +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 1.3.35 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + +using System; +using System.Runtime.InteropServices; + public class EventConsumer : IDisposable { private HandleRef swigCPtr; protected bool swigCMemOwn; @@ -672,132 +798,6 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; -public partial class Event : IDisposable { - private HandleRef swigCPtr; - protected bool swigCMemOwn; - - internal Event(IntPtr cPtr, bool cMemoryOwn) { - swigCMemOwn = cMemoryOwn; - swigCPtr = new HandleRef(this, cPtr); - } - - internal static HandleRef getCPtr(Event obj) { - return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; - } - - ~Event() { - Dispose(); - } - - public virtual void Dispose() { - lock(this) { - if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) { - swigCMemOwn = false; - freeswitchPINVOKE.delete_Event(swigCPtr); - } - swigCPtr = new HandleRef(null, IntPtr.Zero); - GC.SuppressFinalize(this); - } - } - - public switch_event InternalEvent { - set { - freeswitchPINVOKE.Event_InternalEvent_set(swigCPtr, switch_event.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.Event_InternalEvent_get(swigCPtr); - switch_event ret = (cPtr == IntPtr.Zero) ? null : new switch_event(cPtr, false); - return ret; - } - } - - public string serialized_string { - set { - freeswitchPINVOKE.Event_serialized_string_set(swigCPtr, value); - } - get { - string ret = freeswitchPINVOKE.Event_serialized_string_get(swigCPtr); - return ret; - } - } - - public int mine { - set { - freeswitchPINVOKE.Event_mine_set(swigCPtr, value); - } - get { - int ret = freeswitchPINVOKE.Event_mine_get(swigCPtr); - return ret; - } - } - - public Event(string type, string subclass_name) : this(freeswitchPINVOKE.new_Event__SWIG_0(type, subclass_name), true) { - } - - public Event(switch_event wrap_me, int free_me) : this(freeswitchPINVOKE.new_Event__SWIG_1(switch_event.getCPtr(wrap_me), free_me), true) { - } - - public string Serialize(string format) { - string ret = freeswitchPINVOKE.Event_Serialize(swigCPtr, format); - return ret; - } - - public bool SetPriority(switch_priority_t priority) { - bool ret = freeswitchPINVOKE.Event_SetPriority(swigCPtr, (int)priority); - return ret; - } - - public string GetHeader(string header_name) { - string ret = freeswitchPINVOKE.Event_GetHeader(swigCPtr, header_name); - return ret; - } - - public string GetBody() { - string ret = freeswitchPINVOKE.Event_GetBody(swigCPtr); - return ret; - } - - public string GetEventType() { - string ret = freeswitchPINVOKE.Event_GetEventType(swigCPtr); - return ret; - } - - public bool AddBody(string value) { - bool ret = freeswitchPINVOKE.Event_AddBody(swigCPtr, value); - return ret; - } - - public bool AddHeader(string header_name, string value) { - bool ret = freeswitchPINVOKE.Event_AddHeader(swigCPtr, header_name, value); - return ret; - } - - public bool DeleteHeader(string header_name) { - bool ret = freeswitchPINVOKE.Event_DeleteHeader(swigCPtr, header_name); - return ret; - } - - public bool Fire() { - bool ret = freeswitchPINVOKE.Event_Fire(swigCPtr); - return ret; - } - -} - -} -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 1.3.35 - * - * Do not make changes to this file unless you know what you are doing--modify - * the SWIG interface file instead. - * ----------------------------------------------------------------------------- */ - -namespace FreeSWITCH.Native { - -using System; -using System.Runtime.InteropServices; - public class freeswitch { public static switch_directories SWITCH_GLOBAL_dirs { set { @@ -2414,8 +2414,13 @@ public class freeswitch { freeswitchPINVOKE.switch_cond_next(); } - public static switch_status_t switch_core_chat_send(string name, string proto, string from, string to, string subject, string body, string type, string hint) { - switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_chat_send(name, proto, from, to, subject, body, type, hint); + public static switch_status_t switch_core_chat_send_args(string dest_proto, string proto, string from, string to, string subject, string body, string type, string hint) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_chat_send_args(dest_proto, proto, from, to, subject, body, type, hint); + return ret; + } + + public static switch_status_t switch_core_chat_send(string dest_proto, switch_event message_event) { + switch_status_t ret = (switch_status_t)freeswitchPINVOKE.switch_core_chat_send(dest_proto, switch_event.getCPtr(message_event)); return ret; } @@ -8529,8 +8534,11 @@ class freeswitchPINVOKE { [DllImport("mod_managed", EntryPoint="CSharp_switch_cond_next")] public static extern void switch_cond_next(); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_chat_send_args")] + public static extern int switch_core_chat_send_args(string jarg1, string jarg2, string jarg3, string jarg4, string jarg5, string jarg6, string jarg7, string jarg8); + [DllImport("mod_managed", EntryPoint="CSharp_switch_core_chat_send")] - public static extern int switch_core_chat_send(string jarg1, string jarg2, string jarg3, string jarg4, string jarg5, string jarg6, string jarg7, string jarg8); + public static extern int switch_core_chat_send(string jarg1, HandleRef jarg2); [DllImport("mod_managed", EntryPoint="CSharp_switch_ivr_preprocess_session")] public static extern int switch_ivr_preprocess_session(HandleRef jarg1, string jarg2); @@ -15165,36 +15173,6 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; -public class SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char__switch_status_t { - private HandleRef swigCPtr; - - internal SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char__switch_status_t(IntPtr cPtr, bool futureUse) { - swigCPtr = new HandleRef(this, cPtr); - } - - protected SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char__switch_status_t() { - swigCPtr = new HandleRef(null, IntPtr.Zero); - } - - internal static HandleRef getCPtr(SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char__switch_status_t obj) { - return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; - } -} - -} -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 1.3.35 - * - * Do not make changes to this file unless you know what you are doing--modify - * the SWIG interface file instead. - * ----------------------------------------------------------------------------- */ - -namespace FreeSWITCH.Native { - -using System; -using System.Runtime.InteropServices; - public class SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_switch_event_t_p_void__p_switch_xml { private HandleRef swigCPtr; @@ -15795,18 +15773,18 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; -public class SWIGTYPE_p_f_p_switch_codec__switch_status_t { +public class SWIGTYPE_p_f_p_switch_codec_unsigned_long_p_q_const__switch_codec_settings__switch_status_t { private HandleRef swigCPtr; - internal SWIGTYPE_p_f_p_switch_codec__switch_status_t(IntPtr cPtr, bool futureUse) { + internal SWIGTYPE_p_f_p_switch_codec_unsigned_long_p_q_const__switch_codec_settings__switch_status_t(IntPtr cPtr, bool futureUse) { swigCPtr = new HandleRef(this, cPtr); } - protected SWIGTYPE_p_f_p_switch_codec__switch_status_t() { + protected SWIGTYPE_p_f_p_switch_codec_unsigned_long_p_q_const__switch_codec_settings__switch_status_t() { swigCPtr = new HandleRef(null, IntPtr.Zero); } - internal static HandleRef getCPtr(SWIGTYPE_p_f_p_switch_codec__switch_status_t obj) { + internal static HandleRef getCPtr(SWIGTYPE_p_f_p_switch_codec_unsigned_long_p_q_const__switch_codec_settings__switch_status_t obj) { return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; } } @@ -15825,18 +15803,18 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; -public class SWIGTYPE_p_f_p_switch_codec_unsigned_long_p_q_const__switch_codec_settings__switch_status_t { +public class SWIGTYPE_p_f_p_switch_codec__switch_status_t { private HandleRef swigCPtr; - internal SWIGTYPE_p_f_p_switch_codec_unsigned_long_p_q_const__switch_codec_settings__switch_status_t(IntPtr cPtr, bool futureUse) { + internal SWIGTYPE_p_f_p_switch_codec__switch_status_t(IntPtr cPtr, bool futureUse) { swigCPtr = new HandleRef(this, cPtr); } - protected SWIGTYPE_p_f_p_switch_codec_unsigned_long_p_q_const__switch_codec_settings__switch_status_t() { + protected SWIGTYPE_p_f_p_switch_codec__switch_status_t() { swigCPtr = new HandleRef(null, IntPtr.Zero); } - internal static HandleRef getCPtr(SWIGTYPE_p_f_p_switch_codec_unsigned_long_p_q_const__switch_codec_settings__switch_status_t obj) { + internal static HandleRef getCPtr(SWIGTYPE_p_f_p_switch_codec__switch_status_t obj) { return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; } } @@ -16365,18 +16343,18 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; -public class SWIGTYPE_p_f_p_switch_core_session__switch_status_t { +public class SWIGTYPE_p_f_p_switch_core_session_t_p_void_p_switch_caller_profile_t__p_switch_caller_extension { private HandleRef swigCPtr; - internal SWIGTYPE_p_f_p_switch_core_session__switch_status_t(IntPtr cPtr, bool futureUse) { + internal SWIGTYPE_p_f_p_switch_core_session_t_p_void_p_switch_caller_profile_t__p_switch_caller_extension(IntPtr cPtr, bool futureUse) { swigCPtr = new HandleRef(this, cPtr); } - protected SWIGTYPE_p_f_p_switch_core_session__switch_status_t() { + protected SWIGTYPE_p_f_p_switch_core_session_t_p_void_p_switch_caller_profile_t__p_switch_caller_extension() { swigCPtr = new HandleRef(null, IntPtr.Zero); } - internal static HandleRef getCPtr(SWIGTYPE_p_f_p_switch_core_session__switch_status_t obj) { + internal static HandleRef getCPtr(SWIGTYPE_p_f_p_switch_core_session_t_p_void_p_switch_caller_profile_t__p_switch_caller_extension obj) { return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; } } @@ -16395,18 +16373,18 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; -public class SWIGTYPE_p_f_p_switch_core_session_t_p_void_p_switch_caller_profile_t__p_switch_caller_extension { +public class SWIGTYPE_p_f_p_switch_core_session__switch_status_t { private HandleRef swigCPtr; - internal SWIGTYPE_p_f_p_switch_core_session_t_p_void_p_switch_caller_profile_t__p_switch_caller_extension(IntPtr cPtr, bool futureUse) { + internal SWIGTYPE_p_f_p_switch_core_session__switch_status_t(IntPtr cPtr, bool futureUse) { swigCPtr = new HandleRef(this, cPtr); } - protected SWIGTYPE_p_f_p_switch_core_session_t_p_void_p_switch_caller_profile_t__p_switch_caller_extension() { + protected SWIGTYPE_p_f_p_switch_core_session__switch_status_t() { swigCPtr = new HandleRef(null, IntPtr.Zero); } - internal static HandleRef getCPtr(SWIGTYPE_p_f_p_switch_core_session_t_p_void_p_switch_caller_profile_t__p_switch_caller_extension obj) { + internal static HandleRef getCPtr(SWIGTYPE_p_f_p_switch_core_session__switch_status_t obj) { return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; } } @@ -16545,6 +16523,36 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; +public class SWIGTYPE_p_f_p_switch_event__switch_status_t { + private HandleRef swigCPtr; + + internal SWIGTYPE_p_f_p_switch_event__switch_status_t(IntPtr cPtr, bool futureUse) { + swigCPtr = new HandleRef(this, cPtr); + } + + protected SWIGTYPE_p_f_p_switch_event__switch_status_t() { + swigCPtr = new HandleRef(null, IntPtr.Zero); + } + + internal static HandleRef getCPtr(SWIGTYPE_p_f_p_switch_event__switch_status_t obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 1.3.35 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + +using System; +using System.Runtime.InteropServices; + public class SWIGTYPE_p_f_p_switch_event__void { private HandleRef swigCPtr; @@ -18525,18 +18533,18 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; -public class SWIGTYPE_p_p_switch_xml_binding { +public class SWIGTYPE_p_p_switch_xml { private HandleRef swigCPtr; - internal SWIGTYPE_p_p_switch_xml_binding(IntPtr cPtr, bool futureUse) { + internal SWIGTYPE_p_p_switch_xml(IntPtr cPtr, bool futureUse) { swigCPtr = new HandleRef(this, cPtr); } - protected SWIGTYPE_p_p_switch_xml_binding() { + protected SWIGTYPE_p_p_switch_xml() { swigCPtr = new HandleRef(null, IntPtr.Zero); } - internal static HandleRef getCPtr(SWIGTYPE_p_p_switch_xml_binding obj) { + internal static HandleRef getCPtr(SWIGTYPE_p_p_switch_xml obj) { return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; } } @@ -18555,18 +18563,18 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; -public class SWIGTYPE_p_p_switch_xml { +public class SWIGTYPE_p_p_switch_xml_binding { private HandleRef swigCPtr; - internal SWIGTYPE_p_p_switch_xml(IntPtr cPtr, bool futureUse) { + internal SWIGTYPE_p_p_switch_xml_binding(IntPtr cPtr, bool futureUse) { swigCPtr = new HandleRef(this, cPtr); } - protected SWIGTYPE_p_p_switch_xml() { + protected SWIGTYPE_p_p_switch_xml_binding() { swigCPtr = new HandleRef(null, IntPtr.Zero); } - internal static HandleRef getCPtr(SWIGTYPE_p_p_switch_xml obj) { + internal static HandleRef getCPtr(SWIGTYPE_p_p_switch_xml_binding obj) { return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; } } @@ -19245,18 +19253,18 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; -public class SWIGTYPE_p_switch_ivr_menu_action_function_t { +public class SWIGTYPE_p_switch_ivr_menu { private HandleRef swigCPtr; - internal SWIGTYPE_p_switch_ivr_menu_action_function_t(IntPtr cPtr, bool futureUse) { + internal SWIGTYPE_p_switch_ivr_menu(IntPtr cPtr, bool futureUse) { swigCPtr = new HandleRef(this, cPtr); } - protected SWIGTYPE_p_switch_ivr_menu_action_function_t() { + protected SWIGTYPE_p_switch_ivr_menu() { swigCPtr = new HandleRef(null, IntPtr.Zero); } - internal static HandleRef getCPtr(SWIGTYPE_p_switch_ivr_menu_action_function_t obj) { + internal static HandleRef getCPtr(SWIGTYPE_p_switch_ivr_menu obj) { return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; } } @@ -19275,18 +19283,18 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; -public class SWIGTYPE_p_switch_ivr_menu { +public class SWIGTYPE_p_switch_ivr_menu_action_function_t { private HandleRef swigCPtr; - internal SWIGTYPE_p_switch_ivr_menu(IntPtr cPtr, bool futureUse) { + internal SWIGTYPE_p_switch_ivr_menu_action_function_t(IntPtr cPtr, bool futureUse) { swigCPtr = new HandleRef(this, cPtr); } - protected SWIGTYPE_p_switch_ivr_menu() { + protected SWIGTYPE_p_switch_ivr_menu_action_function_t() { swigCPtr = new HandleRef(null, IntPtr.Zero); } - internal static HandleRef getCPtr(SWIGTYPE_p_switch_ivr_menu obj) { + internal static HandleRef getCPtr(SWIGTYPE_p_switch_ivr_menu_action_function_t obj) { return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; } } @@ -20189,7 +20197,8 @@ namespace FreeSWITCH.Native { SAF_NONE = 0, SAF_SUPPORT_NOMEDIA = (1 << 0), SAF_ROUTING_EXEC = (1 << 1), - SAF_MEDIA_TAP = (1 << 2) + SAF_MEDIA_TAP = (1 << 2), + SAF_ZOMBIE_EXEC = (1 << 3) } } @@ -21583,100 +21592,6 @@ public class switch_cache_db_odbc_options_t : IDisposable { namespace FreeSWITCH.Native { -public enum switch_call_cause_t { - SWITCH_CAUSE_NONE = 0, - SWITCH_CAUSE_UNALLOCATED_NUMBER = 1, - SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET = 2, - SWITCH_CAUSE_NO_ROUTE_DESTINATION = 3, - SWITCH_CAUSE_CHANNEL_UNACCEPTABLE = 6, - SWITCH_CAUSE_CALL_AWARDED_DELIVERED = 7, - SWITCH_CAUSE_NORMAL_CLEARING = 16, - SWITCH_CAUSE_USER_BUSY = 17, - SWITCH_CAUSE_NO_USER_RESPONSE = 18, - SWITCH_CAUSE_NO_ANSWER = 19, - SWITCH_CAUSE_SUBSCRIBER_ABSENT = 20, - SWITCH_CAUSE_CALL_REJECTED = 21, - SWITCH_CAUSE_NUMBER_CHANGED = 22, - SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION = 23, - SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR = 25, - SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER = 27, - SWITCH_CAUSE_INVALID_NUMBER_FORMAT = 28, - SWITCH_CAUSE_FACILITY_REJECTED = 29, - SWITCH_CAUSE_RESPONSE_TO_STATUS_ENQUIRY = 30, - SWITCH_CAUSE_NORMAL_UNSPECIFIED = 31, - SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION = 34, - SWITCH_CAUSE_NETWORK_OUT_OF_ORDER = 38, - SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE = 41, - SWITCH_CAUSE_SWITCH_CONGESTION = 42, - SWITCH_CAUSE_ACCESS_INFO_DISCARDED = 43, - SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL = 44, - SWITCH_CAUSE_PRE_EMPTED = 45, - SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED = 50, - SWITCH_CAUSE_OUTGOING_CALL_BARRED = 52, - SWITCH_CAUSE_INCOMING_CALL_BARRED = 54, - SWITCH_CAUSE_BEARERCAPABILITY_NOTAUTH = 57, - SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL = 58, - SWITCH_CAUSE_SERVICE_UNAVAILABLE = 63, - SWITCH_CAUSE_BEARERCAPABILITY_NOTIMPL = 65, - SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED = 66, - SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED = 69, - SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED = 79, - SWITCH_CAUSE_INVALID_CALL_REFERENCE = 81, - SWITCH_CAUSE_INCOMPATIBLE_DESTINATION = 88, - SWITCH_CAUSE_INVALID_MSG_UNSPECIFIED = 95, - SWITCH_CAUSE_MANDATORY_IE_MISSING = 96, - SWITCH_CAUSE_MESSAGE_TYPE_NONEXIST = 97, - SWITCH_CAUSE_WRONG_MESSAGE = 98, - SWITCH_CAUSE_IE_NONEXIST = 99, - SWITCH_CAUSE_INVALID_IE_CONTENTS = 100, - SWITCH_CAUSE_WRONG_CALL_STATE = 101, - SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE = 102, - SWITCH_CAUSE_MANDATORY_IE_LENGTH_ERROR = 103, - SWITCH_CAUSE_PROTOCOL_ERROR = 111, - SWITCH_CAUSE_INTERWORKING = 127, - SWITCH_CAUSE_SUCCESS = 142, - SWITCH_CAUSE_ORIGINATOR_CANCEL = 487, - SWITCH_CAUSE_CRASH = 500, - SWITCH_CAUSE_SYSTEM_SHUTDOWN = 501, - SWITCH_CAUSE_LOSE_RACE = 502, - SWITCH_CAUSE_MANAGER_REQUEST = 503, - SWITCH_CAUSE_BLIND_TRANSFER = 600, - SWITCH_CAUSE_ATTENDED_TRANSFER = 601, - SWITCH_CAUSE_ALLOTTED_TIMEOUT = 602, - SWITCH_CAUSE_USER_CHALLENGE = 603, - SWITCH_CAUSE_MEDIA_TIMEOUT = 604, - SWITCH_CAUSE_PICKED_OFF = 605, - SWITCH_CAUSE_USER_NOT_REGISTERED = 606, - SWITCH_CAUSE_PROGRESS_TIMEOUT = 607 -} - -} -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 1.3.35 - * - * Do not make changes to this file unless you know what you are doing--modify - * the SWIG interface file instead. - * ----------------------------------------------------------------------------- */ - -namespace FreeSWITCH.Native { - -public enum switch_call_direction_t { - SWITCH_CALL_DIRECTION_INBOUND, - SWITCH_CALL_DIRECTION_OUTBOUND -} - -} -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 1.3.35 - * - * Do not make changes to this file unless you know what you are doing--modify - * the SWIG interface file instead. - * ----------------------------------------------------------------------------- */ - -namespace FreeSWITCH.Native { - using System; using System.Runtime.InteropServices; @@ -22312,6 +22227,100 @@ namespace FreeSWITCH.Native { namespace FreeSWITCH.Native { +public enum switch_call_cause_t { + SWITCH_CAUSE_NONE = 0, + SWITCH_CAUSE_UNALLOCATED_NUMBER = 1, + SWITCH_CAUSE_NO_ROUTE_TRANSIT_NET = 2, + SWITCH_CAUSE_NO_ROUTE_DESTINATION = 3, + SWITCH_CAUSE_CHANNEL_UNACCEPTABLE = 6, + SWITCH_CAUSE_CALL_AWARDED_DELIVERED = 7, + SWITCH_CAUSE_NORMAL_CLEARING = 16, + SWITCH_CAUSE_USER_BUSY = 17, + SWITCH_CAUSE_NO_USER_RESPONSE = 18, + SWITCH_CAUSE_NO_ANSWER = 19, + SWITCH_CAUSE_SUBSCRIBER_ABSENT = 20, + SWITCH_CAUSE_CALL_REJECTED = 21, + SWITCH_CAUSE_NUMBER_CHANGED = 22, + SWITCH_CAUSE_REDIRECTION_TO_NEW_DESTINATION = 23, + SWITCH_CAUSE_EXCHANGE_ROUTING_ERROR = 25, + SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER = 27, + SWITCH_CAUSE_INVALID_NUMBER_FORMAT = 28, + SWITCH_CAUSE_FACILITY_REJECTED = 29, + SWITCH_CAUSE_RESPONSE_TO_STATUS_ENQUIRY = 30, + SWITCH_CAUSE_NORMAL_UNSPECIFIED = 31, + SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION = 34, + SWITCH_CAUSE_NETWORK_OUT_OF_ORDER = 38, + SWITCH_CAUSE_NORMAL_TEMPORARY_FAILURE = 41, + SWITCH_CAUSE_SWITCH_CONGESTION = 42, + SWITCH_CAUSE_ACCESS_INFO_DISCARDED = 43, + SWITCH_CAUSE_REQUESTED_CHAN_UNAVAIL = 44, + SWITCH_CAUSE_PRE_EMPTED = 45, + SWITCH_CAUSE_FACILITY_NOT_SUBSCRIBED = 50, + SWITCH_CAUSE_OUTGOING_CALL_BARRED = 52, + SWITCH_CAUSE_INCOMING_CALL_BARRED = 54, + SWITCH_CAUSE_BEARERCAPABILITY_NOTAUTH = 57, + SWITCH_CAUSE_BEARERCAPABILITY_NOTAVAIL = 58, + SWITCH_CAUSE_SERVICE_UNAVAILABLE = 63, + SWITCH_CAUSE_BEARERCAPABILITY_NOTIMPL = 65, + SWITCH_CAUSE_CHAN_NOT_IMPLEMENTED = 66, + SWITCH_CAUSE_FACILITY_NOT_IMPLEMENTED = 69, + SWITCH_CAUSE_SERVICE_NOT_IMPLEMENTED = 79, + SWITCH_CAUSE_INVALID_CALL_REFERENCE = 81, + SWITCH_CAUSE_INCOMPATIBLE_DESTINATION = 88, + SWITCH_CAUSE_INVALID_MSG_UNSPECIFIED = 95, + SWITCH_CAUSE_MANDATORY_IE_MISSING = 96, + SWITCH_CAUSE_MESSAGE_TYPE_NONEXIST = 97, + SWITCH_CAUSE_WRONG_MESSAGE = 98, + SWITCH_CAUSE_IE_NONEXIST = 99, + SWITCH_CAUSE_INVALID_IE_CONTENTS = 100, + SWITCH_CAUSE_WRONG_CALL_STATE = 101, + SWITCH_CAUSE_RECOVERY_ON_TIMER_EXPIRE = 102, + SWITCH_CAUSE_MANDATORY_IE_LENGTH_ERROR = 103, + SWITCH_CAUSE_PROTOCOL_ERROR = 111, + SWITCH_CAUSE_INTERWORKING = 127, + SWITCH_CAUSE_SUCCESS = 142, + SWITCH_CAUSE_ORIGINATOR_CANCEL = 487, + SWITCH_CAUSE_CRASH = 500, + SWITCH_CAUSE_SYSTEM_SHUTDOWN = 501, + SWITCH_CAUSE_LOSE_RACE = 502, + SWITCH_CAUSE_MANAGER_REQUEST = 503, + SWITCH_CAUSE_BLIND_TRANSFER = 600, + SWITCH_CAUSE_ATTENDED_TRANSFER = 601, + SWITCH_CAUSE_ALLOTTED_TIMEOUT = 602, + SWITCH_CAUSE_USER_CHALLENGE = 603, + SWITCH_CAUSE_MEDIA_TIMEOUT = 604, + SWITCH_CAUSE_PICKED_OFF = 605, + SWITCH_CAUSE_USER_NOT_REGISTERED = 606, + SWITCH_CAUSE_PROGRESS_TIMEOUT = 607 +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 1.3.35 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + +public enum switch_call_direction_t { + SWITCH_CALL_DIRECTION_INBOUND, + SWITCH_CALL_DIRECTION_OUTBOUND +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 1.3.35 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + public enum switch_channel_app_flag_t { CF_APP_TAGGED = (1 << 0), CF_APP_T38 = (1 << 1), @@ -22436,6 +22445,7 @@ public enum switch_channel_flag_t { CF_LAZY_ATTENDED_TRANSFER, CF_SIGNAL_DATA, CF_SIMPLIFY, + CF_ZOMBIE_EXEC, CF_FLAG_MAX } @@ -22709,13 +22719,13 @@ public class switch_chat_interface : IDisposable { } } - public SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char__switch_status_t chat_send { + public SWIGTYPE_p_f_p_switch_event__switch_status_t chat_send { set { - freeswitchPINVOKE.switch_chat_interface_chat_send_set(swigCPtr, SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char__switch_status_t.getCPtr(value)); + freeswitchPINVOKE.switch_chat_interface_chat_send_set(swigCPtr, SWIGTYPE_p_f_p_switch_event__switch_status_t.getCPtr(value)); } get { IntPtr cPtr = freeswitchPINVOKE.switch_chat_interface_chat_send_get(swigCPtr); - SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char__switch_status_t ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_f_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char_p_q_const__char__switch_status_t(cPtr, false); + SWIGTYPE_p_f_p_switch_event__switch_status_t ret = (cPtr == IntPtr.Zero) ? null : new SWIGTYPE_p_f_p_switch_event__switch_status_t(cPtr, false); return ret; } } @@ -26704,6 +26714,196 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; +public class switch_io_event_hooks : IDisposable { + private HandleRef swigCPtr; + protected bool swigCMemOwn; + + internal switch_io_event_hooks(IntPtr cPtr, bool cMemoryOwn) { + swigCMemOwn = cMemoryOwn; + swigCPtr = new HandleRef(this, cPtr); + } + + internal static HandleRef getCPtr(switch_io_event_hooks obj) { + return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; + } + + ~switch_io_event_hooks() { + Dispose(); + } + + public virtual void Dispose() { + lock(this) { + if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) { + swigCMemOwn = false; + freeswitchPINVOKE.delete_switch_io_event_hooks(swigCPtr); + } + swigCPtr = new HandleRef(null, IntPtr.Zero); + GC.SuppressFinalize(this); + } + } + + public switch_io_event_hook_outgoing_channel outgoing_channel { + set { + freeswitchPINVOKE.switch_io_event_hooks_outgoing_channel_set(swigCPtr, switch_io_event_hook_outgoing_channel.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_outgoing_channel_get(swigCPtr); + switch_io_event_hook_outgoing_channel ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_outgoing_channel(cPtr, false); + return ret; + } + } + + public switch_io_event_hook_receive_message receive_message { + set { + freeswitchPINVOKE.switch_io_event_hooks_receive_message_set(swigCPtr, switch_io_event_hook_receive_message.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_receive_message_get(swigCPtr); + switch_io_event_hook_receive_message ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_receive_message(cPtr, false); + return ret; + } + } + + public switch_io_event_hook_receive_event receive_event { + set { + freeswitchPINVOKE.switch_io_event_hooks_receive_event_set(swigCPtr, switch_io_event_hook_receive_event.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_receive_event_get(swigCPtr); + switch_io_event_hook_receive_event ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_receive_event(cPtr, false); + return ret; + } + } + + public switch_io_event_hook_read_frame read_frame { + set { + freeswitchPINVOKE.switch_io_event_hooks_read_frame_set(swigCPtr, switch_io_event_hook_read_frame.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_read_frame_get(swigCPtr); + switch_io_event_hook_read_frame ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_read_frame(cPtr, false); + return ret; + } + } + + public switch_io_event_hook_video_read_frame video_read_frame { + set { + freeswitchPINVOKE.switch_io_event_hooks_video_read_frame_set(swigCPtr, switch_io_event_hook_video_read_frame.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_video_read_frame_get(swigCPtr); + switch_io_event_hook_video_read_frame ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_video_read_frame(cPtr, false); + return ret; + } + } + + public switch_io_event_hook_write_frame write_frame { + set { + freeswitchPINVOKE.switch_io_event_hooks_write_frame_set(swigCPtr, switch_io_event_hook_write_frame.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_write_frame_get(swigCPtr); + switch_io_event_hook_write_frame ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_write_frame(cPtr, false); + return ret; + } + } + + public switch_io_event_hook_video_write_frame video_write_frame { + set { + freeswitchPINVOKE.switch_io_event_hooks_video_write_frame_set(swigCPtr, switch_io_event_hook_video_write_frame.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_video_write_frame_get(swigCPtr); + switch_io_event_hook_video_write_frame ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_video_write_frame(cPtr, false); + return ret; + } + } + + public switch_io_event_hook_kill_channel kill_channel { + set { + freeswitchPINVOKE.switch_io_event_hooks_kill_channel_set(swigCPtr, switch_io_event_hook_kill_channel.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_kill_channel_get(swigCPtr); + switch_io_event_hook_kill_channel ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_kill_channel(cPtr, false); + return ret; + } + } + + public switch_io_event_hook_send_dtmf send_dtmf { + set { + freeswitchPINVOKE.switch_io_event_hooks_send_dtmf_set(swigCPtr, switch_io_event_hook_send_dtmf.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_send_dtmf_get(swigCPtr); + switch_io_event_hook_send_dtmf ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_send_dtmf(cPtr, false); + return ret; + } + } + + public switch_io_event_hook_recv_dtmf recv_dtmf { + set { + freeswitchPINVOKE.switch_io_event_hooks_recv_dtmf_set(swigCPtr, switch_io_event_hook_recv_dtmf.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_recv_dtmf_get(swigCPtr); + switch_io_event_hook_recv_dtmf ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_recv_dtmf(cPtr, false); + return ret; + } + } + + public switch_io_event_hook_state_change state_change { + set { + freeswitchPINVOKE.switch_io_event_hooks_state_change_set(swigCPtr, switch_io_event_hook_state_change.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_state_change_get(swigCPtr); + switch_io_event_hook_state_change ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_state_change(cPtr, false); + return ret; + } + } + + public switch_io_event_hook_state_run state_run { + set { + freeswitchPINVOKE.switch_io_event_hooks_state_run_set(swigCPtr, switch_io_event_hook_state_run.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_state_run_get(swigCPtr); + switch_io_event_hook_state_run ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_state_run(cPtr, false); + return ret; + } + } + + public switch_io_event_hook_resurrect_session resurrect_session { + set { + freeswitchPINVOKE.switch_io_event_hooks_resurrect_session_set(swigCPtr, switch_io_event_hook_resurrect_session.getCPtr(value)); + } + get { + IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_resurrect_session_get(swigCPtr); + switch_io_event_hook_resurrect_session ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_resurrect_session(cPtr, false); + return ret; + } + } + + public switch_io_event_hooks() : this(freeswitchPINVOKE.new_switch_io_event_hooks(), true) { + } + +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 1.3.35 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + +using System; +using System.Runtime.InteropServices; + public class switch_io_event_hook_kill_channel : IDisposable { private HandleRef swigCPtr; protected bool swigCMemOwn; @@ -27187,196 +27387,6 @@ namespace FreeSWITCH.Native { using System; using System.Runtime.InteropServices; -public class switch_io_event_hooks : IDisposable { - private HandleRef swigCPtr; - protected bool swigCMemOwn; - - internal switch_io_event_hooks(IntPtr cPtr, bool cMemoryOwn) { - swigCMemOwn = cMemoryOwn; - swigCPtr = new HandleRef(this, cPtr); - } - - internal static HandleRef getCPtr(switch_io_event_hooks obj) { - return (obj == null) ? new HandleRef(null, IntPtr.Zero) : obj.swigCPtr; - } - - ~switch_io_event_hooks() { - Dispose(); - } - - public virtual void Dispose() { - lock(this) { - if(swigCPtr.Handle != IntPtr.Zero && swigCMemOwn) { - swigCMemOwn = false; - freeswitchPINVOKE.delete_switch_io_event_hooks(swigCPtr); - } - swigCPtr = new HandleRef(null, IntPtr.Zero); - GC.SuppressFinalize(this); - } - } - - public switch_io_event_hook_outgoing_channel outgoing_channel { - set { - freeswitchPINVOKE.switch_io_event_hooks_outgoing_channel_set(swigCPtr, switch_io_event_hook_outgoing_channel.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_outgoing_channel_get(swigCPtr); - switch_io_event_hook_outgoing_channel ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_outgoing_channel(cPtr, false); - return ret; - } - } - - public switch_io_event_hook_receive_message receive_message { - set { - freeswitchPINVOKE.switch_io_event_hooks_receive_message_set(swigCPtr, switch_io_event_hook_receive_message.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_receive_message_get(swigCPtr); - switch_io_event_hook_receive_message ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_receive_message(cPtr, false); - return ret; - } - } - - public switch_io_event_hook_receive_event receive_event { - set { - freeswitchPINVOKE.switch_io_event_hooks_receive_event_set(swigCPtr, switch_io_event_hook_receive_event.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_receive_event_get(swigCPtr); - switch_io_event_hook_receive_event ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_receive_event(cPtr, false); - return ret; - } - } - - public switch_io_event_hook_read_frame read_frame { - set { - freeswitchPINVOKE.switch_io_event_hooks_read_frame_set(swigCPtr, switch_io_event_hook_read_frame.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_read_frame_get(swigCPtr); - switch_io_event_hook_read_frame ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_read_frame(cPtr, false); - return ret; - } - } - - public switch_io_event_hook_video_read_frame video_read_frame { - set { - freeswitchPINVOKE.switch_io_event_hooks_video_read_frame_set(swigCPtr, switch_io_event_hook_video_read_frame.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_video_read_frame_get(swigCPtr); - switch_io_event_hook_video_read_frame ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_video_read_frame(cPtr, false); - return ret; - } - } - - public switch_io_event_hook_write_frame write_frame { - set { - freeswitchPINVOKE.switch_io_event_hooks_write_frame_set(swigCPtr, switch_io_event_hook_write_frame.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_write_frame_get(swigCPtr); - switch_io_event_hook_write_frame ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_write_frame(cPtr, false); - return ret; - } - } - - public switch_io_event_hook_video_write_frame video_write_frame { - set { - freeswitchPINVOKE.switch_io_event_hooks_video_write_frame_set(swigCPtr, switch_io_event_hook_video_write_frame.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_video_write_frame_get(swigCPtr); - switch_io_event_hook_video_write_frame ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_video_write_frame(cPtr, false); - return ret; - } - } - - public switch_io_event_hook_kill_channel kill_channel { - set { - freeswitchPINVOKE.switch_io_event_hooks_kill_channel_set(swigCPtr, switch_io_event_hook_kill_channel.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_kill_channel_get(swigCPtr); - switch_io_event_hook_kill_channel ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_kill_channel(cPtr, false); - return ret; - } - } - - public switch_io_event_hook_send_dtmf send_dtmf { - set { - freeswitchPINVOKE.switch_io_event_hooks_send_dtmf_set(swigCPtr, switch_io_event_hook_send_dtmf.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_send_dtmf_get(swigCPtr); - switch_io_event_hook_send_dtmf ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_send_dtmf(cPtr, false); - return ret; - } - } - - public switch_io_event_hook_recv_dtmf recv_dtmf { - set { - freeswitchPINVOKE.switch_io_event_hooks_recv_dtmf_set(swigCPtr, switch_io_event_hook_recv_dtmf.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_recv_dtmf_get(swigCPtr); - switch_io_event_hook_recv_dtmf ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_recv_dtmf(cPtr, false); - return ret; - } - } - - public switch_io_event_hook_state_change state_change { - set { - freeswitchPINVOKE.switch_io_event_hooks_state_change_set(swigCPtr, switch_io_event_hook_state_change.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_state_change_get(swigCPtr); - switch_io_event_hook_state_change ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_state_change(cPtr, false); - return ret; - } - } - - public switch_io_event_hook_state_run state_run { - set { - freeswitchPINVOKE.switch_io_event_hooks_state_run_set(swigCPtr, switch_io_event_hook_state_run.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_state_run_get(swigCPtr); - switch_io_event_hook_state_run ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_state_run(cPtr, false); - return ret; - } - } - - public switch_io_event_hook_resurrect_session resurrect_session { - set { - freeswitchPINVOKE.switch_io_event_hooks_resurrect_session_set(swigCPtr, switch_io_event_hook_resurrect_session.getCPtr(value)); - } - get { - IntPtr cPtr = freeswitchPINVOKE.switch_io_event_hooks_resurrect_session_get(swigCPtr); - switch_io_event_hook_resurrect_session ret = (cPtr == IntPtr.Zero) ? null : new switch_io_event_hook_resurrect_session(cPtr, false); - return ret; - } - } - - public switch_io_event_hooks() : this(freeswitchPINVOKE.new_switch_io_event_hooks(), true) { - } - -} - -} -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 1.3.35 - * - * Do not make changes to this file unless you know what you are doing--modify - * the SWIG interface file instead. - * ----------------------------------------------------------------------------- */ - -namespace FreeSWITCH.Native { - -using System; -using System.Runtime.InteropServices; - public class switch_io_event_hook_send_dtmf : IDisposable { private HandleRef swigCPtr; protected bool swigCMemOwn; @@ -27805,31 +27815,6 @@ namespace FreeSWITCH.Native { namespace FreeSWITCH.Native { -public enum switch_io_routine_name_t { - SWITCH_IO_OUTGOING_CHANNEL, - SWITCH_IO_READ_FRAME, - SWITCH_IO_WRITE_FRAME, - SWITCH_IO_KILL_CHANNEL, - SWITCH_IO_SEND_DTMF, - SWITCH_IO_RECEIVE_MESSAGE, - SWITCH_IO_RECEIVE_EVENT, - SWITCH_IO_STATE_CHANGE, - SWITCH_IO_READ_VIDEO_FRAME, - SWITCH_IO_WRITE_VIDEO_FRAME, - SWITCH_IO_RESURRECT_SESSION -} - -} -/* ---------------------------------------------------------------------------- - * This file was automatically generated by SWIG (http://www.swig.org). - * Version 1.3.35 - * - * Do not make changes to this file unless you know what you are doing--modify - * the SWIG interface file instead. - * ----------------------------------------------------------------------------- */ - -namespace FreeSWITCH.Native { - using System; using System.Runtime.InteropServices; @@ -28020,6 +28005,31 @@ public class switch_io_routines : IDisposable { namespace FreeSWITCH.Native { +public enum switch_io_routine_name_t { + SWITCH_IO_OUTGOING_CHANNEL, + SWITCH_IO_READ_FRAME, + SWITCH_IO_WRITE_FRAME, + SWITCH_IO_KILL_CHANNEL, + SWITCH_IO_SEND_DTMF, + SWITCH_IO_RECEIVE_MESSAGE, + SWITCH_IO_RECEIVE_EVENT, + SWITCH_IO_STATE_CHANGE, + SWITCH_IO_READ_VIDEO_FRAME, + SWITCH_IO_WRITE_VIDEO_FRAME, + SWITCH_IO_RESURRECT_SESSION +} + +} +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 1.3.35 + * + * Do not make changes to this file unless you know what you are doing--modify + * the SWIG interface file instead. + * ----------------------------------------------------------------------------- */ + +namespace FreeSWITCH.Native { + public enum switch_ivr_action_t { SWITCH_IVR_ACTION_DIE, SWITCH_IVR_ACTION_EXECMENU, diff --git a/src/mod/languages/mod_managed/runswig.cmd b/src/mod/languages/mod_managed/runswig.cmd index 631a507a20..5a0634df71 100644 --- a/src/mod/languages/mod_managed/runswig.cmd +++ b/src/mod/languages/mod_managed/runswig.cmd @@ -5,3 +5,5 @@ for %%X in (*.cs) do type %%X >> swig.csx @ECHO ON move swig.csx managed\swig.cs del *.cs +\tools\dos2unix\bin\dos2unix managed\swig.cs +\tools\dos2unix\bin\dos2unix freeswitch_wrap.cxx From d9b096b44d215ac810192616dcd95d444e88c45d Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Thu, 15 Sep 2011 11:42:55 -0500 Subject: [PATCH 104/204] FS-3555 --resolve --- src/switch_ivr_originate.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/switch_ivr_originate.c b/src/switch_ivr_originate.c index 3addeb3c46..1bf38b4775 100644 --- a/src/switch_ivr_originate.c +++ b/src/switch_ivr_originate.c @@ -1050,6 +1050,15 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_wait_for_answer(switch_core_session_t status = SWITCH_STATUS_FALSE; } + if (switch_channel_test_flag(caller_channel, CF_XFER_ZOMBIE)) { + switch_channel_state_t peer_state = switch_channel_get_state(peer_channel); + + while (switch_channel_ready(peer_channel) && switch_channel_get_state(peer_channel) == peer_state) { + switch_channel_ready(caller_channel); + switch_yield(20000); + } + } + if (caller_channel && !switch_channel_up(caller_channel)) { status = SWITCH_STATUS_FALSE; } From aa0a6c9222a70c7a0143af4f9fce3cf0ce0f877a Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 15 Sep 2011 13:50:42 -0400 Subject: [PATCH 105/204] freetdm: print span/chan identifiers on hangup --- libs/freetdm/mod_freetdm/mod_freetdm.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 7e0bb55a1b..435c9a8e64 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -505,6 +505,8 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) private_t *tech_pvt = NULL; ftdm_chan_type_t chantype; const char *name = NULL; + int span_id = 0; + int chan_id = 0; uint32_t tokencnt; channel = switch_core_session_get_channel(session); @@ -517,9 +519,14 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) switch_clear_flag_locked(tech_pvt, TFLAG_IO); name = switch_channel_get_name(channel); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP ENTER\n", name); + + span_id = tech_pvt->ftdmchan ? ftdm_channel_get_span_id(tech_pvt->ftdmchan) : 0; + chan_id = tech_pvt->ftdmchan ? ftdm_channel_get_id(tech_pvt->ftdmchan) : 0; + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%d:%d] %s CHANNEL HANGUP ENTER\n", span_id, chan_id, name); if (!tech_pvt->ftdmchan) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s does not have any ftdmchan attached\n", name); goto end; } @@ -534,7 +541,8 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) symbols = backtrace_symbols(stacktrace, size); tid = syscall(SYS_gettid); for (si = 0; si < size; si++) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%d] %s -> %s\n", tid, name, symbols[si]); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%d:%d][tid:%d] %s -> %s\n", + span_id, chan_id, tid, name, symbols[si]); } free(symbols); } @@ -588,7 +596,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) } switch_mutex_unlock(globals.mutex); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP EXIT\n", name); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%d:%d] %s CHANNEL HANGUP EXIT\n", span_id, chan_id, name); return SWITCH_STATUS_SUCCESS; } From 2205f59f107356f5f0391e1bb8279814b29c4347 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Thu, 15 Sep 2011 21:01:12 +0000 Subject: [PATCH 106/204] whitespace cleanup --- docs/phrase/phrase_en.xml | 241 +++++++++++++++++++------------------- 1 file changed, 122 insertions(+), 119 deletions(-) diff --git a/docs/phrase/phrase_en.xml b/docs/phrase/phrase_en.xml index 22929edcd5..ecdebc9fdf 100644 --- a/docs/phrase/phrase_en.xml +++ b/docs/phrase/phrase_en.xml @@ -5,23 +5,23 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + @@ -239,30 +239,30 @@ - - + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + @@ -287,14 +287,14 @@ - - - - - - - - + + + + + + + + @@ -398,21 +398,21 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + @@ -439,67 +439,64 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + - @@ -1046,3 +1043,9 @@ + From 25417d3ea8d4f1b8e192d79ebad8e9d45dc85790 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 15 Sep 2011 19:32:08 -0400 Subject: [PATCH 107/204] freetdm: Verify that the uuid that is being hung up is still attached to the FreeTDM device This avoids hanging up a device that is no longer attached to the session, in the weird situation where the FreeSWITCH core takes an awful lot of time (more than 3 seconds) to come around to acknowledge the SIGEVENT_STOP signal. --- libs/freetdm/mod_freetdm/mod_freetdm.c | 27 +++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 435c9a8e64..1e07db5e31 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -507,7 +507,11 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) const char *name = NULL; int span_id = 0; int chan_id = 0; + int t = 0; uint32_t tokencnt; + char *uuid = NULL; + const char *token = NULL; + uint8_t uuid_found = 0; channel = switch_core_session_get_channel(session); assert(channel != NULL); @@ -525,11 +529,33 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%d:%d] %s CHANNEL HANGUP ENTER\n", span_id, chan_id, name); + /* First verify this call has a device attached */ if (!tech_pvt->ftdmchan) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s does not have any ftdmchan attached\n", name); goto end; } + /* Now verify the device is still attached to this call :-) + * Sometimes the FS core takes too long (more than 3 seconds) in calling + * channel_on_hangup() and the FreeTDM core decides to take the brute + * force approach and hangup and detach themselves from the call. Later + * when FS finally comes around, we might end up hanging up the device + * attached to another call, this verification avoids that. */ + uuid = switch_core_session_get_uuid(session); + tokencnt = ftdm_channel_get_token_count(tech_pvt->ftdmchan); + for (t = 0; t < tokencnt; t++) { + token = ftdm_channel_get_token(tech_pvt->ftdmchan, tokencnt); + if (!strcasecmp(uuid, token)) { + uuid_found = 1; + break; + } + } + + if (!uuid_found) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Device [%d:%d] is no longer attached to %s. Nothing to do.\n", span_id, chan_id, name); + goto end; + } + #ifdef CUDATEL_DEBUG { pid_t tid = 0; @@ -561,7 +587,6 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) case FTDM_CHAN_TYPE_FXS: { if (!ftdm_channel_call_check_busy(tech_pvt->ftdmchan) && !ftdm_channel_call_check_done(tech_pvt->ftdmchan)) { - tokencnt = ftdm_channel_get_token_count(tech_pvt->ftdmchan); if (tokencnt) { cycle_foreground(tech_pvt->ftdmchan, 0, NULL); } else { From f0ff97fd7c7b6b626484710852769359677117ce Mon Sep 17 00:00:00 2001 From: Brian West Date: Fri, 16 Sep 2011 16:23:32 -0500 Subject: [PATCH 108/204] FS-3427 --resolve --- build/freeswitch.init.redhat | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/freeswitch.init.redhat b/build/freeswitch.init.redhat index b9dc3d8db5..95d15c27ea 100644 --- a/build/freeswitch.init.redhat +++ b/build/freeswitch.init.redhat @@ -43,8 +43,8 @@ start() { fi cd $FS_HOME daemon --user $FS_USER --pidfile $PID_FILE "$FS_FILE $FREESWITCH_ARGS $FREESWITCH_PARAMS >/dev/null 2>&1" - echo RETVAL=$? + echo [ $RETVAL -eq 0 ] && touch $LOCK_FILE; echo return $RETVAL From e1f1c42fbbd6abfb13fafdab6141f37e5eb69261 Mon Sep 17 00:00:00 2001 From: Brian West Date: Fri, 16 Sep 2011 16:24:33 -0500 Subject: [PATCH 109/204] FS-3433 --resolve --- freeswitch-sounds-music.spec | 126 +++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 freeswitch-sounds-music.spec diff --git a/freeswitch-sounds-music.spec b/freeswitch-sounds-music.spec new file mode 100644 index 0000000000..6864e10fa3 --- /dev/null +++ b/freeswitch-sounds-music.spec @@ -0,0 +1,126 @@ +%define prefix /opt/freeswitch +%define _prefix %{prefix} + + +Summary: FreeSWITCH Music on Hold soundfiles +Name: freeswitch-sounds-music +Version: 1.0.8 +Release: 1%{?dist} +License: MPL +Group: Productivity/Telephony/Servers +Packager: Joseph L. Casale +URL: http://www.freeswitch.org +Source0: http://files.freeswitch.org/%{name}-8000-%{version}.tar.gz +Source1: http://files.freeswitch.org/%{name}-16000-%{version}.tar.gz +Source2: http://files.freeswitch.org/%{name}-32000-%{version}.tar.gz +Source3: http://files.freeswitch.org/%{name}-48000-%{version}.tar.gz +BuildArch: noarch +BuildRequires: bash +Requires: freeswitch +Requires: freeswitch-sounds-music-8000 = %{version} +Requires: freeswitch-sounds-music-16000 = %{version} +Requires: freeswitch-sounds-music-32000 = %{version} +Requires: freeswitch-sounds-music-48000 = %{version} +BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) + +%description +FreeSWITCH Music On Hold soundfiles package that installs the 8KHz, 16KHz, +32KHz and 48KHz RPMs + + +%package -n freeswitch-sounds-music-8000 +Summary: FreeSWITCH 8kHz Music On Hold soundfiles +Group: Productivity/Telephony/Servers +BuildArch: noarch +Requires: freeswitch + +%description -n freeswitch-sounds-music-8000 +FreeSWITCH 8kHz Music On Hold soundfiles + + +%package -n freeswitch-sounds-music-16000 +Summary: FreeSWITCH 16kHz Music On Hold soundfiles +Group: Productivity/Telephony/Servers +BuildArch: noarch +Requires: freeswitch + +%description -n freeswitch-sounds-music-16000 +FreeSWITCH 16kHz Music On Hold soundfiles + + +%package -n freeswitch-sounds-music-32000 +Summary: FreeSWITCH 32kHz Music On Hold soundfiles +Group: Productivity/Telephony/Servers +BuildArch: noarch +Requires: freeswitch + +%description -n freeswitch-sounds-music-32000 +FreeSWITCH 32kHz Music On Hold soundfiles + + +%package -n freeswitch-sounds-music-48000 +Summary: FreeSWITCH 48kHz Music On Hold soundfiles +Group: Productivity/Telephony/Servers +BuildArch: noarch +Requires: freeswitch + +%description -n freeswitch-sounds-music-48000 +FreeSWITCH 48kHz Music On Hold soundfiles + + +%prep +%setup -n music +%setup -T -D -b 1 -n music +%setup -T -D -b 2 -n music +%setup -T -D -b 3 -n music + + +%build + + +%install +%{__rm} -rf %{buildroot} +%{__install} -d -m 0750 %{buildroot}/%{_prefix}/sounds/music/{8000,16000,32000,48000} +%{__cp} -prv ./{8000,16000,32000,48000} %{buildroot}%{_prefix}/sounds/music + + +%clean +%{__rm} -rf %{buildroot} + + +%post + + +%postun + + +%files + + +%files -n freeswitch-sounds-music-8000 +%defattr(-,root,root,-) +%dir %{_prefix}/sounds/music/8000 +%{_prefix}/sounds/music/8000/*.wav + + +%files -n freeswitch-sounds-music-16000 +%defattr(-,root,root,-) +%dir %{_prefix}/sounds/music/16000 +%{_prefix}/sounds/music/16000/*.wav + + +%files -n freeswitch-sounds-music-32000 +%defattr(-,root,root,-) +%dir %{_prefix}/sounds/music/32000 +%{_prefix}/sounds/music/32000/*.wav + + +%files -n freeswitch-sounds-music-48000 +%defattr(-,root,root,-) +%dir %{_prefix}/sounds/music/48000 +%{_prefix}/sounds/music/48000/*.wav + + +%changelog +* Sat Jul 16 2011 Joseph Casale 1.0.8-1 +- Initial release \ No newline at end of file From d9ce90d7b9cd35705ab03a42953b6bf866a9caf8 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 11:39:41 -0500 Subject: [PATCH 110/204] FS-3570 generate side --- src/switch_channel.c | 2 +- src/switch_core.c | 18 ++++++++++++++++++ src/switch_ivr_async.c | 33 ++++++++++++++++++++++++++------- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/switch_channel.c b/src/switch_channel.c index 2055e8fc07..a8669f1602 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -446,7 +446,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf_string(switch_channel_ dur = switch_core_default_dtmf_duration(0) / 8; if ((p = strchr(argv[i], '@'))) { *p++ = '\0'; - if ((dur = atoi(p)) > 50) { + if ((dur = atoi(p)) > switch_core_min_dtmf_duration(0) / 8) { dtmf.duration = dur * 8; } } diff --git a/src/switch_core.c b/src/switch_core.c index 045ff3978c..85a710c085 100644 --- a/src/switch_core.c +++ b/src/switch_core.c @@ -1263,6 +1263,9 @@ SWITCH_DECLARE(uint32_t) switch_core_max_dtmf_duration(uint32_t duration) duration = SWITCH_MIN_DTMF_DURATION; } runtime.max_dtmf_duration = duration; + if (duration < runtime.min_dtmf_duration) { + runtime.min_dtmf_duration = duration; + } } return runtime.max_dtmf_duration; } @@ -1277,6 +1280,15 @@ SWITCH_DECLARE(uint32_t) switch_core_default_dtmf_duration(uint32_t duration) duration = SWITCH_MAX_DTMF_DURATION; } runtime.default_dtmf_duration = duration; + + if (duration < runtime.min_dtmf_duration) { + runtime.min_dtmf_duration = duration; + } + + if (duration > runtime.max_dtmf_duration) { + runtime.max_dtmf_duration = duration; + } + } return runtime.default_dtmf_duration; } @@ -1290,6 +1302,12 @@ SWITCH_DECLARE(uint32_t) switch_core_min_dtmf_duration(uint32_t duration) if (duration > SWITCH_MAX_DTMF_DURATION) { duration = SWITCH_MAX_DTMF_DURATION; } + + runtime.min_dtmf_duration = duration; + + if (duration > runtime.max_dtmf_duration) { + runtime.max_dtmf_duration = duration; + } } return runtime.min_dtmf_duration; } diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index b5d0591ec5..6fe6048173 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -2229,6 +2229,7 @@ typedef struct { switch_mutex_t *mutex; int read; int ready; + int skip; } switch_inband_dtmf_generate_t; static int teletone_dtmf_generate_handler(teletone_generation_session_t *ts, teletone_tone_map_t *map) @@ -2257,13 +2258,17 @@ static switch_status_t generate_on_dtmf(switch_core_session_t *session, const sw if (pvt) { switch_mutex_lock(pvt->mutex); + if (pvt->ready) { switch_dtmf_t *dt = NULL; switch_zmalloc(dt, sizeof(*dt)); *dt = *dtmf; + if (!switch_buffer_inuse(pvt->audio_buffer)) { + pvt->skip = 10; + } if (switch_queue_trypush(pvt->digit_queue, dt) == SWITCH_STATUS_SUCCESS) { switch_event_t *event; - + if (switch_event_create(&event, SWITCH_EVENT_DTMF) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(channel, event); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "DTMF-Digit", "%c", dtmf->digit); @@ -2310,7 +2315,11 @@ static switch_bool_t inband_dtmf_generate_callback(switch_media_bug_t *bug, void pvt->ts.rate = read_impl.actual_samples_per_second; pvt->ts.channels = 1; switch_mutex_init(&pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(pvt->session)); - switch_core_event_hook_add_recv_dtmf(pvt->session, generate_on_dtmf); + if (pvt->read) { + switch_core_event_hook_add_recv_dtmf(pvt->session, generate_on_dtmf); + } else { + switch_core_event_hook_add_send_dtmf(pvt->session, generate_on_dtmf); + } switch_mutex_lock(pvt->mutex); pvt->ready = 1; switch_mutex_unlock(pvt->mutex); @@ -2331,6 +2340,12 @@ static switch_bool_t inband_dtmf_generate_callback(switch_media_bug_t *bug, void { switch_size_t bytes; void *pop; + + if (pvt->skip) { + pvt->skip--; + return SWITCH_TRUE; + } + switch_mutex_lock(pvt->mutex); @@ -2348,17 +2363,21 @@ static switch_bool_t inband_dtmf_generate_callback(switch_media_bug_t *bug, void if (!switch_buffer_inuse(pvt->audio_buffer)) { if (switch_queue_trypop(pvt->digit_queue, &pop) == SWITCH_STATUS_SUCCESS) { switch_dtmf_t *dtmf = (switch_dtmf_t *) pop; + + if (dtmf->source != SWITCH_DTMF_INBAND_AUDIO) { char buf[2] = ""; int duration = dtmf->duration; buf[0] = dtmf->digit; - if (duration > 8000) { - duration = 4000; + if (duration > switch_core_max_dtmf_duration(0)) { + duration = switch_core_default_dtmf_duration(0); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), - SWITCH_LOG_WARNING, "%s Truncating ridiculous DTMF duration %d ms to 1/2 second.\n", - switch_channel_get_name(switch_core_session_get_channel(pvt->session)), dtmf->duration / 8); + SWITCH_LOG_WARNING, "%s Truncating DTMF duration %d ms to %d ms\n", + switch_channel_get_name(switch_core_session_get_channel(pvt->session)), dtmf->duration / 8, duration); } + + pvt->ts.duration = duration; teletone_run(&pvt->ts, buf); } @@ -2429,7 +2448,7 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_inband_dtmf_generate_session(switch_c if ((status = switch_core_media_bug_add(session, "inband_dtmf_generate", NULL, inband_dtmf_generate_callback, pvt, 0, - SMBF_NO_PAUSE | pvt->read ? SMBF_READ_REPLACE : SMBF_WRITE_REPLACE , &bug)) != SWITCH_STATUS_SUCCESS) { + SMBF_NO_PAUSE | (pvt->read ? SMBF_READ_REPLACE : SMBF_WRITE_REPLACE) , &bug)) != SWITCH_STATUS_SUCCESS) { return status; } From a65794fb5ef82e8c542694ddfaab7e4b7f363373 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 10:05:43 -0500 Subject: [PATCH 111/204] FS-3570 receive side, update libteletone to track duration so it is less likely to double detect and push api changes down to freetdm --- libs/freetdm/src/detect_dtmf.c | 26 ++- libs/freetdm/src/ftdm_io.c | 14 +- .../freetdm/src/include/private/libteletone.h | 12 +- .../src/include/private/libteletone_detect.h | 88 +++++++--- .../include/private/libteletone_generate.h | 37 +++- libs/freetdm/src/libteletone_detect.c | 161 ++++++++++++------ libs/freetdm/src/libteletone_generate.c | 63 ++++++- libs/libteletone/src/libteletone.h | 4 +- libs/libteletone/src/libteletone_detect.c | 102 ++++++----- libs/libteletone/src/libteletone_detect.h | 25 ++- libs/libteletone/src/libteletone_generate.c | 4 +- libs/libteletone/src/libteletone_generate.h | 4 +- .../mod_valet_parking/mod_valet_parking.c | 61 ++++--- src/switch_ivr_async.c | 24 +-- 14 files changed, 434 insertions(+), 191 deletions(-) diff --git a/libs/freetdm/src/detect_dtmf.c b/libs/freetdm/src/detect_dtmf.c index e7d9648192..62af298aef 100644 --- a/libs/freetdm/src/detect_dtmf.c +++ b/libs/freetdm/src/detect_dtmf.c @@ -6,7 +6,6 @@ int main(int argc, char *argv[]) int fd, b; short sln[512] = {0}; teletone_dtmf_detect_state_t dtmf_detect = {0}; - char digit_str[128] = ""; if (argc < 2) { fprintf(stderr, "Arg Error!\n"); @@ -21,10 +20,29 @@ int main(int argc, char *argv[]) } while((b = read(fd, sln, 320)) > 0) { + char digit_char; + unsigned int dur; + teletone_dtmf_detect(&dtmf_detect, sln, b / 2); - teletone_dtmf_get(&dtmf_detect, digit_str, sizeof(digit_str)); - if (*digit_str) { - printf("digit: %s\n", digit_str); + if ((hit = teletone_dtmf_get(&dtmf_detect, &digit_char, &dur))) { + char *hs = NULL; + + + switch(hit) { + case TT_HIT_BEGIN: + hs = "begin"; + break; + + case TT_HIT_MIDDLE: + hs = "middle"; + break; + + case TT_HIT_END: + hs = "end"; + break; + } + + printf("%s digit: %s\n", hs, digit_str); } } close(fd); diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 0d0fdb655f..a472ca1694 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -3859,7 +3859,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v uint8_t sln_buf[1024] = {0}; int16_t *sln; ftdm_size_t slen = 0; - char digit_str[80] = ""; if (ftdmchan->effective_codec == FTDM_CODEC_SLIN) { sln = data; @@ -3960,13 +3959,18 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v } if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT) && !ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) { - teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen); - teletone_dtmf_get(&ftdmchan->dtmf_detect, digit_str, sizeof(digit_str)); + teletone_hit_type_t hit; + char digit_char; + uint32_t dur; - if(*digit_str) { - if (ftdmchan->state == FTDM_CHANNEL_STATE_CALLWAITING && (*digit_str == 'D' || *digit_str == 'A')) { + teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen); + + if ((hit = teletone_dtmf_get(&ftdmchan->dtmf_detect, &digit_char, &dur)) == TT_HIT_BEGIN) { + if (ftdmchan->state == FTDM_CHANNEL_STATE_CALLWAITING && (digit_char == 'D' || digit_char == 'A')) { ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK]++; } else { + char digit_str[2] = { digit_char, 0}; + if (!ftdmchan->span->sig_dtmf || (ftdmchan->span->sig_dtmf(ftdmchan, (const char*)digit_str) != FTDM_BREAK)) { ftdm_channel_queue_dtmf(ftdmchan, digit_str); } diff --git a/libs/freetdm/src/include/private/libteletone.h b/libs/freetdm/src/include/private/libteletone.h index dc98c8cb6c..61078b4984 100644 --- a/libs/freetdm/src/include/private/libteletone.h +++ b/libs/freetdm/src/include/private/libteletone.h @@ -4,10 +4,10 @@ * * Version: MPL 1.1 * - * The contents of this file are subject to the Mftilla Public License Version + * 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.mftilla.org/MPL/ + * 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 @@ -33,8 +33,8 @@ * Exception: * The author hereby grants the use of this source code under the * following license if and only if the source code is distributed - * as part of the freetdm library. Any use or distribution of this - * source code outside the scope of the freetdm library will nullify the + * as part of the OpenZAP or FreeTDM library. Any use or distribution of this + * source code outside the scope of the OpenZAP or FreeTDM library will nullify the * following license and reinact the MPL 1.1 as stated above. * * Copyright (c) 2007, Anthony Minessale II @@ -136,8 +136,8 @@ typedef __int16 int16_t; #endif #endif -#include "libteletone_generate.h" -#include "libteletone_detect.h" +#include +#include #ifdef HAVE_STRING_H #include diff --git a/libs/freetdm/src/include/private/libteletone_detect.h b/libs/freetdm/src/include/private/libteletone_detect.h index 71bf067514..4da368969c 100644 --- a/libs/freetdm/src/include/private/libteletone_detect.h +++ b/libs/freetdm/src/include/private/libteletone_detect.h @@ -2,13 +2,60 @@ * libteletone * Copyright (C) 2005-2011, Anthony Minessale II * + * 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 tone_detect.c - General telephony tone detection, and specific detection of DTMF. + * + * + * The Initial Developer of the Original Code is + * Stephen Underwood + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * The the original interface designed by Steve Underwood was preserved to retain + *the optimizations when considering DTMF tones though the names were changed in the interest + * of namespace. + * + * Much less efficient expansion interface was added to allow for the detection of + * a single arbitrary tone combination which may also exceed 2 simultaneous tones. + * (controlled by compile time constant TELETONE_MAX_TONES) + * + * Copyright (C) 2006 Anthony Minessale II + * + * * libteletone_detect.c Tone Detection Code * + * + ********************************************************************************* + * + * Derived from tone_detect.h - General telephony tone detection, and specific + * detection of DTMF. + * + * Copyright (C) 2001 Steve Underwood + * + * Despite my general liking of the GPL, I place this code in the + * public domain for the benefit of all mankind - even the slimy + * ones who might try to proprietize my work and use it to my + * detriment. + * + * * Exception: * The author hereby grants the use of this source code under the * following license if and only if the source code is distributed - * as part of the freetdm library. Any use or distribution of this - * source code outside the scope of the freetdm library will nullify the + * as part of the OpenZAP or FreeTDM library. Any use or distribution of this + * source code outside the scope of the OpenZAP or FreeTDM library will nullify the * following license and reinact the MPL 1.1 as stated above. * * Copyright (c) 2007, Anthony Minessale II @@ -41,20 +88,6 @@ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ********************************************************************************* - * - * Derived from tone_detect.h - General telephony tone detection, and specific - * detection of DTMF. - * - * Copyright (C) 2001 Steve Underwood - * - * Despite my general liking of the GPL, I place this code in the - * public domain for the benefit of all mankind - even the slimy - * ones who might try to proprietize my work and use it to my - * detriment. - * - * */ #ifndef LIBTELETONE_DETECT_H @@ -63,7 +96,7 @@ #ifdef __cplusplus extern "C" { #endif -#include "libteletone.h" +#include /*! \file libteletone_detect.h \brief Tone Detection Routines @@ -101,6 +134,14 @@ extern "C" { #define BLOCK_LEN 102 #define M_TWO_PI 2.0*M_PI + typedef enum { + TT_HIT_NONE = 0, + TT_HIT_BEGIN = 1, + TT_HIT_MIDDLE = 2, + TT_HIT_END = 3 + } teletone_hit_type_t; + + /*! \brief A continer for the elements of a Goertzel Algorithm (The names are from his formula) */ typedef struct { float v2; @@ -114,16 +155,19 @@ extern "C" { int hit2; int hit3; int hit4; - int mhit; + int dur; + int zc; + teletone_goertzel_state_t row_out[GRID_FACTOR]; teletone_goertzel_state_t col_out[GRID_FACTOR]; teletone_goertzel_state_t row_out2nd[GRID_FACTOR]; teletone_goertzel_state_t col_out2nd[GRID_FACTOR]; float energy; + float lenergy; int current_sample; - char digits[TELETONE_MAX_DTMF_DIGITS + 1]; + char digit; int current_digits; int detected_digits; int lost_digits; @@ -196,7 +240,7 @@ TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf \param samples the number of samples present in sample_buffer \return true when DTMF was detected or false when it is not */ -TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state, +TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state, int16_t sample_buffer[], int samples); /*! @@ -206,9 +250,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec \param max the maximum length of buf \return the number of characters written to buf */ -TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, - char *buf, - int max); +TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur); /*! \brief Step through the Goertzel Algorithm for each sample in a buffer diff --git a/libs/freetdm/src/include/private/libteletone_generate.h b/libs/freetdm/src/include/private/libteletone_generate.h index 6d71694761..0ff39e0dfa 100644 --- a/libs/freetdm/src/include/private/libteletone_generate.h +++ b/libs/freetdm/src/include/private/libteletone_generate.h @@ -2,6 +2,41 @@ * libteletone * Copyright (C) 2005-2011, Anthony Minessale II * + * 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 libteletone + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * + * + * libteletone.h -- Tone Generator + * + * + * + * Exception: + * The author hereby grants the use of this source code under the + * following license if and only if the source code is distributed + * as part of the OpenZAP or FreeTDM library. Any use or distribution of this + * source code outside the scope of the OpenZAP or FreeTDM library will nullify the + * following license and reinact the MPL 1.1 as stated above. + * * Copyright (c) 2007, Anthony Minessale II * All rights reserved. * @@ -81,7 +116,7 @@ extern float powf (float, float); #endif #include #include -#include "libteletone.h" +#include #define TELETONE_VOL_DB_MAX 0 #define TELETONE_VOL_DB_MIN -63 diff --git a/libs/freetdm/src/libteletone_detect.c b/libs/freetdm/src/libteletone_detect.c index 0436c25953..e995f98d0f 100644 --- a/libs/freetdm/src/libteletone_detect.c +++ b/libs/freetdm/src/libteletone_detect.c @@ -2,14 +2,62 @@ * libteletone * Copyright (C) 2005-2011, Anthony Minessale II * + * 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 tone_detect.c - General telephony tone detection, and specific detection of DTMF. + * + * + * The Initial Developer of the Original Code is + * Stephen Underwood + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * The the original interface designed by Steve Underwood was preserved to retain + *the optimizations when considering DTMF tones though the names were changed in the interest + * of namespace. + * * Much less efficient expansion interface was added to allow for the detection of * a single arbitrary tone combination which may also exceed 2 simultaneous tones. * (controlled by compile time constant TELETONE_MAX_TONES) * * Copyright (C) 2006 Anthony Minessale II * + * * libteletone_detect.c Tone Detection Code * + * + ********************************************************************************* + * + * Derived from tone_detect.c - General telephony tone detection, and specific + * detection of DTMF. + * + * Copyright (C) 2001 Steve Underwood + * + * Despite my general liking of the GPL, I place this code in the + * public domain for the benefit of all mankind - even the slimy + * ones who might try to proprietize my work and use it to my + * detriment. + * + * + * Exception: + * The author hereby grants the use of this source code under the + * following license if and only if the source code is distributed + * as part of the OpenZAP or FreeTDM library. Any use or distribution of this + * source code outside the scope of the OpenZAP or FreeTDM library will nullify the + * following license and reinact the MPL 1.1 as stated above. + * * Copyright (c) 2007, Anthony Minessale II * All rights reserved. * @@ -40,21 +88,6 @@ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ********************************************************************************* - * - * Derived from tone_detect.c - General telephony tone detection, and specific - * detection of DTMF. - * - * Copyright (C) 2001 Steve Underwood - * - * Despite my general liking of the GPL, I place this code in the - * public domain for the benefit of all mankind - even the slimy - * ones who might try to proprietize my work and use it to my - * detriment. - * - * - * */ #include @@ -67,7 +100,8 @@ #include #include - +#define LOW_ENG 10000000 +#define ZC 2 static teletone_detection_descriptor_t dtmf_detect_row[GRID_FACTOR]; static teletone_detection_descriptor_t dtmf_detect_col[GRID_FACTOR]; static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR]; @@ -132,8 +166,8 @@ TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf dtmf_detect_state->current_sample = 0; dtmf_detect_state->detected_digits = 0; dtmf_detect_state->lost_digits = 0; - dtmf_detect_state->digits[0] = '\0'; - dtmf_detect_state->mhit = 0; + dtmf_detect_state->digit = 0; + dtmf_detect_state->dur = 0; } TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map) @@ -266,7 +300,7 @@ TELETONE_API(int) teletone_multi_tone_detect (teletone_multi_tone_t *mt, } -TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state, +TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state, int16_t sample_buffer[], int samples) { @@ -281,6 +315,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec int best_col; char hit; int limit; + teletone_hit_type_t r = 0; hit = 0; for (sample = 0; sample < samples; sample = limit) { @@ -317,6 +352,32 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec } + if (dtmf_detect_state->zc > 0) { + if (dtmf_detect_state->energy < LOW_ENG && dtmf_detect_state->lenergy < LOW_ENG) { + if (!--dtmf_detect_state->zc) { + /* Reinitialise the detector for the next block */ + dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0; + for (i = 0; i < GRID_FACTOR; i++) { + goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]); + goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]); + goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]); + goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]); + } + dtmf_detect_state->dur -= samples; + return TT_HIT_END; + } + } + + dtmf_detect_state->dur += samples; + dtmf_detect_state->lenergy = dtmf_detect_state->energy; + dtmf_detect_state->energy = 0.0; + dtmf_detect_state->current_sample = 0; + return TT_HIT_MIDDLE; + } else if (dtmf_detect_state->digit) { + return TT_HIT_END; + } + + dtmf_detect_state->current_sample += (limit - sample); if (dtmf_detect_state->current_sample < BLOCK_LEN) { continue; @@ -361,58 +422,54 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec back to back differing digits. More importantly, it can work with nasty phones that give a very wobbly start to a digit. */ - if (hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) { - dtmf_detect_state->mhit = hit; + if (! r && hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) { dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++; dtmf_detect_state->detected_digits++; if (dtmf_detect_state->current_digits < TELETONE_MAX_DTMF_DIGITS) { - dtmf_detect_state->digits[dtmf_detect_state->current_digits++] = hit; - dtmf_detect_state->digits[dtmf_detect_state->current_digits] = '\0'; + dtmf_detect_state->digit = hit; + } else { + dtmf_detect_state->lost_digits++; } - else - { - dtmf_detect_state->lost_digits++; - } + + if (!dtmf_detect_state->zc) { + dtmf_detect_state->zc = ZC; + dtmf_detect_state->dur = 0; + r = TT_HIT_BEGIN; + } + } } } + dtmf_detect_state->hit1 = dtmf_detect_state->hit2; dtmf_detect_state->hit2 = dtmf_detect_state->hit3; dtmf_detect_state->hit3 = hit; - /* Reinitialise the detector for the next block */ - for (i = 0; i < GRID_FACTOR; i++) { - goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]); - goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]); - goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]); - goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]); - } + dtmf_detect_state->energy = 0.0; dtmf_detect_state->current_sample = 0; + } - if ((!dtmf_detect_state->mhit) || (dtmf_detect_state->mhit != hit)) { - dtmf_detect_state->mhit = 0; - return(0); - } - return (hit); + + return r; } -TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, - char *buf, - int max) +TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur) { - teletone_assert(dtmf_detect_state->current_digits <= TELETONE_MAX_DTMF_DIGITS); + if (!dtmf_detect_state->digit) { + return 0; + } - if (max > dtmf_detect_state->current_digits) { - max = dtmf_detect_state->current_digits; + *buf = dtmf_detect_state->digit; + + *dur = dtmf_detect_state->dur; + + if (!dtmf_detect_state->zc) { + dtmf_detect_state->dur = 0; + dtmf_detect_state->digit = 0; } - if (max > 0) { - memcpy (buf, dtmf_detect_state->digits, max); - memmove (dtmf_detect_state->digits, dtmf_detect_state->digits + max, dtmf_detect_state->current_digits - max); - dtmf_detect_state->current_digits -= max; - } - buf[max] = '\0'; - return max; + + return 1; } /* For Emacs: diff --git a/libs/freetdm/src/libteletone_generate.c b/libs/freetdm/src/libteletone_generate.c index c0d6a54349..7448508944 100644 --- a/libs/freetdm/src/libteletone_generate.c +++ b/libs/freetdm/src/libteletone_generate.c @@ -1,5 +1,41 @@ /* - * libteletone_generate.c -- Tone Generator + * libteletone + * Copyright (C) 2005-2011, Anthony Minessale II + * + * 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 libteletone + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * + * + * libteletone.c -- Tone Generator + * + * + * + * Exception: + * The author hereby grants the use of this source code under the + * following license if and only if the source code is distributed + * as part of the OpenZAP or FreeTDM library. Any use or distribution of this + * source code outside the scope of the OpenZAP or FreeTDM library will nullify the + * following license and reinact the MPL 1.1 as stated above. * * Copyright (c) 2007, Anthony Minessale II * All rights reserved. @@ -34,7 +70,6 @@ */ #include -#include "private/ftdm_core.h" #define SMAX 32767 #define SMIN -32768 @@ -111,7 +146,7 @@ TELETONE_API(int) teletone_init_session(teletone_generation_session_t *ts, int b ts->decay_step = 0; ts->decay_factor = 1; if (buflen) { - if ((ts->buffer = ftdm_calloc(buflen, sizeof(teletone_audio_t))) == 0) { + if ((ts->buffer = calloc(buflen, sizeof(teletone_audio_t))) == 0) { return -1; } ts->datalen = buflen; @@ -142,7 +177,7 @@ TELETONE_API(int) teletone_init_session(teletone_generation_session_t *ts, int b TELETONE_API(int) teletone_destroy_session(teletone_generation_session_t *ts) { if (ts->buffer) { - ftdm_safe_free(ts->buffer); + free(ts->buffer); ts->buffer = NULL; ts->samples = 0; } @@ -270,6 +305,19 @@ TELETONE_API(int) teletone_mux_tones(teletone_generation_session_t *ts, teletone return ts->samples / ts->channels; } +/* don't ask */ +static char *my_strdup (const char *s) +{ + size_t len = strlen (s) + 1; + void *new = malloc (len); + + if (new == NULL) { + return NULL; + } + + return (char *) memcpy (new, s, len); +} + TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cmd) { char *data = NULL, *cur = NULL, *end = NULL; @@ -280,7 +328,7 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm } do { - if (!(data = ftdm_strdup(cmd))) { + if (!(data = my_strdup(cmd))) { return -1; } @@ -363,6 +411,9 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm *e++ = '\0'; } do { + if (!p) { + break; + } if ((next = strchr(p, ',')) != 0) { *next++ = '\0'; } @@ -427,7 +478,7 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm } } bottom: - ftdm_safe_free(data); + free(data); data = NULL; if (ts->LOOPS > 0) { ts->LOOPS--; diff --git a/libs/libteletone/src/libteletone.h b/libs/libteletone/src/libteletone.h index b54098c8ee..61078b4984 100644 --- a/libs/libteletone/src/libteletone.h +++ b/libs/libteletone/src/libteletone.h @@ -33,8 +33,8 @@ * Exception: * The author hereby grants the use of this source code under the * following license if and only if the source code is distributed - * as part of the openzap library. Any use or distribution of this - * source code outside the scope of the openzap library will nullify the + * as part of the OpenZAP or FreeTDM library. Any use or distribution of this + * source code outside the scope of the OpenZAP or FreeTDM library will nullify the * following license and reinact the MPL 1.1 as stated above. * * Copyright (c) 2007, Anthony Minessale II diff --git a/libs/libteletone/src/libteletone_detect.c b/libs/libteletone/src/libteletone_detect.c index ae959535b5..e995f98d0f 100644 --- a/libs/libteletone/src/libteletone_detect.c +++ b/libs/libteletone/src/libteletone_detect.c @@ -54,8 +54,8 @@ * Exception: * The author hereby grants the use of this source code under the * following license if and only if the source code is distributed - * as part of the openzap library. Any use or distribution of this - * source code outside the scope of the openzap library will nullify the + * as part of the OpenZAP or FreeTDM library. Any use or distribution of this + * source code outside the scope of the OpenZAP or FreeTDM library will nullify the * following license and reinact the MPL 1.1 as stated above. * * Copyright (c) 2007, Anthony Minessale II @@ -100,7 +100,8 @@ #include #include - +#define LOW_ENG 10000000 +#define ZC 2 static teletone_detection_descriptor_t dtmf_detect_row[GRID_FACTOR]; static teletone_detection_descriptor_t dtmf_detect_col[GRID_FACTOR]; static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR]; @@ -165,8 +166,8 @@ TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf dtmf_detect_state->current_sample = 0; dtmf_detect_state->detected_digits = 0; dtmf_detect_state->lost_digits = 0; - dtmf_detect_state->digits[0] = '\0'; - dtmf_detect_state->mhit = 0; + dtmf_detect_state->digit = 0; + dtmf_detect_state->dur = 0; } TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map) @@ -299,7 +300,7 @@ TELETONE_API(int) teletone_multi_tone_detect (teletone_multi_tone_t *mt, } -TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state, +TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state, int16_t sample_buffer[], int samples) { @@ -314,6 +315,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec int best_col; char hit; int limit; + teletone_hit_type_t r = 0; hit = 0; for (sample = 0; sample < samples; sample = limit) { @@ -350,6 +352,32 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec } + if (dtmf_detect_state->zc > 0) { + if (dtmf_detect_state->energy < LOW_ENG && dtmf_detect_state->lenergy < LOW_ENG) { + if (!--dtmf_detect_state->zc) { + /* Reinitialise the detector for the next block */ + dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0; + for (i = 0; i < GRID_FACTOR; i++) { + goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]); + goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]); + goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]); + goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]); + } + dtmf_detect_state->dur -= samples; + return TT_HIT_END; + } + } + + dtmf_detect_state->dur += samples; + dtmf_detect_state->lenergy = dtmf_detect_state->energy; + dtmf_detect_state->energy = 0.0; + dtmf_detect_state->current_sample = 0; + return TT_HIT_MIDDLE; + } else if (dtmf_detect_state->digit) { + return TT_HIT_END; + } + + dtmf_detect_state->current_sample += (limit - sample); if (dtmf_detect_state->current_sample < BLOCK_LEN) { continue; @@ -394,58 +422,54 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec back to back differing digits. More importantly, it can work with nasty phones that give a very wobbly start to a digit. */ - if (hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) { - dtmf_detect_state->mhit = hit; + if (! r && hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) { dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++; dtmf_detect_state->detected_digits++; if (dtmf_detect_state->current_digits < TELETONE_MAX_DTMF_DIGITS) { - dtmf_detect_state->digits[dtmf_detect_state->current_digits++] = hit; - dtmf_detect_state->digits[dtmf_detect_state->current_digits] = '\0'; + dtmf_detect_state->digit = hit; + } else { + dtmf_detect_state->lost_digits++; } - else - { - dtmf_detect_state->lost_digits++; - } + + if (!dtmf_detect_state->zc) { + dtmf_detect_state->zc = ZC; + dtmf_detect_state->dur = 0; + r = TT_HIT_BEGIN; + } + } } } + dtmf_detect_state->hit1 = dtmf_detect_state->hit2; dtmf_detect_state->hit2 = dtmf_detect_state->hit3; dtmf_detect_state->hit3 = hit; - /* Reinitialise the detector for the next block */ - for (i = 0; i < GRID_FACTOR; i++) { - goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]); - goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]); - goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]); - goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]); - } + dtmf_detect_state->energy = 0.0; dtmf_detect_state->current_sample = 0; + } - if ((!dtmf_detect_state->mhit) || (dtmf_detect_state->mhit != hit)) { - dtmf_detect_state->mhit = 0; - return(0); - } - return (hit); + + return r; } -TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, - char *buf, - int max) +TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur) { - teletone_assert(dtmf_detect_state->current_digits <= TELETONE_MAX_DTMF_DIGITS); + if (!dtmf_detect_state->digit) { + return 0; + } - if (max > dtmf_detect_state->current_digits) { - max = dtmf_detect_state->current_digits; + *buf = dtmf_detect_state->digit; + + *dur = dtmf_detect_state->dur; + + if (!dtmf_detect_state->zc) { + dtmf_detect_state->dur = 0; + dtmf_detect_state->digit = 0; } - if (max > 0) { - memcpy (buf, dtmf_detect_state->digits, max); - memmove (dtmf_detect_state->digits, dtmf_detect_state->digits + max, dtmf_detect_state->current_digits - max); - dtmf_detect_state->current_digits -= max; - } - buf[max] = '\0'; - return max; + + return 1; } /* For Emacs: diff --git a/libs/libteletone/src/libteletone_detect.h b/libs/libteletone/src/libteletone_detect.h index e2a8c20b33..4da368969c 100644 --- a/libs/libteletone/src/libteletone_detect.h +++ b/libs/libteletone/src/libteletone_detect.h @@ -54,8 +54,8 @@ * Exception: * The author hereby grants the use of this source code under the * following license if and only if the source code is distributed - * as part of the openzap library. Any use or distribution of this - * source code outside the scope of the openzap library will nullify the + * as part of the OpenZAP or FreeTDM library. Any use or distribution of this + * source code outside the scope of the OpenZAP or FreeTDM library will nullify the * following license and reinact the MPL 1.1 as stated above. * * Copyright (c) 2007, Anthony Minessale II @@ -134,6 +134,14 @@ extern "C" { #define BLOCK_LEN 102 #define M_TWO_PI 2.0*M_PI + typedef enum { + TT_HIT_NONE = 0, + TT_HIT_BEGIN = 1, + TT_HIT_MIDDLE = 2, + TT_HIT_END = 3 + } teletone_hit_type_t; + + /*! \brief A continer for the elements of a Goertzel Algorithm (The names are from his formula) */ typedef struct { float v2; @@ -147,16 +155,19 @@ extern "C" { int hit2; int hit3; int hit4; - int mhit; + int dur; + int zc; + teletone_goertzel_state_t row_out[GRID_FACTOR]; teletone_goertzel_state_t col_out[GRID_FACTOR]; teletone_goertzel_state_t row_out2nd[GRID_FACTOR]; teletone_goertzel_state_t col_out2nd[GRID_FACTOR]; float energy; + float lenergy; int current_sample; - char digits[TELETONE_MAX_DTMF_DIGITS + 1]; + char digit; int current_digits; int detected_digits; int lost_digits; @@ -229,7 +240,7 @@ TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf \param samples the number of samples present in sample_buffer \return true when DTMF was detected or false when it is not */ -TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state, +TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state, int16_t sample_buffer[], int samples); /*! @@ -239,9 +250,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec \param max the maximum length of buf \return the number of characters written to buf */ -TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, - char *buf, - int max); +TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur); /*! \brief Step through the Goertzel Algorithm for each sample in a buffer diff --git a/libs/libteletone/src/libteletone_generate.c b/libs/libteletone/src/libteletone_generate.c index a5cefac98d..7448508944 100644 --- a/libs/libteletone/src/libteletone_generate.c +++ b/libs/libteletone/src/libteletone_generate.c @@ -33,8 +33,8 @@ * Exception: * The author hereby grants the use of this source code under the * following license if and only if the source code is distributed - * as part of the openzap library. Any use or distribution of this - * source code outside the scope of the openzap library will nullify the + * as part of the OpenZAP or FreeTDM library. Any use or distribution of this + * source code outside the scope of the OpenZAP or FreeTDM library will nullify the * following license and reinact the MPL 1.1 as stated above. * * Copyright (c) 2007, Anthony Minessale II diff --git a/libs/libteletone/src/libteletone_generate.h b/libs/libteletone/src/libteletone_generate.h index 5e6444b0c4..0ff39e0dfa 100644 --- a/libs/libteletone/src/libteletone_generate.h +++ b/libs/libteletone/src/libteletone_generate.h @@ -33,8 +33,8 @@ * Exception: * The author hereby grants the use of this source code under the * following license if and only if the source code is distributed - * as part of the openzap library. Any use or distribution of this - * source code outside the scope of the openzap library will nullify the + * as part of the OpenZAP or FreeTDM library. Any use or distribution of this + * source code outside the scope of the OpenZAP or FreeTDM library will nullify the * following license and reinact the MPL 1.1 as stated above. * * Copyright (c) 2007, Anthony Minessale II diff --git a/src/mod/applications/mod_valet_parking/mod_valet_parking.c b/src/mod/applications/mod_valet_parking/mod_valet_parking.c index 0b25a47e94..3ac27b1533 100644 --- a/src/mod/applications/mod_valet_parking/mod_valet_parking.c +++ b/src/mod/applications/mod_valet_parking/mod_valet_parking.c @@ -92,40 +92,49 @@ static void check_timeouts(void) void *val; time_t now; valet_lot_t *lot; + switch_console_callback_match_t *matches = NULL; + switch_console_callback_match_node_t *m; + switch_hash_index_t *i_hi; + const void *i_var; + void *i_val; + char *i_ext; + valet_token_t *token; now = switch_epoch_time_now(NULL); switch_mutex_lock(globals.mutex); - - for (hi = switch_hash_first(NULL, globals.hash); hi; hi = switch_hash_next(hi)) { - switch_hash_index_t *i_hi; - const void *i_var; - void *i_val; - char *i_ext; - valet_token_t *token; - switch_hash_this(hi, &var, NULL, &val); - lot = (valet_lot_t *) val; - - switch_mutex_lock(lot->mutex); - - top: - - for (i_hi = switch_hash_first(NULL, lot->hash); i_hi; i_hi = switch_hash_next(i_hi)) { - switch_hash_this(i_hi, &i_var, NULL, &i_val); - i_ext = (char *) i_var; - token = (valet_token_t *) i_val; - if (token->timeout > 0 && (token->timeout < now || token->timeout == 1)) { - switch_core_hash_delete(lot->hash, i_ext); - switch_safe_free(token); - goto top; - } - } - - switch_mutex_unlock(lot->mutex); + switch_console_push_match(&matches, (const char *) var); } switch_mutex_unlock(globals.mutex); + + + if (matches) { + for (m = matches->head; m; m = m->next) { + + lot = valet_find_lot(m->val); + switch_mutex_lock(lot->mutex); + + top: + + for (i_hi = switch_hash_first(NULL, lot->hash); i_hi; i_hi = switch_hash_next(i_hi)) { + switch_hash_this(i_hi, &i_var, NULL, &i_val); + i_ext = (char *) i_var; + token = (valet_token_t *) i_val; + if (token->timeout > 0 && (token->timeout < now || token->timeout == 1)) { + switch_core_hash_delete(lot->hash, i_ext); + switch_safe_free(token); + goto top; + } + } + + switch_mutex_unlock(lot->mutex); + } + + switch_console_free_matches(&matches); + } + } static int next_id(valet_lot_t *lot, int min, int max, int in) diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 6fe6048173..99449082bb 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -2139,8 +2139,8 @@ static switch_bool_t inband_dtmf_callback(switch_media_bug_t *bug, void *user_da { switch_inband_dtmf_t *pvt = (switch_inband_dtmf_t *) user_data; switch_frame_t *frame = NULL; - char digit_str[80]; switch_channel_t *channel = switch_core_session_get_channel(pvt->session); + teletone_hit_type_t hit; switch (type) { case SWITCH_ABC_TYPE_INIT: @@ -2149,20 +2149,14 @@ static switch_bool_t inband_dtmf_callback(switch_media_bug_t *bug, void *user_da break; case SWITCH_ABC_TYPE_READ_REPLACE: if ((frame = switch_core_media_bug_get_read_replace_frame(bug))) { - teletone_dtmf_detect(&pvt->dtmf_detect, frame->data, frame->samples); - teletone_dtmf_get(&pvt->dtmf_detect, digit_str, sizeof(digit_str)); - if (digit_str[0]) { - char *p = digit_str; - while (p && *p) { - switch_dtmf_t dtmf = {0}; - dtmf.digit = *p; - dtmf.duration = switch_core_default_dtmf_duration(0); - dtmf.source = SWITCH_DTMF_INBAND_AUDIO; - switch_channel_queue_dtmf(channel, &dtmf); - p++; - } - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_DEBUG, "DTMF DETECTED: [%s]\n", - digit_str); + if ((hit = teletone_dtmf_detect(&pvt->dtmf_detect, frame->data, frame->samples)) == TT_HIT_END) { + switch_dtmf_t dtmf = {0}; + + teletone_dtmf_get(&pvt->dtmf_detect, &dtmf.digit, &dtmf.duration); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_DEBUG, "DTMF DETECTED: [%c][%d]\n", + dtmf.digit, dtmf.duration); + dtmf.source = SWITCH_DTMF_INBAND_AUDIO; + switch_channel_queue_dtmf(channel, &dtmf); } switch_core_media_bug_set_read_replace_frame(bug, frame); } From c4464c65fd24c6936d31fb32c9eb21ceda4e892e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 12:05:04 -0500 Subject: [PATCH 112/204] FS-3551 please update to this revision or greater and retest gathering the same logs with loglevel debug and global siptrace on --- src/mod/applications/mod_voicemail/mod_voicemail.c | 3 +++ src/mod/endpoints/mod_sofia/mod_sofia.c | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mod/applications/mod_voicemail/mod_voicemail.c b/src/mod/applications/mod_voicemail/mod_voicemail.c index 0b88532874..3b12e7c7a1 100644 --- a/src/mod/applications/mod_voicemail/mod_voicemail.c +++ b/src/mod/applications/mod_voicemail/mod_voicemail.c @@ -1538,6 +1538,9 @@ static switch_status_t listen_file(switch_core_session_t *session, vm_profile_t msg.from = __FILE__; msg.string_arg = cid_buf; msg.message_id = SWITCH_MESSAGE_INDICATE_DISPLAY; + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Sending display update [%s] to %s\n", + cid_buf, switch_channel_get_name(channel)); switch_core_session_receive_message(session, &msg); if (!zstr(cbt->cid_number) && (vm_announce_cid = switch_channel_get_variable(channel, "vm_announce_cid"))) { diff --git a/src/mod/endpoints/mod_sofia/mod_sofia.c b/src/mod/endpoints/mod_sofia/mod_sofia.c index 8ef3b92663..810d67e5ba 100644 --- a/src/mod/endpoints/mod_sofia/mod_sofia.c +++ b/src/mod/endpoints/mod_sofia/mod_sofia.c @@ -1981,12 +1981,15 @@ static switch_status_t sofia_receive_message(switch_core_session_t *session, swi char message[256] = ""; const char *ua = switch_channel_get_variable(tech_pvt->channel, "sip_user_agent"); switch_event_t *event; - + if (zstr(number)) { number = tech_pvt->caller_profile->destination_number; } - if (!sofia_test_flag(tech_pvt, TFLAG_UPDATING_DISPLAY)) { + if (sofia_test_flag(tech_pvt, TFLAG_UPDATING_DISPLAY)) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_ERROR, + "Cannot send display update to %s Did not receive reply to last update\n", switch_channel_get_name(tech_pvt->channel)); + } else { if (zstr(tech_pvt->last_sent_callee_id_name) || strcmp(tech_pvt->last_sent_callee_id_name, name) || zstr(tech_pvt->last_sent_callee_id_number) || strcmp(tech_pvt->last_sent_callee_id_number, number)) { From 77c01bc4b7e8b455cc4c73ec6263b395a1823cbb Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Fri, 16 Sep 2011 12:34:24 -0500 Subject: [PATCH 113/204] fix warnings --- src/switch_channel.c | 2 +- src/switch_ivr_async.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/switch_channel.c b/src/switch_channel.c index a8669f1602..30a2e85da2 100644 --- a/src/switch_channel.c +++ b/src/switch_channel.c @@ -446,7 +446,7 @@ SWITCH_DECLARE(switch_status_t) switch_channel_queue_dtmf_string(switch_channel_ dur = switch_core_default_dtmf_duration(0) / 8; if ((p = strchr(argv[i], '@'))) { *p++ = '\0'; - if ((dur = atoi(p)) > switch_core_min_dtmf_duration(0) / 8) { + if ((dur = atoi(p)) > (int)switch_core_min_dtmf_duration(0) / 8) { dtmf.duration = dur * 8; } } diff --git a/src/switch_ivr_async.c b/src/switch_ivr_async.c index 99449082bb..c36d5e648c 100644 --- a/src/switch_ivr_async.c +++ b/src/switch_ivr_async.c @@ -2364,7 +2364,7 @@ static switch_bool_t inband_dtmf_generate_callback(switch_media_bug_t *bug, void int duration = dtmf->duration; buf[0] = dtmf->digit; - if (duration > switch_core_max_dtmf_duration(0)) { + if (duration > (int)switch_core_max_dtmf_duration(0)) { duration = switch_core_default_dtmf_duration(0); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(switch_core_media_bug_get_session(bug)), SWITCH_LOG_WARNING, "%s Truncating DTMF duration %d ms to %d ms\n", From 3a477c42a0f8bec473fd26dc70ccb0751c95ed9c Mon Sep 17 00:00:00 2001 From: Mathieu Rene Date: Fri, 16 Sep 2011 13:56:28 -0400 Subject: [PATCH 114/204] Add mod_blacklist from contrib. Can be used to maintain lists of numbers and query/modify them with api commands. Example: blacklist add blacklist del blacklist check (outputs true or false) --- build/modules.conf.in | 1 + .../mod_blacklist/mod_blacklist.c | 279 ++++++++++++++++++ 2 files changed, 280 insertions(+) create mode 100644 src/mod/applications/mod_blacklist/mod_blacklist.c diff --git a/build/modules.conf.in b/build/modules.conf.in index 9f5cfa5eb7..08edfaaab8 100644 --- a/build/modules.conf.in +++ b/build/modules.conf.in @@ -2,6 +2,7 @@ loggers/mod_console loggers/mod_logfile loggers/mod_syslog #applications/mod_cidlookup +#applications/mod_blacklist applications/mod_commands applications/mod_conference applications/mod_dptools diff --git a/src/mod/applications/mod_blacklist/mod_blacklist.c b/src/mod/applications/mod_blacklist/mod_blacklist.c new file mode 100644 index 0000000000..a8fe5e6da5 --- /dev/null +++ b/src/mod/applications/mod_blacklist/mod_blacklist.c @@ -0,0 +1,279 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2011, Anthony Minessale II + * + * 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 FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Mathieu Rene + * + * mod_blacklist.c -- Blacklist module + * + */ +#include + +/* Prototypes */ +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_blacklist_shutdown); +SWITCH_MODULE_RUNTIME_FUNCTION(mod_blacklist_runtime); +SWITCH_MODULE_LOAD_FUNCTION(mod_blacklist_load); + + +SWITCH_MODULE_DEFINITION(mod_blacklist, mod_blacklist_load, mod_blacklist_shutdown, NULL); + +typedef struct { + switch_hash_t *list; + switch_mutex_t *list_mutex; + switch_memory_pool_t *pool; +} blacklist_t; + +static struct { + switch_hash_t *lists; + switch_mutex_t *lists_mutex; + switch_memory_pool_t *pool; +} globals; + +blacklist_t *blacklist_create(const char *name) +{ + switch_memory_pool_t *pool = NULL; + blacklist_t *bl = NULL; + + switch_core_new_memory_pool(&pool); + bl = switch_core_alloc(pool, sizeof(*bl)); + switch_assert(bl); + bl->pool = pool; + + switch_core_hash_init(&bl->list, pool); + switch_mutex_init(&bl->list_mutex, SWITCH_MUTEX_NESTED, pool); + + return bl; +} + +void blacklist_free(blacklist_t *bl) +{ + switch_core_destroy_memory_pool(&bl->pool); +} + + +void trim(char *string) +{ + char *p; + if ((p = strchr(string, '\n'))) { + *p = '\0'; + } + if ((p = strchr(string, '\r'))) { + *p = '\0'; + } +} + +static switch_status_t load_list(const char *name, const char *filename) +{ + FILE *f; + blacklist_t *bl = blacklist_create(name); + /* Create a hashtable + mutex for that list */ + + if ((f = fopen(filename, "r"))) { + char buf[1024] = {0}; + while (fgets(buf, 1024, f)) { + trim(buf); + switch_core_hash_insert(bl->list, buf, (void*)SWITCH_TRUE); + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't open [%s] to load list [%s]\n", filename, name); + return SWITCH_STATUS_FALSE; + } + + switch_core_hash_insert(globals.lists, name, bl); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Loaded list [%s]\n", name); + + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t do_config(switch_bool_t reload) +{ + /* Load up blacklists */ + switch_xml_t xml, cfg, lists, list; + switch_hash_index_t *hi; + + if (!(xml = switch_xml_open_cfg("mod_blacklist.conf", &cfg, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't load configuration section\n"); + return SWITCH_STATUS_FALSE; + } + + switch_mutex_lock(globals.lists_mutex); + + /* Destroy any active lists */ + while ((hi = switch_hash_first(NULL, globals.lists))) { + const void *key; + void *val; + switch_hash_this(hi, &key, NULL, &val); + blacklist_free((blacklist_t*)val); + switch_core_hash_delete(globals.lists, (const char*)key); + } + + if ((lists = switch_xml_child(cfg, "lists"))) { + for (list = switch_xml_child(lists, "list"); list; list = list->next) { + const char *name = switch_xml_attr_soft(list, "name"); + const char *filename = switch_xml_attr_soft(list, "filename"); + + if (name && filename) { + load_list(name, filename); + } + } + } + + switch_mutex_unlock(globals.lists_mutex); + + if (xml) { + switch_xml_free(xml); + xml = NULL; + } + + return SWITCH_STATUS_SUCCESS; +} + +SWITCH_STANDARD_API(blacklist_api_function) +{ + char *data; + int argc; + char *argv[3]; + + data = strdup(cmd); + trim(data); + if (!(argc = switch_separate_string(data, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid usage\n"); + goto done; + } + + if (!strcasecmp(argv[0], "check")) { + blacklist_t *bl = NULL; + switch_bool_t result; + + if (argc < 2 || zstr(argv[1]) || zstr(argv[2])) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Wrong syntax"); + goto done; + } + + switch_mutex_lock(globals.lists_mutex); + bl = switch_core_hash_find(globals.lists, argv[1]); + switch_mutex_unlock(globals.lists_mutex); + + if (!bl) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown blacklist [%s]\n", argv[1]); + stream->write_function(stream, "false"); + goto done; + } + + switch_mutex_lock(bl->list_mutex); + result = (switch_bool_t)(intptr_t)switch_core_hash_find(bl->list, argv[2]); + stream->write_function(stream, "%s", result ? "true" : "false"); + switch_mutex_unlock(bl->list_mutex); + } else if (!strcasecmp(argv[0], "add")) { + blacklist_t *bl = NULL; + if (argc < 2 || zstr(argv[1]) || zstr(argv[2])) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Wrong syntax"); + goto done; + } + + switch_mutex_lock(globals.lists_mutex); + bl = switch_core_hash_find(globals.lists, argv[1]); + switch_mutex_unlock(globals.lists_mutex); + + if (!bl) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown blacklist [%s]\n", argv[1]); + stream->write_function(stream, "-ERR Unknown blacklist\n"); + goto done; + } + + switch_mutex_lock(bl->list_mutex); + switch_core_hash_insert(bl->list, argv[2], (void*)SWITCH_TRUE); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Added [%s] to list [%s]\n", argv[2], argv[1]); + switch_mutex_unlock(bl->list_mutex); + stream->write_function(stream, "+OK\n"); + } else if (!strcasecmp(argv[0], "del")) { + blacklist_t *bl = NULL; + if (argc < 2 || zstr(argv[1]) || zstr(argv[2])) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Wrong syntax"); + goto done; + } + + switch_mutex_lock(globals.lists_mutex); + bl = switch_core_hash_find(globals.lists, argv[1]); + switch_mutex_unlock(globals.lists_mutex); + + if (!bl) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown blacklist [%s]\n", argv[1]); + stream->write_function(stream, "-ERR Unknown blacklist\n"); + goto done; + } + + switch_mutex_lock(bl->list_mutex); + switch_core_hash_insert(bl->list, argv[2], NULL); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Removed [%s] from list [%s]\n", argv[2], argv[1]); + switch_mutex_unlock(bl->list_mutex); + stream->write_function(stream, "+OK\n"); + } else if (!strcasecmp(argv[0], "reload")) { + do_config(SWITCH_TRUE); + stream->write_function(stream, "+OK\n"); + } + +done: + switch_safe_free(data); + return SWITCH_STATUS_SUCCESS; +} + + +SWITCH_MODULE_LOAD_FUNCTION(mod_blacklist_load) +{ + switch_api_interface_t *api_interface; + //switch_application_interface_t *app_interface; + /* connect my internal structure to the blank pointer passed to me */ + *module_interface = switch_loadable_module_create_module_interface(pool, modname); + + memset(&globals, 0, sizeof(globals)); + globals.pool = pool; + + switch_core_hash_init(&globals.lists, globals.pool); + switch_mutex_init(&globals.lists_mutex, SWITCH_MUTEX_NESTED, globals.pool); + + do_config(SWITCH_FALSE); + + SWITCH_ADD_API(api_interface, "blacklist", "Control blacklists", blacklist_api_function, ""); + + return SWITCH_STATUS_SUCCESS; +} + +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_blacklist_shutdown) +{ + 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 + */ From 142fa9922cdc0328aa1d4f6d2bda636fe01d79de Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 11:18:50 -0500 Subject: [PATCH 115/204] Do not include descriptions on socket shutdowns for failures since they probably will never get it anyway and its in a protected section of code --- src/mod/event_handlers/mod_event_socket/mod_event_socket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c index aaf270cb26..f6ea4735ce 100644 --- a/src/mod/event_handlers/mod_event_socket/mod_event_socket.c +++ b/src/mod/event_handlers/mod_event_socket/mod_event_socket.c @@ -184,7 +184,7 @@ static switch_status_t socket_logger(const switch_log_node_t *node, switch_log_l } else { switch_log_node_free(&dnode); if (++l->lost_logs > MAX_MISSED) { - kill_listener(l, "Disconnected due to log queue failure.\n"); + kill_listener(l, NULL); } } } @@ -384,7 +384,7 @@ static void event_handler(switch_event_t *event) } } else { if (++l->lost_events > MAX_MISSED) { - kill_listener(l, "Disconnected due to event queue failure.\n"); + kill_listener(l, NULL); } switch_event_destroy(&clone); } From 752ec93d370fd10f3aaf8fec468ae6a450648774 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 11:46:40 -0500 Subject: [PATCH 116/204] revert --- .../mod_valet_parking/mod_valet_parking.c | 51 ++++++++----------- 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/src/mod/applications/mod_valet_parking/mod_valet_parking.c b/src/mod/applications/mod_valet_parking/mod_valet_parking.c index 3ac27b1533..0b25a47e94 100644 --- a/src/mod/applications/mod_valet_parking/mod_valet_parking.c +++ b/src/mod/applications/mod_valet_parking/mod_valet_parking.c @@ -92,49 +92,40 @@ static void check_timeouts(void) void *val; time_t now; valet_lot_t *lot; - switch_console_callback_match_t *matches = NULL; - switch_console_callback_match_node_t *m; - switch_hash_index_t *i_hi; - const void *i_var; - void *i_val; - char *i_ext; - valet_token_t *token; now = switch_epoch_time_now(NULL); switch_mutex_lock(globals.mutex); + + for (hi = switch_hash_first(NULL, globals.hash); hi; hi = switch_hash_next(hi)) { + switch_hash_index_t *i_hi; + const void *i_var; + void *i_val; + char *i_ext; + valet_token_t *token; + switch_hash_this(hi, &var, NULL, &val); - switch_console_push_match(&matches, (const char *) var); - } - switch_mutex_unlock(globals.mutex); + lot = (valet_lot_t *) val; + switch_mutex_lock(lot->mutex); - if (matches) { - for (m = matches->head; m; m = m->next) { - - lot = valet_find_lot(m->val); - switch_mutex_lock(lot->mutex); - - top: + top: - for (i_hi = switch_hash_first(NULL, lot->hash); i_hi; i_hi = switch_hash_next(i_hi)) { - switch_hash_this(i_hi, &i_var, NULL, &i_val); - i_ext = (char *) i_var; - token = (valet_token_t *) i_val; - if (token->timeout > 0 && (token->timeout < now || token->timeout == 1)) { - switch_core_hash_delete(lot->hash, i_ext); - switch_safe_free(token); - goto top; - } + for (i_hi = switch_hash_first(NULL, lot->hash); i_hi; i_hi = switch_hash_next(i_hi)) { + switch_hash_this(i_hi, &i_var, NULL, &i_val); + i_ext = (char *) i_var; + token = (valet_token_t *) i_val; + if (token->timeout > 0 && (token->timeout < now || token->timeout == 1)) { + switch_core_hash_delete(lot->hash, i_ext); + switch_safe_free(token); + goto top; } - - switch_mutex_unlock(lot->mutex); } - switch_console_free_matches(&matches); + switch_mutex_unlock(lot->mutex); } - + switch_mutex_unlock(globals.mutex); } static int next_id(valet_lot_t *lot, int min, int max, int in) From 3514c780d3d03d5b7c43ae5ea7e4cbeae749e605 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 11:51:44 -0500 Subject: [PATCH 117/204] refactor timeout tracker for valet --- .../mod_valet_parking/mod_valet_parking.c | 72 ++++++++++++------- 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/src/mod/applications/mod_valet_parking/mod_valet_parking.c b/src/mod/applications/mod_valet_parking/mod_valet_parking.c index 0b25a47e94..bd40512a7e 100644 --- a/src/mod/applications/mod_valet_parking/mod_valet_parking.c +++ b/src/mod/applications/mod_valet_parking/mod_valet_parking.c @@ -47,6 +47,7 @@ typedef struct { switch_hash_t *hash; switch_mutex_t *mutex; switch_memory_pool_t *pool; + time_t last_timeout_check; } valet_lot_t; static valet_lot_t globals = { 0 }; @@ -92,40 +93,55 @@ static void check_timeouts(void) void *val; time_t now; valet_lot_t *lot; + switch_console_callback_match_t *matches = NULL; + switch_console_callback_match_node_t *m; + switch_hash_index_t *i_hi; + const void *i_var; + void *i_val; + char *i_ext; + valet_token_t *token; now = switch_epoch_time_now(NULL); switch_mutex_lock(globals.mutex); + if (now - globals.last_timeout_check > 30) { + switch_mutex_unlock(globals.mutex); + return; + } - + globals.last_timeout_check = now; for (hi = switch_hash_first(NULL, globals.hash); hi; hi = switch_hash_next(hi)) { - switch_hash_index_t *i_hi; - const void *i_var; - void *i_val; - char *i_ext; - valet_token_t *token; - switch_hash_this(hi, &var, NULL, &val); - lot = (valet_lot_t *) val; - - switch_mutex_lock(lot->mutex); - - top: - - for (i_hi = switch_hash_first(NULL, lot->hash); i_hi; i_hi = switch_hash_next(i_hi)) { - switch_hash_this(i_hi, &i_var, NULL, &i_val); - i_ext = (char *) i_var; - token = (valet_token_t *) i_val; - if (token->timeout > 0 && (token->timeout < now || token->timeout == 1)) { - switch_core_hash_delete(lot->hash, i_ext); - switch_safe_free(token); - goto top; - } - } - - switch_mutex_unlock(lot->mutex); + switch_console_push_match(&matches, (const char *) var); } switch_mutex_unlock(globals.mutex); + + + if (matches) { + for (m = matches->head; m; m = m->next) { + + lot = valet_find_lot(m->val); + switch_mutex_lock(lot->mutex); + + top: + + for (i_hi = switch_hash_first(NULL, lot->hash); i_hi; i_hi = switch_hash_next(i_hi)) { + switch_hash_this(i_hi, &i_var, NULL, &i_val); + i_ext = (char *) i_var; + token = (valet_token_t *) i_val; + if (token->timeout > 0 && (token->timeout < now || token->timeout == 1)) { + switch_core_hash_delete(lot->hash, i_ext); + switch_safe_free(token); + goto top; + } + } + + switch_mutex_unlock(lot->mutex); + } + + switch_console_free_matches(&matches); + } + } static int next_id(valet_lot_t *lot, int min, int max, int in) @@ -170,8 +186,6 @@ SWITCH_STANDARD_APP(valet_parking_function) play_announce = switch_true(var); } - check_timeouts(); - if (!zstr(data) && (lbuf = switch_core_session_strdup(session, data)) && (argc = switch_separate_string(lbuf, ' ', argv, (sizeof(argv) / sizeof(argv[0])))) >= 2) { char *lot_name = argv[0]; @@ -391,6 +405,8 @@ SWITCH_STANDARD_APP(valet_parking_function) end: + check_timeouts(); + if (token) { token->timeout = 1; } @@ -452,6 +468,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_valet_parking_load) return SWITCH_STATUS_TERM; } + memset(&globals, 0, sizeof(globals)); + globals.pool = pool; switch_core_hash_init(&globals.hash, NULL); switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, globals.pool); From 44822df63d6fbd1c80b46b90aa8208efc393734b Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 12:13:25 -0500 Subject: [PATCH 118/204] we need to fix this build system it masks errors --- libs/freetdm/src/detect_dtmf.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/src/detect_dtmf.c b/libs/freetdm/src/detect_dtmf.c index 62af298aef..34335256f0 100644 --- a/libs/freetdm/src/detect_dtmf.c +++ b/libs/freetdm/src/detect_dtmf.c @@ -6,6 +6,7 @@ int main(int argc, char *argv[]) int fd, b; short sln[512] = {0}; teletone_dtmf_detect_state_t dtmf_detect = {0}; + teletone_hit_type_t hit; if (argc < 2) { fprintf(stderr, "Arg Error!\n"); @@ -25,7 +26,7 @@ int main(int argc, char *argv[]) teletone_dtmf_detect(&dtmf_detect, sln, b / 2); if ((hit = teletone_dtmf_get(&dtmf_detect, &digit_char, &dur))) { - char *hs = NULL; + const char *hs = NULL; switch(hit) { @@ -40,9 +41,11 @@ int main(int argc, char *argv[]) case TT_HIT_END: hs = "end"; break; + default: + break; } - printf("%s digit: %s\n", hs, digit_str); + printf("%s digit: %c\n", hs, digit_char); } } close(fd); From 81575eadb5616d1a423b938cb12f94b0bd83aecd Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 12:31:49 -0500 Subject: [PATCH 119/204] hack so openzap only finds its own teletone includes --- libs/openzap/src/detect_dtmf.c | 2 +- libs/openzap/src/include/libteletone.h | 4 ++-- libs/openzap/src/libteletone_detect.c | 2 +- libs/openzap/src/libteletone_generate.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libs/openzap/src/detect_dtmf.c b/libs/openzap/src/detect_dtmf.c index f73586adcb..ad582874a3 100644 --- a/libs/openzap/src/detect_dtmf.c +++ b/libs/openzap/src/detect_dtmf.c @@ -1,5 +1,5 @@ //#include "openzap.h" -#include "libteletone_detect.h" +#include "../openzap/src/include/libteletone_detect.h" int main(int argc, char *argv[]) { diff --git a/libs/openzap/src/include/libteletone.h b/libs/openzap/src/include/libteletone.h index b54098c8ee..12b75d8109 100644 --- a/libs/openzap/src/include/libteletone.h +++ b/libs/openzap/src/include/libteletone.h @@ -136,8 +136,8 @@ typedef __int16 int16_t; #endif #endif -#include -#include +#include "libteletone_generate.h" +#include "libteletone_detect.h" #ifdef HAVE_STRING_H #include diff --git a/libs/openzap/src/libteletone_detect.c b/libs/openzap/src/libteletone_detect.c index 0436c25953..b0b93ad115 100644 --- a/libs/openzap/src/libteletone_detect.c +++ b/libs/openzap/src/libteletone_detect.c @@ -57,7 +57,7 @@ * */ -#include +#include "../openzap/src/include/libteletone_detect.h" #ifndef _MSC_VER #include diff --git a/libs/openzap/src/libteletone_generate.c b/libs/openzap/src/libteletone_generate.c index 1d5d696af2..6cbde910fe 100644 --- a/libs/openzap/src/libteletone_generate.c +++ b/libs/openzap/src/libteletone_generate.c @@ -33,7 +33,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include "../openzap/src/include/libteletone.h" #define SMAX 32767 #define SMIN -32768 From 7bc6e8f183e7b78a01c8fb3e60a68c25079b6baa Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 13:27:38 -0500 Subject: [PATCH 120/204] better version of last patch --- libs/openzap/configure.ac | 3 +++ libs/openzap/src/detect_dtmf.c | 2 +- libs/openzap/src/include/libteletone.h | 4 ++-- libs/openzap/src/libteletone_detect.c | 2 +- libs/openzap/src/libteletone_generate.c | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/libs/openzap/configure.ac b/libs/openzap/configure.ac index c2b9e0bd67..d2c23c1091 100644 --- a/libs/openzap/configure.ac +++ b/libs/openzap/configure.ac @@ -107,7 +107,10 @@ case "$host" in ;; esac +DEFAULT_INCLUDES="-I. -I./src/include -I$(srcdir)" + AC_SUBST(SOLINK) +AC_SUBST(DEFAULT_INCLUDES) AC_SUBST(DYNAMIC_LIB_EXTEN) AC_CHECK_LIB([dl], [dlopen]) diff --git a/libs/openzap/src/detect_dtmf.c b/libs/openzap/src/detect_dtmf.c index ad582874a3..f73586adcb 100644 --- a/libs/openzap/src/detect_dtmf.c +++ b/libs/openzap/src/detect_dtmf.c @@ -1,5 +1,5 @@ //#include "openzap.h" -#include "../openzap/src/include/libteletone_detect.h" +#include "libteletone_detect.h" int main(int argc, char *argv[]) { diff --git a/libs/openzap/src/include/libteletone.h b/libs/openzap/src/include/libteletone.h index 12b75d8109..b54098c8ee 100644 --- a/libs/openzap/src/include/libteletone.h +++ b/libs/openzap/src/include/libteletone.h @@ -136,8 +136,8 @@ typedef __int16 int16_t; #endif #endif -#include "libteletone_generate.h" -#include "libteletone_detect.h" +#include +#include #ifdef HAVE_STRING_H #include diff --git a/libs/openzap/src/libteletone_detect.c b/libs/openzap/src/libteletone_detect.c index b0b93ad115..0436c25953 100644 --- a/libs/openzap/src/libteletone_detect.c +++ b/libs/openzap/src/libteletone_detect.c @@ -57,7 +57,7 @@ * */ -#include "../openzap/src/include/libteletone_detect.h" +#include #ifndef _MSC_VER #include diff --git a/libs/openzap/src/libteletone_generate.c b/libs/openzap/src/libteletone_generate.c index 6cbde910fe..1d5d696af2 100644 --- a/libs/openzap/src/libteletone_generate.c +++ b/libs/openzap/src/libteletone_generate.c @@ -33,7 +33,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "../openzap/src/include/libteletone.h" +#include #define SMAX 32767 #define SMIN -32768 From dfbb22fe919cbcdd712c19ca739a90d993a192b3 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 14:16:31 -0500 Subject: [PATCH 121/204] alternate fix to f479462026d6d245511ef635ded70c7c645ac5ee --- src/mod/applications/mod_fifo/mod_fifo.c | 3 +++ src/mod/endpoints/mod_sofia/sofia_glue.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mod/applications/mod_fifo/mod_fifo.c b/src/mod/applications/mod_fifo/mod_fifo.c index 9e263056c9..827905590f 100644 --- a/src/mod/applications/mod_fifo/mod_fifo.c +++ b/src/mod/applications/mod_fifo/mod_fifo.c @@ -2968,6 +2968,9 @@ SWITCH_STANDARD_APP(fifo_function) switch_safe_free(sql); + switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(other_session)); + switch_channel_set_variable(other_channel, SWITCH_SIGNAL_BOND_VARIABLE, switch_core_session_get_uuid(session)); + switch_ivr_multi_threaded_bridge(session, other_session, on_dtmf, other_session, session); if (outbound_id) { diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index b098358845..0e4b5ab870 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -5566,7 +5566,7 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName } - if (switch_channel_get_variable(channel, SWITCH_BRIDGE_VARIABLE)) { + if (switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) { sofia_set_flag(tech_pvt, TFLAG_RECOVERING_BRIDGE); } else { switch_xml_t callflow, param, x_extension; From 4d1a76ee5c687fb0fdd1ea9131644fb90c0370c4 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 14:30:32 -0500 Subject: [PATCH 122/204] save telephony event data for recovery --- src/mod/endpoints/mod_sofia/sofia_glue.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 0e4b5ab870..8b0af39523 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -3371,11 +3371,13 @@ switch_status_t sofia_glue_activate_rtp(private_object_t *tech_pvt, switch_rtp_f if (tech_pvt->te) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set 2833 dtmf send payload to %u\n", tech_pvt->te); switch_rtp_set_telephony_event(tech_pvt->rtp_session, tech_pvt->te); + switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_send_payload", "%d", tech_pvt->te); } if (tech_pvt->recv_te) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Set 2833 dtmf receive payload to %u\n", tech_pvt->recv_te); switch_rtp_set_telephony_recv_event(tech_pvt->rtp_session, tech_pvt->recv_te); + switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_recv_payload", "%d", tech_pvt->recv_te); } if (tech_pvt->audio_recv_pt != tech_pvt->agreed_pt) { @@ -4853,13 +4855,16 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set 2833 dtmf send payload to %u\n", best_te); if (tech_pvt->rtp_session) { switch_rtp_set_telephony_event(tech_pvt->rtp_session, (switch_payload_t) best_te); + switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_send_payload", "%d", best_te); } } else { te = tech_pvt->recv_te = tech_pvt->te = (switch_payload_t) best_te; switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Set 2833 dtmf send/recv payload to %u\n", te); if (tech_pvt->rtp_session) { switch_rtp_set_telephony_event(tech_pvt->rtp_session, te); + switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_send_payload", "%d", te); switch_rtp_set_telephony_recv_event(tech_pvt->rtp_session, te); + switch_channel_set_variable_printf(tech_pvt->channel, "sip_2833_recv_payload", "%d", te); } } } else { @@ -5402,9 +5407,19 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName tech_pvt->remote_port = atoi(switch_str_nil(switch_channel_get_variable(channel, "sip_network_port"))); tech_pvt->caller_profile = switch_channel_get_caller_profile(channel); + if ((tmp = switch_channel_get_variable(tech_pvt->channel, "sip_2833_send_payload"))) { + int te = atoi(tmp); + if (te > 64) { + tech_pvt->te = te; + } + } - - + if ((tmp = switch_channel_get_variable(tech_pvt->channel, "sip_2833_recv_payload"))) { + int te = atoi(tmp); + if (te > 64) { + tech_pvt->recv_te = te; + } + } if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { tech_pvt->dest = switch_core_session_sprintf(session, "sip:%s", switch_channel_get_variable(channel, "sip_req_uri")); From dbd5d2575efdb72ae5ecef0fba68a549f9a5d850 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 14:50:46 -0500 Subject: [PATCH 123/204] fix build on freetdm --- libs/freetdm/configure.ac | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac index 70033a7a0a..a69618ba6f 100644 --- a/libs/freetdm/configure.ac +++ b/libs/freetdm/configure.ac @@ -54,6 +54,9 @@ fi AC_SUBST([confdir]) +DEFAULT_INCLUDES="-I. -I./src/include -I$(srcdir)" +AC_SUBST([DEFAULT_INCLUDES]) + # Where to install the modules AC_ARG_WITH([modinstdir], [AS_HELP_STRING([--with-modinstdir=DIR], [Install modules into this location (default: ${prefix}/mod)])], From 8a3c2925349deefef95785a38a1444d62d7f47cf Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 14:52:14 -0500 Subject: [PATCH 124/204] fix seg in recent change --- libs/freetdm/mod_freetdm/mod_freetdm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 1e07db5e31..9ae717d8cb 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -545,7 +545,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) tokencnt = ftdm_channel_get_token_count(tech_pvt->ftdmchan); for (t = 0; t < tokencnt; t++) { token = ftdm_channel_get_token(tech_pvt->ftdmchan, tokencnt); - if (!strcasecmp(uuid, token)) { + if (!zstr(token) && !strcasecmp(uuid, token)) { uuid_found = 1; break; } From 4048a087b7f83313aa9f7d4ea1e4181b00d2caa1 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 15:35:16 -0500 Subject: [PATCH 125/204] more 2833 recover code --- src/mod/endpoints/mod_sofia/sofia_glue.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 8b0af39523..6fcbbe3bc2 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -5579,6 +5579,14 @@ static int recover_callback(void *pArg, int argc, char **argv, char **columnName } } + if (tech_pvt->te) { + switch_rtp_set_telephony_event(tech_pvt->rtp_session, tech_pvt->te); + } + + if (tech_pvt->recv_te) { + switch_rtp_set_telephony_recv_event(tech_pvt->rtp_session, tech_pvt->recv_te); + } + } if (switch_channel_get_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE)) { From 42ff14d22ab51cea28d21b396b62f2104df8d361 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 15:53:49 -0500 Subject: [PATCH 126/204] use index in this loop instead of the max val for the iteration --- libs/freetdm/mod_freetdm/mod_freetdm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 9ae717d8cb..c61738d9df 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -544,7 +544,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) uuid = switch_core_session_get_uuid(session); tokencnt = ftdm_channel_get_token_count(tech_pvt->ftdmchan); for (t = 0; t < tokencnt; t++) { - token = ftdm_channel_get_token(tech_pvt->ftdmchan, tokencnt); + token = ftdm_channel_get_token(tech_pvt->ftdmchan, t); if (!zstr(token) && !strcasecmp(uuid, token)) { uuid_found = 1; break; From 91b73d1ff8d39f6156837cdecf205584e111cb6b Mon Sep 17 00:00:00 2001 From: Raymond Chandler Date: Fri, 16 Sep 2011 19:08:30 -0400 Subject: [PATCH 127/204] add params so xml curl can know who's calling the directory request --- src/mod/endpoints/mod_rtmp/rtmp.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/mod/endpoints/mod_rtmp/rtmp.c b/src/mod/endpoints/mod_rtmp/rtmp.c index 1db027405c..10a48b3748 100644 --- a/src/mod/endpoints/mod_rtmp/rtmp.c +++ b/src/mod/endpoints/mod_rtmp/rtmp.c @@ -188,9 +188,14 @@ switch_status_t rtmp_check_auth(rtmp_session_t *rsession, const char *user, cons switch_xml_t xml = NULL, x_param, x_params; switch_bool_t allow_empty_password = SWITCH_FALSE; const char *passwd = NULL; + switch_event_t *locate_params; + + switch_event_create(&locate_params, SWITCH_EVENT_GENERAL); + switch_assert(locate_params); + switch_event_add_header_string(locate_params, SWITCH_STACK_BOTTOM, "source", "mod_rtmp"); /* Locate user */ - if (switch_xml_locate_user_merged("id", user, domain, NULL, &xml, NULL) != SWITCH_STATUS_SUCCESS) { + if (switch_xml_locate_user_merged("id", user, domain, NULL, &xml, locate_params) != 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; } @@ -231,6 +236,9 @@ done: if (xml) { switch_xml_free(xml); } + + switch_event_destroy(&locate_params); + return status; } From 995d7dcb021dace553b335dc49d229621f107086 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 16:44:08 -0500 Subject: [PATCH 128/204] dont clear token on SIGEVENT_STOP for ISDN legs, save it for the hangup handler --- libs/freetdm/mod_freetdm/mod_freetdm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index c61738d9df..44accde0dd 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -2440,7 +2440,6 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal) switch_set_flag_locked(tech_pvt, TFLAG_DEAD); channel = switch_core_session_get_channel(session); switch_channel_hangup(channel, caller_data->hangup_cause); - ftdm_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session)); switch_core_session_rwunlock(session); } } From f7b40140bb83c33418664fcbdc64fed597b3f4f0 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 17:07:48 -0500 Subject: [PATCH 129/204] fix messup in dtmf change --- libs/freetdm/src/ftdm_io.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index a472ca1694..52dc1c49ba 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -3963,9 +3963,9 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v char digit_char; uint32_t dur; - teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen); - - if ((hit = teletone_dtmf_get(&ftdmchan->dtmf_detect, &digit_char, &dur)) == TT_HIT_BEGIN) { + if ((hit = teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen)) == TT_HIT_BEGIN) { + teletone_dtmf_get(&ftdmchan->dtmf_detect, &digit_char, &dur); + if (ftdmchan->state == FTDM_CHANNEL_STATE_CALLWAITING && (digit_char == 'D' || digit_char == 'A')) { ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK]++; } else { From 379c9fc41dd0196ccd7bf9640ae704b995cbc15e Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Fri, 16 Sep 2011 17:23:15 -0500 Subject: [PATCH 130/204] fix messup in dtmf change --- libs/freetdm/src/ftdm_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 52dc1c49ba..9da6e1e903 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -3963,7 +3963,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v char digit_char; uint32_t dur; - if ((hit = teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen)) == TT_HIT_BEGIN) { + if ((hit = teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen)) == TT_HIT_END) { teletone_dtmf_get(&ftdmchan->dtmf_detect, &digit_char, &dur); if (ftdmchan->state == FTDM_CHANNEL_STATE_CALLWAITING && (digit_char == 'D' || digit_char == 'A')) { From 0f45b8baddc3c8162013e4c1ca31ea8d57d9bf02 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Sun, 18 Sep 2011 01:14:56 +0200 Subject: [PATCH 131/204] mod_dingaling: Remove unused but set variables (GCC-4.6 -Wunused-but-set-variable) Subject and type event headers were never used in chat_send(), remove them. Signed-off-by: Stefan Knoblich --- src/mod/endpoints/mod_dingaling/mod_dingaling.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index a7e8537180..527a2a0fa2 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -496,17 +496,13 @@ static switch_status_t chat_send(switch_event_t *message_event) const char *proto; const char *from; const char *to; - const char *subject; const char *body; - const char *type; const char *hint; proto = switch_event_get_header(message_event, "proto"); from = switch_event_get_header(message_event, "from"); to = switch_event_get_header(message_event, "to"); - subject = switch_event_get_header(message_event, "subject"); body = switch_event_get_body(message_event); - type = switch_event_get_header(message_event, "type"); hint = switch_event_get_header(message_event, "hint"); switch_assert(proto != NULL); From 836804707a6b2e59025d5314fbecba3594e20283 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Mon, 19 Sep 2011 15:47:06 +0200 Subject: [PATCH 132/204] Make top-level configure python checks python 3 ready print syntax does not work in python 3. Add round braces to call it like any other function. Tested with python-2.4 and 3.1. NOTE: Only fixes the configure check, mod_python does NOT build with python 3.x! Signed-off-by: Stefan Knoblich --- configure.in | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.in b/configure.in index 25c0c2a675..62977f5fb5 100644 --- a/configure.in +++ b/configure.in @@ -871,7 +871,7 @@ then if test "$python_has_distutils" != "no" ; then AC_MSG_CHECKING([location of site-packages]) - PYTHON_SITE_DIR="`$PYTHON -c 'from distutils import sysconfig; print sysconfig.get_python_lib(0);'`" + PYTHON_SITE_DIR="`$PYTHON -c 'from distutils import sysconfig; print(sysconfig.get_python_lib(0));'`" if test -z "$PYTHON_SITE_DIR" ; then AC_MSG_ERROR([Unable to detect python site-packages path]) @@ -884,10 +884,10 @@ then # # python distutils found, get settings from python directly # - PYTHON_CFLAGS="`$PYTHON -c 'from distutils import sysconfig; flags = [[\"-I\" + sysconfig.get_python_inc(0), \"-I\" + sysconfig.get_python_inc(1), \" \".join(sysconfig.get_config_var(\"CFLAGS\").split())]]; print \" \".join(flags);'`" - PYTHON_LDFLAGS="`$PYTHON -c 'from distutils import sysconfig; libs = sysconfig.get_config_var(\"LIBS\").split() + sysconfig.get_config_var(\"SYSLIBS\").split(); libs.append(\"-lpython\"+sysconfig.get_config_var(\"VERSION\")); print \" \".join(libs);'`" - PYTHON_LIB="`$PYTHON -c 'from distutils import sysconfig; print \"python\" + sysconfig.get_config_var(\"VERSION\");'`" - PYTHON_LIBDIR="`$PYTHON -c 'from distutils import sysconfig; print sysconfig.get_config_var(\"LIBDIR\");'`" + PYTHON_CFLAGS="`$PYTHON -c 'from distutils import sysconfig; flags = [[\"-I\" + sysconfig.get_python_inc(0), \"-I\" + sysconfig.get_python_inc(1), \" \".join(sysconfig.get_config_var(\"CFLAGS\").split())]]; print(\" \".join(flags));'`" + PYTHON_LDFLAGS="`$PYTHON -c 'from distutils import sysconfig; libs = sysconfig.get_config_var(\"LIBS\").split() + sysconfig.get_config_var(\"SYSLIBS\").split(); libs.append(\"-lpython\"+sysconfig.get_config_var(\"VERSION\")); print(\" \".join(libs));'`" + PYTHON_LIB="`$PYTHON -c 'from distutils import sysconfig; print(\"python\" + sysconfig.get_config_var(\"VERSION\"));'`" + PYTHON_LIBDIR="`$PYTHON -c 'from distutils import sysconfig; print(sysconfig.get_config_var(\"LIBDIR\"));'`" # handle python being installed into /usr/local AC_MSG_CHECKING([python libdir]) From 975ac0ac70f6d4ad5d3ab4dca2e785fcc1c4570b Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Mon, 19 Sep 2011 15:55:07 +0200 Subject: [PATCH 133/204] FreeTDM: Fix private/libteletone*.h includes libteletone headers include each other, use #include "" to look in the local dir rather than the include search path. Unbreaking all of my (still) external FreeTDM projects. Signed-off-by: Stefan Knoblich --- libs/freetdm/src/include/private/libteletone.h | 4 ++-- libs/freetdm/src/include/private/libteletone_detect.h | 2 +- libs/freetdm/src/include/private/libteletone_generate.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libs/freetdm/src/include/private/libteletone.h b/libs/freetdm/src/include/private/libteletone.h index 61078b4984..b039f1f078 100644 --- a/libs/freetdm/src/include/private/libteletone.h +++ b/libs/freetdm/src/include/private/libteletone.h @@ -136,8 +136,8 @@ typedef __int16 int16_t; #endif #endif -#include -#include +#include "libteletone_generate.h" +#include "libteletone_detect.h" #ifdef HAVE_STRING_H #include diff --git a/libs/freetdm/src/include/private/libteletone_detect.h b/libs/freetdm/src/include/private/libteletone_detect.h index 4da368969c..28ae2f5492 100644 --- a/libs/freetdm/src/include/private/libteletone_detect.h +++ b/libs/freetdm/src/include/private/libteletone_detect.h @@ -96,7 +96,7 @@ #ifdef __cplusplus extern "C" { #endif -#include +#include "libteletone.h" /*! \file libteletone_detect.h \brief Tone Detection Routines diff --git a/libs/freetdm/src/include/private/libteletone_generate.h b/libs/freetdm/src/include/private/libteletone_generate.h index 0ff39e0dfa..8e49afaabe 100644 --- a/libs/freetdm/src/include/private/libteletone_generate.h +++ b/libs/freetdm/src/include/private/libteletone_generate.h @@ -116,7 +116,7 @@ extern float powf (float, float); #endif #include #include -#include +#include "libteletone.h" #define TELETONE_VOL_DB_MAX 0 #define TELETONE_VOL_DB_MIN -63 From 2ad4f00c9f7c7c424cb6621514a01ee2a41d61f3 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 19 Sep 2011 08:08:55 -0500 Subject: [PATCH 134/204] add missing break on begin detect --- libs/freetdm/src/libteletone_detect.c | 1 + libs/libteletone/src/libteletone_detect.c | 1 + 2 files changed, 2 insertions(+) diff --git a/libs/freetdm/src/libteletone_detect.c b/libs/freetdm/src/libteletone_detect.c index e995f98d0f..0d0fd27eec 100644 --- a/libs/freetdm/src/libteletone_detect.c +++ b/libs/freetdm/src/libteletone_detect.c @@ -435,6 +435,7 @@ TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_sta dtmf_detect_state->zc = ZC; dtmf_detect_state->dur = 0; r = TT_HIT_BEGIN; + break; } } diff --git a/libs/libteletone/src/libteletone_detect.c b/libs/libteletone/src/libteletone_detect.c index e995f98d0f..0d0fd27eec 100644 --- a/libs/libteletone/src/libteletone_detect.c +++ b/libs/libteletone/src/libteletone_detect.c @@ -435,6 +435,7 @@ TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_sta dtmf_detect_state->zc = ZC; dtmf_detect_state->dur = 0; r = TT_HIT_BEGIN; + break; } } From 8df1872fbef70e8c2b0b68a6643472e6a0a01c5f Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Mon, 19 Sep 2011 13:51:41 -0400 Subject: [PATCH 135/204] freetdm:Support for transmission of Caller ID Name on NI-2 --- .../ftmod_sangoma_isdn_stack_out.c | 2 ++ .../ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) 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 c2305e445f..add4d3fad0 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 @@ -69,6 +69,8 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan) set_calling_subaddr(ftdmchan, &conEvnt.cgPtySad); set_redir_num(ftdmchan, &conEvnt.redirNmb); set_calling_name(ftdmchan, &conEvnt); + + /* set_facility_ie will overwrite Calling Name for NI-2 if user specifies custom Facility IE */ set_facility_ie(ftdmchan, &conEvnt.facilityStr); set_prog_ind_ie(ftdmchan, &conEvnt.progInd, prog_ind); 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 9a633b902a..d744ad2942 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 @@ -719,12 +719,19 @@ ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt) } else { switch (signal_data->switchtype) { case SNGISDN_SWITCH_NI2: - /* TODO: Need to send the caller ID as a facility IE */ - +#ifdef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY + { + if (signal_data->signalling == SNGISDN_SIGNALING_NET) { + sng_isdn_encode_facility_caller_name(caller_data->cid_name, conEvnt->facilityStr.facilityStr.val, &conEvnt->facilityStr.facilityStr.len); + conEvnt->facilityStr.eh.pres = PRSNT_NODEF; + conEvnt->facilityStr.facilityStr.pres = PRSNT_NODEF; + } + } +#endif break; case SNGISDN_SWITCH_EUROISDN: if (signal_data->signalling != SNGISDN_SIGNALING_NET) { - break; + break; } /* follow through */ case SNGISDN_SWITCH_5ESS: From d820fe082bc7015438fddc74984f642774b9191f Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 19 Sep 2011 17:09:50 -0500 Subject: [PATCH 136/204] fix small valet parking issue --- .../mod_valet_parking/mod_valet_parking.c | 108 ++++++++++-------- 1 file changed, 63 insertions(+), 45 deletions(-) diff --git a/src/mod/applications/mod_valet_parking/mod_valet_parking.c b/src/mod/applications/mod_valet_parking/mod_valet_parking.c index bd40512a7e..23196c5226 100644 --- a/src/mod/applications/mod_valet_parking/mod_valet_parking.c +++ b/src/mod/applications/mod_valet_parking/mod_valet_parking.c @@ -39,6 +39,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_valet_parking_load); SWITCH_MODULE_DEFINITION(mod_valet_parking, mod_valet_parking_load, NULL, NULL); typedef struct { + char ext[256]; char uuid[SWITCH_UUID_FORMATTED_LENGTH + 1]; time_t timeout; } valet_token_t; @@ -104,7 +105,7 @@ static void check_timeouts(void) now = switch_epoch_time_now(NULL); switch_mutex_lock(globals.mutex); - if (now - globals.last_timeout_check > 30) { + if (now - globals.last_timeout_check < 30) { switch_mutex_unlock(globals.mutex); return; } @@ -144,10 +145,10 @@ static void check_timeouts(void) } -static int next_id(valet_lot_t *lot, int min, int max, int in) +static valet_token_t *next_id(switch_core_session_t *session, valet_lot_t *lot, int min, int max, int in) { int i, r = 0; - char buf[128] = ""; + char buf[256] = ""; valet_token_t *token; if (!min) { @@ -164,9 +165,20 @@ static int next_id(valet_lot_t *lot, int min, int max, int in) break; } } + + token = NULL; + + if (r) { + switch_snprintf(buf, sizeof(buf), "%d", r); + switch_zmalloc(token, sizeof(*token)); + switch_set_string(token->uuid, switch_core_session_get_uuid(session)); + switch_set_string(token->ext, buf); + switch_core_hash_insert(lot->hash, buf, token); + } + switch_mutex_unlock(globals.mutex); - return r; + return token; } @@ -182,6 +194,9 @@ SWITCH_STANDARD_APP(valet_parking_function) const char *var; valet_token_t *token = NULL; + + check_timeouts(); + if ((var = switch_channel_get_variable(channel, "valet_announce_slot"))) { play_announce = switch_true(var); } @@ -206,7 +221,7 @@ SWITCH_STANDARD_APP(valet_parking_function) const char *io = argv[2]; const char *min = argv[3]; const char *max = argv[4]; - int min_i, max_i, id, in = -1; + int min_i, max_i, in = -1; if (argc < 5) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Usage: %s\n", VALET_APP_SYNTAX); @@ -231,13 +246,13 @@ SWITCH_STANDARD_APP(valet_parking_function) min_i = atoi(min); max_i = atoi(max); - if (!(id = next_id(lot, min_i, max_i, in))) { + if (!(token = next_id(session, lot, min_i, max_i, in))) { switch_ivr_phrase_macro(session, in ? "valet_lot_full" : "valet_lot_empty", "", NULL, NULL); switch_mutex_unlock(lot->mutex); return; } - switch_snprintf(dtmf_buf, sizeof(dtmf_buf), "%d", id); + switch_snprintf(dtmf_buf, sizeof(dtmf_buf), "%s", token->ext); ext = dtmf_buf; } else if (!strcasecmp(ext, "ask")) { const char *prompt = "ivr/ivr-enter_ext_pound.wav"; @@ -283,60 +298,63 @@ SWITCH_STANDARD_APP(valet_parking_function) } } - switch_mutex_lock(lot->mutex); - if ((token = (valet_token_t *) switch_core_hash_find(lot->hash, ext))) { - switch_core_session_t *b_session; + if (!token) { + switch_mutex_lock(lot->mutex); + if ((token = (valet_token_t *) switch_core_hash_find(lot->hash, ext))) { + switch_core_session_t *b_session; - if (token->timeout) { - const char *var = switch_channel_get_variable(channel, "valet_ticket"); + if (token->timeout) { + const char *var = switch_channel_get_variable(channel, "valet_ticket"); - if (!zstr(var)) { - if (!strcmp(var, token->uuid)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Valet ticket %s accepted.\n", var); + if (!zstr(var)) { + if (!strcmp(var, token->uuid)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Valet ticket %s accepted.\n", var); + token->timeout = 0; + switch_channel_set_variable(channel, "valet_ticket", NULL); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid token %s\n", token->uuid); + switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + return; + } + } + } + + if (!zstr(token->uuid) && (b_session = switch_core_session_locate(token->uuid))) { + if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, VALET_EVENT) == SWITCH_STATUS_SUCCESS) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Lot-Name", lot_name); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Extension", ext); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "bridge"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridge-To-UUID", switch_core_session_get_uuid(session)); + switch_channel_event_set_data(switch_core_session_get_channel(b_session), event); + switch_event_fire(&event); + switch_core_session_rwunlock(b_session); token->timeout = 0; - switch_channel_set_variable(channel, "valet_ticket", NULL); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid token %s\n", token->uuid); - switch_channel_hangup(channel, SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER); + switch_ivr_uuid_bridge(switch_core_session_get_uuid(session), token->uuid); + switch_mutex_unlock(lot->mutex); return; } } } - if (!zstr(token->uuid) && (b_session = switch_core_session_locate(token->uuid))) { - if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, VALET_EVENT) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Lot-Name", lot_name); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Valet-Extension", ext); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Action", "bridge"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Bridge-To-UUID", switch_core_session_get_uuid(session)); - switch_channel_event_set_data(switch_core_session_get_channel(b_session), event); - switch_event_fire(&event); - switch_core_session_rwunlock(b_session); - token->timeout = 0; - switch_ivr_uuid_bridge(switch_core_session_get_uuid(session), token->uuid); - switch_mutex_unlock(lot->mutex); - return; - } - } + token = NULL; + + switch_zmalloc(token, sizeof(*token)); + switch_set_string(token->uuid, switch_core_session_get_uuid(session)); + switch_core_hash_insert(lot->hash, ext, token); } - - token = NULL; - if (!(tmp = switch_channel_get_variable(channel, "valet_hold_music"))) { tmp = switch_channel_get_hold_music(channel); } - if (tmp) + + if (tmp) { music = tmp; + } if (!strcasecmp(music, "silence")) { music = "silence_stream://-1"; } - - switch_zmalloc(token, sizeof(*token)); - switch_set_string(token->uuid, switch_core_session_get_uuid(session)); - switch_core_hash_insert(lot->hash, ext, token); - + dest = switch_core_session_sprintf(session, "set:valet_ticket=%s,set:valet_hold_music=%s,sleep:1000,valet_park:%s %s", token->uuid, music, lot_name, ext); switch_channel_set_variable(channel, "inline_destination", dest); @@ -351,6 +369,7 @@ SWITCH_STANDARD_APP(valet_parking_function) if ((b_session = switch_core_session_locate(uuid))) { token->timeout = switch_epoch_time_now(NULL) + 10; if (play_announce) { + switch_ivr_sleep(session, 1500, SWITCH_TRUE, NULL); switch_ivr_phrase_macro(session, "valet_announce_ext", tmp, NULL, NULL); } switch_ivr_session_transfer(b_session, dest, "inline", NULL); @@ -362,6 +381,7 @@ SWITCH_STANDARD_APP(valet_parking_function) } if (play_announce) { + switch_ivr_sleep(session, 1500, SWITCH_TRUE, NULL); switch_ivr_phrase_macro(session, "valet_announce_ext", tmp, NULL, NULL); } } @@ -405,8 +425,6 @@ SWITCH_STANDARD_APP(valet_parking_function) end: - check_timeouts(); - if (token) { token->timeout = 1; } From 626b5cb2a206c5f89bcd4b318c7c9d92238265fe Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Mon, 19 Sep 2011 20:11:23 -0500 Subject: [PATCH 137/204] FS-3571 FS-3442 FS-957 --resolve tighten up the parsing of these boolean vals issue in t38 sdp --- src/include/switch_types.h | 1 + src/include/switch_utils.h | 12 ++ .../mod_spandsp/mod_spandsp_fax.c | 11 +- src/mod/endpoints/mod_sofia/sofia_glue.c | 128 +++++++----------- 4 files changed, 69 insertions(+), 83 deletions(-) diff --git a/src/include/switch_types.h b/src/include/switch_types.h index 6a6b0be69c..c7e8a5f472 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -868,6 +868,7 @@ typedef struct { uint16_t remote_port; const char *local_ip; uint16_t local_port; + const char *sdp_o_line; } switch_t38_options_t; /*! diff --git a/src/include/switch_utils.h b/src/include/switch_utils.h index b5a1fa1868..33b4173513 100644 --- a/src/include/switch_utils.h +++ b/src/include/switch_utils.h @@ -525,6 +525,18 @@ static inline char *switch_clean_name_string(char *s) +/*! + \brief Turn a string into a number (default if NULL) + \param nptr the string + \param dft the default + \return the number version of the string or the default +*/ +static inline int switch_safe_atoi(const char *nptr, int dft) +{ + return nptr ? atoi(nptr) : dft; +} + + /*! \brief Free a pointer and set it to NULL unless it already is NULL \param it the pointer diff --git a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c index 0504b0b082..4653d9cee8 100644 --- a/src/mod/applications/mod_spandsp/mod_spandsp_fax.c +++ b/src/mod/applications/mod_spandsp/mod_spandsp_fax.c @@ -806,7 +806,9 @@ static t38_mode_t negotiate_t38(pvt_t *pvt) switch_channel_set_private(channel, "t38_options", NULL); } else { pvt->t38_mode = T38_MODE_NEGOTIATED; - + + + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "T38 SDP Origin = %s\n", t38_options->sdp_o_line); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "T38FaxVersion = %d\n", t38_options->T38FaxVersion); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "T38MaxBitRate = %d\n", t38_options->T38MaxBitRate); switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "T38FaxFillBitRemoval = %d\n", t38_options->T38FaxFillBitRemoval); @@ -827,7 +829,12 @@ static t38_mode_t negotiate_t38(pvt_t *pvt) t38_options->T38FaxVersion = 3; } t38_options->T38MaxBitRate = (pvt->disable_v17) ? 9600 : 14400; - t38_options->T38FaxFillBitRemoval = 1; + + /* cisco gets mad when we set this to one in a response where they set it to 0, are we allowed to hardcode this to 1 on responses? */ + if (!zstr(t38_options->sdp_o_line) && !switch_stristr("cisco", t38_options->sdp_o_line)) { + t38_options->T38FaxFillBitRemoval = 1; + } + t38_options->T38FaxTranscodingMMR = 0; t38_options->T38FaxTranscodingJBIG = 0; t38_options->T38FaxRateManagement = "transferredTCF"; diff --git a/src/mod/endpoints/mod_sofia/sofia_glue.c b/src/mod/endpoints/mod_sofia/sofia_glue.c index 6fcbbe3bc2..af55c13a9a 100644 --- a/src/mod/endpoints/mod_sofia/sofia_glue.c +++ b/src/mod/endpoints/mod_sofia/sofia_glue.c @@ -48,12 +48,23 @@ void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t * uint32_t port = t38_options->local_port; const char *family = "IP4"; const char *username = tech_pvt->profile->username; - char MMR[32] = ""; - char JBIG[32] = ""; - char FILLBIT[32] = ""; + const char *bit_removal_on = "a=T38FaxFillBitRemoval\n"; + const char *bit_removal_off = ""; + + const char *mmr_on = "a=T38FaxTranscodingMMR\n"; + const char *mmr_off = ""; + + const char *jbig_on = "a=T38FaxTranscodingJBIG\n"; + const char *jbig_off = ""; + const char *var; + int broken_boolean; //sofia_clear_flag(tech_pvt, TFLAG_ENABLE_SOA); + var = switch_channel_get_variable(tech_pvt->channel, "t38_broken_boolean"); + + broken_boolean = switch_true(var); + if (!ip) { if (!(ip = tech_pvt->adv_sdp_audio_ip)) { ip = tech_pvt->proxy_sdp_audio_ip; @@ -94,48 +105,6 @@ void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t * "o=%s %010u %010u IN %s %s\n" "s=%s\n" "c=IN %s %s\n" "t=0 0\n", username, tech_pvt->owner_id, tech_pvt->session_id, family, ip, username, family, ip); - if(t38_options->T38FaxFillBitRemoval) { - if (switch_true(switch_channel_get_variable(tech_pvt->channel, "broken_T38FaxFillBitRemoval"))) { - switch_snprintf(FILLBIT, sizeof(FILLBIT), "a=T38FaxFillBitRemoval:1\n"); - } else { - switch_set_string(FILLBIT, "a=T38FaxFillBitRemoval\n"); - } - } else { - if (switch_true(switch_channel_get_variable(tech_pvt->channel, "broken_T38FaxFillBitRemoval"))) { - switch_snprintf(FILLBIT, sizeof(FILLBIT), "a=T38FaxFillBitRemoval:0\n"); - } else { - switch_set_string(FILLBIT, ""); - } - } - - if( t38_options->T38FaxTranscodingMMR) { - if (switch_true(switch_channel_get_variable(tech_pvt->channel, "broken_T38FaxTranscodingMMR"))) { - switch_snprintf(MMR, sizeof(MMR), "a=T38FaxTranscodingMMR:1\n"); - } else { - switch_set_string(MMR, "a=T38FaxTranscodingMMR\n"); - } - } else { - if (switch_true(switch_channel_get_variable(tech_pvt->channel, "broken_T38FaxTranscodingMMR"))) { - switch_snprintf(MMR, sizeof(MMR), "a=T38FaxTranscodingMMR:0\n"); - } else { - switch_set_string(MMR, ""); - } - } - - if( t38_options->T38FaxTranscodingJBIG) { - if (switch_true(switch_channel_get_variable(tech_pvt->channel, "broken_T38FaxTranscodingJBIG"))) { - switch_snprintf(JBIG, sizeof(JBIG), "a=T38FaxTranscodingJBIG:1\n"); - } else { - switch_set_string(JBIG, "a=T38FaxTranscodingJBIG\n"); - } - } else { - if (switch_true(switch_channel_get_variable(tech_pvt->channel, "broken_T38FaxTranscodingJBIG"))) { - switch_snprintf(JBIG, sizeof(JBIG), "a=T38FaxTranscodingJBIG:0\n"); - } else { - switch_set_string(JBIG, ""); - } - } - if (t38_options->T38FaxMaxBuffer) { switch_snprintf(max_buf, sizeof(max_buf), "a=T38FaxMaxBuffer:%d\n", t38_options->T38FaxMaxBuffer); }; @@ -145,6 +114,21 @@ void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t * }; + + + if (broken_boolean) { + bit_removal_on = "a=T38FaxFillBitRemoval:1\n"; + bit_removal_off = "a=T38FaxFillBitRemoval:0\n"; + + mmr_on = "a=T38FaxTranscodingMMR:1\n"; + mmr_off = "a=T38FaxTranscodingMMR:0\n"; + + jbig_on = "a=T38FaxTranscodingJBIG:1\n"; + jbig_off = "a=T38FaxTranscodingJBIG:0\n"; + + } + + switch_snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "m=image %d udptl t38\n" "a=T38FaxVersion:%d\n" @@ -160,9 +144,9 @@ void sofia_glue_set_image_sdp(private_object_t *tech_pvt, switch_t38_options_t * port, t38_options->T38FaxVersion, t38_options->T38MaxBitRate, - FILLBIT, - MMR, - JBIG, + t38_options->T38FaxFillBitRemoval ? bit_removal_on : bit_removal_off, + t38_options->T38FaxTranscodingMMR ? mmr_on : mmr_off, + t38_options->T38FaxTranscodingJBIG ? jbig_on : jbig_off, t38_options->T38FaxRateManagement, max_buf, max_data, @@ -4006,6 +3990,7 @@ void sofia_glue_copy_t38_options(switch_t38_options_t *t38_options, switch_core_ switch_channel_set_private(channel, "t38_options", local_t38_options); } + static switch_t38_options_t *tech_process_udptl(private_object_t *tech_pvt, sdp_session_t *sdp, sdp_media_t *m) { switch_t38_options_t *t38_options = switch_channel_get_private(tech_pvt->channel, "t38_options"); @@ -4025,6 +4010,12 @@ static switch_t38_options_t *tech_process_udptl(private_object_t *tech_pvt, sdp_ t38_options->remote_port = (switch_port_t)m->m_port; + if (sdp->sdp_origin) { + t38_options->sdp_o_line = switch_core_session_strdup(tech_pvt->session, sdp->sdp_origin->o_username); + } else { + t38_options->sdp_o_line = "unknown"; + } + if (m->m_connections && m->m_connections->c_address) { t38_options->remote_ip = switch_core_session_strdup(tech_pvt->session, m->m_connections->c_address); } else if (sdp && sdp->sdp_connection && sdp->sdp_connection->c_address) { @@ -4037,41 +4028,11 @@ static switch_t38_options_t *tech_process_udptl(private_object_t *tech_pvt, sdp_ } else if (!strcasecmp(attr->a_name, "T38MaxBitRate") && attr->a_value) { t38_options->T38MaxBitRate = (uint32_t) atoi(attr->a_value); } else if (!strcasecmp(attr->a_name, "T38FaxFillBitRemoval")) { - if (switch_stristr("T38FaxFillBitRemoval:", tech_pvt->remote_sdp_str)) { - switch_channel_set_variable(tech_pvt->channel, "broken_T38FaxFillBitRemoval", "true"); - if (atoi(attr->a_value) == 0) { - t38_options->T38FaxFillBitRemoval = SWITCH_FALSE; - } else { - t38_options->T38FaxFillBitRemoval = SWITCH_TRUE; - } - } else { - switch_channel_set_variable(tech_pvt->channel, "broken_T38FaxFillBitRemoval", "false"); - t38_options->T38FaxFillBitRemoval = SWITCH_TRUE; - } + t38_options->T38FaxFillBitRemoval = switch_safe_atoi(attr->a_value, 1); } else if (!strcasecmp(attr->a_name, "T38FaxTranscodingMMR")) { - if (switch_stristr("T38FaxTranscodingMMR:", tech_pvt->remote_sdp_str)) { - switch_channel_set_variable(tech_pvt->channel, "broken_T38FaxTranscodingMMR", "true"); - if (atoi(attr->a_value) == 0) { - t38_options->T38FaxTranscodingMMR = SWITCH_FALSE; - } else { - t38_options->T38FaxTranscodingMMR = SWITCH_TRUE; - } - } else { - switch_channel_set_variable(tech_pvt->channel, "broken_T38FaxTranscodingMMR", "false"); - t38_options->T38FaxTranscodingMMR = SWITCH_TRUE; - } + t38_options->T38FaxTranscodingMMR = switch_safe_atoi(attr->a_value, 1); } else if (!strcasecmp(attr->a_name, "T38FaxTranscodingJBIG")) { - if (switch_stristr("T38FaxTranscodingJBIG:", tech_pvt->remote_sdp_str)) { - switch_channel_set_variable(tech_pvt->channel, "broken_T38FaxTranscodingJBIG", "true"); - if (atoi(attr->a_value) == 0) { - t38_options->T38FaxTranscodingJBIG = SWITCH_FALSE; - } else { - t38_options->T38FaxTranscodingJBIG = SWITCH_TRUE; - } - } else { - switch_channel_set_variable(tech_pvt->channel, "broken_T38FaxTranscodingJBIG", "false"); - t38_options->T38FaxTranscodingJBIG = SWITCH_TRUE; - } + t38_options->T38FaxTranscodingJBIG = switch_safe_atoi(attr->a_value, 1); } else if (!strcasecmp(attr->a_name, "T38FaxRateManagement") && attr->a_value) { t38_options->T38FaxRateManagement = switch_core_session_strdup(tech_pvt->session, attr->a_value); } else if (!strcasecmp(attr->a_name, "T38FaxMaxBuffer") && attr->a_value) { @@ -4420,6 +4381,11 @@ uint8_t sofia_glue_negotiate_sdp(switch_core_session_t *session, const char *r_s total_codecs = tech_pvt->num_negotiated_codecs; } + if (switch_stristr("T38FaxFillBitRemoval:", r_sdp) || switch_stristr("T38FaxTranscodingMMR:", r_sdp) || + switch_stristr("T38FaxTranscodingJBIG:", r_sdp)) { + switch_channel_set_variable(tech_pvt->channel, "t38_broken_boolean", "true"); + } + for (m = sdp->sdp_media; m; m = m->m_next) { sdp_connection_t *connection; switch_core_session_t *other_session; From 6f4c4ea0887c96ae032a2ac4afd2eb15e237248e Mon Sep 17 00:00:00 2001 From: Georgiewskiy Yuriy Date: Tue, 20 Sep 2011 15:22:09 +0400 Subject: [PATCH 138/204] moves the switch_rtp_request_port() call from the contructor to FSH323Connection::CreateRealTimeLogicalChannel() - fix rtp port leak. tnx to Peter Olsson. --- src/mod/endpoints/mod_h323/changes.txt | 3 +++ src/mod/endpoints/mod_h323/mod_h323.cpp | 10 ++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/mod/endpoints/mod_h323/changes.txt b/src/mod/endpoints/mod_h323/changes.txt index 0076291621..80d9119e4d 100644 --- a/src/mod/endpoints/mod_h323/changes.txt +++ b/src/mod/endpoints/mod_h323/changes.txt @@ -1,3 +1,6 @@ +moves the switch_rtp_request_port() call from the contructor to FSH323Connection::CreateRealTimeLogicalChannel() - fix + rtp port leak. tnx to Peter Olsson. +fix log printing fix small interoperability issues if remote endpoint send progress twice make sure dtmfinband gets initialized make gk-identifier and gk-interface settings optional (documentation sayed that about gk-identifier already) diff --git a/src/mod/endpoints/mod_h323/mod_h323.cpp b/src/mod/endpoints/mod_h323/mod_h323.cpp index 72846b07dc..26323ddaea 100644 --- a/src/mod/endpoints/mod_h323/mod_h323.cpp +++ b/src/mod/endpoints/mod_h323/mod_h323.cpp @@ -413,7 +413,7 @@ bool FSH323EndPoint::Initialise(switch_loadable_module_interface_t *iface) } } } - + if (m_fax_old_asn) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "--->fax_old_asn\n"); SetT38_IFP_PRE(); @@ -714,6 +714,7 @@ FSH323Connection::FSH323Connection(FSH323EndPoint& endpoint, H323Transport* tran , m_rtp_resetting(0) , m_isRequst_fax(false) , m_channel_hangup(false) + , m_RTPlocalPort(0) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"======>FSH323Connection::FSH323Connection [%p]\n",this); @@ -739,8 +740,6 @@ FSH323Connection::FSH323Connection(FSH323EndPoint& endpoint, H323Transport* tran switch_channel_set_state(m_fsChannel, CS_INIT); } - - m_RTPlocalPort = switch_rtp_request_port((const char *)m_RTPlocalIP.AsString()); } FSH323Connection::~FSH323Connection() @@ -974,6 +973,9 @@ H323Channel* FSH323Connection::CreateRealTimeLogicalChannel(const H323Capability H323TransportAddress m_h323transportadd = GetSignallingChannel()->GetLocalAddress(); m_h323transportadd.GetIpAddress(m_RTPlocalIP); + if (!m_RTPlocalPort) { + m_RTPlocalPort = switch_rtp_request_port((const char *)m_RTPlocalIP.AsString()); + } return new FSH323_ExternalRTPChannel(*this, capability, dir, sessionID,m_RTPlocalIP,m_RTPlocalPort); } @@ -2044,7 +2046,7 @@ PBoolean FSH323_ExternalRTPChannel::Start() , GetMainTypes[m_capability->GetMainType()],(const char*)(m_capability->GetFormatName()),this); } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"%s initialise %s codec %s for connection [%p]\n",switch_channel_get_name(m_fsChannel),((GetDirection() == IsReceiver)? " read" : " write") + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,"%s Unsupported ptime of %u on %s %s codec %s for connection [%p]\n",switch_channel_get_name(m_fsChannel),((GetDirection() == IsReceiver)? " read" : " write") , GetMainTypes[m_capability->GetMainType()],(const char*)(m_capability->GetFormatName()),this); if (GetDirection() == IsReceiver) { From d00f74640f8d380a3c687b0b05182ecd5edac726 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Wed, 21 Sep 2011 15:10:37 +0200 Subject: [PATCH 139/204] mod_blacklist: Add example configuration file Signed-off-by: Stefan Knoblich --- conf/autoload_configs/blacklist.conf.xml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 conf/autoload_configs/blacklist.conf.xml diff --git a/conf/autoload_configs/blacklist.conf.xml b/conf/autoload_configs/blacklist.conf.xml new file mode 100644 index 0000000000..d6a810cc6f --- /dev/null +++ b/conf/autoload_configs/blacklist.conf.xml @@ -0,0 +1,7 @@ + + + + + From 3ddb7d6c38dbd5a0aea24de3a31c718b4f344e26 Mon Sep 17 00:00:00 2001 From: Michal Bielicki - cypromis Date: Wed, 21 Sep 2011 15:16:24 +0200 Subject: [PATCH 140/204] added mod_blacklist to spec file --- freeswitch.spec | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/freeswitch.spec b/freeswitch.spec index c6226aaa9e..adebd057c2 100644 --- a/freeswitch.spec +++ b/freeswitch.spec @@ -432,7 +432,7 @@ export QA_RPATHS=$[ 0x0001|0x0002 ] APPLICATION_MODULES_AE="applications/mod_avmd applications/mod_callcenter applications/mod_cidlookup applications/mod_cluechoo \ applications/mod_commands applications/mod_conference applications/mod_curl applications/mod_db applications/mod_directory \ applications/mod_distributor applications/mod_dptools applications/mod_easyroute applications/mod_enum \ - applications/mod_esf applications/mod_expr" + applications/mod_esf applications/mod_expr applications/mod_blacklist" APPLICATION_MODULES_FM="applications/mod_fifo applications/mod_fsv applications/mod_hash applications/mod_lcr applications/mod_limit \ applications/mod_memcache" APPLICATION_MODULES_NY="applications/mod_nibblebill applications/mod_redis applications/mod_rss applications/mod_snom \ @@ -751,6 +751,7 @@ fi %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/mime.types %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/acl.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/alsa.conf.xml +%config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/blacklist.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/callcenter.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/cdr_csv.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{prefix}/conf/autoload_configs/cdr_mongodb.conf.xml @@ -881,6 +882,7 @@ fi ###################################################################################################################### %{prefix}/mod/mod_amrwb.so* %{prefix}/mod/mod_avmd.so* +%{prefix}/mod/mod_blacklist.so* %{prefix}/mod/mod_bv.so* %{prefix}/mod/mod_callcenter.so* %{prefix}/mod/mod_cdr_csv.so* From 41abb3e644cfd127e81c963e0d940a81ff1f5f25 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Wed, 21 Sep 2011 15:50:57 +0200 Subject: [PATCH 141/204] mod_blacklist: Resource leak fixes, config checks and add help output for api interface Don't leak the file handle after parsing the configuration Don't leak memory if the file could not be opened Check list name and filename attribute of configuration entry. Add "blacklist help" and error messages to api interface. Signed-off-by: Stefan Knoblich --- conf/autoload_configs/blacklist.conf.xml | 6 ++- .../mod_blacklist/mod_blacklist.c | 45 +++++++++++++------ 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/conf/autoload_configs/blacklist.conf.xml b/conf/autoload_configs/blacklist.conf.xml index d6a810cc6f..a981ebbdb0 100644 --- a/conf/autoload_configs/blacklist.conf.xml +++ b/conf/autoload_configs/blacklist.conf.xml @@ -1,6 +1,10 @@ - diff --git a/src/mod/applications/mod_blacklist/mod_blacklist.c b/src/mod/applications/mod_blacklist/mod_blacklist.c index a8fe5e6da5..ab9f7f6c8c 100644 --- a/src/mod/applications/mod_blacklist/mod_blacklist.c +++ b/src/mod/applications/mod_blacklist/mod_blacklist.c @@ -86,24 +86,25 @@ void trim(char *string) static switch_status_t load_list(const char *name, const char *filename) { FILE *f; - blacklist_t *bl = blacklist_create(name); - /* Create a hashtable + mutex for that list */ - + if ((f = fopen(filename, "r"))) { char buf[1024] = {0}; + blacklist_t *bl = blacklist_create(name); /* Create a hashtable + mutex for that list */ + while (fgets(buf, 1024, f)) { trim(buf); - switch_core_hash_insert(bl->list, buf, (void*)SWITCH_TRUE); + switch_core_hash_insert(bl->list, buf, (void *)SWITCH_TRUE); } + + switch_core_hash_insert(globals.lists, name, bl); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Loaded list [%s]\n", name); + + fclose(f); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't open [%s] to load list [%s]\n", filename, name); return SWITCH_STATUS_FALSE; } - - switch_core_hash_insert(globals.lists, name, bl); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Loaded list [%s]\n", name); - - + return SWITCH_STATUS_SUCCESS; } @@ -133,10 +134,17 @@ static switch_status_t do_config(switch_bool_t reload) for (list = switch_xml_child(lists, "list"); list; list = list->next) { const char *name = switch_xml_attr_soft(list, "name"); const char *filename = switch_xml_attr_soft(list, "filename"); - - if (name && filename) { - load_list(name, filename); + + if (zstr(name)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "list has no name\n"); + continue; } + if (zstr(filename)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "list [%s] has no filename\n", name); + continue; + } + + load_list(name, filename); } } @@ -150,6 +158,13 @@ static switch_status_t do_config(switch_bool_t reload) return SWITCH_STATUS_SUCCESS; } +#define BLACKLIST_API_SYNTAX \ + "blacklist check \n" \ + "blacklist add \n" \ + "blacklist del \n" \ + "blacklist reload\n" \ + "blacklist help\n" + SWITCH_STANDARD_API(blacklist_api_function) { char *data; @@ -209,7 +224,7 @@ SWITCH_STANDARD_API(blacklist_api_function) switch_mutex_unlock(bl->list_mutex); stream->write_function(stream, "+OK\n"); } else if (!strcasecmp(argv[0], "del")) { - blacklist_t *bl = NULL; + blacklist_t *bl = NULL; if (argc < 2 || zstr(argv[1]) || zstr(argv[2])) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Wrong syntax"); goto done; @@ -233,6 +248,10 @@ SWITCH_STANDARD_API(blacklist_api_function) } else if (!strcasecmp(argv[0], "reload")) { do_config(SWITCH_TRUE); stream->write_function(stream, "+OK\n"); + } else if (!strcasecmp(argv[0], "help")) { + stream->write_function(stream, BLACKLIST_API_SYNTAX "+OK\n"); + } else if (!zstr(argv[0])) { + stream->write_function(stream, "-ERR: No such command: %s (see 'blacklist help')\n", argv[0]); } done: From 5fe3a22d83867d07f30ef7974329b2fa966747ea Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Sep 2011 11:05:33 -0500 Subject: [PATCH 142/204] fix inaccurate sample count in file handle, buffered samples were being double tallied --- src/switch_core_file.c | 2 -- src/switch_ivr_play_say.c | 6 +++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/switch_core_file.c b/src/switch_core_file.c index 28f1172ff8..6beaa83584 100644 --- a/src/switch_core_file.c +++ b/src/switch_core_file.c @@ -395,7 +395,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_write(switch_file_handle_t *fh, } } } - fh->samples_out += orig_len; return status; } else { @@ -550,7 +549,6 @@ SWITCH_DECLARE(switch_status_t) switch_core_file_close(switch_file_handle_t *fh) if (fh->file_interface->file_write(fh, fh->pre_buffer_data, &blen) != SWITCH_STATUS_SUCCESS) { break; } - fh->samples_out += blen; } } } diff --git a/src/switch_ivr_play_say.c b/src/switch_ivr_play_say.c index f941ff85c8..f3d554faeb 100644 --- a/src/switch_ivr_play_say.c +++ b/src/switch_ivr_play_say.c @@ -779,9 +779,9 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_record_file(switch_core_session_t *se } - if (read_impl.samples_per_second) { - switch_channel_set_variable_printf(channel, "record_seconds", "%d", fh->samples_out / read_impl.samples_per_second); - switch_channel_set_variable_printf(channel, "record_ms", "%d", fh->samples_out / (read_impl.samples_per_second / 1000)); + if (read_impl.actual_samples_per_second) { + switch_channel_set_variable_printf(channel, "record_seconds", "%d", fh->samples_out / read_impl.actual_samples_per_second); + switch_channel_set_variable_printf(channel, "record_ms", "%d", fh->samples_out / (read_impl.actual_samples_per_second / 1000)); } From 7333d46d5b90bc5d94a2bf83169997f2c2322112 Mon Sep 17 00:00:00 2001 From: Anthony Minessale Date: Wed, 21 Sep 2011 14:31:10 -0500 Subject: [PATCH 143/204] add new chatplan concept and mod_sms. Apps for chat messages: copy new base freeswitch.xml and chatplan dir if you are upgrading on existing config base --- conf/chatplan/default.xml | 14 + conf/freeswitch.xml | 4 + libs/esl/src/esl_event.c | 20 +- libs/esl/src/include/esl_event.h | 1 + src/include/switch_core.h | 2 +- src/include/switch_cpp.h | 2 + src/include/switch_event.h | 10 +- src/include/switch_ivr.h | 2 + src/include/switch_loadable_module.h | 51 +- src/include/switch_module_interfaces.h | 21 + src/include/switch_regex.h | 1 + src/include/switch_types.h | 14 +- .../applications/mod_sms/mod_sms.2008.vcproj | 287 ++++ .../applications/mod_sms/mod_sms.2010.vcxproj | 135 ++ src/mod/applications/mod_sms/mod_sms.c | 510 +++++++ .../endpoints/mod_dingaling/mod_dingaling.c | 2 +- src/mod/endpoints/mod_sofia/sofia_presence.c | 121 +- src/mod/endpoints/mod_sofia/sofia_reg.c | 2 +- .../src/org/freeswitch/swig/Event.java | 8 + .../org/freeswitch/swig/freeswitchJNI.java | 2 + .../languages/mod_java/switch_swig_wrap.cpp | 51 + src/mod/languages/mod_lua/mod_lua.cpp | 20 + src/mod/languages/mod_lua/mod_lua_wrap.cpp | 65 + .../languages/mod_managed/freeswitch_wrap.cxx | 463 ++++++ src/mod/languages/mod_managed/managed/swig.cs | 1316 +++++++++++------ src/mod/languages/mod_perl/freeswitch.pm | 2 + src/mod/languages/mod_perl/mod_perl_wrap.cpp | 95 ++ src/mod/languages/mod_python/freeswitch.py | 2 + .../languages/mod_python/mod_python_wrap.cpp | 86 ++ src/switch_cpp.cpp | 13 + src/switch_event.c | 107 +- src/switch_ivr.c | 13 + src/switch_loadable_module.c | 380 ++++- src/switch_regex.c | 7 + src/switch_xml.c | 1 + 35 files changed, 3263 insertions(+), 567 deletions(-) create mode 100644 conf/chatplan/default.xml create mode 100644 src/mod/applications/mod_sms/mod_sms.2008.vcproj create mode 100644 src/mod/applications/mod_sms/mod_sms.2010.vcxproj create mode 100644 src/mod/applications/mod_sms/mod_sms.c diff --git a/conf/chatplan/default.xml b/conf/chatplan/default.xml new file mode 100644 index 0000000000..b67bb638fa --- /dev/null +++ b/conf/chatplan/default.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/conf/freeswitch.xml b/conf/freeswitch.xml index 42eede31ee..7a1b1d3d15 100644 --- a/conf/freeswitch.xml +++ b/conf/freeswitch.xml @@ -46,6 +46,10 @@
+
+ +
+
diff --git a/libs/esl/src/esl_event.c b/libs/esl/src/esl_event.c index 71e7d42b2a..ead853ea46 100644 --- a/libs/esl/src/esl_event.c +++ b/libs/esl/src/esl_event.c @@ -270,8 +270,9 @@ ESL_DECLARE(char *) esl_event_get_header_idx(esl_event_t *event, const char *hea } return hp->value; - - } + } else if (!strcmp(header_name, "_body")) { + return event->body; + } return NULL; } @@ -414,6 +415,10 @@ static esl_status_t esl_event_base_add_header(esl_event_t *event, esl_stack_t st int index = 0; char *real_header_name = NULL; + if (!strcmp(header_name, "_body")) { + esl_event_set_body(event, data); + } + if ((index_ptr = strchr(header_name, '['))) { index_ptr++; index = atoi(index_ptr); @@ -604,6 +609,17 @@ ESL_DECLARE(esl_status_t) esl_event_add_header_string(esl_event_t *event, esl_st return ESL_FAIL; } +ESL_DECLARE(esl_status_t) esl_event_set_body(esl_event_t *event, const char *body) +{ + esl_safe_free(event->body); + + if (body) { + event->body = DUP(body); + } + + return ESL_SUCCESS; +} + ESL_DECLARE(esl_status_t) esl_event_add_body(esl_event_t *event, const char *fmt, ...) { int ret = 0; diff --git a/libs/esl/src/include/esl_event.h b/libs/esl/src/include/esl_event.h index d6be0470e8..1cc6134e42 100644 --- a/libs/esl/src/include/esl_event.h +++ b/libs/esl/src/include/esl_event.h @@ -298,6 +298,7 @@ ESL_DECLARE(esl_status_t) esl_event_create_json(esl_event_t **event, const char \note the body parameter can be shadowed by the esl_event_reserve_subclass_detailed function */ ESL_DECLARE(esl_status_t) esl_event_add_body(esl_event_t *event, const char *fmt, ...); +ESL_DECLARE(esl_status_t) esl_event_set_body(esl_event_t *event, const char *body); /*! \brief Create a new event assuming it will not be custom event and therefore hiding the unused parameters diff --git a/src/include/switch_core.h b/src/include/switch_core.h index 1591cf18cc..7f1db105f8 100644 --- a/src/include/switch_core.h +++ b/src/include/switch_core.h @@ -2110,7 +2110,7 @@ SWITCH_DECLARE(void) switch_cond_next(void); SWITCH_DECLARE(switch_status_t) switch_core_chat_send_args(const char *dest_proto, const char *proto, const char *from, const char *to, const char *subject, const char *body, const char *type, const char *hint); SWITCH_DECLARE(switch_status_t) switch_core_chat_send(const char *dest_proto, switch_event_t *message_event); - +SWITCH_DECLARE(switch_status_t) switch_core_chat_deliver(const char *dest_proto, switch_event_t **message_event); SWITCH_DECLARE(switch_status_t) switch_ivr_preprocess_session(switch_core_session_t *session, const char *cmds); diff --git a/src/include/switch_cpp.h b/src/include/switch_cpp.h index e9f5c29d92..70e484bf51 100644 --- a/src/include/switch_cpp.h +++ b/src/include/switch_cpp.h @@ -156,6 +156,8 @@ SWITCH_DECLARE(bool) email(char *to, char *from, char *headers = NULL, char *bod SWITCH_DECLARE_CONSTRUCTOR Event(const char *type, const char *subclass_name = NULL); SWITCH_DECLARE_CONSTRUCTOR Event(switch_event_t *wrap_me, int free_me = 0); virtual SWITCH_DECLARE_CONSTRUCTOR ~ Event(); + SWITCH_DECLARE(int) chat_execute(const char *app, const char *data = NULL); + SWITCH_DECLARE(int) chat_send(const char *dest_proto = NULL); SWITCH_DECLARE(const char *) serialize(const char *format = NULL); SWITCH_DECLARE(bool) setPriority(switch_priority_t priority = SWITCH_PRIORITY_NORMAL); SWITCH_DECLARE(const char *) getHeader(const char *header_name); diff --git a/src/include/switch_event.h b/src/include/switch_event.h index c6b1d64c35..23cd0825b5 100644 --- a/src/include/switch_event.h +++ b/src/include/switch_event.h @@ -103,7 +103,8 @@ struct switch_event { }; typedef enum { - EF_UNIQ_HEADERS = (1 << 0) + EF_UNIQ_HEADERS = (1 << 0), + EF_NO_CHAT_EXEC = (1 << 1) } switch_event_flag_t; @@ -157,6 +158,8 @@ _Ret_opt_z_ SWITCH_DECLARE(char *) switch_event_get_header_idx(switch_event_t *e #define switch_event_get_header_nil(e, h) switch_str_nil(switch_event_get_header(e,h)) +SWITCH_DECLARE(switch_status_t) switch_event_rename_header(switch_event_t *event, const char *header_name, const char *new_header_name); + /*! \brief Retrieve the body value from an event \param event the event to read the body from @@ -207,6 +210,8 @@ SWITCH_DECLARE(void) switch_event_destroy(switch_event_t **event); */ SWITCH_DECLARE(switch_status_t) switch_event_dup(switch_event_t **event, switch_event_t *todup); SWITCH_DECLARE(void) switch_event_merge(switch_event_t *event, switch_event_t *tomerge); +SWITCH_DECLARE(switch_status_t) switch_event_dup_reply(switch_event_t **event, switch_event_t *todup); + /*! \brief Fire an event with full arguement list \param file the calling file @@ -321,6 +326,9 @@ SWITCH_DECLARE(switch_status_t) switch_event_running(void); */ SWITCH_DECLARE(switch_status_t) switch_event_add_body(switch_event_t *event, const char *fmt, ...) PRINTF_FUNCTION(2, 3); #endif + +SWITCH_DECLARE(switch_status_t) switch_event_set_body(switch_event_t *event, const char *body); + SWITCH_DECLARE(char *) switch_event_expand_headers(switch_event_t *event, const char *in); SWITCH_DECLARE(switch_status_t) switch_event_create_pres_in_detailed(_In_z_ char *file, _In_z_ char *func, _In_ int line, diff --git a/src/include/switch_ivr.h b/src/include/switch_ivr.h index 6b2a10d43f..901519f7dd 100644 --- a/src/include/switch_ivr.h +++ b/src/include/switch_ivr.h @@ -931,6 +931,8 @@ SWITCH_DECLARE(switch_status_t) switch_ivr_release_file_handle(switch_core_sessi SWITCH_DECLARE(switch_status_t) switch_ivr_process_fh(switch_core_session_t *session, const char *cmd, switch_file_handle_t *fhp); SWITCH_DECLARE(switch_status_t) switch_ivr_insert_file(switch_core_session_t *session, const char *file, const char *insert_file, switch_size_t sample_point); +SWITCH_DECLARE(switch_status_t) switch_ivr_create_message_reply(switch_event_t **reply, switch_event_t *message, const char *new_proto); + /** @} */ SWITCH_END_EXTERN_C diff --git a/src/include/switch_loadable_module.h b/src/include/switch_loadable_module.h index 4b81a1f25e..62fcac2343 100644 --- a/src/include/switch_loadable_module.h +++ b/src/include/switch_loadable_module.h @@ -55,33 +55,35 @@ SWITCH_BEGIN_EXTERN_C struct switch_loadable_module_interface { /*! the name of the module */ const char *module_name; - /*! the table of endpoints the module has implmented */ + /*! the table of endpoints the module has implemented */ switch_endpoint_interface_t *endpoint_interface; - /*! the table of timers the module has implmented */ + /*! the table of timers the module has implemented */ switch_timer_interface_t *timer_interface; - /*! the table of dialplans the module has implmented */ + /*! the table of dialplans the module has implemented */ switch_dialplan_interface_t *dialplan_interface; - /*! the table of codecs the module has implmented */ + /*! the table of codecs the module has implemented */ switch_codec_interface_t *codec_interface; - /*! the table of applications the module has implmented */ + /*! the table of applications the module has implemented */ switch_application_interface_t *application_interface; - /*! the table of api functions the module has implmented */ + /*! the table of chat applications the module has implemented */ + switch_chat_application_interface_t *chat_application_interface; + /*! the table of api functions the module has implemented */ switch_api_interface_t *api_interface; - /*! the table of file formats the module has implmented */ + /*! the table of file formats the module has implemented */ switch_file_interface_t *file_interface; - /*! the table of speech interfaces the module has implmented */ + /*! the table of speech interfaces the module has implemented */ switch_speech_interface_t *speech_interface; - /*! the table of directory interfaces the module has implmented */ + /*! the table of directory interfaces the module has implemented */ switch_directory_interface_t *directory_interface; - /*! the table of chat interfaces the module has implmented */ + /*! the table of chat interfaces the module has implemented */ switch_chat_interface_t *chat_interface; - /*! the table of say interfaces the module has implmented */ + /*! the table of say interfaces the module has implemented */ switch_say_interface_t *say_interface; - /*! the table of asr interfaces the module has implmented */ + /*! the table of asr interfaces the module has implemented */ switch_asr_interface_t *asr_interface; - /*! the table of management interfaces the module has implmented */ + /*! the table of management interfaces the module has implemented */ switch_management_interface_t *management_interface; - /*! the table of limit interfaces the module has implmented */ + /*! the table of limit interfaces the module has implemented */ switch_limit_interface_t *limit_interface; switch_thread_rwlock_t *rwlock; int refs; @@ -169,6 +171,15 @@ SWITCH_DECLARE(switch_timer_interface_t *) switch_loadable_module_get_timer_inte */ SWITCH_DECLARE(switch_application_interface_t *) switch_loadable_module_get_application_interface(const char *name); +/*! + \brief Retrieve the chat application interface by it's registered name + \param name the name of the chat application + \return the desired chat application interface + */ +SWITCH_DECLARE(switch_chat_application_interface_t *) switch_loadable_module_get_chat_application_interface(const char *name); + +SWITCH_DECLARE(switch_status_t) switch_core_execute_chat_app(switch_event_t *message, const char *app, const char *data); + /*! \brief Retrieve the API interface by it's registered name \param name the name of the API @@ -335,6 +346,18 @@ SWITCH_MOD_DECLARE(switch_status_t) switch_module_shutdown(void); break; \ } +#define SWITCH_ADD_CHAT_APP(app_int, int_name, short_descript, long_descript, funcptr, syntax_string, app_flags) \ + for (;;) { \ + app_int = (switch_chat_application_interface_t *)switch_loadable_module_create_interface(*module_interface, SWITCH_CHAT_APPLICATION_INTERFACE); \ + app_int->interface_name = int_name; \ + app_int->chat_application_function = funcptr; \ + app_int->short_desc = short_descript; \ + app_int->long_desc = long_descript; \ + app_int->syntax = syntax_string; \ + app_int->flags = app_flags; \ + break; \ + } + #define SWITCH_ADD_DIALPLAN(dp_int, int_name, funcptr) \ for (;;) { \ dp_int = (switch_dialplan_interface_t *)switch_loadable_module_create_interface(*module_interface, SWITCH_DIALPLAN_INTERFACE); \ diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index 7c666ab9f4..acb85407c7 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -681,6 +681,27 @@ struct switch_application_interface { struct switch_application_interface *next; }; +/*! \brief A module interface to implement a chat application */ +struct switch_chat_application_interface { + /*! the name of the interface */ + const char *interface_name; + /*! function the application implements */ + switch_chat_application_function_t chat_application_function; + /*! the long winded description of the application */ + const char *long_desc; + /*! the short and sweet description of the application */ + const char *short_desc; + /*! an example of the application syntax */ + const char *syntax; + /*! flags to control behaviour */ + uint32_t flags; + switch_thread_rwlock_t *rwlock; + int refs; + switch_mutex_t *reflock; + switch_loadable_module_interface_t *parent; + struct switch_chat_application_interface *next; +}; + /*! \brief A module interface to implement an api function */ struct switch_api_interface { /*! the name of the interface */ diff --git a/src/include/switch_regex.h b/src/include/switch_regex.h index 27f4852966..6558299b53 100644 --- a/src/include/switch_regex.h +++ b/src/include/switch_regex.h @@ -74,6 +74,7 @@ SWITCH_DECLARE(void) switch_capture_regex(switch_regex_t *re, int match_count, c int *ovector, const char *var, switch_cap_callback_t callback, void *user_data); SWITCH_DECLARE_NONSTD(void) switch_regex_set_var_callback(const char *var, const char *val, void *user_data); +SWITCH_DECLARE_NONSTD(void) switch_regex_set_event_header_callback(const char *var, const char *val, void *user_data); #define switch_regex_safe_free(re) if (re) {\ switch_regex_free(re);\ diff --git a/src/include/switch_types.h b/src/include/switch_types.h index c7e8a5f472..e0419718c1 100644 --- a/src/include/switch_types.h +++ b/src/include/switch_types.h @@ -325,7 +325,8 @@ typedef enum { SWITCH_SAY_INTERFACE, SWITCH_ASR_INTERFACE, SWITCH_MANAGEMENT_INTERFACE, - SWITCH_LIMIT_INTERFACE + SWITCH_LIMIT_INTERFACE, + SWITCH_CHAT_APPLICATION_INTERFACE } switch_module_interface_name_t; typedef enum { @@ -495,6 +496,7 @@ typedef enum { SWITCH_XML_SECTION_DIRECTORY = (1 << 1), SWITCH_XML_SECTION_DIALPLAN = (1 << 2), SWITCH_XML_SECTION_PHRASES = (1 << 3), + SWITCH_XML_SECTION_CHATPLAN = (1 << 4), /* Nothing after this line */ SWITCH_XML_SECTION_MAX = (1 << 4) @@ -1221,6 +1223,12 @@ typedef enum { } switch_application_flag_enum_t; typedef uint32_t switch_application_flag_t; +typedef enum { + SCAF_NONE = 0 +} switch_chat_application_flag_enum_t; +typedef uint32_t switch_chat_application_flag_t; + + /*! \enum switch_signal_t \brief Signals to send to channels @@ -1729,6 +1737,7 @@ typedef struct switch_timer_interface switch_timer_interface_t; typedef struct switch_dialplan_interface switch_dialplan_interface_t; typedef struct switch_codec_interface switch_codec_interface_t; typedef struct switch_application_interface switch_application_interface_t; +typedef struct switch_chat_application_interface switch_chat_application_interface_t; typedef struct switch_api_interface switch_api_interface_t; typedef struct switch_file_interface switch_file_interface_t; typedef struct switch_speech_interface switch_speech_interface_t; @@ -1780,7 +1789,8 @@ typedef switch_status_t (*switch_core_codec_fmtp_parse_func_t) (const char *fmtp typedef switch_status_t (*switch_core_codec_destroy_func_t) (switch_codec_t *); - +typedef switch_status_t (*switch_chat_application_function_t) (switch_event_t *, const char *); +#define SWITCH_STANDARD_CHAT_APP(name) static switch_status_t name (switch_event_t *message, const char *data) typedef void (*switch_application_function_t) (switch_core_session_t *, const char *); #define SWITCH_STANDARD_APP(name) static void name (switch_core_session_t *session, const char *data) diff --git a/src/mod/applications/mod_sms/mod_sms.2008.vcproj b/src/mod/applications/mod_sms/mod_sms.2008.vcproj new file mode 100644 index 0000000000..6d9109b4bb --- /dev/null +++ b/src/mod/applications/mod_sms/mod_sms.2008.vcproj @@ -0,0 +1,287 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/mod/applications/mod_sms/mod_sms.2010.vcxproj b/src/mod/applications/mod_sms/mod_sms.2010.vcxproj new file mode 100644 index 0000000000..4dbbf47874 --- /dev/null +++ b/src/mod/applications/mod_sms/mod_sms.2010.vcxproj @@ -0,0 +1,135 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + mod_sms + {11C9BC3D-45E9-46E3-BE84-B8CEE4685E39} + mod_sms + Win32Proj + + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + + + + + + + + false + + + + + + + X64 + + + + + + + false + + + MachineX64 + + + + + + + + + false + + + + + + + X64 + + + + + + + false + + + MachineX64 + + + + + + + + {202d7a4e-760d-4d0e-afa1-d7459ced30ff} + false + + + + + + diff --git a/src/mod/applications/mod_sms/mod_sms.c b/src/mod/applications/mod_sms/mod_sms.c new file mode 100644 index 0000000000..096ee6be36 --- /dev/null +++ b/src/mod/applications/mod_sms/mod_sms.c @@ -0,0 +1,510 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2011, Anthony Minessale II + * + * 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 FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Anthony Minessale II + * + * mod_sms.c -- Abstract SMS + * + */ +#include +#define SMS_CHAT_PROTO "GLOBAL_SMS" +#define MY_EVENT_SEND_MESSAGE "SMS::SEND_MESSAGE" + +/* Prototypes */ +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sms_shutdown); +SWITCH_MODULE_RUNTIME_FUNCTION(mod_sms_runtime); +SWITCH_MODULE_LOAD_FUNCTION(mod_sms_load); +SWITCH_MODULE_DEFINITION(mod_sms, mod_sms_load, mod_sms_shutdown, NULL); + + +static void event_handler(switch_event_t *event) +{ + const char *dest_proto = switch_event_get_header(event, "dest_proto"); + switch_core_chat_send(dest_proto, event); +} + +typedef enum { + BREAK_ON_TRUE, + BREAK_ON_FALSE, + BREAK_ALWAYS, + BREAK_NEVER +} break_t; + + + +static int parse_exten(switch_event_t *event, switch_xml_t xexten, switch_event_t **extension) +{ + switch_xml_t xcond, xaction, xexpression; + char *exten_name = (char *) switch_xml_attr(xexten, "name"); + int proceed = 0; + char *expression_expanded = NULL, *field_expanded = NULL; + switch_regex_t *re = NULL; + const char *to = switch_event_get_header(event, "to"); + + if (!to) { + to = "nobody"; + } + + if (!exten_name) { + exten_name = "_anon_"; + } + + for (xcond = switch_xml_child(xexten, "condition"); xcond; xcond = xcond->next) { + char *field = NULL; + char *do_break_a = NULL; + char *expression = NULL; + const char *field_data = NULL; + int ovector[30]; + switch_bool_t anti_action = SWITCH_TRUE; + break_t do_break_i = BREAK_ON_FALSE; + + int time_match = switch_xml_std_datetime_check(xcond); + + switch_safe_free(field_expanded); + switch_safe_free(expression_expanded); + + if (switch_xml_child(xcond, "condition")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Nested conditions are not allowed!\n"); + proceed = 1; + goto done; + } + + field = (char *) switch_xml_attr(xcond, "field"); + + if ((xexpression = switch_xml_child(xcond, "expression"))) { + expression = switch_str_nil(xexpression->txt); + } else { + expression = (char *) switch_xml_attr_soft(xcond, "expression"); + } + + if ((expression_expanded = switch_event_expand_headers(event, expression)) == expression) { + expression_expanded = NULL; + } else { + expression = expression_expanded; + } + + if ((do_break_a = (char *) switch_xml_attr(xcond, "break"))) { + if (!strcasecmp(do_break_a, "on-true")) { + do_break_i = BREAK_ON_TRUE; + } else if (!strcasecmp(do_break_a, "on-false")) { + do_break_i = BREAK_ON_FALSE; + } else if (!strcasecmp(do_break_a, "always")) { + do_break_i = BREAK_ALWAYS; + } else if (!strcasecmp(do_break_a, "never")) { + do_break_i = BREAK_NEVER; + } else { + do_break_a = NULL; + } + } + + if (time_match == 1) { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, + "Chatplan: %s Date/Time Match (PASS) [%s] break=%s\n", + to, exten_name, do_break_a ? do_break_a : "on-false"); + anti_action = SWITCH_FALSE; + } else if (time_match == 0) { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, + "Chatplan: %s Date/Time Match (FAIL) [%s] break=%s\n", + to, exten_name, do_break_a ? do_break_a : "on-false"); + } + + if (field) { + if (strchr(field, '$')) { + if ((field_expanded = switch_event_expand_headers(event, field)) == field) { + field_expanded = NULL; + field_data = field; + } else { + field_data = field_expanded; + } + } else { + field_data = switch_event_get_header(event, field); + } + if (!field_data) { + field_data = ""; + } + + if ((proceed = switch_regex_perform(field_data, expression, &re, ovector, sizeof(ovector) / sizeof(ovector[0])))) { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, + "Chatplan: %s Regex (PASS) [%s] %s(%s) =~ /%s/ break=%s\n", + to, exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false"); + anti_action = SWITCH_FALSE; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, + "Chatplan: %s Regex (FAIL) [%s] %s(%s) =~ /%s/ break=%s\n", + to, exten_name, field, field_data, expression, do_break_a ? do_break_a : "on-false"); + } + } else if (time_match == -1) { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, + "Chatplan: %s Absolute Condition [%s]\n", to, exten_name); + anti_action = SWITCH_FALSE; + } + + if (anti_action) { + for (xaction = switch_xml_child(xcond, "anti-action"); xaction; xaction = xaction->next) { + const char *application = switch_xml_attr_soft(xaction, "application"); + const char *loop = switch_xml_attr(xaction, "loop"); + const char *data; + const char *inline_ = switch_xml_attr_soft(xaction, "inline"); + int xinline = switch_true(inline_); + int loop_count = 1; + + if (!zstr(xaction->txt)) { + data = xaction->txt; + } else { + data = (char *) switch_xml_attr_soft(xaction, "data"); + } + + if (!*extension) { + if ((switch_event_create(extension, SWITCH_EVENT_CLONE)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); + abort(); + } + } + + if (loop) { + loop_count = atoi(loop); + } + + for (;loop_count > 0; loop_count--) { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, + "Chatplan: %s ANTI-Action %s(%s) %s\n", to, application, data, xinline ? "INLINE" : ""); + + if (xinline) { + switch_core_execute_chat_app(event, application, data); + } else { + switch_event_add_header_string(*extension, SWITCH_STACK_BOTTOM, application, data); + } + } + proceed = 1; + } + } else { + if (field && strchr(expression, '(')) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "DP_MATCH", NULL); + switch_capture_regex(re, proceed, field_data, ovector, "DP_MATCH", switch_regex_set_event_header_callback, event); + } + + 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"); + char *data = NULL; + char *substituted = NULL; + uint32_t len = 0; + char *app_data = NULL; + const char *inline_ = switch_xml_attr_soft(xaction, "inline"); + int xinline = switch_true(inline_); + int loop_count = 1; + + if (!zstr(xaction->txt)) { + data = xaction->txt; + } else { + data = (char *) switch_xml_attr_soft(xaction, "data"); + } + + if (field && strchr(expression, '(')) { + len = (uint32_t) (strlen(data) + strlen(field_data) + 10) * proceed; + if (!(substituted = malloc(len))) { + abort(); + } + memset(substituted, 0, len); + switch_perform_substitution(re, proceed, data, field_data, substituted, len, ovector); + app_data = substituted; + } else { + app_data = data; + } + + if (!*extension) { + if ((switch_event_create(extension, SWITCH_EVENT_CLONE)) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); + abort(); + } + } + + if (loop) { + loop_count = atoi(loop); + } + for (;loop_count > 0; loop_count--) { + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, + "Chatplan: %s Action %s(%s) %s\n", to, application, app_data, xinline ? "INLINE" : ""); + + if (xinline) { + switch_core_execute_chat_app(event, application, app_data); + } else { + switch_event_add_header_string(*extension, SWITCH_STACK_BOTTOM, application, data); + } + } + switch_safe_free(substituted); + } + } + switch_regex_safe_free(re); + + if (((anti_action == SWITCH_FALSE && do_break_i == BREAK_ON_TRUE) || + (anti_action == SWITCH_TRUE && do_break_i == BREAK_ON_FALSE)) || do_break_i == BREAK_ALWAYS) { + break; + } + } + + done: + switch_regex_safe_free(re); + switch_safe_free(field_expanded); + switch_safe_free(expression_expanded); + return proceed; +} + + +static switch_event_t *chatplan_hunt(switch_event_t *event) +{ + switch_event_t *extension = NULL; + switch_xml_t alt_root = NULL, cfg, xml = NULL, xcontext, xexten = NULL; + const char *alt_path; + const char *context; + const char *from; + const char *to; + + if (!(context = switch_event_get_header(event, "context"))) { + context = "default"; + } + + if (!(from = switch_event_get_header(event, "from_user"))) { + from = switch_event_get_header(event, "from"); + } + + if (!(to = switch_event_get_header(event, "to_user"))) { + to = switch_event_get_header(event, "to"); + } + + alt_path = switch_event_get_header(event, "alt_path"); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Processing text message %s->%s in context %s\n", from, to, context); + + /* get our handle to the "chatplan" section of the config */ + + if (!zstr(alt_path)) { + switch_xml_t conf = NULL, tag = NULL; + if (!(alt_root = switch_xml_parse_file_simple(alt_path))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of [%s] failed\n", alt_path); + goto done; + } + + if ((conf = switch_xml_find_child(alt_root, "section", "name", "chatplan")) && (tag = switch_xml_find_child(conf, "chatplan", NULL, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Getting chatplan from alternate path: %s\n", alt_path); + xml = alt_root; + cfg = tag; + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of chatplan failed\n"); + goto done; + } + } else { + if (switch_xml_locate("chatplan", NULL, NULL, NULL, &xml, &cfg, event, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of chatplan failed\n"); + goto done; + } + } + + /* get a handle to the context tag */ + if (!(xcontext = switch_xml_find_child(cfg, "context", "name", context))) { + if (!(xcontext = switch_xml_find_child(cfg, "context", "name", "global"))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Context %s not found\n", context); + goto done; + } + } + + xexten = switch_xml_child(xcontext, "extension"); + + while (xexten) { + int proceed = 0; + const char *cont = switch_xml_attr(xexten, "continue"); + const char *exten_name = switch_xml_attr(xexten, "name"); + + if (!exten_name) { + exten_name = "UNKNOWN"; + } + + switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, SWITCH_LOG_DEBUG, + "Chatplan: %s parsing [%s->%s] continue=%s\n", + to, context, exten_name, cont ? cont : "false"); + + proceed = parse_exten(event, xexten, &extension); + + if (proceed && !switch_true(cont)) { + break; + } + + xexten = xexten->next; + } + + switch_xml_free(xml); + xml = NULL; + + done: + switch_xml_free(xml); + return extension; +} + + +static switch_status_t chat_send(switch_event_t *message_event) + { + switch_status_t status = SWITCH_STATUS_SUCCESS; + switch_event_t *exten; + + if ((exten = chatplan_hunt(message_event))) { + switch_event_header_t *hp; + + for (hp = exten->headers; hp; hp = hp->next) { + status = switch_core_execute_chat_app(message_event, hp->name, hp->value); + if (!SWITCH_READ_ACCEPTABLE(status)) { + break; + } + } + + switch_event_destroy(&exten); + } + + + status = SWITCH_STATUS_BREAK; + + + return status; + +} + +SWITCH_STANDARD_CHAT_APP(stop_function) +{ + switch_set_flag(message, EF_NO_CHAT_EXEC); + return SWITCH_STATUS_FALSE; +} + +SWITCH_STANDARD_CHAT_APP(send_function) +{ + const char *dest_proto = data; + + if (zstr(dest_proto)) { + dest_proto = switch_event_get_header(message, "dest_proto"); + } + + switch_core_chat_send(dest_proto, message); + + return SWITCH_STATUS_SUCCESS; +} + +SWITCH_STANDARD_CHAT_APP(set_function) +{ + char *var, *val; + + if (data) { + var = strdup(data); + if ((val = strchr(var, '='))) { + *val++ = '\0'; + } + + if (zstr(val)) { + switch_event_del_header(message, var); + } else { + switch_event_add_header_string(message, SWITCH_STACK_BOTTOM, var, val); + } + } + + return SWITCH_STATUS_SUCCESS; +} + +SWITCH_STANDARD_CHAT_APP(fire_function) +{ + switch_event_t *fireme; + + switch_event_dup(&fireme, message); + switch_event_fire(&fireme); + + return SWITCH_STATUS_SUCCESS; +} + +SWITCH_STANDARD_CHAT_APP(reply_function) +{ + switch_event_t *reply; + const char *proto = switch_event_get_header(message, "proto"); + + if (proto) { + switch_ivr_create_message_reply(&reply, message, SMS_CHAT_PROTO); + + if (!zstr(data)) { + switch_event_add_body(reply, data); + } + + switch_core_chat_deliver(proto, &reply); + + return SWITCH_STATUS_SUCCESS; + } + + return SWITCH_STATUS_SUCCESS; +} + +/* Macro expands to: switch_status_t mod_sms_load(switch_loadable_module_interface_t **module_interface, switch_memory_pool_t *pool) */ +SWITCH_MODULE_LOAD_FUNCTION(mod_sms_load) +{ + switch_chat_interface_t *chat_interface; + switch_chat_application_interface_t *chat_app_interface; + + + if (switch_event_bind(modname, SWITCH_EVENT_CUSTOM, MY_EVENT_SEND_MESSAGE, event_handler, NULL) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n"); + return SWITCH_STATUS_GENERR; + } + + /* connect my internal structure to the blank pointer passed to me */ + *module_interface = switch_loadable_module_create_module_interface(pool, modname); + + SWITCH_ADD_CHAT(chat_interface, SMS_CHAT_PROTO, chat_send); + + SWITCH_ADD_CHAT_APP(chat_app_interface, "reply", "reply to a message", "reply to a message", reply_function, "", SCAF_NONE); + SWITCH_ADD_CHAT_APP(chat_app_interface, "stop", "stop execution", "stop execution", stop_function, "", SCAF_NONE); + SWITCH_ADD_CHAT_APP(chat_app_interface, "set", "set a variable", "set a variable", set_function, "", SCAF_NONE); + SWITCH_ADD_CHAT_APP(chat_app_interface, "send", "send the message as-is", "send the message as-is", send_function, "", SCAF_NONE); + SWITCH_ADD_CHAT_APP(chat_app_interface, "fire", "fire the message", "fire the message", fire_function, "", SCAF_NONE); + + /* indicate that the module should continue to be loaded */ + return SWITCH_STATUS_SUCCESS; +} + +/* + Called when the system shuts down + Macro expands to: switch_status_t mod_sms_shutdown() */ +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_sms_shutdown) +{ + switch_event_unbind_callback(event_handler); + + 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_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index 527a2a0fa2..1a7dd221ef 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -2929,7 +2929,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi } switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to", to); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", subject); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "normal"); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "text/plain"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", hint); if (msg) { diff --git a/src/mod/endpoints/mod_sofia/sofia_presence.c b/src/mod/endpoints/mod_sofia/sofia_presence.c index db7aa94a3a..06b1ce496e 100644 --- a/src/mod/endpoints/mod_sofia/sofia_presence.c +++ b/src/mod/endpoints/mod_sofia/sofia_presence.c @@ -99,7 +99,10 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event) //const char *subject; const char *body; const char *type; - const char *hint; + const char *from_full; + char header[256] = ""; + char *route_uri = NULL; + const char *network_ip = NULL, *network_port = NULL; proto = switch_event_get_header(message_event, "proto"); from = switch_event_get_header(message_event, "from"); @@ -107,8 +110,10 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event) //subject = switch_event_get_header(message_event, "subject"); body = switch_event_get_body(message_event); type = switch_event_get_header(message_event, "type"); - hint = switch_event_get_header(message_event, "hint"); - + from_full = switch_event_get_header(message_event, "from_full"); + + network_ip = switch_event_get_header(message_event, "to_sip_ip"); + network_port = switch_event_get_header(message_event, "to_sip_port"); if (!to) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing To: header.\n"); @@ -130,6 +135,10 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event) user = prof; prof = NULL; } + + if (!prof) { + prof = switch_event_get_header(message_event, "sip_profile"); + } if (!strncasecmp(user, "sip:", 4)) { to_uri = user; @@ -141,8 +150,9 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event) } else { host++; } - if (!prof) + if (!prof) { prof = host; + } } if (!prof || !(profile = sofia_glue_find_profile(prof))) { @@ -159,24 +169,34 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event) } } + if (to_uri) { switch_console_push_match(&list, to_uri); } else if (!(list = sofia_reg_find_reg_url_multi(profile, user, host))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Can't find registered user %s@%s\n", user, host); - goto end; + sofia_profile_t *test; + + if ((test = sofia_glue_find_profile(host))) { + sofia_glue_release_profile(test); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Not sending to local box for %s@%s\n", user, host); + /* our box let's not send it */ + } else { + char *tmp; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Can't find registered user %s@%s\n", user, host); + tmp = switch_mprintf("sip:%s@%s", user, host); + switch_console_push_match(&list, tmp); + free(tmp); + } + } if (!strcasecmp(proto, SOFIA_CHAT_PROTO)) { - from = hint; + from = from_full; } else { char *fp, *p = NULL; fp = strdup(from); + switch_assert(fp); - if (!fp) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Memory Error!\n"); - goto end; - } if ((p = strchr(fp, '@'))) { *p++ = '\0'; @@ -189,12 +209,23 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event) } } - ffrom = switch_mprintf("\"%s\" ", fp, proto, fp, p); + if (switch_stristr("global", proto)) { + ffrom = switch_mprintf("\"%s\" ", fp, fp, p); + } else { + ffrom = switch_mprintf("\"%s\" ", fp, proto, fp, p); + } from = ffrom; switch_safe_free(fp); } + if (!list) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, + "Chat proto [%s]\nfrom [%s]\nto [%s]\n%s\nNobody to send to: Profile %s\n", proto, from, to, + body ? body : "[no body]", prof ? prof : "NULL"); + goto end; + } + for (m = list->head; m; m = m->next) { if (!(dst = sofia_glue_get_destination(m->val))) { @@ -250,21 +281,34 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event) /* if this cries, add contact here too, change the 1 to 0 and omit the safe_free */ + //printf("DEBUG To: [%s] From: [%s] Contact: [%s] RURI [%s] ip [%s] port [%s]\n", to, from, contact, dst->route_uri, network_ip, network_port); + + //DUMP_EVENT(message_event); + + if (zstr(dst->route_uri) && !zstr(user) && !zstr(network_ip) && (zstr(host) || strcmp(network_ip, host))) { + route_uri = switch_mprintf("sip:%s@%s:%s", user, network_ip, network_port); + } + msg_nh = nua_handle(profile->nua, NULL, - TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), - TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), - SIPTAG_FROM_STR(from), - TAG_IF(contact, NUTAG_URL(contact)), - SIPTAG_TO_STR(dup_dest), - SIPTAG_CONTACT_STR(contact_str), TAG_END()); nua_handle_bind(msg_nh, &mod_sofia_globals.destroy_private); + switch_snprintf(header, sizeof(header), "X-FS-Sending-Message: %s", switch_core_get_uuid()); + nua_message(msg_nh, + TAG_IF(dst->route_uri, NUTAG_PROXY(dst->route_uri)), + TAG_IF(route_uri, NUTAG_PROXY(route_uri)), + TAG_IF(dst->route, SIPTAG_ROUTE_STR(dst->route)), + SIPTAG_FROM_STR(from), + TAG_IF(contact, NUTAG_URL(contact)), + SIPTAG_TO_STR(dup_dest), + SIPTAG_CONTACT_STR(contact_str), + TAG_IF(user_via, SIPTAG_VIA_STR(user_via)), SIPTAG_CONTENT_TYPE_STR(ct), SIPTAG_PAYLOAD_STR(body), + SIPTAG_HEADER_STR(header), TAG_END()); sofia_glue_free_destination(dst); @@ -277,6 +321,7 @@ switch_status_t sofia_presence_chat_send(switch_event_t *message_event) end: switch_safe_free(contact); + switch_safe_free(route_uri); switch_safe_free(ffrom); switch_safe_free(dup); @@ -2873,13 +2918,25 @@ void sofia_presence_handle_sip_i_message(int status, const char *to_host = NULL; sip_payload_t *payload = sip->sip_payload; char *msg = NULL; + const char *us; + char network_ip[80]; + int network_port = 0; + + if ((us = sofia_glue_get_unknown_header(sip, "X-FS-Sending-Message")) && !strcmp(us, switch_core_get_uuid())) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Not sending message to ourselves!\n"); + goto end; + } if (sip->sip_content_type && sip->sip_content_type->c_subtype) { if (strstr(sip->sip_content_type->c_subtype, "composing")) { - return; + goto end; } } + + sofia_glue_get_addr(de->data->e_msg, network_ip, sizeof(network_ip), &network_port); + + if (from) { from_user = from->a_url->url_user; from_host = from->a_url->url_host; @@ -2891,7 +2948,7 @@ void sofia_presence_handle_sip_i_message(int status, } if (!to_user) { - return; + goto end; } if (payload) { @@ -2924,7 +2981,7 @@ void sofia_presence_handle_sip_i_message(int status, to_addr = switch_mprintf("%s@%s", to_user, to_host); } - from_addr = switch_mprintf("%s/%s@%s", profile->name, from_user, from_host); + from_addr = switch_mprintf("%s@%s", from_user, from_host); if (sofia_test_pflag(profile, PFLAG_IN_DIALOG_CHAT)) { sofia_presence_set_hash_key(hash_key, sizeof(hash_key), sip); @@ -2936,10 +2993,22 @@ void sofia_presence_handle_sip_i_message(int status, switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", from_addr); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_user", from_user); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_host", from_host); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_user", to_user); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_host", to_host); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_sip_ip", network_ip); + switch_event_add_header(event, SWITCH_STACK_BOTTOM, "from_sip_port", "%d", network_port); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to", to_addr); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "SIMPLE MESSAGE"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "normal"); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", full_from); + + + if (sip->sip_content_type && sip->sip_content_type->c_subtype) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", sip->sip_content_type->c_type); + } else { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "type", "text/plain"); + } + + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_full", full_from); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "sip_profile", profile->name); if (msg) { switch_event_add_body(event, "%s", msg); @@ -2952,7 +3021,6 @@ void sofia_presence_handle_sip_i_message(int status, switch_core_session_queue_event(tech_pvt->session, &event); } else { switch_core_chat_send(proto, event); - switch_core_chat_send("GLOBAL", event); switch_event_destroy(&event); } @@ -2964,6 +3032,11 @@ void sofia_presence_handle_sip_i_message(int status, } } } + + end: + + nua_respond(nh, SIP_200_OK, NUTAG_WITH_THIS_MSG(de->data->e_msg), TAG_END()); + } void sofia_presence_set_chat_hash(private_object_t *tech_pvt, sip_t const *sip) diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index c591e9393d..ad7438e487 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1397,7 +1397,7 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand } /* Log line added to support Fail2Ban */ if (sofia_test_pflag(profile, PFLAG_LOG_AUTH_FAIL)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "SIP auth challenge (%s) on sofia profile '%s' " + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG10, "SIP auth challenge (%s) on sofia profile '%s' " "for [%s@%s] from ip %s\n", (regtype == REG_INVITE) ? "INVITE" : "REGISTER", profile->name, to_user, to_host, network_ip); } diff --git a/src/mod/languages/mod_java/src/org/freeswitch/swig/Event.java b/src/mod/languages/mod_java/src/org/freeswitch/swig/Event.java index c1c9ba17e7..d1adc09dc6 100644 --- a/src/mod/languages/mod_java/src/org/freeswitch/swig/Event.java +++ b/src/mod/languages/mod_java/src/org/freeswitch/swig/Event.java @@ -66,6 +66,14 @@ public class Event { this(freeswitchJNI.new_Event__SWIG_1(SWIGTYPE_p_switch_event_t.getCPtr(wrap_me), free_me), true); } + public int chat_execute(String app, String data) { + return freeswitchJNI.Event_chat_execute(swigCPtr, this, app, data); + } + + public int chat_send(String dest_proto) { + return freeswitchJNI.Event_chat_send(swigCPtr, this, dest_proto); + } + public String serialize(String format) { return freeswitchJNI.Event_serialize(swigCPtr, this, format); } diff --git a/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java b/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java index 069b7eecf2..fc74914d15 100644 --- a/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java +++ b/src/mod/languages/mod_java/src/org/freeswitch/swig/freeswitchJNI.java @@ -54,6 +54,8 @@ class freeswitchJNI { public final static native long new_Event__SWIG_0(String jarg1, String jarg2); public final static native long new_Event__SWIG_1(long jarg1, int jarg2); public final static native void delete_Event(long jarg1); + public final static native int Event_chat_execute(long jarg1, Event jarg1_, String jarg2, String jarg3); + public final static native int Event_chat_send(long jarg1, Event jarg1_, String jarg2); public final static native String Event_serialize(long jarg1, Event jarg1_, String jarg2); public final static native boolean Event_setPriority(long jarg1, Event jarg1_, long jarg2); public final static native String Event_getHeader(long jarg1, Event jarg1_, String jarg2); diff --git a/src/mod/languages/mod_java/switch_swig_wrap.cpp b/src/mod/languages/mod_java/switch_swig_wrap.cpp index 4b3c9d38d1..5061dc46f6 100644 --- a/src/mod/languages/mod_java/switch_swig_wrap.cpp +++ b/src/mod/languages/mod_java/switch_swig_wrap.cpp @@ -1054,6 +1054,57 @@ SWIGEXPORT void JNICALL Java_org_freeswitch_swig_freeswitchJNI_delete_1Event(JNI } +SWIGEXPORT jint JNICALL Java_org_freeswitch_swig_freeswitchJNI_Event_1chat_1execute(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2, jstring jarg3) { + jint jresult = 0 ; + Event *arg1 = (Event *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) NULL ; + int result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(Event **)&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 = (int)(arg1)->chat_execute((char const *)arg2,(char const *)arg3); + jresult = (jint)result; + if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2); + if (arg3) jenv->ReleaseStringUTFChars(jarg3, (const char *)arg3); + return jresult; +} + + +SWIGEXPORT jint JNICALL Java_org_freeswitch_swig_freeswitchJNI_Event_1chat_1send(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) { + jint jresult = 0 ; + Event *arg1 = (Event *) 0 ; + char *arg2 = (char *) NULL ; + int result; + + (void)jenv; + (void)jcls; + (void)jarg1_; + arg1 = *(Event **)&jarg1; + arg2 = 0; + if (jarg2) { + arg2 = (char *)jenv->GetStringUTFChars(jarg2, 0); + if (!arg2) return 0; + } + result = (int)(arg1)->chat_send((char const *)arg2); + jresult = (jint)result; + if (arg2) jenv->ReleaseStringUTFChars(jarg2, (const char *)arg2); + return jresult; +} + + SWIGEXPORT jstring JNICALL Java_org_freeswitch_swig_freeswitchJNI_Event_1serialize(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jstring jarg2) { jstring jresult = 0 ; Event *arg1 = (Event *) 0 ; diff --git a/src/mod/languages/mod_lua/mod_lua.cpp b/src/mod/languages/mod_lua/mod_lua.cpp index dc01aa9fa9..a165795cb0 100644 --- a/src/mod/languages/mod_lua/mod_lua.cpp +++ b/src/mod/languages/mod_lua/mod_lua.cpp @@ -430,6 +430,24 @@ SWITCH_STANDARD_API(luarun_api_function) return SWITCH_STATUS_SUCCESS; } +SWITCH_STANDARD_CHAT_APP(lua_chat_function) +{ + lua_State *L = lua_init(); + char *dup = NULL; + + if (data) { + dup = strdup(data); + } + + mod_lua_conjure_event(L, message, "message", 1); + lua_parse_and_execute(L, (char *)dup); + lua_uninit(L); + + switch_safe_free(dup); + + return SWITCH_STATUS_SUCCESS; + +} SWITCH_STANDARD_API(lua_api_function) { @@ -591,6 +609,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_lua_load) switch_api_interface_t *api_interface; switch_application_interface_t *app_interface; switch_dialplan_interface_t *dp_interface; + switch_chat_application_interface_t *chat_app_interface; /* connect my internal structure to the blank pointer passed to me */ *module_interface = switch_loadable_module_create_module_interface(pool, modname); @@ -600,6 +619,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_lua_load) SWITCH_ADD_APP(app_interface, "lua", "Launch LUA ivr", "Run a lua ivr on a channel", lua_function, "