diff --git a/conf/directory/default/skinny-example.xml b/conf/directory/default/skinny-example.xml index 2f19710136..357eb72f12 100644 --- a/conf/directory/default/skinny-example.xml +++ b/conf/directory/default/skinny-example.xml @@ -3,6 +3,7 @@ diff --git a/conf/skinny_profiles/internal.xml b/conf/skinny_profiles/internal.xml index e48557b234..5feac1ffbf 100644 --- a/conf/skinny_profiles/internal.xml +++ b/conf/skinny_profiles/internal.xml @@ -13,6 +13,17 @@ + + + + + + + + + + + diff --git a/docs/ChangeLog b/docs/ChangeLog index 0bc629ef60..a2ed493f37 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -15,6 +15,7 @@ freeswitch (1.0.7) build: Fix build with --with-curl (r:e704f021/FSBUILD-285) build: VS 2010 - Change to V4 framework, add SWIG v2.0 files to fix release build exceptions(temp fix till we upgrade all SWIG files) (r:812f4309) build: Windows VS2010 build - remove strange characters (r:ba1546e0/FSBUILD-297) + build: Make bootstrap.sh Bourne shell compatible (r:8dbd62ff/FSBUILD-301) config: move limit.conf to db.conf config: Update VM phrase macros to voice option then action on main, config menus config: Remove 99xx extension numbers to avoid dp conflicts (r:0c9bb174/DP-17) @@ -30,7 +31,7 @@ freeswitch (1.0.7) core: always export 'export_vars' core: add sanity check to launch threads that catch hangup and are not in a thread to make sure they clean up core: Tweak bridge_early_media to support passthrough codecs - core: cleanup C reserved identifer violation (JANITOR-3) + core: cleanup C reserved identifier violation (JANITOR-3) core: add sound_prefix support in uuid_displace (FSCORE-550) core: add 'critical' param on modules.conf to abort on mod load failure from Moc core: add 'direction' chan var @@ -71,6 +72,12 @@ freeswitch (1.0.7) core: Improve RTP timing on playback of files (r:d6d7773c/FSCORE-639) core: Allows bind_meta_app to use chars other than * (r:fd254766/FSCORE-630) core: Fixed core lib won't build for win32 (r:9327c994/FSCORE-646) + core: add last_bridge_to var to keep uuid of last bridged channel and fix race in show calls on hangup of bypass_media channels (r:77e2dccf) + core: Phrase "speak-text" application returns on first key press in phrase file on Windows (r:6d74d7ab/MODAPP-448) + core: pass originate flags into session_request so we can selectivly skip throttling (r:46c6650a) + core: Implemented 'Block Fork' and removed possibility for "-nc -nf" potential issue. (r:f26a6972/FSCORE-652) + core: Add console callback for listing loaded/available modules for load/unload/reload commands (r:d68a1218/FSCORE-662) + core: strip trailing and leading whitespace in api execute args and commands (r:ca481842) lang: Improve French phrase files (FSCONFIG-23) libdingaling: fix race on shutdown causing crash (FSMOD-47) libesl: Fix potential race condition (ESL-36) @@ -88,8 +95,10 @@ freeswitch (1.0.7) libfreetdm: implemented freetdm config nodes and ss7 initial configuration libopenzap: Add CLI tracing libs: Merged OpenZAP and FreeTDM into the FreeSWITCH tree. + libs: Add support for TLS on Windows using openssl (r:1abe3b93/MODSOFIA-92) libsofiasip: Fix random crashes (r:c15ee980/SFSIP-219) libsofiasip: Fix T.38 bug in sofia_glue (r:2843f1ad/MODSOFIA-94) + libsofiasip: VS2010 sofia posix problem (r:46dd24c2/SFSIP-220) 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) @@ -101,6 +110,13 @@ freeswitch (1.0.7) mod_callcenter: Try to fix the ring-all, also add cli auto complete done in previous commit (r:1666783c) mod_callcenter: Add missing odbc db support (Not tested, please someone test this) (r:42436e27) mod_callcenter: More ODBC changes. It is not a global settings value. Cannot be changed in runtime. (r:6980305f) + mod_callcenter: Added value busy_delay_time and reject_delay_time so we can wait if those 2 occur (Un registred phone are considered as busy). Add a ready_time epoch time when we can contact an again again, fix ring-all (good this time I hope). (r:8082aa98) + mod_callcenter: Add tiers rules before jumping to a different level. Also added support for dial-in agent. (r:86c9bed7) + mod_callcenter: Default the level to 0 since the new tier system will wait x second at level 1... just level 0 that will ring agent right away (if set to do so) (r:6558276a) + mod_callcenter: You can now allow caller that have hangup before agent answer to call back and resume their previous position. (r:ab2529d4) + mod_callcenter: correct multiple little things following the recent tiers and join back features (r:9b33bd1c) + mod_callcenter: Add more channel variable and event and fix a mem leak (r:2d3d8c8d) + od_callcenter: Make more sence to bridge the caller to the agent. Before, in the xml_cdr you saw it it like the agent initiated the call to the member (r:0be95658) mod_cidlookup: null xml is bad (r:095815f8) mod_cid_lookup: honor skipcitystate when using whitepages (r:a66654de/FSMOD-53) mod_commands: make break uuid_break and add cascade flag @@ -118,7 +134,11 @@ freeswitch (1.0.7) mod_conference: add conference_member_id variable to all sessions with the member id used by their conference participation (For drk__) (r:49c9bfdb) mod_conference: fix relate nohear (r:f029ce07/MODAPP-428) mod_conference: Fix floor change events not always firing (r:8f1767d3/MODAPP-424) + mod_curl: use method=post when post requested (r:c6a4ddd0/FSMOD-69) mod_dialplan_xml: Add in the INFO log the caller id number when processing a request (Currenly only show the caller name) (r:e1df5e13) + mod_dingaling: make mod_dingaling compat with google's new free phonecalls thing (r:ba0a2a32) + mod_dingaling: make dingaling work with google voice inbound too (r:4ee68141) + mod_dingaling: Fix crash when testing the new gv-dingaling with around 24 concurrent calls (r:73e1ec5e/FSCORE-667) mod_db: fix stack corruption (MODAPP-407) mod_dptools: add eavesdrop_enable_dtmf chan var (r:596c0012) mod_dptools: Make park app not send 183 session progress (r:76932995/FSCORE-567) @@ -126,7 +146,9 @@ freeswitch (1.0.7) mod_erlang_event: Make XML fetch reply ACKs distinguishable, update freeswitch.erl (r:9d44ed04) mod_erlang_event: Add 3 new commands; session_event, session_noevents, session_nixevent (r:698fa045) mod_erlang_event: generate long node names the same as erlang does (r:9ad509c2) + mod_erlang_event: Improve some logging to include UUIDs (r:c0d51b83) 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_fifo: allow multiple dtmf to exit fifo, set fifo_caller_exit_key to specify which (MODAPP-420) mod_fifo: cancel outbound call if customer hangs up (r:cadb4d94) mod_fifo: add taking_calls param to fifo member add and config file (r:821488bf) @@ -159,6 +181,8 @@ freeswitch (1.0.7) mod_freetdm: fix fxs dialtone - should be stopped on first digit (r:f822180f) mod_freetdm: add bearer capability and layer1 pass-thru for boost (r:07b81760) mod_freetdm: OPENZAP-107 - Patched by Jeff Lenk (r:aa075136/OPENZAP-107) + mod_freetdm: allocate channels in their own memory page when debugging (r:fcd8df0a) + mod_freetdm: lock the channel when placing call (r:705dd237) mod_gsmopen: copy from branch mod_hash: free all hashtables on shutdown (r:e76d7d92) mod_hash: remove unneeded initializer (r:10d468a6) @@ -179,6 +203,7 @@ freeswitch (1.0.7) mod_h323: add missing conf prameter (r:0b353d7a) mod_h323: Add mod_h323 to windows (r:015bcaf6/MODENDP-301) mod_h323: move PTrace level set to FSH323EndPoint::Initialise. partially apply patch from from Peter Olsson, Remove UnLock() when TryLock() failed and DEBUG_RTP_PACKETS directiv e. (r:7b5803f7) + mod_h323: set network_addr of caller profile to signaling ip address. (requested by Steven Ayre) (r:072bf5ad) mod_java: fix eventConsumer issue and add flush() method (r:7fd3aff6) mod_java: Allow user defined java methods to be called at startup and shutdown of JVM (r:1339e218/MODLANG-117) mod_json_cdr: Fix segfault in mod_json_cdr.c (r:f347698a/MODEVENT-66) @@ -210,7 +235,9 @@ freeswitch (1.0.7) mod_sangoma_codec: rename load/noload to register/noregister mod_sangoma_codec: silence suppression (r:73d9d56f) mod_say_es: fix grammar when saying dates and time (r:6bed19b2/MODAPP-429) + mod_say_ru: Fix saying time with +1 hour of current time (r:68d74c31/MODAPP-444) mod_say_zh: Number reading should now be OK for the whole range of integers for Cantonese and Mandarin + 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) mod_skinny: rewrite of the skinny state machine (r:8cc89ab0) @@ -225,8 +252,16 @@ freeswitch (1.0.7) mod_skinny: ib_calls stats (r:165140e0) mod_skinny: blind transfer MODSKINNY-10 (r:53f75e9c/MODSKINNY-10) mod_skinny: ring tone on dialing side (r:0a04ecb8) + mod_skinny: stop media on early media hangup (ring-out) (r:ce352bcc) + mod_skinny: add windows x64 build support for mod_skinny (r:3e205683) + mod_skinny: avoid "-ERR no reply" when using API commands from CLI (r:690ae1b3) + mod_skinny: allow configuration of softkeys via xml (r:f5a6831f) + mod_skinny: allow skinny-default-soft-key-set-set per device (r:07c3c94d) + mod_skinny: Rename skinny-default-soft-key-set-set to skinny-soft-key-set-set (r:ba3a6ad6) mod_skypopen: making XEvents to works when EARLYMEDIA, and correctly manage threads death mod_skypopen: now answer a call only when directed to do it (before was trying to answer any incoming call). Lot of changes to a messy part, so maybe some problem will come out... (r:45c6c4d3) + mod_skypopen: ignore early media sent by channels to be bridged before our channel is answered (r:ef14b78a) + mod_sndfile: Add support for .alaw and .ulaw to mod_sndfile (r:facf09b8/MODFORM-41) mod_sofia: Send SIP MESSAGE to unregistered users by prefixing sip: to user@domain mod_sofia: fix callee being updated with callee information mod_sofia: set appearance-index in update statement for SLA @@ -258,6 +293,16 @@ freeswitch (1.0.7) mod_sofia: Fix segfault (r:72be253d/MODSOFIA-83) mod_sofia: Add openssl build support to windows - no external build support needed (step 1 - not hooked up yet) vs2008 pro+ only (r:b0de3585/MODSOFIA-92) mod_sofia: REFER: to-tag and from-tag should be set other way around when other (bridged) channel is incoming. (r:92d324d3/MODSOFIA-91) + mod_sofia: fix 302 to hangup in the two cases where switch_ivr_transfer is used and not in the case when it should carry on and follow the redirect (r:00b51403) + mod_sofia: Remove OPENSSL_USE_APPLINK - not needed (r:437c7805/MODSOFIA-92) + mod_sofia: Send Instant Messages To All Endpoints Registered to Targeted Extension (r:96b790fa/BOUNTY-20) + mod_sofia: increase sps during recovery (r:f1aead31) + mod_sofia: Forward unsolicited MWI nofity (r:5481d9a9/MODSOFIA-86) + mod_sofia: Add a quick fix for basic Polycom presence support. A more sane solution need to be implemented (r:a55b9d07) + mod_sofia: Unify gateway printing between 'sofia xmlstatus gateway' and 'sofia xmlstatus gateway ' (r:37c22467) + mod_sofia: Fix memleak and mwi event not generated on first register (r:04b9b3e2) + mod_sofia: when getting presence with no payload consider it an extension to the expires time in the dialog (r:70331e88) + mod_sofia: don't put blank 'version' attr in dialog-info packets (r:749dc864) 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) @@ -276,6 +321,7 @@ freeswitch (1.0.7) mod_voicemail: add 'vm-enabled' param (default true) mod_voicemail: fix vm msg being deleted when pressing key to forward to email (MODAPP-403) mod_voicemail: make voicemails use the uuid of the channel who recorded it when applicable (r:98a5a30a) + mod_voicemail: user unable to play or delete voicemail via web API (r:b5205c0b/MODAPP-447) 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) diff --git a/libs/freetdm/msvc/freetdm.2008.vcproj b/libs/freetdm/msvc/freetdm.2008.vcproj index 851017e9a8..c72891e525 100644 --- a/libs/freetdm/msvc/freetdm.2008.vcproj +++ b/libs/freetdm/msvc/freetdm.2008.vcproj @@ -338,6 +338,10 @@ RelativePath="..\src\include\private\ftdm_buffer.h" > + + @@ -416,6 +420,10 @@ RelativePath="..\src\ftdm_buffer.c" > + + diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index d8b3c7d40d..be99f94aff 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -259,7 +259,10 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start chan->physical_chan_id = x; chan->rate = 8000; - if (type == FTDM_CHAN_TYPE_FXS || type == FTDM_CHAN_TYPE_FXO || type == FTDM_CHAN_TYPE_B) { + if (type == FTDM_CHAN_TYPE_FXS + || type == FTDM_CHAN_TYPE_FXO + || type == FTDM_CHAN_TYPE_CAS + || type == FTDM_CHAN_TYPE_B) { int err; dtmf = "software"; diff --git a/libs/libdingaling/src/libdingaling.c b/libs/libdingaling/src/libdingaling.c index ef6e7447a1..11a9a8a5b8 100644 --- a/libs/libdingaling/src/libdingaling.c +++ b/libs/libdingaling/src/libdingaling.c @@ -1974,10 +1974,19 @@ unsigned int ldl_session_terminate(ldl_session_t *session) { iks *iq, *sess; unsigned int id; + apr_hash_t *hash = session->handle->sessions; new_session_iq(session, &iq, &sess, &id, "terminate"); schedule_packet(session->handle, id, iq, LDL_RETRY); + if (session->id) { + apr_hash_set(hash, session->id, APR_HASH_KEY_STRING, NULL); + } + + if (session->them) { + apr_hash_set(hash, session->them, APR_HASH_KEY_STRING, NULL); + } + return id; } @@ -2471,6 +2480,11 @@ int ldl_handle_running(ldl_handle_t *handle) } +void ldl_session_set_gateway(ldl_session_t *session) +{ + ldl_set_flag(session, LDL_FLAG_GATEWAY); +} + int ldl_session_gateway(ldl_session_t *session) { return ldl_test_flag(session, LDL_FLAG_GATEWAY) ? 1 : 0; diff --git a/libs/libdingaling/src/libdingaling.h b/libs/libdingaling/src/libdingaling.h index d78643810c..c32b9363d9 100644 --- a/libs/libdingaling/src/libdingaling.h +++ b/libs/libdingaling/src/libdingaling.h @@ -593,6 +593,7 @@ ldl_status ldl_handle_init(ldl_handle_t **handle, void ldl_handle_run(ldl_handle_t *handle); int ldl_session_gateway(ldl_session_t *handle); +void ldl_session_set_gateway(ldl_session_t *session); /*! \brief Stop a libDingaLing handle diff --git a/src/mod/applications/mod_callcenter/mod_callcenter.c b/src/mod/applications/mod_callcenter/mod_callcenter.c index 0c4241c5f3..e56309d005 100644 --- a/src/mod/applications/mod_callcenter/mod_callcenter.c +++ b/src/mod/applications/mod_callcenter/mod_callcenter.c @@ -1307,8 +1307,11 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa } if (!strcasecmp(h->agent_type, CC_AGENT_TYPE_CALLBACK)) { switch_event_create(&ovars, SWITCH_EVENT_REQUEST_PARAMS); + switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_queue", "%s", h->queue); switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_uuid", "%s", h->member_uuid); switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_member_pre_answer_uuid", "%s", h->member_uuid); + switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent", "%s", h->agent_name); + switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "cc_agent_type", "%s", h->agent_type); switch_event_add_header(ovars, SWITCH_STACK_BOTTOM, "ignore_early_media", "true"); t_agent_called = switch_epoch_time_now(NULL); @@ -1323,6 +1326,12 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa switch_channel_t *agent_channel = switch_core_session_get_channel(agent_session); switch_event_t *event; const char *cc_warning_tone = switch_channel_get_variable(agent_channel, "cc_warning_tone"); + + switch_channel_set_variable(agent_channel, "cc_queue", h->queue); + switch_channel_set_variable(agent_channel, "cc_agent", h->agent_name); + switch_channel_set_variable(agent_channel, "cc_agent_type", h->agent_type); + switch_channel_set_variable(agent_channel, "cc_member_uuid", h->member_uuid); + /* Playback this to the agent */ if (cc_warning_tone && switch_event_create(&event, SWITCH_EVENT_COMMAND) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "call-command", "execute"); @@ -1417,7 +1426,7 @@ static void *SWITCH_THREAD_FUNC outbound_agent_thread_run(switch_thread_t *threa switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Agent %s answered \"%s\" (%s) from queue %s%s\n", h->agent_name, h->member_caller_name, h->member_caller_number, h->queue, (h->record_template?" (Recorded)":"")); - switch_ivr_uuid_bridge(switch_core_session_get_uuid(agent_session), h->member_uuid); + switch_ivr_uuid_bridge(h->member_uuid, switch_core_session_get_uuid(agent_session)); /* Wait until the member hangup or the agent hangup. This will quit also if the agent transfer the call */ while(switch_channel_up(member_channel) && switch_channel_up(agent_channel) && globals.running) { @@ -1772,7 +1781,7 @@ static int members_callback(void *pArg, int argc, char **argv, char **columnName switch_safe_free(sql); } /* Skip this member */ - return 0; + goto end; } memset(&cbt, 0, sizeof(cbt)); cbt.tier = 0; diff --git a/src/mod/endpoints/mod_dingaling/mod_dingaling.c b/src/mod/endpoints/mod_dingaling/mod_dingaling.c index 69ce125d0f..7558e1b1b8 100644 --- a/src/mod/endpoints/mod_dingaling/mod_dingaling.c +++ b/src/mod/endpoints/mod_dingaling/mod_dingaling.c @@ -1002,7 +1002,7 @@ static int do_candidates(struct private_object *tech_pvt, int force) switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(tech_pvt->session), SWITCH_LOG_DEBUG, "Send Candidate %s:%d [%s]\n", cand[0].address, cand[0].port, cand[0].username); - if (ldl_session_gateway(tech_pvt->dlsession)) { + if (ldl_session_gateway(tech_pvt->dlsession) && switch_test_flag(tech_pvt, TFLAG_OUTBOUND)) { tech_pvt->cand_id = ldl_session_transport(tech_pvt->dlsession, cand, 1); } else { tech_pvt->cand_id = ldl_session_candidates(tech_pvt->dlsession, cand, 1); @@ -1247,7 +1247,8 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session) tech_pvt->rtp_session = NULL; } - if (globals.auto_nat && tech_pvt->profile->local_network && !switch_check_network_list_ip(tech_pvt->remote_ip, tech_pvt->profile->local_network)) { + if (globals.auto_nat && tech_pvt->profile->local_network && tech_pvt->remote_ip && tech_pvt->profile->local_network && + !switch_check_network_list_ip(tech_pvt->remote_ip, tech_pvt->profile->local_network)) { switch_nat_del_mapping((switch_port_t) tech_pvt->local_port, SWITCH_NAT_UDP); } @@ -1259,6 +1260,10 @@ static switch_status_t channel_on_destroy(switch_core_session_t *session) switch_core_codec_destroy(&tech_pvt->write_codec); } + if (tech_pvt->dlsession) { + ldl_session_destroy(&tech_pvt->dlsession); + } + switch_thread_rwlock_unlock(tech_pvt->profile->rwlock); if (tech_pvt->profile->purge) { @@ -1296,13 +1301,12 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session) if ((tech_pvt->profile->user_flags & LDL_FLAG_COMPONENT) && is_special(tech_pvt->them)) { ldl_handle_send_presence(tech_pvt->profile->handle, tech_pvt->them, tech_pvt->us, NULL, NULL, "Click To Call", tech_pvt->profile->avatar); } - if (tech_pvt->dlsession) { - if (!switch_test_flag(tech_pvt, TFLAG_TERM)) { - ldl_session_terminate(tech_pvt->dlsession); - switch_set_flag_locked(tech_pvt, TFLAG_TERM); - } - ldl_session_destroy(&tech_pvt->dlsession); + + if (!switch_test_flag(tech_pvt, TFLAG_TERM) && tech_pvt->dlsession) { + ldl_session_terminate(tech_pvt->dlsession); + switch_set_flag_locked(tech_pvt, TFLAG_TERM); } + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel)); @@ -1324,15 +1328,6 @@ static switch_status_t channel_kill_channel(switch_core_session_t *session, int switch_clear_flag_locked(tech_pvt, TFLAG_VOICE); switch_set_flag_locked(tech_pvt, TFLAG_BYE); - if (tech_pvt->dlsession) { - if (!switch_test_flag(tech_pvt, TFLAG_TERM)) { - ldl_session_terminate(tech_pvt->dlsession); - switch_set_flag_locked(tech_pvt, TFLAG_TERM); - } - ldl_session_destroy(&tech_pvt->dlsession); - - } - if (switch_rtp_ready(tech_pvt->rtp_session)) { switch_rtp_kill_socket(tech_pvt->rtp_session); } @@ -2980,6 +2975,8 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi tech_pvt->flags |= profile->flags; channel = switch_core_session_get_channel(session); switch_core_session_set_private(session, tech_pvt); + tech_pvt->dlsession = dlsession; + tech_pvt->session = session; tech_pvt->codec_index = -1; tech_pvt->profile = profile; @@ -3025,6 +3022,24 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi cid_num = tech_pvt->recip; } + + if (switch_stristr("voice.google.com", from)) { + char *id = switch_core_session_strdup(session, from); + char *p; + + if ((p = strchr(id, '@'))) { + *p++ = '\0'; + cid_name = "Google Voice"; + cid_num = id; + } + + ldl_session_set_gateway(dlsession); + + do_candidates(tech_pvt, 1); + } + + + /* context of "_auto_" means set it to the domain */ if (profile->context && !strcmp(profile->context, "_auto_")) { context = profile->name; @@ -3047,7 +3062,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi switch_safe_free(tmp); } - + if (!tech_pvt->caller_profile) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Creating an identity for %s %s <%s> %s\n", ldl_session_get_id(dlsession), cid_name, cid_num, exten); @@ -3079,7 +3094,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi } switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Creating a session for %s\n", ldl_session_get_id(dlsession)); ldl_session_set_private(dlsession, session); - tech_pvt->dlsession = dlsession; + switch_channel_set_name(channel, "DingaLing/new"); switch_channel_set_state(channel, CS_INIT); if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) { @@ -3230,6 +3245,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi } } } + } break; @@ -3259,7 +3275,15 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi if (profile->acl_count) { for (x = 0; x < len; x++) { uint32_t y = 0; + + if (strcasecmp(candidates[x].protocol, "udp")) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "candidate %s:%d has an unsupported protocol!\n", + candidates[x].address, candidates[x].port); + continue; + } + for (y = 0; y < profile->acl_count; y++) { + if (switch_check_network_list_ip(candidates[x].address, profile->acl[y])) { choice = x; ok = 1; @@ -3268,7 +3292,7 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi if (ok) { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "candidate %s:%d PASS ACL %s\n", candidates[x].address, candidates[x].port, profile->acl[y]); - break; + goto end_candidates; } else { switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "candidate %s:%d FAIL ACL %s\n", candidates[x].address, candidates[x].port, profile->acl[y]); @@ -3311,6 +3335,8 @@ static ldl_status handle_signalling(ldl_handle_t *handle, ldl_session_t *dlsessi } } + end_candidates: + if (ok) { ldl_payload_t payloads[5]; diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.c b/src/mod/endpoints/mod_skinny/mod_skinny.c index cbeae6cf5a..165815078b 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.c +++ b/src/mod/endpoints/mod_skinny/mod_skinny.c @@ -1233,7 +1233,6 @@ static void walk_listeners(skinny_listener_callback_func_t callback, void *pvt) switch_hash_index_t *hi; void *val; skinny_profile_t *profile; - listener_t *l; /* walk listeners */ switch_mutex_lock(globals.mutex); @@ -1241,11 +1240,7 @@ static void walk_listeners(skinny_listener_callback_func_t callback, void *pvt) switch_hash_this(hi, NULL, NULL, &val); profile = (skinny_profile_t *) val; - switch_mutex_lock(profile->listener_mutex); - for (l = profile->listeners; l; l = l->next) { - callback(l, pvt); - } - switch_mutex_unlock(profile->listener_mutex); + profile_walk_listeners(profile, callback, pvt); } switch_mutex_unlock(globals.mutex); } @@ -1509,6 +1504,7 @@ static void *SWITCH_THREAD_FUNC skinny_profile_run(switch_thread_t *thread, void new_socket: while(globals.running) { + switch_clear_flag_locked(profile, PFLAG_RESPAWN); rv = switch_sockaddr_info_get(&sa, profile->ip, SWITCH_INET, profile->port, 0, tmp_pool); if (rv) goto fail; @@ -1546,8 +1542,10 @@ new_socket: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting Down\n"); goto end; } else if (switch_test_flag(profile, PFLAG_RESPAWN)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Creating a new socket\n"); - switch_clear_flag_locked(profile, PFLAG_RESPAWN); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Respawn in progress. Waiting for socket to close.\n"); + while (profile->sock) { + switch_cond_next(); + } goto new_socket; } else { /* I wish we could use strerror_r here but its not defined everywhere =/ */ @@ -1619,6 +1617,18 @@ switch_endpoint_interface_t *skinny_get_endpoint_interface() return skinny_endpoint_interface; } +switch_status_t skinny_profile_respawn(skinny_profile_t *profile, int force) +{ + if (force || switch_test_flag(profile, PFLAG_SHOULD_RESPAWN)) { + switch_clear_flag_locked(profile, PFLAG_SHOULD_RESPAWN); + switch_set_flag_locked(profile, PFLAG_RESPAWN); + switch_clear_flag_locked(profile, PFLAG_LISTENER_READY); + profile_walk_listeners(profile, kill_listener, NULL); + close_socket(&profile->sock, profile); + } + return SWITCH_STATUS_SUCCESS; +} + switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, const char *val) { if (!var) @@ -1633,9 +1643,15 @@ switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, c if (!strcasecmp(var, "domain")) { profile->domain = switch_core_strdup(profile->pool, val); } else if (!strcasecmp(var, "ip")) { - profile->ip = switch_core_strdup(profile->pool, val); + if (!profile->ip || strcmp(val, profile->ip)) { + profile->ip = switch_core_strdup(profile->pool, val); + switch_set_flag_locked(profile, PFLAG_SHOULD_RESPAWN); + } } else if (!strcasecmp(var, "port")) { - profile->port = atoi(val); + if (atoi(val) != profile->port) { + profile->port = atoi(val); + switch_set_flag_locked(profile, PFLAG_SHOULD_RESPAWN); + } } else if (!strcasecmp(var, "patterns-dialplan")) { profile->patterns_dialplan = switch_core_strdup(profile->pool, val); } else if (!strcasecmp(var, "patterns-context")) { @@ -1669,15 +1685,21 @@ switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, c } else { return SWITCH_STATUS_FALSE; } - if (profile->sock && (!strcasecmp(var, "ip") || !strcasecmp(var, "port"))) { - switch_set_flag_locked(profile, PFLAG_RESPAWN); - switch_clear_flag_locked(profile, PFLAG_LISTENER_READY); - close_socket(&profile->sock, profile); - } return SWITCH_STATUS_SUCCESS; } +void profile_walk_listeners(skinny_profile_t *profile, skinny_listener_callback_func_t callback, void *pvt) +{ + listener_t *l; + + switch_mutex_lock(profile->listener_mutex); + for (l = profile->listeners; l; l = l->next) { + callback(l, pvt); + } + switch_mutex_unlock(profile->listener_mutex); +} + static switch_status_t load_skinny_config(void) { char *cf = "skinny.conf"; @@ -1692,8 +1714,7 @@ static switch_status_t load_skinny_config(void) if ((xprofiles = switch_xml_child(xcfg, "profiles"))) { for (xprofile = switch_xml_child(xprofiles, "profile"); xprofile; xprofile = xprofile->next) { char *profile_name = (char *) switch_xml_attr_soft(xprofile, "name"); - switch_xml_t xsettings; - switch_xml_t xdevice_types; + switch_xml_t xsettings, xdevice_types, xsoft_key_set_sets; if (zstr(profile_name)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, " is missing name attribute\n"); @@ -1749,6 +1770,96 @@ static switch_status_t load_skinny_config(void) profile->port = 2000; } + /* Soft Key Set Sets */ + switch_core_hash_init(&profile->soft_key_set_sets_hash, profile->pool); + if ((xsoft_key_set_sets = switch_xml_child(xprofile, "soft-key-set-sets"))) { + switch_xml_t xsoft_key_set_set; + for (xsoft_key_set_set = switch_xml_child(xsoft_key_set_sets, "soft-key-set-set"); xsoft_key_set_set; xsoft_key_set_set = xsoft_key_set_set->next) { + char *soft_key_set_set_name = (char *) switch_xml_attr_soft(xsoft_key_set_set, "name"); + if (soft_key_set_set_name) { + switch_xml_t xsoft_key_set; + skinny_message_t *message; + message = switch_core_alloc(profile->pool, 12+sizeof(message->data.soft_key_set)); + message->type = SOFT_KEY_SET_RES_MESSAGE; + message->length = 4 + sizeof(message->data.soft_key_set); + message->data.soft_key_set.soft_key_set_offset = 0; + message->data.soft_key_set.soft_key_set_count = 11; + message->data.soft_key_set.total_soft_key_set_count = 11; + for (xsoft_key_set = switch_xml_child(xsoft_key_set_set, "soft-key-set"); xsoft_key_set; xsoft_key_set = xsoft_key_set->next) { + uint32_t soft_key_set_id; + if ((soft_key_set_id = skinny_str2soft_key_set(switch_xml_attr_soft(xsoft_key_set, "name"))) != -1) { + char *val =switch_core_strdup(profile->pool, switch_xml_attr_soft(xsoft_key_set, "value")); + size_t string_len = strlen(val); + size_t string_pos, start = 0; + int field_no = 0; + if (soft_key_set_id > 15) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "soft-key-set name '%s' is greater than 15 in soft-key-set-set '%s' in profile %s.\n", + switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name); + continue; + } + for (string_pos = 0; string_pos <= string_len; string_pos++) { + if ((val[string_pos] == ',') || (string_pos == string_len)) { + val[string_pos] = '\0'; + if (field_no > 15) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "soft-key-set name '%s' is limited to 16 buttons in soft-key-set-set '%s' in profile %s.\n", + switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name); + break; + } + message->data.soft_key_set.soft_key_set[soft_key_set_id].soft_key_template_index[field_no++] = skinny_str2soft_key_event(&val[start]); + start = string_pos+1; + } + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "Unknown soft-key-set name '%s' in soft-key-set-set '%s' in profile %s.\n", + switch_xml_attr_soft(xsoft_key_set, "name"), soft_key_set_set_name, profile->name); + } + } /* soft-key-set */ + switch_core_hash_insert(profile->soft_key_set_sets_hash, soft_key_set_set_name, message); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + " is missing a name attribute in profile %s.\n", profile->name); + } + } /* soft-key-set-set */ + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + " is missing in profile %s.\n", profile->name); + } /* soft-key-set-sets */ + if (!switch_core_hash_find(profile->soft_key_set_sets_hash, "default")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, + "Profile %s doesn't have a default . Profile ignored.\n", profile->name); + switch_core_destroy_memory_pool(&profile_pool); + continue; + } + + + /* Device types */ + switch_core_hash_init(&profile->device_type_params_hash, profile->pool); + if ((xdevice_types = switch_xml_child(xprofile, "device-types"))) { + switch_xml_t xdevice_type; + for (xdevice_type = switch_xml_child(xdevice_types, "device-type"); xdevice_type; xdevice_type = xdevice_type->next) { + uint32_t id = skinny_str2device_type(switch_xml_attr_soft(xdevice_type, "id")); + if (id != 0) { + char *id_str = switch_mprintf("%d", id); + skinny_device_type_params_t *params = switch_core_alloc(profile->pool, sizeof(skinny_device_type_params_t)); + for (param = switch_xml_child(xdevice_type, "param"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + char *val = (char *) switch_xml_attr_soft(param, "value"); + + if (!strcasecmp(var, "firmware-version")) { + strncpy(params->firmware_version, val, 16); + } + } /* param */ + switch_core_hash_insert(profile->device_type_params_hash, id_str, params); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, + "Unknow device type %s in profile %s.\n", switch_xml_attr_soft(xdevice_type, "id"), profile->name); + } + } + } + /* Database */ switch_snprintf(dbname, sizeof(dbname), "skinny_%s", profile->name); profile->dbname = switch_core_strdup(profile->pool, dbname); @@ -1787,30 +1898,7 @@ static switch_status_t load_skinny_config(void) skinny_execute_sql_callback(profile, profile->sql_mutex, "DELETE FROM skinny_buttons", NULL, NULL); skinny_execute_sql_callback(profile, profile->sql_mutex, "DELETE FROM skinny_active_lines", NULL, NULL); - /* Device types */ - switch_core_hash_init(&profile->device_type_params_hash, profile->pool); - if ((xdevice_types = switch_xml_child(xprofile, "device-types"))) { - switch_xml_t xdevice_type; - for (xdevice_type = switch_xml_child(xdevice_types, "device-type"); xdevice_type; xdevice_type = xdevice_type->next) { - uint32_t id = skinny_str2device_type(switch_xml_attr_soft(xdevice_type, "id")); - if (id != 0) { - char *id_str = switch_mprintf("%d", id); - skinny_device_type_params_t *params = switch_core_alloc(profile->pool, sizeof(skinny_device_type_params_t)); - for (param = switch_xml_child(xdevice_type, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - if (!strcasecmp(var, "firmware-version")) { - strncpy(params->firmware_version, val, 16); - } - } /* param */ - switch_core_hash_insert(profile->device_type_params_hash, id_str, params); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, - "Unknow device type %s in profile %s.\n", switch_xml_attr_soft(xdevice_type, "id"), profile->name); - } - } - } + skinny_profile_respawn(profile, 0); /* Register profile */ switch_mutex_lock(globals.mutex); @@ -2009,6 +2097,7 @@ static void skinny_trap_event_handler(switch_event_t *event) } else if (!strcmp(profile->ip, old_ip6)) { skinny_profile_set(profile, "ip", new_ip6); } + skinny_profile_respawn(profile, 0); } } } @@ -2034,9 +2123,14 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load) load_skinny_config(); + /* at least one profile */ + if (!switch_hash_first(NULL, globals.profile_hash)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No profile found!\n"); + return SWITCH_STATUS_TERM; + } /* bind to events */ if ((switch_event_bind_removable(modname, SWITCH_EVENT_HEARTBEAT, NULL, skinny_heartbeat_event_handler, NULL, &globals.heartbeat_node) != SWITCH_STATUS_SUCCESS)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our heartbeat handler!\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't bind our heartbeat handler!\n"); /* Not such severe to prevent loading */ } if ((switch_event_bind_removable(modname, SWITCH_EVENT_CUSTOM, SKINNY_EVENT_CALL_STATE, skinny_call_state_event_handler, NULL, &globals.call_state_node) != SWITCH_STATUS_SUCCESS)) { @@ -2044,11 +2138,11 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_skinny_load) return SWITCH_STATUS_TERM; } if ((switch_event_bind_removable(modname, SWITCH_EVENT_MESSAGE_WAITING, NULL, skinny_message_waiting_event_handler, NULL, &globals.message_waiting_node) != SWITCH_STATUS_SUCCESS)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our message waiting handler!\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't bind our message waiting handler!\n"); /* Not such severe to prevent loading */ } if ((switch_event_bind_removable(modname, SWITCH_EVENT_TRAP, NULL, skinny_trap_event_handler, NULL, &globals.trap_node) != SWITCH_STATUS_SUCCESS)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind our trap handler!\n"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't bind our trap handler!\n"); /* Not such severe to prevent loading */ } diff --git a/src/mod/endpoints/mod_skinny/mod_skinny.h b/src/mod/endpoints/mod_skinny/mod_skinny.h index f52f171fdc..bbd318b746 100644 --- a/src/mod/endpoints/mod_skinny/mod_skinny.h +++ b/src/mod/endpoints/mod_skinny/mod_skinny.h @@ -61,7 +61,8 @@ extern skinny_globals_t globals; typedef enum { PFLAG_LISTENER_READY = (1 << 0), - PFLAG_RESPAWN = (1 << 1), + PFLAG_SHOULD_RESPAWN = (1 << 1), + PFLAG_RESPAWN = (1 << 2), } profile_flag_t; struct skinny_profile { @@ -78,6 +79,7 @@ struct skinny_profile { char date_format[6]; int debug; int auto_restart; + switch_hash_t *soft_key_set_sets_hash; switch_hash_t *device_type_params_hash; /* db */ char *dbname; @@ -133,6 +135,7 @@ struct listener { uint32_t device_type; char firmware_version[16]; + char *soft_key_set_set; switch_socket_t *sock; switch_memory_pool_t *pool; @@ -220,6 +223,9 @@ switch_core_session_t * skinny_profile_perform_find_session(skinny_profile_t *pr switch_core_session_t * skinny_profile_find_session(skinny_profile_t *profile, listener_t *listener, uint32_t *line_instance_p, uint32_t call_id); #endif switch_status_t dump_device(skinny_profile_t *profile, const char *device_name, switch_stream_handle_t *stream); +switch_status_t skinny_profile_respawn(skinny_profile_t *profile, int force); +switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, const char *val); +void profile_walk_listeners(skinny_profile_t *profile, skinny_listener_callback_func_t callback, void *pvt); /*****************************************************************************/ /* SQL FUNCTIONS */ @@ -262,7 +268,6 @@ switch_status_t channel_kill_channel(switch_core_session_t *session, int sig); /* MODULE FUNCTIONS */ /*****************************************************************************/ switch_endpoint_interface_t *skinny_get_endpoint_interface(); -switch_status_t skinny_profile_set(skinny_profile_t *profile, const char *var, const char *val); #endif /* _MOD_SKINNY_H */ diff --git a/src/mod/endpoints/mod_skinny/skinny_api.c b/src/mod/endpoints/mod_skinny/skinny_api.c index 86eea74fc8..90699d1ad2 100644 --- a/src/mod/endpoints/mod_skinny/skinny_api.c +++ b/src/mod/endpoints/mod_skinny/skinny_api.c @@ -275,6 +275,7 @@ static switch_status_t skinny_api_cmd_profile_device_send_ringer_message(const c skinny_profile_find_listener_by_device_name(profile, device_name, &listener); if(listener) { send_set_ringer(listener, skinny_str2ring_type(ring_type), skinny_str2ring_mode(ring_mode), 0, 0); + stream->write_function(stream, "+OK\n"); } else { stream->write_function(stream, "Listener not found!\n"); } @@ -294,6 +295,7 @@ static switch_status_t skinny_api_cmd_profile_device_send_lamp_message(const cha skinny_profile_find_listener_by_device_name(profile, device_name, &listener); if(listener) { send_set_lamp(listener, skinny_str2button(stimulus), atoi(instance), skinny_str2lamp_mode(lamp_mode)); + stream->write_function(stream, "+OK\n"); } else { stream->write_function(stream, "Listener not found!\n"); } @@ -313,6 +315,7 @@ static switch_status_t skinny_api_cmd_profile_device_send_speaker_mode_message(c skinny_profile_find_listener_by_device_name(profile, device_name, &listener); if(listener) { send_set_speaker_mode(listener, skinny_str2speaker_mode(speaker_mode)); + stream->write_function(stream, "+OK\n"); } else { stream->write_function(stream, "Listener not found!\n"); } @@ -332,6 +335,7 @@ static switch_status_t skinny_api_cmd_profile_device_send_call_state_message(con skinny_profile_find_listener_by_device_name(profile, device_name, &listener); if(listener) { send_call_state(listener, skinny_str2call_state(call_state), atoi(line_instance), atoi(call_id)); + stream->write_function(stream, "+OK\n"); } else { stream->write_function(stream, "Listener not found!\n"); } @@ -351,6 +355,7 @@ static switch_status_t skinny_api_cmd_profile_device_send_reset_message(const ch skinny_profile_find_listener_by_device_name(profile, device_name, &listener); if(listener) { send_reset(listener, skinny_str2device_reset_type(reset_type)); + stream->write_function(stream, "+OK\n"); } else { stream->write_function(stream, "Listener not found!\n"); } @@ -366,7 +371,10 @@ static switch_status_t skinny_api_cmd_profile_set(const char *profile_name, cons skinny_profile_t *profile; if ((profile = skinny_find_profile(profile_name))) { - if (skinny_profile_set(profile, name, value) != SWITCH_STATUS_SUCCESS) { + if (skinny_profile_set(profile, name, value) == SWITCH_STATUS_SUCCESS) { + skinny_profile_respawn(profile, 0); + stream->write_function(stream, "+OK\n"); + } else { stream->write_function(stream, "Unable to set skinny setting '%s'. Does it exists?\n", name); } } else { diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.c b/src/mod/endpoints/mod_skinny/skinny_protocol.c index c519dc4bf5..1aea812574 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.c +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.c @@ -122,6 +122,9 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req) while (listener_is_ready(listener)) { uint8_t do_sleep = 1; + if (listener->expire_time && listener->expire_time < switch_epoch_time_now(NULL)) { + return SWITCH_STATUS_TIMEOUT; + } if(bytes < SKINNY_MESSAGE_FIELD_SIZE) { /* We have nothing yet, get length header field */ mlen = SKINNY_MESSAGE_FIELD_SIZE - bytes; @@ -171,9 +174,6 @@ switch_status_t skinny_read_packet(listener_t *listener, skinny_message_t **req) } } } - if (listener->expire_time && listener->expire_time < switch_epoch_time_now(NULL)) { - return SWITCH_STATUS_TIMEOUT; - } if (do_sleep) { switch_cond_next(); } diff --git a/src/mod/endpoints/mod_skinny/skinny_protocol.h b/src/mod/endpoints/mod_skinny/skinny_protocol.h index fe001c7b4d..236c667509 100644 --- a/src/mod/endpoints/mod_skinny/skinny_protocol.h +++ b/src/mod/endpoints/mod_skinny/skinny_protocol.h @@ -151,7 +151,7 @@ struct PACKED open_receive_channel_ack_message { /* SoftKeyEventMessage */ #define SOFT_KEY_EVENT_MESSAGE 0x0026 struct PACKED soft_key_event_message { - uint32_t event; + uint32_t event; /* See enum skinny_soft_key_event */ uint32_t line_instance; uint32_t call_id; }; diff --git a/src/mod/endpoints/mod_skinny/skinny_server.c b/src/mod/endpoints/mod_skinny/skinny_server.c index 2f640a8345..3fa4aab6c4 100644 --- a/src/mod/endpoints/mod_skinny/skinny_server.c +++ b/src/mod/endpoints/mod_skinny/skinny_server.c @@ -999,6 +999,8 @@ switch_status_t skinny_handle_register(listener_t *listener, skinny_message_t *r const char *value = switch_xml_attr_soft(xparam, "value"); if (!strcasecmp(name, "skinny-firmware-version")) { strncpy(listener->firmware_version, value, 16); + } else if (!strcasecmp(name, "skinny-soft-key-set-set")) { + listener->soft_key_set_set = switch_core_strdup(profile->pool, value); } } } @@ -1693,49 +1695,20 @@ end: switch_status_t skinny_handle_soft_key_set_request(listener_t *listener, skinny_message_t *request) { - skinny_message_t *message; - skinny_profile_t *profile; + skinny_message_t *message = NULL; - switch_assert(listener->profile); - switch_assert(listener->device_name); - - profile = listener->profile; - - message = switch_core_alloc(listener->pool, 12+sizeof(message->data.soft_key_set)); - message->type = SOFT_KEY_SET_RES_MESSAGE; - message->length = 4 + sizeof(message->data.soft_key_set); - - message->data.soft_key_set.soft_key_set_offset = 0; - message->data.soft_key_set.soft_key_set_count = 11; - message->data.soft_key_set.total_soft_key_set_count = 11; - - /* TODO fill the set */ - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[0] = SOFTKEY_NEWCALL; - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOOK].soft_key_template_index[1] = SOFTKEY_REDIAL; - - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK].soft_key_template_index[1] = SOFTKEY_REDIAL; - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK].soft_key_template_index[2] = SOFTKEY_ENDCALL; - - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT].soft_key_template_index[0] = SOFTKEY_BACKSPACE; - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_DIGITS_AFTER_DIALING_FIRST_DIGIT].soft_key_template_index[2] = SOFTKEY_ENDCALL; - - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[0] = SOFTKEY_ENDCALL; - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[1] = SOFTKEY_HOLD; - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[2] = SOFTKEY_NEWCALL; - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_CONNECTED].soft_key_template_index[3] = SOFTKEY_TRANSFER; - - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[0] = SOFTKEY_ANSWER; - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[1] = SOFTKEY_ENDCALL; - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_RING_IN].soft_key_template_index[2] = SOFTKEY_NEWCALL; - - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[0] = SOFTKEY_NEWCALL; - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[1] = SOFTKEY_RESUME; - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_ON_HOLD].soft_key_template_index[2] = SOFTKEY_ENDCALL; - - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES].soft_key_template_index[1] = SOFTKEY_REDIAL; - message->data.soft_key_set.soft_key_set[SKINNY_KEY_SET_OFF_HOOK_WITH_FEATURES].soft_key_template_index[2] = SOFTKEY_ENDCALL; - - skinny_send_reply(listener, message); + if (listener->soft_key_set_set) { + message = switch_core_hash_find(listener->profile->soft_key_set_sets_hash, listener->soft_key_set_set); + } + if (!message) { + message = switch_core_hash_find(listener->profile->soft_key_set_sets_hash, "default"); + } + if (message) { + skinny_send_reply(listener, message); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, + "Profile %s doesn't have a default .\n", listener->profile->name); + } /* Init the states */ send_select_soft_keys(listener, 0, 0, SKINNY_KEY_SET_ON_HOOK, 0xffff); diff --git a/src/mod/endpoints/mod_skinny/skinny_tables.c b/src/mod/endpoints/mod_skinny/skinny_tables.c index f76e84320e..43b2290560 100644 --- a/src/mod/endpoints/mod_skinny/skinny_tables.c +++ b/src/mod/endpoints/mod_skinny/skinny_tables.c @@ -152,6 +152,32 @@ struct skinny_table SKINNY_BUTTONS[] = { SKINNY_DECLARE_ID2STR(skinny_button2str, SKINNY_BUTTONS, "Unknown") SKINNY_DECLARE_STR2ID(skinny_str2button, SKINNY_BUTTONS, -1) +struct skinny_table SKINNY_SOFT_KEY_EVENTS[] = { + {"SoftkeyRedial", SOFTKEY_REDIAL}, + {"SoftkeyNewcall", SOFTKEY_NEWCALL}, + {"SoftkeyHold", SOFTKEY_HOLD}, + {"SoftkeyTransfer", SOFTKEY_TRANSFER}, + {"SoftkeyCfwdall", SOFTKEY_CFWDALL}, + {"SoftkeyCfwdbusy", SOFTKEY_CFWDBUSY}, + {"SoftkeyCfwdnoanswer", SOFTKEY_CFWDNOANSWER}, + {"SoftkeyBackspace", SOFTKEY_BACKSPACE}, + {"SoftkeyEndcall", SOFTKEY_ENDCALL}, + {"SoftkeyResume", SOFTKEY_RESUME}, + {"SoftkeyAnswer", SOFTKEY_ANSWER }, + {"SoftkeyInfo", SOFTKEY_INFO}, + {"SoftkeyConfrm", SOFTKEY_CONFRM}, + {"SoftkeyPark", SOFTKEY_PARK}, + {"SoftkeyJoin", SOFTKEY_JOIN}, + {"SoftkeyMeetmeconfrm", SOFTKEY_MEETMECONFRM}, + {"SoftkeyCallpickup", SOFTKEY_CALLPICKUP}, + {"SoftkeyGrpcallpickup", SOFTKEY_GRPCALLPICKUP}, + {"SoftkeyDnd", SOFTKEY_DND}, + {"SoftkeyIdivert", SOFTKEY_IDIVERT}, + {NULL, 0} +}; +SKINNY_DECLARE_ID2STR(skinny_soft_key_event2str, SKINNY_SOFT_KEY_EVENTS, "SoftkeyUnknown") +SKINNY_DECLARE_STR2ID(skinny_str2soft_key_event, SKINNY_SOFT_KEY_EVENTS, 0) + struct skinny_table SKINNY_LAMP_MODES[] = { {"Off", SKINNY_LAMP_OFF}, {"On", SKINNY_LAMP_ON}, diff --git a/src/mod/endpoints/mod_skinny/skinny_tables.h b/src/mod/endpoints/mod_skinny/skinny_tables.h index 6c9182516e..1747360264 100644 --- a/src/mod/endpoints/mod_skinny/skinny_tables.h +++ b/src/mod/endpoints/mod_skinny/skinny_tables.h @@ -194,6 +194,10 @@ enum skinny_soft_key_event { SOFTKEY_DND = 0x13, SOFTKEY_IDIVERT = 0x14, }; +extern struct skinny_table SKINNY_SOFT_KEY_EVENTS[21]; +const char *skinny_soft_key_event2str(uint32_t id); +uint32_t skinny_str2soft_key_event(const char *str); +#define SKINNY_PUSH_SOFT_KEY_EVENTS SKINNY_DECLARE_PUSH_MATCH(SOFT_KEY_EVENTS) enum skinny_key_set { SKINNY_KEY_SET_ON_HOOK = 0, diff --git a/src/mod/endpoints/mod_sofia/sofia_reg.c b/src/mod/endpoints/mod_sofia/sofia_reg.c index d22c79a9e4..eb9b03d958 100644 --- a/src/mod/endpoints/mod_sofia/sofia_reg.c +++ b/src/mod/endpoints/mod_sofia/sofia_reg.c @@ -1178,17 +1178,6 @@ uint8_t sofia_reg_handle_register(nua_t *nua, sofia_profile_t *profile, nua_hand switch_find_local_ip(guess_ip4, sizeof(guess_ip4), NULL, AF_INET); - if (profile->reg_db_domain) { - if (!sofia_glue_profile_exists(to_host)) { - if (sofia_glue_add_profile(switch_core_strdup(profile->pool, to_host), profile) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Auto-Adding Alias [%s] for profile [%s]\n", to_host, profile->name); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Alias [%s] for profile [%s] (already exists)\n", - to_host, profile->name); - } - } - } - sql = switch_mprintf("insert into sip_registrations " "(call_id,sip_user,sip_host,presence_hosts,contact,status,rpid,expires," @@ -1430,6 +1419,17 @@ void sofia_reg_handle_sip_i_register(nua_t *nua, sofia_profile_t *profile, nua_h int network_port = 0; char *is_nat = NULL; + if (sip->sip_to && sip->sip_to->a_url && sip->sip_to->a_url->url_host) { + const char *to_host = sip->sip_to->a_url->url_host; + if (profile->reg_db_domain) { + if (!sofia_glue_profile_exists(to_host)) { + if (sofia_glue_add_profile(switch_core_strdup(profile->pool, to_host), profile) == SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Auto-Adding Alias [%s] for profile [%s]\n", to_host, profile->name); + } + } + } + } + sofia_glue_get_addr(nua_current_request(nua), network_ip, sizeof(network_ip), &network_port); if (!(sip->sip_contact && sip->sip_contact->m_url)) { diff --git a/src/mod/languages/mod_lua/freeswitch.i b/src/mod/languages/mod_lua/freeswitch.i index 3631aca62f..383580103f 100644 --- a/src/mod/languages/mod_lua/freeswitch.i +++ b/src/mod/languages/mod_lua/freeswitch.i @@ -18,6 +18,10 @@ %} +/* Lua function typemap */ +%typemap(in,checkfn="lua_isfunction") SWIGLUA_FN +%{ $1.L=L; $1.idx=$input; %} + %ignore SwitchToMempool; %newobject EventConsumer::pop; @@ -25,6 +29,7 @@ %newobject CoreSession; %newobject Event; %newobject Stream; +%newobject Dbh; /** * tell swig to grok everything defined in these header files and @@ -66,9 +71,18 @@ class Session : public CoreSession { void setLUA(lua_State *state); }; + +class Dbh { + private: + switch_cache_db_handle_t *dbh; + bool connected; + static int query_callback(void *pArg, int argc, char **argv, char **cargv); + public: + Dbh(char *dsn, char *user = NULL, char *pass = NULL); + ~Dbh(); + bool release(); + bool query(char *sql, SWIGLUA_FN lua_fun); +}; + } - - - - diff --git a/src/mod/languages/mod_lua/freeswitch_lua.cpp b/src/mod/languages/mod_lua/freeswitch_lua.cpp index c73c88c553..17d12bc1cb 100644 --- a/src/mod/languages/mod_lua/freeswitch_lua.cpp +++ b/src/mod/languages/mod_lua/freeswitch_lua.cpp @@ -308,3 +308,69 @@ switch_status_t Session::run_dtmf_callback(void *input, switch_input_type_t ityp return SWITCH_STATUS_SUCCESS; } + +Dbh::Dbh(char *dsn, char *user, char *pass) +{ + switch_cache_db_connection_options_t options = { {0} }; + + options.odbc_options.dsn = dsn; + options.odbc_options.user = user; + options.odbc_options.pass = pass; + + if (switch_cache_db_get_db_handle(&dbh, SCDB_TYPE_ODBC, &options) == SWITCH_STATUS_SUCCESS) { + connected = true; + } else { + connected = false; + } +} + +Dbh::~Dbh() +{ + release(); +} + +bool Dbh::release() +{ + if (connected) { + switch_cache_db_release_db_handle(&dbh); + connected = false; + return true; + } + return false; +} + +int Dbh::query_callback(void *pArg, int argc, char **argv, char **cargv) +{ + SWIGLUA_FN *lua_fun = (SWIGLUA_FN *)pArg; + + lua_pushvalue(lua_fun->L, lua_fun->idx); /* get the lua callback function onto the stack */ + + lua_newtable(lua_fun->L); /* push a row (table) */ + + for (int i = 0; i < argc; i++) { + lua_pushstring(lua_fun->L, switch_str_nil(cargv[i])); + lua_pushstring(lua_fun->L, switch_str_nil(argv[i])); + lua_settable(lua_fun->L, -3); + } + + lua_call(lua_fun->L, 1, 1); /* 1 in, 1 out */ + + if (lua_isnumber(lua_fun->L, -1)) { + if (lua_tonumber(lua_fun->L, -1) != 0) { + return 1; + } + } + + return 0; /* 0 to continue with next row */ +} + +bool Dbh::query(char *sql, SWIGLUA_FN lua_fun) +{ + if (connected) { + if (switch_cache_db_execute_sql_callback(dbh, sql, query_callback, &lua_fun, NULL) == SWITCH_STATUS_SUCCESS) { + return true; + } + } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no workie workie :(\n"); + return false; +} diff --git a/src/mod/languages/mod_lua/freeswitch_lua.h b/src/mod/languages/mod_lua/freeswitch_lua.h index a1f4a85ce3..a0780b1537 100644 --- a/src/mod/languages/mod_lua/freeswitch_lua.h +++ b/src/mod/languages/mod_lua/freeswitch_lua.h @@ -8,6 +8,16 @@ extern "C" { #include "mod_lua_extra.h" } #include + + +typedef struct{ + lua_State* L; + int idx; +}SWIGLUA_FN; + +#define SWIGLUA_FN_GET(fn) {lua_pushvalue(fn.L,fn.idx);} + + namespace LUA { class Session:public CoreSession { private: @@ -41,5 +51,17 @@ namespace LUA { void setLUA(lua_State * state); }; + + class Dbh { + protected: + switch_cache_db_handle_t *dbh; + bool connected; + static int query_callback(void *pArg, int argc, char **argv, char **cargv); + public: + Dbh(char *dsn, char *user = NULL, char *pass = NULL); + ~Dbh(); + bool release(); + bool query(char *sql, SWIGLUA_FN lua_fun); + }; } #endif diff --git a/src/mod/languages/mod_lua/hack.diff b/src/mod/languages/mod_lua/hack.diff index afd37b086d..fc33ddb9d6 100644 --- a/src/mod/languages/mod_lua/hack.diff +++ b/src/mod/languages/mod_lua/hack.diff @@ -1,38 +1,38 @@ ---- mod_lua_wrap.cpp 2008-07-16 16:58:58.000000000 -0400 -+++ old.cpp 2008-07-16 16:58:42.000000000 -0400 -@@ -6731,7 +6731,7 @@ - SWIG_check_num_args("LUA::Session",0,0) +--- mod_lua_wrap.cpp.orig 2010-09-05 16:39:26.000000000 +0200 ++++ mod_lua_wrap.cpp 2010-09-05 16:39:44.000000000 +0200 +@@ -4913,7 +4913,7 @@ + result = (LUA::Session *)new LUA::Session(); SWIG_arg=0; - SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; + SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; result->setLUA(L); return SWIG_arg; - if(0) SWIG_fail; -@@ -6759,7 +6759,7 @@ - + fail: +@@ -4934,7 +4934,7 @@ + arg2=(CoreSession *)SWIG_MustGetPtr(L,2,SWIGTYPE_p_CoreSession,0,2,"new_Session"); result = (LUA::Session *)new LUA::Session(arg1,arg2); SWIG_arg=0; - SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; + SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; result->setLUA(L); return SWIG_arg; - if(0) SWIG_fail; -@@ -6780,7 +6780,7 @@ - arg1 = (char *)lua_tostring(L, 1); + fail: +@@ -4952,7 +4952,7 @@ + arg1 = (char*)lua_tostring(L, 1); result = (LUA::Session *)new LUA::Session(arg1); SWIG_arg=0; - SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; + SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; result->setLUA(L); return SWIG_arg; - if(0) SWIG_fail; -@@ -6805,7 +6805,7 @@ - + fail: +@@ -4970,7 +4970,7 @@ + arg1=(switch_core_session_t *)SWIG_MustGetPtr(L,1,SWIGTYPE_p_switch_core_session_t,0,1,"new_Session"); result = (LUA::Session *)new LUA::Session(arg1); SWIG_arg=0; - SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; + SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Session,1); SWIG_arg++; result->setLUA(L); return SWIG_arg; - if(0) SWIG_fail; + fail: diff --git a/src/mod/languages/mod_lua/mod_lua_wrap.cpp b/src/mod/languages/mod_lua/mod_lua_wrap.cpp index bdb50972a4..991b667a62 100644 --- a/src/mod/languages/mod_lua/mod_lua_wrap.cpp +++ b/src/mod/languages/mod_lua/mod_lua_wrap.cpp @@ -1490,29 +1490,31 @@ SWIG_Lua_dostring(lua_State *L, const char* str) { #define SWIGTYPE_p_Event swig_types[3] #define SWIGTYPE_p_EventConsumer swig_types[4] #define SWIGTYPE_p_IVRMenu swig_types[5] -#define SWIGTYPE_p_LUA__Session swig_types[6] -#define SWIGTYPE_p_Stream swig_types[7] -#define SWIGTYPE_p_input_callback_state swig_types[8] -#define SWIGTYPE_p_lua_State swig_types[9] -#define SWIGTYPE_p_p_switch_event_node_t swig_types[10] -#define SWIGTYPE_p_session_flag_t swig_types[11] -#define SWIGTYPE_p_switch_call_cause_t swig_types[12] -#define SWIGTYPE_p_switch_channel_state_t swig_types[13] -#define SWIGTYPE_p_switch_channel_t swig_types[14] -#define SWIGTYPE_p_switch_core_session_t swig_types[15] -#define SWIGTYPE_p_switch_event_t swig_types[16] -#define SWIGTYPE_p_switch_event_types_t swig_types[17] -#define SWIGTYPE_p_switch_input_args_t swig_types[18] -#define SWIGTYPE_p_switch_input_type_t swig_types[19] -#define SWIGTYPE_p_switch_priority_t swig_types[20] -#define SWIGTYPE_p_switch_queue_t swig_types[21] -#define SWIGTYPE_p_switch_state_handler_table_t swig_types[22] -#define SWIGTYPE_p_switch_status_t swig_types[23] -#define SWIGTYPE_p_switch_stream_handle_t swig_types[24] -#define SWIGTYPE_p_uint32_t swig_types[25] -#define SWIGTYPE_p_void swig_types[26] -static swig_type_info *swig_types[28]; -static swig_module_info swig_module = {swig_types, 27, 0, 0, 0, 0}; +#define SWIGTYPE_p_LUA__Dbh swig_types[6] +#define SWIGTYPE_p_LUA__Session swig_types[7] +#define SWIGTYPE_p_SWIGLUA_FN swig_types[8] +#define SWIGTYPE_p_Stream swig_types[9] +#define SWIGTYPE_p_input_callback_state swig_types[10] +#define SWIGTYPE_p_lua_State swig_types[11] +#define SWIGTYPE_p_p_switch_event_node_t swig_types[12] +#define SWIGTYPE_p_session_flag_t swig_types[13] +#define SWIGTYPE_p_switch_call_cause_t swig_types[14] +#define SWIGTYPE_p_switch_channel_state_t swig_types[15] +#define SWIGTYPE_p_switch_channel_t swig_types[16] +#define SWIGTYPE_p_switch_core_session_t swig_types[17] +#define SWIGTYPE_p_switch_event_t swig_types[18] +#define SWIGTYPE_p_switch_event_types_t swig_types[19] +#define SWIGTYPE_p_switch_input_args_t swig_types[20] +#define SWIGTYPE_p_switch_input_type_t swig_types[21] +#define SWIGTYPE_p_switch_priority_t swig_types[22] +#define SWIGTYPE_p_switch_queue_t swig_types[23] +#define SWIGTYPE_p_switch_state_handler_table_t swig_types[24] +#define SWIGTYPE_p_switch_status_t swig_types[25] +#define SWIGTYPE_p_switch_stream_handle_t swig_types[26] +#define SWIGTYPE_p_uint32_t swig_types[27] +#define SWIGTYPE_p_void swig_types[28] +static swig_type_info *swig_types[30]; +static swig_module_info swig_module = {swig_types, 29, 0, 0, 0, 0}; #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) @@ -7005,6 +7007,230 @@ static swig_lua_class *swig_LUA_Session_bases[] = {0,0}; static const char *swig_LUA_Session_base_names[] = {"CoreSession *",0}; static swig_lua_class _wrap_class_LUA_Session = { "Session", &SWIGTYPE_p_LUA__Session,_wrap_new_Session, swig_delete_Session, swig_LUA_Session_methods, swig_LUA_Session_attributes, swig_LUA_Session_bases, swig_LUA_Session_base_names }; +static int _wrap_new_Dbh__SWIG_0(lua_State* L) { + int SWIG_arg = -1; + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + char *arg3 = (char *) 0 ; + LUA::Dbh *result = 0 ; + + SWIG_check_num_args("LUA::Dbh",3,3) + if(!lua_isstring(L,1)) SWIG_fail_arg("LUA::Dbh",1,"char *"); + if(!lua_isstring(L,2)) SWIG_fail_arg("LUA::Dbh",2,"char *"); + if(!lua_isstring(L,3)) SWIG_fail_arg("LUA::Dbh",3,"char *"); + arg1 = (char *)lua_tostring(L, 1); + arg2 = (char *)lua_tostring(L, 2); + arg3 = (char *)lua_tostring(L, 3); + result = (LUA::Dbh *)new LUA::Dbh(arg1,arg2,arg3); + SWIG_arg=0; + SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Dbh,1); SWIG_arg++; + return SWIG_arg; + + if(0) SWIG_fail; + +fail: + lua_error(L); + return SWIG_arg; +} + + +static int _wrap_new_Dbh__SWIG_1(lua_State* L) { + int SWIG_arg = -1; + char *arg1 = (char *) 0 ; + char *arg2 = (char *) 0 ; + LUA::Dbh *result = 0 ; + + SWIG_check_num_args("LUA::Dbh",2,2) + if(!lua_isstring(L,1)) SWIG_fail_arg("LUA::Dbh",1,"char *"); + if(!lua_isstring(L,2)) SWIG_fail_arg("LUA::Dbh",2,"char *"); + arg1 = (char *)lua_tostring(L, 1); + arg2 = (char *)lua_tostring(L, 2); + result = (LUA::Dbh *)new LUA::Dbh(arg1,arg2); + SWIG_arg=0; + SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Dbh,1); SWIG_arg++; + return SWIG_arg; + + if(0) SWIG_fail; + +fail: + lua_error(L); + return SWIG_arg; +} + + +static int _wrap_new_Dbh__SWIG_2(lua_State* L) { + int SWIG_arg = -1; + char *arg1 = (char *) 0 ; + LUA::Dbh *result = 0 ; + + SWIG_check_num_args("LUA::Dbh",1,1) + if(!lua_isstring(L,1)) SWIG_fail_arg("LUA::Dbh",1,"char *"); + arg1 = (char *)lua_tostring(L, 1); + result = (LUA::Dbh *)new LUA::Dbh(arg1); + SWIG_arg=0; + SWIG_NewPointerObj(L,result,SWIGTYPE_p_LUA__Dbh,1); SWIG_arg++; + return SWIG_arg; + + if(0) SWIG_fail; + +fail: + lua_error(L); + return SWIG_arg; +} + + +static int _wrap_new_Dbh(lua_State* L) { + int argc; + int argv[4]={ + 1,2,3,4 + }; + + argc = lua_gettop(L); + if (argc == 1) { + int _v; + { + _v = lua_isstring(L,argv[0]); + } + if (_v) { + return _wrap_new_Dbh__SWIG_2(L); + } + } + if (argc == 2) { + int _v; + { + _v = lua_isstring(L,argv[0]); + } + if (_v) { + { + _v = lua_isstring(L,argv[1]); + } + if (_v) { + return _wrap_new_Dbh__SWIG_1(L); + } + } + } + if (argc == 3) { + int _v; + { + _v = lua_isstring(L,argv[0]); + } + if (_v) { + { + _v = lua_isstring(L,argv[1]); + } + if (_v) { + { + _v = lua_isstring(L,argv[2]); + } + if (_v) { + return _wrap_new_Dbh__SWIG_0(L); + } + } + } + } + + lua_pushstring(L,"No matching function for overloaded 'new_Dbh'"); + lua_error(L);return 0; +} + + +static int _wrap_delete_Dbh(lua_State* L) { + int SWIG_arg = -1; + LUA::Dbh *arg1 = (LUA::Dbh *) 0 ; + + SWIG_check_num_args("LUA::~Dbh",1,1) + if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("LUA::~Dbh",1,"LUA::Dbh *"); + + if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,SWIG_POINTER_DISOWN))){ + SWIG_fail_ptr("delete_Dbh",1,SWIGTYPE_p_LUA__Dbh); + } + + delete arg1; + + SWIG_arg=0; + + return SWIG_arg; + + if(0) SWIG_fail; + +fail: + lua_error(L); + return SWIG_arg; +} + + +static int _wrap_Dbh_release(lua_State* L) { + int SWIG_arg = -1; + LUA::Dbh *arg1 = (LUA::Dbh *) 0 ; + bool result; + + SWIG_check_num_args("release",1,1) + if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("release",1,"LUA::Dbh *"); + + if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,0))){ + SWIG_fail_ptr("Dbh_release",1,SWIGTYPE_p_LUA__Dbh); + } + + result = (bool)(arg1)->release(); + SWIG_arg=0; + lua_pushboolean(L,(int)(result==true)); SWIG_arg++; + return SWIG_arg; + + if(0) SWIG_fail; + +fail: + lua_error(L); + return SWIG_arg; +} + + +static int _wrap_Dbh_query(lua_State* L) { + int SWIG_arg = -1; + LUA::Dbh *arg1 = (LUA::Dbh *) 0 ; + char *arg2 = (char *) 0 ; + SWIGLUA_FN arg3 ; + bool result; + + SWIG_check_num_args("query",3,3) + if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("query",1,"LUA::Dbh *"); + if(!lua_isstring(L,2)) SWIG_fail_arg("query",2,"char *"); + if(!lua_isfunction(L,3)) SWIG_fail_arg("query",3,"SWIGLUA_FN"); + + if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_LUA__Dbh,0))){ + SWIG_fail_ptr("Dbh_query",1,SWIGTYPE_p_LUA__Dbh); + } + + arg2 = (char *)lua_tostring(L, 2); + (&arg3)->L=L; (&arg3)->idx=3; + result = (bool)(arg1)->query(arg2,arg3); + SWIG_arg=0; + lua_pushboolean(L,(int)(result==true)); SWIG_arg++; + return SWIG_arg; + + if(0) SWIG_fail; + +fail: + lua_error(L); + return SWIG_arg; +} + + +static void swig_delete_Dbh(void *obj) { +LUA::Dbh *arg1 = (LUA::Dbh *) obj; +delete arg1; +} +static swig_lua_method swig_LUA_Dbh_methods[] = { + {"release", _wrap_Dbh_release}, + {"query", _wrap_Dbh_query}, + {0,0} +}; +static swig_lua_attribute swig_LUA_Dbh_attributes[] = { + {0,0,0} +}; +static swig_lua_class *swig_LUA_Dbh_bases[] = {0}; +static const char *swig_LUA_Dbh_base_names[] = {0}; +static swig_lua_class _wrap_class_LUA_Dbh = { "Dbh", &SWIGTYPE_p_LUA__Dbh,_wrap_new_Dbh, swig_delete_Dbh, swig_LUA_Dbh_methods, swig_LUA_Dbh_attributes, swig_LUA_Dbh_bases, swig_LUA_Dbh_base_names }; + #ifdef __cplusplus } #endif @@ -7043,7 +7269,9 @@ static swig_type_info _swigt__p_DTMF = {"_p_DTMF", "DTMF *", 0, 0, (void*)&_wrap static swig_type_info _swigt__p_Event = {"_p_Event", "Event *", 0, 0, (void*)&_wrap_class_Event, 0}; static swig_type_info _swigt__p_EventConsumer = {"_p_EventConsumer", "EventConsumer *", 0, 0, (void*)&_wrap_class_EventConsumer, 0}; static swig_type_info _swigt__p_IVRMenu = {"_p_IVRMenu", "IVRMenu *", 0, 0, (void*)&_wrap_class_IVRMenu, 0}; +static swig_type_info _swigt__p_LUA__Dbh = {"_p_LUA__Dbh", "LUA::Dbh *", 0, 0, (void*)&_wrap_class_LUA_Dbh, 0}; static swig_type_info _swigt__p_LUA__Session = {"_p_LUA__Session", "LUA::Session *", 0, 0, (void*)&_wrap_class_LUA_Session, 0}; +static swig_type_info _swigt__p_SWIGLUA_FN = {"_p_SWIGLUA_FN", "SWIGLUA_FN *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_Stream = {"_p_Stream", "Stream *", 0, 0, (void*)&_wrap_class_Stream, 0}; static swig_type_info _swigt__p_input_callback_state = {"_p_input_callback_state", "input_callback_state_t *|input_callback_state *", 0, 0, (void*)&_wrap_class_input_callback_state_t, 0}; static swig_type_info _swigt__p_lua_State = {"_p_lua_State", "lua_State *", 0, 0, (void*)0, 0}; @@ -7072,7 +7300,9 @@ static swig_type_info *swig_type_initial[] = { &_swigt__p_Event, &_swigt__p_EventConsumer, &_swigt__p_IVRMenu, + &_swigt__p_LUA__Dbh, &_swigt__p_LUA__Session, + &_swigt__p_SWIGLUA_FN, &_swigt__p_Stream, &_swigt__p_input_callback_state, &_swigt__p_lua_State, @@ -7101,7 +7331,9 @@ static swig_cast_info _swigc__p_DTMF[] = { {&_swigt__p_DTMF, 0, 0, 0},{0, 0, 0, static swig_cast_info _swigc__p_Event[] = { {&_swigt__p_Event, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_EventConsumer[] = { {&_swigt__p_EventConsumer, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_IVRMenu[] = { {&_swigt__p_IVRMenu, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_LUA__Dbh[] = { {&_swigt__p_LUA__Dbh, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_LUA__Session[] = { {&_swigt__p_LUA__Session, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_SWIGLUA_FN[] = { {&_swigt__p_SWIGLUA_FN, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_Stream[] = { {&_swigt__p_Stream, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_input_callback_state[] = { {&_swigt__p_input_callback_state, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_lua_State[] = { {&_swigt__p_lua_State, 0, 0, 0},{0, 0, 0, 0}}; @@ -7130,7 +7362,9 @@ static swig_cast_info *swig_cast_initial[] = { _swigc__p_Event, _swigc__p_EventConsumer, _swigc__p_IVRMenu, + _swigc__p_LUA__Dbh, _swigc__p_LUA__Session, + _swigc__p_SWIGLUA_FN, _swigc__p_Stream, _swigc__p_input_callback_state, _swigc__p_lua_State, diff --git a/src/mod/languages/mod_lua/my_swigable_cpp.h b/src/mod/languages/mod_lua/my_swigable_cpp.h index d4d3168a63..ebe597260f 100644 --- a/src/mod/languages/mod_lua/my_swigable_cpp.h +++ b/src/mod/languages/mod_lua/my_swigable_cpp.h @@ -49,6 +49,19 @@ class Event { }; +class Dbh { + protected: + switch_cache_db_handle_t *dbh; + bool connected; + static int query_callback(void *pArg, int argc, char **argv, char **cargv); + public: + Dbh(char *dsn, char *user = NULL, char *pass = NULL); + ~Dbh(); + bool release(); + bool query(char *sql, SWIGLUA_FN lua_fun); +}; + + class CoreSession { protected: switch_input_args_t args; diff --git a/src/switch_core_sqldb.c b/src/switch_core_sqldb.c index feb92b3c80..3a5e0bb6e2 100644 --- a/src/switch_core_sqldb.c +++ b/src/switch_core_sqldb.c @@ -35,6 +35,8 @@ #include #include "private/switch_core_pvt.h" +#define SQLLEN 32768 + static struct { switch_cache_db_handle_t *event_db; switch_queue_t *sql_queue[2]; @@ -537,7 +539,7 @@ SWITCH_DECLARE(switch_status_t) switch_cache_db_execute_sql(switch_cache_db_hand switch (dbh->type) { default: { - status = switch_cache_db_execute_sql_chunked(dbh, (char *) sql, 32768, err); + status = switch_cache_db_execute_sql_chunked(dbh, (char *) sql, SQLLEN, err); } break; } @@ -845,7 +847,7 @@ SWITCH_DECLARE(switch_bool_t) switch_cache_db_test_reactive(switch_cache_db_hand -#define SQLLEN 1024 * 1024 + static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, void *obj) { void *pop; @@ -853,13 +855,14 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, uint8_t trans = 0, nothing_in_queue = 0; uint32_t target = 100000; switch_size_t len = 0, sql_len = SQLLEN; - char *tmp, *sqlbuf = (char *) malloc(sql_len); - char *sql; + char *sqlbuf = (char *) malloc(sql_len); + char *sql = NULL; switch_size_t newlen; int lc = 0; uint32_t loops = 0, sec = 0; uint32_t l1 = 1000; uint32_t sanity = 120; + int item_remained = 0; switch_assert(sqlbuf); @@ -897,10 +900,17 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, continue; } - if (switch_queue_trypop(sql_manager.sql_queue[0], &pop) == SWITCH_STATUS_SUCCESS || - switch_queue_trypop(sql_manager.sql_queue[1], &pop) == SWITCH_STATUS_SUCCESS) { - sql = (char *) pop; + //printf("SIZE %d %d\n", switch_queue_size(sql_manager.sql_queue[0]), switch_queue_size(sql_manager.sql_queue[1])); + if (item_remained || switch_queue_trypop(sql_manager.sql_queue[0], &pop) == SWITCH_STATUS_SUCCESS || + switch_queue_trypop(sql_manager.sql_queue[1], &pop) == SWITCH_STATUS_SUCCESS) { + + if (item_remained) { + item_remained = 0; + } else { + sql = (char *) pop; + } + if (sql) { newlen = strlen(sql) + 2; @@ -911,20 +921,18 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, /* ignore abnormally large strings sql strings as potential buffer overflow */ if (newlen < SQLLEN) { itterations++; - if (len + newlen > sql_len) { - sql_len = len + SQLLEN; - if (!(tmp = realloc(sqlbuf, sql_len))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL thread ending on mem err\n"); - abort(); - break; - } - sqlbuf = tmp; + + if (len + newlen < sql_len) { + sprintf(sqlbuf + len, "%s;\n", sql); + len += newlen; + } else { + item_remained = 1; } - sprintf(sqlbuf + len, "%s;\n", sql); - len += newlen; - } - free(sql); + + if (!item_remained) { + free(sql); + } } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "SQL thread ending\n"); break; @@ -934,7 +942,8 @@ static void *SWITCH_THREAD_FUNC switch_core_sql_thread(switch_thread_t *thread, } - if (trans && ((itterations == target) || (nothing_in_queue && ++lc >= 500))) { + if ((item_remained || (trans && ((itterations == target) || (nothing_in_queue && ++lc >= 500)))) && + (sql_manager.event_db->native_handle.core_db_dbh)) { if (switch_cache_db_persistant_execute_trans(sql_manager.event_db, sqlbuf, 1) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "SQL thread unable to commit transaction, records lost!\n"); }