mod_kazoo_la_SOURCES += kazoo_message.c
mod_kazoo_la_SOURCES += kazoo_ei_config.c kazoo_ei_utils.c kazoo_event_stream.c
mod_kazoo_la_SOURCES += kazoo_fetch_agent.c kazoo_node.c
+mod_kazoo_la_SOURCES += kazoo_endpoints.c
mod_kazoo_la_CFLAGS = $(AM_CFLAGS) @ERLANG_CFLAGS@ -D_REENTRANT
mod_kazoo_la_LIBADD = $(KAZOO_DEFS) $(switch_builddir)/libfreeswitch.la
<field name="Metaflow-Control" type="reference" />
</definition>
+ <definition name="Privacy">
+ <field name="Caller-Privacy-Hide-Number" as="Hide-Number" serialize-as="boolean" />
+ <field name="Caller-Privacy-Hide-Name" as="Hide-Name" serialize-as="boolean" />
+ <field name="Caller-Screen-Bit" as="Screen-Bit" serialize-as="boolean" />
+ </definition>
+
<definition name="Custom-Channel-Vars">
<field name="Custom-Channel-Vars" type="static" serialize-as="object">
<fields verbose="false">
+ <field name="X-ecallmgr_" type="prefix"
+ exclude-prefix="true" />
<field name="variable_sip_h_X-ecallmgr_" type="prefix"
exclude-prefix="true" />
<field name="variable_ecallmgr_" type="prefix"
exclude-prefix="true" />
- <!-- special case for booleans -->
- <field name="variable_ecallmgr_Caller-Privacy-Hide-Number"
- as="Caller-Privacy-Hide-Number" serialize-as="boolean" />
- <field name="variable_ecallmgr_Caller-Privacy-Hide-Name" as="Caller-Privacy-Hide-Name"
- serialize-as="boolean" />
- <field name="variable_ecallmgr_Caller-Screen-Bit" as="Caller-Screen-Bit"
- serialize-as="boolean" />
-
- <field name="Caller-Privacy-Hide-Number" serialize-as="boolean" />
- <field name="Caller-Privacy-Hide-Name" serialize-as="boolean" />
- <field name="Caller-Screen-Bit" serialize-as="boolean" />
-
<field name="Fetch-UUID" as="Fetch-ID" />
+
<field name="Referred-To" type="expand"
- value="${regex(${url_decode(${variable_sip_refer_to})}|<sips?:(.*)>|%1)}">
+ value="sip:${regex(${url_decode(${variable_sip_refer_to})}|<sips?:(.*)>|%1)}">
<filters>
<filter name="variable_sip_refer_to" type="include" compare="exists" />
</filters>
</field>
- <field name="Referred-By" type="expand" value="${regex(${variable_sip_h_Referred-By}|<sips?:(.*)>|%1)}">
+ <field name="Referred-By" type="expand" value="sip:${regex(${variable_sip_h_Referred-By}|<sips?:(.*)>|%1)}">
<filters>
<filter name="variable_sip_h_Referred-By" type="include" compare="exists" />
</filters>
<filter name="variable_sip_redirected_by" type="include" compare="exists" />
</filters>
<fields verbose="false">
- <field name="Redirected-By" type="expand" value="${regex(${variable_sip_redirected_by}|<sips?:(.*)>|%1)}"/>
+ <field name="Redirected-By" type="expand" value="sip:${regex(${variable_sip_redirected_by}|<sips?:(.*)>|%1)}"/>
<field name="Redirected-Reason" type="expand" value="${regex(${variable_sip_redirected_by}|reason=(.*)|%1)}"/>
</fields>
</field>
<field name="Hunt-Context" />
<field name="Hunt-Dialplan" />
<field name="Hunt-Destination-Number" />
+ <!--
+ <field name="Request" type="expand"
+ value="${first-of(variable_sip_to_uri|variable_sip_req_uri|#${Hunt-Destination-Number}@${first-of(variable_sip_invite_domain|variable_sip_to_host|variable_sip_req_host|variable_ecallmgr_Realm)})}" />
+ <field name="To" type="expand"
+ value="${first-of(variable_sip_to_uri|variable_sip_req_uri|#${Hunt-Destination-Number}@${first-of(variable_sip_invite_domain|variable_sip_to_host|variable_sip_req_host|variable_ecallmgr_Realm)})}" />
+ -->
<field name="Request" type="expand"
- value="${Hunt-Destination-Number}@${first-of(variable_sip_invite_domain|variable_sip_to_host|variable_sip_req_host)}" />
+ value="${Hunt-Destination-Number}@${first-of(variable_sip_invite_domain|variable_sip_to_host|variable_sip_req_host|variable_ecallmgr_Realm)}" />
<field name="To" type="expand"
- value="${first-of(variable_sip_to_uri|variable_sip_req_uri|#${Hunt-Destination-Number}@${first-of(variable_sip_invite_domain|variable_sip_to_host|variable_sip_req_host)})}" />
+ value="${Hunt-Destination-Number}@${first-of(variable_sip_invite_domain|variable_sip_to_host|variable_sip_req_host|variable_ecallmgr_Realm)}" />
+ <field name="From" type="expand"
+ value="${first-of(Hunt-Caller-ID-Number|origination_callee_id_number|variable_sip_from_user)}@${first-of(variable_sip_invite_domain|variable_sip_from_host|variable_sip_req_host|variable_ecallmgr_Realm)}" />
</definition>
<definition name="sip-tags">
<field name="user-agent" type="reference" />
<field name="Custom-Channel-Vars" type="reference" />
<field name="Custom-Application-Vars" type="reference" />
- <field name="Control" type="reference" />
+ <field name="Control" type="reference" />
</definition>
<definition name="fetch-info">
<field name="Custom-Application-Vars" type="reference" />
<field name="freeswitch-url" type="reference" />
<field name="Control" type="reference" />
+ <field name="Privacy" type="reference" />
+
</definition>
<definition name="destination-number">
<definition name="from-to">
<field name="Request" type="first-of"
- value="variable_sip_req_uri|variable_sip_loopback_req_uri" />
+ value="variable_sip_req_uri|variable_sip_loopback_req_uri|variable_sip_to_uri" />
<field name="To" type="first-of"
value="variable_sip_to_uri|variable_sip_req_uri|variable_sip_loopback_req_uri" />
<field name="variable_sip_to_uri" as="To-URI" />
serialize-as="object">
<fields verbose="false">
<field name="Conference-" type="prefix" exclude-prefix="true" />
+ <field name="Account-ID" type="first-of" value="Account-ID|Conference-Account-ID|variable_ecallmgr_Account-ID" />
</fields>
</field>
</definition>
<field name="Application-Name" type="static" value="record" />
<field name="Application-Response" type="first-of"
value="Record-File-Path|kazoo_application_response" />
- <field name="recording_vars" type="reference" />
+ <field name="recording_vars" type="reference" />
</definition>
<definition name="fax_data">
<field name="variable_fax_success" as="Fax-Success" serialize-as="boolean" />
<field name="variable_has_t38" as="Fax-T38-Used" serialize-as="boolean" />
- <field name="variable_fax_ecm_used" as="Fax-ECM-Used" serialize-as="boolean" />
<field name="variable_fax_t38_status" as="Fax-T38-Status" />
+ <field name="variable_fax_ecm_used" as="Fax-ECM-Used" serialize-as="boolean" />
+ <field name="variable_fax_ecm_requested" as="Fax-ECM-Requested" serialize-as="boolean" />
<field name="variable_fax_document_transferred_pages" as="Fax-Transferred-Pages" serialize-as="number" />
<field name="variable_fax_document_total_pages" as="Fax-Total-Pages" serialize-as="number" />
<field name="variable_fax_bad_rows" as="Fax-Bad-Rows" serialize-as="number" />
<field name="Custom-Application-Vars" type="reference" />
</definition>
-
<definition name="voice_dialplan">
<field name="fetch-info" type="reference" />
<field name="Timestamp" type="expand"
<field name="user-agent" type="reference" />
<field name="from-to" type="reference" />
<field name="to-did" type="reference" />
+ <field name="loopback" type="reference" />
<field name="sip-tags" type="reference" />
<field name="freeswitch-url" type="reference" />
<field name="destination-number" type="reference" />
<field name="Event-Name" type="static" value="route_req" />
<field name="Hunt-Context" as="Fetch-Key-Value" />
</definition>
-
<definition name="metaflow_dialplan">
<field name="metaflow" type="group">
<filters>
serialize-as="object">
<fields verbose="false">
<field name="Metaflow-Request-Type" type="static" value="in-call" />
- <field name="Other-Leg-Call-ID" type="first-of" value="variable_Application-Other-Leg-UUID|Other-Leg-Unique-ID" />
+ <field name="Other-Leg-Unique-ID" as="Other-Leg-Call-ID" />
<field name="Hunt-Destination-Number" as="Metaflow-Request" />
</fields>
</field>
</field>
</definition>
-
</definitions>
+
<event-handlers>
<profile name="default">
<events>
switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);
switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10);
switch_curl_easy_setopt(curl_handle, CURLOPT_FAILONERROR, 1);
- switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-http-cache/1.0");
+ switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-kazoo/1.0");
switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, stream->param_event);
switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_callback);
switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, body_callback);
expanded = switch_channel_expand_variables(channel, val);
}
- switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SET [%s]=[%s]\n", switch_channel_get_name(channel), var,
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SET [%s]=[%s] => [%s]\n", switch_channel_get_name(channel), var, val,
expanded ? expanded : "UNDEF");
switch_channel_add_variable_var_check(channel, var, expanded, SWITCH_FALSE, stack);
kz_check_set_profile_var(channel, var, expanded);
switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, response);
}
+SWITCH_STANDARD_APP(kz_restore_caller_id_function)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_caller_profile_t *cp = switch_channel_get_caller_profile(channel);
+ cp->caller_id_name = cp->orig_caller_id_name;
+ cp->caller_id_number = cp->orig_caller_id_number;
+}
+
+SWITCH_STANDARD_APP(kz_audio_bridge_function)
+{
+ switch_channel_t *caller_channel = switch_core_session_get_channel(session);
+ switch_core_session_t *peer_session = NULL;
+ switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
+ switch_status_t status = SWITCH_STATUS_FALSE;
+
+ if (zstr(data)) {
+ return;
+ }
+
+ status = switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL);
+
+ if (status != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Originate Failed. Cause: %s\n", switch_channel_cause2str(cause));
+
+ switch_channel_set_variable(caller_channel, "originate_failed_cause", switch_channel_cause2str(cause));
+ switch_channel_set_variable(caller_channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, switch_channel_cause2str(cause));
+ switch_channel_handle_cause(caller_channel, cause);
+
+ return;
+ } else {
+ const char* uuid = switch_core_session_get_uuid(session);
+ const char* peer_uuid = switch_core_session_get_uuid(peer_session);
+
+
+ switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
+ if (switch_true(switch_channel_get_variable(caller_channel, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE)) ||
+ switch_true(switch_channel_get_variable(peer_channel, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE))) {
+ switch_channel_set_flag(caller_channel, CF_BYPASS_MEDIA_AFTER_BRIDGE);
+ }
+
+ while(1) {
+ const char *xfer_uuid;
+ switch_channel_state_t a_state , a_running_state;
+ switch_channel_state_t b_state , b_running_state;
+ status = switch_ivr_multi_threaded_bridge(session, peer_session, NULL, NULL, NULL);
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "BRIDGE RESULT %i\n", status);
+ if(status != 0) {
+ break;
+ }
+
+ a_state = switch_channel_get_state(caller_channel);
+ a_running_state = switch_channel_get_running_state(caller_channel);
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "A STATE %s %s => %s , %s\n", switch_channel_state_name(a_running_state), switch_channel_state_name(a_state), uuid, peer_uuid);
+
+ if(a_state >= CS_HANGUP) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "A HANGUP = %s , %s\n", uuid, peer_uuid);
+ break;
+ }
+
+ b_state = switch_channel_get_state(peer_channel);
+ b_running_state = switch_channel_get_running_state(peer_channel);
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "B STATE %s %s => %s , %s\n", switch_channel_state_name(b_running_state), switch_channel_state_name(b_state), uuid, peer_uuid);
+
+ if(b_state >= CS_HANGUP) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "B HANGUP = %s , %s\n", uuid, peer_uuid);
+ switch_channel_set_variable(caller_channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, switch_channel_cause2str(switch_channel_get_cause(peer_channel)));
+ break;
+ }
+
+ if(!(xfer_uuid=switch_channel_get_variable(caller_channel, "att_xfer_peer_uuid"))) {
+ if(!(xfer_uuid=switch_channel_get_variable(peer_channel, "att_xfer_peer_uuid"))) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "XFER UUID NULL\n");
+ break;
+ }
+ }
+
+ switch_channel_set_variable(caller_channel, "att_xfer_peer_uuid", NULL);
+ switch_channel_set_variable(peer_channel, "att_xfer_peer_uuid", NULL);
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "WAIT 1\n");
+
+ switch_channel_clear_flag(peer_channel, CF_UUID_BRIDGE_ORIGINATOR);
+ switch_channel_set_state(peer_channel, CS_RESET);
+ switch_channel_wait_for_state(peer_channel, NULL, CS_RESET);
+ switch_channel_clear_state_handler(peer_channel, NULL);
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "WAIT 3\n");
+
+ switch_channel_set_flag(caller_channel, CF_UUID_BRIDGE_ORIGINATOR);
+ switch_channel_clear_flag(caller_channel, CF_TRANSFER);
+ switch_channel_clear_flag(caller_channel, CF_REDIRECT);
+ switch_channel_set_flag(peer_channel, CF_UUID_BRIDGE_ORIGINATOR);
+ switch_channel_clear_flag(peer_channel, CF_TRANSFER);
+ switch_channel_clear_flag(peer_channel, CF_REDIRECT);
+
+ if(!switch_channel_media_up(caller_channel)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "A MEDIA DOWN HANGUP = %s, %s , %s\n", xfer_uuid, uuid, peer_uuid);
+ }
+ if(!switch_channel_media_up(peer_channel)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "B MEDIA DOWN HANGUP = %s, %s , %s\n", xfer_uuid, uuid, peer_uuid);
+ }
+ switch_channel_set_state(caller_channel, CS_EXECUTE);
+ switch_channel_set_state(peer_channel, CS_EXECUTE);
+
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "XFER LOOP %s %s , %s\n", xfer_uuid, uuid, peer_uuid);
+
+ }
+
+ if (peer_session) {
+ switch_core_session_rwunlock(peer_session);
+ }
+ }
+}
+
void add_kz_dptools(switch_loadable_module_interface_t **module_interface, switch_application_interface_t *app_interface) {
SWITCH_ADD_APP(app_interface, "kz_set", SET_SHORT_DESC, SET_LONG_DESC, set_function, SET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "kz_set_encoded", SET_SHORT_DESC, SET_LONG_DESC, set_encoded_function, SET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "kz_uuid_multiset", UUID_MULTISET_SHORT_DESC, UUID_MULTISET_LONG_DESC, uuid_multiset_function, UUID_MULTISET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "kz_uuid_multiset_encoded", UUID_MULTISET_SHORT_DESC, UUID_MULTISET_LONG_DESC, uuid_multiset_encoded_function, UUID_MULTISET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC);
SWITCH_ADD_APP(app_interface, "kz_endless_playback", KZ_ENDLESS_PLAYBACK_SHORT_DESC, KZ_ENDLESS_PLAYBACK_LONG_DESC, kz_endless_playback_function, KZ_ENDLESS_PLAYBACK_SYNTAX, SAF_NONE);
+ SWITCH_ADD_APP(app_interface, "kz_restore_caller_id", NOOP_SHORT_DESC, NOOP_LONG_DESC, kz_restore_caller_id_function, NOOP_SYNTAX, SAF_NONE);
SWITCH_ADD_APP(app_interface, "noop", NOOP_SHORT_DESC, NOOP_LONG_DESC, noop_function, NOOP_SYNTAX, SAF_NONE);
+ SWITCH_ADD_APP(app_interface, "kz_bridge", "Bridge Audio", "Bridge the audio between two sessions", kz_audio_bridge_function, "<channel_url>", SAF_SUPPORT_NOMEDIA|SAF_SUPPORT_TEXT_ONLY);
}
char ipbuf[48];
const char *ip_addr;
+ ei_init();
+
/* if the config has specified an erlang release compatibility then pass that along to the erlang interface */
if (kazoo_globals.ei_compat_rel) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Compatability with OTP R%d requested\n", kazoo_globals.ei_compat_rel);
--- /dev/null
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
+ *
+ * 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 <anthm@freeswitch.org>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Karl Anderson <karl@2600hz.com>
+ * Darren Schreiber <darren@2600hz.com>
+ *
+ *
+ * kazoo_dptools.c -- clones of mod_dptools commands slightly modified for kazoo
+ *
+ */
+#include "mod_kazoo.h"
+
+/* kazoo endpoint */
+switch_endpoint_interface_t *kz_endpoint_interface;
+static switch_call_cause_t kz_endpoint_outgoing_channel(switch_core_session_t *session,
+ switch_event_t *var_event,
+ switch_caller_profile_t *outbound_profile,
+ switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
+ switch_call_cause_t *cancel_cause);
+switch_io_routines_t kz_endpoint_io_routines = {
+ /*.outgoing_channel */ kz_endpoint_outgoing_channel
+};
+
+static switch_call_cause_t kz_endpoint_outgoing_channel(switch_core_session_t *session,
+ switch_event_t *var_event,
+ switch_caller_profile_t *outbound_profile,
+ switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
+ switch_call_cause_t *cancel_cause)
+{
+ switch_xml_t x_user = NULL, x_param, x_params;
+ char *user = NULL, *domain = NULL, *dup_domain = NULL, *dialed_user = NULL;
+ const char *dest = NULL;
+ switch_call_cause_t cause = SWITCH_CAUSE_NONE;
+ unsigned int timelimit = SWITCH_DEFAULT_TIMEOUT;
+ switch_channel_t *new_channel = NULL;
+ switch_event_t *params = NULL, *var_event_orig = var_event;
+ char stupid[128] = "";
+ const char *skip = NULL, *var = NULL;
+
+ if (zstr(outbound_profile->destination_number)) {
+ goto done;
+ }
+
+ user = strdup(outbound_profile->destination_number);
+
+ if (!user)
+ goto done;
+
+ if ((domain = strchr(user, '@'))) {
+ *domain++ = '\0';
+ } else {
+ domain = switch_core_get_domain(SWITCH_TRUE);
+ dup_domain = domain;
+ }
+
+ if (!domain) {
+ goto done;
+ }
+
+
+ switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS);
+ switch_assert(params);
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "as_channel", "true");
+ switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "action", "user_call");
+
+ if (var_event) {
+ switch_event_merge(params, var_event);
+ }
+
+ if (var_event && (skip = switch_event_get_header(var_event, "user_recurse_variables")) && switch_false(skip)) {
+ if ((var = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) || (var = switch_event_get_header(var_event, "leg_timeout"))) {
+ timelimit = atoi(var);
+ }
+ var_event = NULL;
+ }
+
+ if (switch_xml_locate_user_merged("id", user, domain, NULL, &x_user, params) != SWITCH_STATUS_SUCCESS) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Can't find user [%s@%s]\n", user, domain);
+ cause = SWITCH_CAUSE_SUBSCRIBER_ABSENT;
+ goto done;
+ }
+
+ if ((x_params = switch_xml_child(x_user, "params"))) {
+ for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
+ const char *pvar = switch_xml_attr_soft(x_param, "name");
+ const char *val = switch_xml_attr(x_param, "value");
+
+ if (!strcasecmp(pvar, "dial-string")) {
+ dest = val;
+ } else if (!strncasecmp(pvar, "dial-var-", 9)) {
+ if (!var_event) {
+ switch_event_create(&var_event, SWITCH_EVENT_GENERAL);
+ } else {
+ switch_event_del_header(var_event, pvar + 9);
+ }
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "adding variable to var_event => %s = %s\n", pvar + 9, val);
+ switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, pvar + 9, val);
+ }
+ }
+ }
+
+ dialed_user = (char *)switch_xml_attr(x_user, "id");
+
+ if (var_event) {
+ switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_user", dialed_user);
+ switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
+ if (!zstr(dest) && !strstr(dest, "presence_id=")) {
+ switch_event_add_header(var_event, SWITCH_STACK_BOTTOM, "presence_id", "%s@%s", dialed_user, domain);
+ }
+ }
+
+ if (!dest) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No dial-string available, please check your user directory.\n");
+ cause = SWITCH_CAUSE_MANDATORY_IE_MISSING;
+ } else {
+ const char *varval;
+ char *d_dest = NULL;
+ switch_channel_t *channel;
+ switch_originate_flag_t myflags = SOF_NONE;
+ char *cid_name_override = NULL;
+ char *cid_num_override = NULL;
+
+ if (var_event) {
+ cid_name_override = switch_event_get_header(var_event, "origination_caller_id_name");
+ cid_num_override = switch_event_get_header(var_event, "origination_caller_id_number");
+ }
+
+ if (session) {
+ switch_event_t *event = NULL;
+ switch_event_create(&event, SWITCH_EVENT_GENERAL);
+ channel = switch_core_session_get_channel(session);
+ if ((varval = switch_channel_get_variable(channel, SWITCH_CALL_TIMEOUT_VARIABLE))
+ || (var_event && (varval = switch_event_get_header(var_event, "leg_timeout")))) {
+ timelimit = atoi(varval);
+ }
+ switch_channel_event_set_data(channel, event);
+ if(var_event) {
+ switch_event_merge(event, var_event);
+ }
+
+ switch_channel_set_variable(channel, "dialed_user", dialed_user);
+ switch_channel_set_variable(channel, "dialed_domain", domain);
+
+ d_dest = switch_event_expand_headers(event, dest);
+
+ switch_event_destroy(&event);
+
+ } else {
+ switch_event_t *event = NULL;
+
+ if (var_event) {
+ switch_event_dup(&event, var_event);
+ switch_event_del_header(event, "dialed_user");
+ switch_event_del_header(event, "dialed_domain");
+ if ((varval = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) ||
+ (varval = switch_event_get_header(var_event, "leg_timeout"))) {
+ timelimit = atoi(varval);
+ }
+ } else {
+ switch_event_create(&event, SWITCH_EVENT_REQUEST_PARAMS);
+ switch_assert(event);
+ }
+
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialed_user", dialed_user);
+ switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialed_domain", domain);
+ d_dest = switch_event_expand_headers(event, dest);
+ switch_event_destroy(&event);
+ }
+
+ if ((flags & SOF_NO_LIMITS)) {
+ myflags |= SOF_NO_LIMITS;
+ }
+
+ if ((flags & SOF_FORKED_DIAL)) {
+ myflags |= SOF_NOBLOCK;
+ }
+
+ switch_snprintf(stupid, sizeof(stupid), "kz/%s", dialed_user);
+ if (switch_stristr(stupid, d_dest)) {
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Waddya Daft? You almost called '%s' in an infinate loop!\n",
+ stupid);
+ cause = SWITCH_CAUSE_INVALID_IE_CONTENTS;
+ } else if (switch_ivr_originate(session, new_session, &cause, d_dest, timelimit, NULL,
+ cid_name_override, cid_num_override, outbound_profile, var_event, myflags,
+ cancel_cause, NULL) == SWITCH_STATUS_SUCCESS) {
+ const char *context;
+ switch_caller_profile_t *cp;
+
+ if (var_event) {
+ switch_event_del_header(var_event, "origination_uuid");
+ }
+
+ new_channel = switch_core_session_get_channel(*new_session);
+
+ if ((context = switch_channel_get_variable(new_channel, "user_context"))) {
+ if ((cp = switch_channel_get_caller_profile(new_channel))) {
+ cp->context = switch_core_strdup(cp->pool, context);
+ }
+ }
+
+ if ((x_params = switch_xml_child(x_user, "variables"))) {
+ for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
+ const char *pvar = switch_xml_attr(x_param, "name");
+ const char *val = switch_xml_attr(x_param, "value");
+ switch_channel_set_variable(new_channel, pvar, val);
+ }
+ }
+
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG1, "CHECKING CALLER-ID\n");
+ if ((x_params = switch_xml_child(x_user, "profile-variables"))) {
+ switch_caller_profile_t *cp = NULL;
+ const char* val = NULL;
+ for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) {
+ const char *pvar = switch_xml_attr(x_param, "name");
+ const char *val = switch_xml_attr(x_param, "value");
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG1, "setting profile var %s = %s\n", pvar, val);
+ switch_channel_set_profile_var(new_channel, pvar, val);
+ }
+ cp = switch_channel_get_caller_profile(new_channel);
+ if((val=switch_caller_get_field_by_name(cp, "Endpoint-Caller-ID-Name"))) {
+ cp->callee_id_name = val;
+ cp->orig_caller_id_name = val;
+ }
+ if((val=switch_caller_get_field_by_name(cp, "Endpoint-Caller-ID-Number"))) {
+ cp->callee_id_number = val;
+ cp->orig_caller_id_number = val;
+ }
+ }
+ switch_core_session_rwunlock(*new_session);
+ }
+
+ if (d_dest != dest) {
+ switch_safe_free(d_dest);
+ }
+ }
+
+ done:
+
+ if (x_user) {
+ switch_xml_free(x_user);
+ }
+
+ if (params) {
+ switch_event_destroy(¶ms);
+ }
+
+ if (var_event && var_event_orig != var_event) {
+ switch_event_destroy(&var_event);
+ }
+
+ switch_safe_free(user);
+ switch_safe_free(dup_domain);
+
+ return cause;
+}
+
+
+void add_kz_endpoints(switch_loadable_module_interface_t **module_interface) {
+ kz_endpoint_interface = (switch_endpoint_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
+ kz_endpoint_interface->interface_name = "kz";
+ kz_endpoint_interface->io_routines = &kz_endpoint_io_routines;
+}
"Call-Control-Node",
"ecallmgr_Call-Interaction-ID",
"ecallmgr_Ecallmgr-Node",
+ "sip_h_k-cid",
+ "Switch-URI",
+ "Switch-URL",
NULL
};
}
}
}
+
}
+
}
-static void kz_tweaks_handle_bridge_replaces_caller_id(switch_event_t *event)
+static void kz_tweaks_handle_bridge_replaces_call_id(switch_event_t *event)
{
switch_event_t *my_event;
}
-
static void kz_tweaks_channel_bridge_event_handler(switch_event_t *event)
{
- kz_tweaks_handle_bridge_variables(event);
- kz_tweaks_handle_bridge_replaces_caller_id(event);
+ kz_tweaks_handle_bridge_replaces_call_id(event);
kz_tweaks_handle_bridge_replaces(event);
+ kz_tweaks_handle_bridge_variables(event);
}
// TRANSFERS
for(header = event->headers; header; header = header->next) {
if(!strncmp(header->name, "Export-Loopback-", 16)) {
- switch_event_add_variable_name_printf(to_add, SWITCH_STACK_BOTTOM, header->value, "%s", header->name+16);
+ kz_switch_event_add_variable_name_printf(to_add, SWITCH_STACK_BOTTOM, header->value, "%s", header->name+16);
switch_channel_set_variable(channel, header->name, NULL);
n++;
} else if(!strncmp(header->name, "sip_loopback_", 13)) {
- switch_event_add_variable_name_printf(to_add, SWITCH_STACK_BOTTOM, header->value, "sip_%s", header->name+13);
+ kz_switch_event_add_variable_name_printf(to_add, SWITCH_STACK_BOTTOM, header->value, "sip_%s", header->name+13);
} else if(!strncmp(header->name, "ecallmgr_", 9)) {
switch_event_add_header_string(to_remove, SWITCH_STACK_BOTTOM, header->name, header->value);
}
static void kz_tweaks_handle_caller_id(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
- const char *acl_token = switch_channel_get_variable(channel, "acl_token");
- if(acl_token) {
- switch_ivr_set_user(session, acl_token);
+ const char *token = switch_channel_get_variable(channel, "acl_token");
+ switch_caller_profile_t* caller = switch_channel_get_caller_profile(channel);
+ switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "CHECKING CALLER-ID\n");
+ if (token) {
+ const char* val = NULL;
+ if((val=switch_caller_get_field_by_name(caller, "Endpoint-Caller-ID-Name"))) {
+ caller->caller_id_name = val;
+ caller->orig_caller_id_name = val;
+ }
+ if((val=switch_caller_get_field_by_name(caller, "Endpoint-Caller-ID-Number"))) {
+ caller->caller_id_number = val;
+ caller->orig_caller_id_number = val;
+ }
}
}
switch_core_session_t *replace_call_session = NULL;
switch_event_t *event;
switch_channel_t *channel = switch_core_session_get_channel(session);
- switch_memory_pool_t *pool = switch_core_session_get_pool(session);
const char *replaced_call_id = switch_channel_get_variable(channel, "sip_replaces_call_id");
const char *core_uuid = switch_channel_get_variable(channel, "sip_h_X-FS-From-Core-UUID");
if((!core_uuid) && replaced_call_id) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "checking replaces header tweak for %s\n", replaced_call_id);
if ((replace_call_session = switch_core_session_locate(replaced_call_id))) {
- const char* tmp_caller = NULL;
- switch_caller_profile_t * cp = switch_channel_get_caller_profile(channel);
switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_call_session);
int i;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "setting bridge variables from %s to %s\n", replaced_call_id, switch_channel_get_uuid(channel));
switch_channel_event_set_data(channel, event);
switch_event_fire(&event);
}
- if((tmp_caller = switch_channel_get_variable(channel, "Internal-Caller-ID-Number")) != NULL) {
- profile_dup_clean(tmp_caller, cp->caller_id_number, pool);
- }
- if((tmp_caller = switch_channel_get_variable(channel, "Internal-Caller-ID-Name")) != NULL) {
- profile_dup_clean(tmp_caller, cp->caller_id_name, pool);
- }
switch_core_session_rwunlock(replace_call_session);
}
}
}
+static switch_status_t kz_tweaks_register_handle_xfer(switch_core_session_t *session)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+ switch_channel_set_variable(channel, "execute_on_blind_transfer", "kz_restore_caller_id");
+ return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t kz_tweaks_set_export_vars(switch_core_session_t *session)
+{
+ switch_channel_t *channel = switch_core_session_get_channel(session);
+
+ const char *exports;
+ char *var, *new_exports, *new_exports_d = NULL;
+
+ exports = switch_channel_get_variable(channel, SWITCH_EXPORT_VARS_VARIABLE);
+ var = switch_core_session_strdup(session, "Switch-URI,Switch-URL");
+
+ if (exports) {
+ new_exports_d = switch_mprintf("%s,%s", exports, var);
+ new_exports = new_exports_d;
+ } else {
+ new_exports = var;
+ }
+
+ switch_channel_set_variable(channel, SWITCH_EXPORT_VARS_VARIABLE, new_exports);
+
+ switch_safe_free(new_exports_d);
+
+
+ return SWITCH_STATUS_SUCCESS;
+}
static switch_status_t kz_tweaks_on_init(switch_core_session_t *session)
{
switch_channel_t *channel = switch_core_session_get_channel(session);
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "checking tweaks for %s\n", switch_channel_get_uuid(channel));
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "checking tweaks for %s\n", switch_channel_get_uuid(channel));
switch_channel_set_flag(channel, CF_VERBOSE_EVENTS);
kz_tweaks_handle_switch_uri(session);
kz_tweaks_handle_caller_id(session);
kz_tweaks_handle_nightmare_xfer(session);
kz_tweaks_handle_replaces_id(session);
kz_tweaks_handle_loopback(session);
+ kz_tweaks_register_handle_xfer(session);
+ kz_tweaks_set_export_vars(session);
return SWITCH_STATUS_SUCCESS;
}
*/
#include "mod_kazoo.h"
+#define kz_resize(l) {\
+char *dp;\
+olen += (len + l + block);\
+cpos = c - data;\
+if ((dp = realloc(data, olen))) {\
+ data = dp;\
+ c = data + cpos;\
+ memset(c, 0, olen - cpos);\
+ }} \
+
+
void kz_check_set_profile_var(switch_channel_t *channel, char* var, char *val)
{
int idx = 0;
}
}
+SWITCH_DECLARE(switch_status_t) kz_switch_core_merge_variables(switch_event_t *event)
+{
+ switch_event_t *global_vars;
+ switch_status_t status = switch_core_get_variables(&global_vars);
+ if(status == SWITCH_STATUS_SUCCESS) {
+ switch_event_merge(event, global_vars);
+ switch_event_destroy(&global_vars);
+ }
+ return status;
+}
+
+SWITCH_DECLARE(switch_status_t) kz_switch_core_base_headers_for_expand(switch_event_t **event)
+{
+ switch_status_t status = SWITCH_STATUS_GENERR;
+ *event = NULL;
+ if(switch_event_create(event, SWITCH_EVENT_GENERAL) == SWITCH_STATUS_SUCCESS) {
+ status = kz_switch_core_merge_variables(*event);
+ }
+ return status;
+}
+
SWITCH_DECLARE(switch_status_t) kz_expand_api_execute(const char *cmd, const char *arg, switch_core_session_t *session, switch_stream_handle_t *stream)
{
switch_api_interface_t *api;
return status;
}
-#define resize(l) {\
-char *dp;\
-olen += (len + l + block);\
-cpos = c - data;\
-if ((dp = realloc(data, olen))) {\
- data = dp;\
- c = data + cpos;\
- memset(c, 0, olen - cpos);\
- }} \
SWITCH_DECLARE(char *) kz_event_expand_headers_check(switch_event_t *event, const char *in, switch_event_t *var_list, switch_event_t *api_list, uint32_t recur)
{
continue;
} else if (*(p + 1) == '\\') {
if (len + 1 >= olen) {
- resize(1);
+ kz_resize(1);
}
*c++ = *p++;
if (nv) {
if (len + 1 >= olen) {
- resize(1);
+ kz_resize(1);
}
*c++ = *p;
}
if ((nlen = sub_val ? strlen(sub_val) : 0)) {
if (len + nlen >= olen) {
- resize(nlen);
+ kz_resize(nlen);
}
len += nlen;
if (sp) {
if (len + 1 >= olen) {
- resize(1);
+ kz_resize(1);
}
*c++ = ' ';
p--;
} else {
if (len + 1 >= olen) {
- resize(1);
+ kz_resize(1);
}
*c++ = *p;
return kz_event_expand_headers_check(event, in, NULL, NULL, 0);
}
+SWITCH_DECLARE(char *) kz_event_expand(const char *in)
+{
+ switch_event_t *event = NULL;
+ char *ret = NULL;
+ kz_switch_core_base_headers_for_expand(&event);
+ ret = kz_event_expand_headers_check(event, in, NULL, NULL, 0);
+ switch_event_destroy(&event);
+ return ret;
+}
+
char *kazoo_expand_header(switch_memory_pool_t *pool, switch_event_t *event, char *val)
{
char *expanded;
return dup;
}
-char* switch_event_get_first_of(switch_event_t *event, const char *list[])
+char* kz_switch_event_get_first_of(switch_event_t *event, const char *list[])
{
switch_event_header_t *header = NULL;
int i = 0;
}
}
-SWITCH_DECLARE(switch_status_t) switch_event_add_variable_name_printf(switch_event_t *event, switch_stack_t stack, const char *val, const char *fmt, ...)
+SWITCH_DECLARE(switch_status_t) kz_switch_event_add_variable_name_printf(switch_event_t *event, switch_stack_t stack, const char *val, const char *fmt, ...)
{
int ret = 0;
char *varname;
/* add our modified dptools */
add_kz_dptools(module_interface, app_interface);
+ /* add our endpoints */
+ add_kz_endpoints(module_interface);
+
/* add tweaks */
kz_tweaks_start();
void remove_cli_api();
/* kazoo_utils.c */
+SWITCH_DECLARE(switch_status_t) kz_switch_core_merge_variables(switch_event_t *event);
+SWITCH_DECLARE(switch_status_t) kz_switch_core_base_headers_for_expand(switch_event_t **event);
void kz_check_set_profile_var(switch_channel_t *channel, char* var, char *val);
char *kazoo_expand_header(switch_memory_pool_t *pool, switch_event_t *event, char *val);
-char* switch_event_get_first_of(switch_event_t *event, const char *list[]);
-SWITCH_DECLARE(switch_status_t) switch_event_add_variable_name_printf(switch_event_t *event, switch_stack_t stack, const char *val, const char *fmt, ...);
+char* kz_switch_event_get_first_of(switch_event_t *event, const char *list[]);
+SWITCH_DECLARE(switch_status_t) kz_switch_event_add_variable_name_printf(switch_event_t *event, switch_stack_t stack, const char *val, const char *fmt, ...);
void kz_xml_process(switch_xml_t cfg);
void kz_event_decode(switch_event_t *event);
char * kz_expand_vars(char *xml_str);
char * kz_expand_vars_pool(char *xml_str, switch_memory_pool_t *pool);
SWITCH_DECLARE(char *) kz_event_expand_headers(switch_event_t *event, const char *in);
+/* kazoo_endpoints.c */
+void add_kz_endpoints(switch_loadable_module_interface_t **module_interface);
+
+
/* kazoo_tweaks.c */
void kz_tweaks_start();
void kz_tweaks_stop();