]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-11791 [mod_kazoo] fixes & improvements
authorlazedo <luis.azedo@factorlusitano.com>
Thu, 18 Apr 2019 03:05:31 +0000 (04:05 +0100)
committerlazedo <luis.azedo@factorlusitano.com>
Thu, 18 Apr 2019 03:05:31 +0000 (04:05 +0100)
* tweak configuration
* customized att_xfer
* json_api with uuid support

src/mod/event_handlers/mod_kazoo/kazoo.conf.xml
src/mod/event_handlers/mod_kazoo/kazoo_dptools.c
src/mod/event_handlers/mod_kazoo/kazoo_ei.h
src/mod/event_handlers/mod_kazoo/kazoo_ei_config.c
src/mod/event_handlers/mod_kazoo/kazoo_event_stream.c
src/mod/event_handlers/mod_kazoo/kazoo_node.c
src/mod/event_handlers/mod_kazoo/kazoo_tweaks.c
src/mod/event_handlers/mod_kazoo/mod_kazoo.h

index 1ca1b60e6ac846837069218d422793563ff68f98..5464407c7a92eeb610d8f4deb30c2a7ef0f2bf82 100644 (file)
                             <filter name="variable_sip_refer_to" type="include" compare="exists" />
                         </filters>
                     </field>
-                    <field name="Referred-By" type="expand" value="sip:${regex(${variable_sip_h_Referred-By}|&lt;sips?:(.*)&gt;|%1)}">
+                    <field name="variable_sip_h_Referred-By" as="Referred-By"/>
+                    <!-- <field name="Referred-By" type="expand" value="sip:${regex(${variable_sip_h_Referred-By}|&lt;sips?:(.*)&gt;|%1)}">
                         <filters>
                             <filter name="variable_sip_h_Referred-By" type="include" compare="exists" />
                         </filters>
                     </field>
+                    -->
 
                     <!-- <field name="variable_Call-Interaction-ID" as="Call-Interaction-ID" /> -->
                     <field name="interaction-id" type="reference" />
                                                        name="variable_Call-Control-Queue" />
                         <filter type="include" compare="exists"
                             name="Application-UUID-Name" />
+                        <filter type="exclude" name="Application-UUID-Name" value="set" />
                                                <filter type="exclude" name="Application" value="set" />
                         <filter name="Application" value="park" />
                         <filter name="Application" value="export" />
                                                        value="Application-Response|variable_originate_disposition|variable_endpoint_disposition|#NONE" />
                                                <field name="Disposition" type="first-of"
                                                        value="variable_originate_disposition|variable_endpoint_disposition" />
-                                               <field name="Bridge-Hangup-Cause" type="first-of" value="variable_last_bridge_hangup_cause|variable_bridge_hangup_cause" />
+                                               <field name="Bridge-Hangup-Cause" type="first-of" value="variable_bridge_hangup_cause|variable_last_bridge_hangup_cause" />
                                                <field name="debug-call" type="reference" />
                                        </fields>
 
                         <field name="Resigning-Peer-UUID"/>
                         <field name="Acquired-UUID"/>
                         <field name="Acquired-UUID" as="Replaced-By"/>
+                        <field name="Connecting-Leg-A-UUID" />
+                        <field name="Connecting-Leg-B-UUID" />
                     </fields>
                 </event>
 
                                        </fields>
                                </event>
 
+                <event name="CHANNEL_METAFLOW">
+                    <fields verbose="false">
+                        <field name="call_event" type="reference" />
+                               <field name="from-to" type="reference" />                        
+                        <field name="user-agent" type="reference" />
+                        <field name="Metaflow-Collected-Digits"/>
+                    </fields>
+                </event>
+
                        </events>
                </profile>
        </event-handlers>
index 4905f09b33dd31a0891b860fa487f886ff196540..72e2afa18f9aaa58f674dc8cbc36b3cabb54a93e 100644 (file)
@@ -576,6 +576,321 @@ SWITCH_STANDARD_APP(kz_audio_bridge_function)
        }
 }
 
+SWITCH_STANDARD_APP(kz_audio_bridge_uuid_function)
+{
+       switch_core_session_t *peer_session = NULL;
+       const char * peer_uuid = NULL;
+
+       if (zstr(data)) {
+               return;
+       }
+
+       peer_uuid = switch_core_session_strdup(session, data);
+       if (peer_uuid && (peer_session = switch_core_session_locate(peer_uuid))) {
+               switch_ivr_multi_threaded_bridge(session, peer_session, NULL, NULL, NULL);
+       }
+
+       if (peer_session) {
+               switch_core_session_rwunlock(peer_session);
+       }
+}
+
+
+struct kz_att_keys {
+       const char *attxfer_cancel_key;
+       const char *attxfer_hangup_key;
+       const char *attxfer_conf_key;
+};
+
+static switch_status_t kz_att_xfer_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen)
+{
+       switch_core_session_t *peer_session = (switch_core_session_t *) buf;
+       if (!buf || !peer_session) {
+               return SWITCH_STATUS_SUCCESS;
+       }
+
+       switch (itype) {
+       case SWITCH_INPUT_TYPE_DTMF:
+               {
+                       switch_dtmf_t *dtmf = (switch_dtmf_t *) input;
+                       switch_channel_t *channel = switch_core_session_get_channel(session);
+                       switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
+                       struct kz_att_keys *keys = switch_channel_get_private(channel, "__kz_keys");
+
+                       if (dtmf->digit == *keys->attxfer_hangup_key) {
+                               switch_channel_hangup(channel, SWITCH_CAUSE_ATTENDED_TRANSFER);
+                               return SWITCH_STATUS_FALSE;
+                       }
+
+                       if (dtmf->digit == *keys->attxfer_cancel_key) {
+                               switch_channel_hangup(peer_channel, SWITCH_CAUSE_NORMAL_CLEARING);
+                               return SWITCH_STATUS_FALSE;
+                       }
+
+                       if (dtmf->digit == *keys->attxfer_conf_key) {
+                               switch_caller_extension_t *extension = NULL;
+                               const char *app = "three_way";
+                               const char *app_arg = switch_core_session_get_uuid(session);
+                               const char *holding = switch_channel_get_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE);
+                               switch_core_session_t *b_session;
+
+                               if (holding && (b_session = switch_core_session_locate(holding))) {
+                                       switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
+                                       if (!switch_channel_ready(b_channel)) {
+                                               app = "intercept";
+                                       }
+                                       switch_core_session_rwunlock(b_session);
+                               }
+
+                               if ((extension = switch_caller_extension_new(peer_session, app, app_arg)) == 0) {
+                                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n");
+                                       abort();
+                               }
+
+                               switch_caller_extension_add_application(peer_session, extension, app, app_arg);
+                               switch_channel_set_caller_extension(peer_channel, extension);
+                               switch_channel_set_state(peer_channel, CS_RESET);
+                               switch_channel_wait_for_state(peer_channel, channel, CS_RESET);
+                               switch_channel_set_state(peer_channel, CS_EXECUTE);
+                               switch_channel_set_variable(channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, NULL);
+                               return SWITCH_STATUS_FALSE;
+                       }
+
+               }
+               break;
+       default:
+               break;
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t kz_att_xfer_tmp_hanguphook(switch_core_session_t *session)
+{
+       switch_channel_t *channel = switch_core_session_get_channel(session);
+       switch_channel_state_t state = switch_channel_get_state(channel);
+
+       if (state == CS_HANGUP || state == CS_ROUTING) {
+               const char *bond = switch_channel_get_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE);
+
+               if (!zstr(bond)) {
+                       switch_core_session_t *b_session;
+
+                       if ((b_session = switch_core_session_locate(bond))) {
+                               switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
+                               if (switch_channel_up(b_channel)) {
+                                       switch_channel_set_flag(b_channel, CF_REDIRECT);
+                               }
+                               switch_core_session_rwunlock(b_session);
+                       }
+               }
+
+               switch_core_event_hook_remove_state_change(session, kz_att_xfer_tmp_hanguphook);
+       }
+
+       return SWITCH_STATUS_SUCCESS;
+}
+
+static switch_status_t kz_att_xfer_hanguphook(switch_core_session_t *session)
+{
+       switch_channel_t *channel = switch_core_session_get_channel(session);
+       switch_channel_state_t state = switch_channel_get_state(channel);
+       const char *id = NULL;
+
+       if (state == CS_HANGUP || state == CS_ROUTING) {
+               if ((id = switch_channel_get_variable(channel, "xfer_uuids"))) {
+                       switch_stream_handle_t stream = { 0 };
+                       SWITCH_STANDARD_STREAM(stream);
+                       switch_api_execute("uuid_bridge", id, NULL, &stream);
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "\nHangup Command uuid_bridge(%s):\n%s\n", id,
+                                                         switch_str_nil((char *) stream.data));
+                       switch_safe_free(stream.data);
+               }
+
+               switch_core_event_hook_remove_state_change(session, kz_att_xfer_hanguphook);
+       }
+       return SWITCH_STATUS_SUCCESS;
+}
+
+
+static void kz_att_xfer_set_result(switch_channel_t *channel, switch_status_t status)
+{
+       switch_channel_set_variable(channel, SWITCH_ATT_XFER_RESULT_VARIABLE, status == SWITCH_STATUS_SUCCESS ? "success" : "failure");
+}
+
+struct kz_att_obj {
+       switch_core_session_t *session;
+       const char *data;
+       int running;
+};
+
+void *SWITCH_THREAD_FUNC kz_att_thread_run(switch_thread_t *thread, void *obj)
+{
+       struct kz_att_obj *att = (struct kz_att_obj *) obj;
+       struct kz_att_keys *keys = NULL;
+       switch_core_session_t *session = att->session;
+       switch_core_session_t *peer_session = NULL;
+       const char *data = att->data;
+       switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING;
+       switch_channel_t *channel = switch_core_session_get_channel(session), *peer_channel = NULL;
+       const char *bond = NULL;
+       switch_core_session_t *b_session = NULL;
+       switch_bool_t follow_recording = switch_true(switch_channel_get_variable(channel, "recording_follow_attxfer"));
+       const char *attxfer_cancel_key = NULL, *attxfer_hangup_key = NULL, *attxfer_conf_key = NULL;
+
+       att->running = 1;
+
+       if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) {
+               return NULL;
+       }
+
+       bond = switch_channel_get_partner_uuid(channel);
+       if ((b_session = switch_core_session_locate(bond)) == NULL) {
+               switch_core_session_rwunlock(peer_session);
+               return NULL;
+       }
+
+       switch_channel_set_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE, bond);
+       switch_core_event_hook_add_state_change(session, kz_att_xfer_tmp_hanguphook);
+
+       if (follow_recording && (b_session = switch_core_session_locate(bond))) {
+               switch_ivr_transfer_recordings(b_session, session);
+               switch_core_session_rwunlock(b_session);
+       }
+
+       if (switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL)
+               != SWITCH_STATUS_SUCCESS || !peer_session) {
+               switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond);
+               goto end;
+       }
+
+       peer_channel = switch_core_session_get_channel(peer_session);
+       switch_channel_set_flag(peer_channel, CF_INNER_BRIDGE);
+       switch_channel_set_flag(channel, CF_INNER_BRIDGE);
+
+       if (!(attxfer_cancel_key = switch_channel_get_variable(channel, "attxfer_cancel_key"))) {
+               if (!(attxfer_cancel_key = switch_channel_get_variable(peer_channel, "attxfer_cancel_key"))) {
+                       attxfer_cancel_key = "#";
+               }
+       }
+
+       if (!(attxfer_hangup_key = switch_channel_get_variable(channel, "attxfer_hangup_key"))) {
+               if (!(attxfer_hangup_key = switch_channel_get_variable(peer_channel, "attxfer_hangup_key"))) {
+                       attxfer_hangup_key = "*";
+               }
+       }
+
+       if (!(attxfer_conf_key = switch_channel_get_variable(channel, "attxfer_conf_key"))) {
+               if (!(attxfer_conf_key = switch_channel_get_variable(peer_channel, "attxfer_conf_key"))) {
+                       attxfer_conf_key = "0";
+               }
+       }
+
+       keys = switch_core_session_alloc(session, sizeof(*keys));
+       keys->attxfer_cancel_key = switch_core_session_strdup(session, attxfer_cancel_key);
+       keys->attxfer_hangup_key = switch_core_session_strdup(session, attxfer_hangup_key);
+       keys->attxfer_conf_key = switch_core_session_strdup(session, attxfer_conf_key);
+       switch_channel_set_private(channel, "__kz_keys", keys);
+
+       switch_channel_set_variable(channel, "att_xfer_peer_uuid", switch_core_session_get_uuid(peer_session));
+
+       switch_ivr_multi_threaded_bridge(session, peer_session, kz_att_xfer_on_dtmf, peer_session, NULL);
+
+       switch_channel_clear_flag(peer_channel, CF_INNER_BRIDGE);
+       switch_channel_clear_flag(channel, CF_INNER_BRIDGE);
+
+       if (zstr(bond) && switch_channel_down(peer_channel)) {
+               switch_core_session_rwunlock(peer_session);
+               switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond);
+               goto end;
+       }
+
+       if (bond) {
+               int br = 0;
+
+               switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond);
+
+               if (!switch_channel_down(peer_channel)) {
+                       /*
+                        * we're emiting the transferee event so that callctl can update
+                        */
+                       switch_event_t *event = NULL;
+                       switch_channel_t *b_channel = switch_core_session_get_channel(b_session);
+                       if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "sofia::transferee") == SWITCH_STATUS_SUCCESS) {
+                               switch_channel_event_set_data(b_channel, event);
+                               switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_call_id", switch_core_session_get_uuid(peer_session));
+                               switch_event_fire(&event);
+                       }
+                       if (!switch_channel_ready(channel)) {
+                               switch_status_t status;
+
+                               if (follow_recording) {
+                                       switch_ivr_transfer_recordings(session, peer_session);
+                               }
+                               status = switch_ivr_uuid_bridge(switch_core_session_get_uuid(peer_session), bond);
+                               kz_att_xfer_set_result(peer_channel, status);
+                               br++;
+                       } else {
+                               switch_channel_set_variable_printf(b_channel, "xfer_uuids", "%s %s", switch_core_session_get_uuid(peer_session), switch_core_session_get_uuid(session));
+                               switch_channel_set_variable_printf(channel, "xfer_uuids", "%s %s", switch_core_session_get_uuid(peer_session), bond);
+
+                               switch_core_event_hook_add_state_change(session, kz_att_xfer_hanguphook);
+                               switch_core_event_hook_add_state_change(b_session, kz_att_xfer_hanguphook);
+                       }
+               }
+
+/*
+ * this was commented so that the existing bridge
+ * doesn't end
+ *
+               if (!br) {
+                       switch_status_t status = switch_ivr_uuid_bridge(switch_core_session_get_uuid(session), bond);
+                       att_xfer_set_result(channel, status);
+               }
+*/
+
+       }
+
+       switch_core_session_rwunlock(peer_session);
+
+  end:
+
+       switch_core_event_hook_remove_state_change(session, kz_att_xfer_tmp_hanguphook);
+
+       switch_channel_set_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE, NULL);
+       switch_channel_clear_flag(channel, CF_XFER_ZOMBIE);
+
+       switch_core_session_rwunlock(b_session);
+       switch_core_session_rwunlock(session);
+       att->running = 0;
+
+       return NULL;
+}
+
+SWITCH_STANDARD_APP(kz_att_xfer_function)
+{
+       switch_thread_t *thread;
+       switch_threadattr_t *thd_attr = NULL;
+       switch_memory_pool_t *pool = switch_core_session_get_pool(session);
+       struct kz_att_obj *att;
+       switch_channel_t *channel = switch_core_session_get_channel(session);
+
+       switch_threadattr_create(&thd_attr, pool);
+       switch_threadattr_detach_set(thd_attr, 1);
+       switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
+       switch_threadattr_detach_set(thd_attr, 1);
+
+       att = switch_core_session_alloc(session, sizeof(*att));
+       att->running = -1;
+       att->session = session;
+       att->data = switch_core_session_strdup(session, data);
+       switch_thread_create(&thread, thd_attr, kz_att_thread_run, att, pool);
+
+       while(att->running && switch_channel_up(channel)) {
+               switch_yield(100000);
+       }
+}
+
 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);
@@ -592,4 +907,6 @@ void add_kz_dptools(switch_loadable_module_interface_t **module_interface, switc
        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);
+       SWITCH_ADD_APP(app_interface, "kz_bridge_uuid", "Bridge Audio", "Bridge the audio between two sessions", kz_audio_bridge_uuid_function, "<channel_url>", SAF_SUPPORT_NOMEDIA|SAF_SUPPORT_TEXT_ONLY);
+       SWITCH_ADD_APP(app_interface, "kz_att_xfer", "Attended Transfer", "Attended Transfer", kz_att_xfer_function, "<channel_url>", SAF_NONE);
 }
index e3947420089fbabd7b8d4a8df5ceee81189f648e..3d844655b79e83fd572eaaa62ff5b4cf84c2a468 100644 (file)
@@ -139,6 +139,24 @@ struct ei_xml_agent_s {
 
 };
 
+typedef enum {
+       KZ_TWEAK_INTERACTION_ID,
+       KZ_TWEAK_EXPORT_VARS,
+       KZ_TWEAK_SWITCH_URI,
+       KZ_TWEAK_REPLACES_CALL_ID,
+       KZ_TWEAK_LOOPBACK_VARS,
+       KZ_TWEAK_CALLER_ID,
+       KZ_TWEAK_TRANSFERS,
+       KZ_TWEAK_BRIDGE,
+       KZ_TWEAK_BRIDGE_REPLACES_ALEG,
+       KZ_TWEAK_BRIDGE_REPLACES_CALL_ID,
+       KZ_TWEAK_BRIDGE_VARIABLES,
+       KZ_TWEAK_RESTORE_CALLER_ID_ON_BLIND_XFER,
+
+       /* No new flags below this line */
+       KZ_TWEAK_MAX
+} kz_tweak_t;
+
 struct globals_s {
        switch_memory_pool_t *pool;
        switch_atomic_t threads;
@@ -164,8 +182,6 @@ struct globals_s {
        char *hostname;
        char *ei_cookie;
        char *ei_nodename;
-//     char *kazoo_var_prefix;
-//     int var_prefix_length;
        uint32_t flags;
        int send_all_headers;
        int send_all_private_headers;
@@ -184,11 +200,13 @@ struct globals_s {
        kazoo_config_ptr fetch_handlers;
        kazoo_json_term  json_encoding;
 
-       int enable_legacy;
        char **profile_vars_prefixes;
        char **kazoo_var_prefixes;
 
-       int tweaks_restore_caller_id;
+       int legacy_events;
+       uint8_t tweaks[KZ_TWEAK_MAX];
+
+
 };
 typedef struct globals_s globals_t;
 extern globals_t kazoo_globals;
@@ -254,6 +272,12 @@ switch_status_t kazoo_config_handlers(switch_xml_t cfg);
 /* runtime */
 SWITCH_MODULE_RUNTIME_FUNCTION(mod_kazoo_runtime);
 
+
+
+#define kz_test_tweak(flag) (kazoo_globals.tweaks[flag] ? 1 : 0)
+#define kz_set_tweak(flag) kazoo_globals.tweaks[flag] = 1
+#define kz_clear_tweak(flag) kazoo_globals.tweaks[flag] = 0
+
 #endif /* KAZOO_EI_H */
 
 /* For Emacs:
index 3f396103f8749e38dfe687df7cd01bae78b2d136..9357211afb7e0c7228acf737886039381a68a7fe 100644 (file)
@@ -113,8 +113,22 @@ switch_status_t kazoo_ei_config(switch_xml_t cfg) {
        kazoo_globals.port = 0;
        kazoo_globals.io_fault_tolerance = 10;
        kazoo_globals.json_encoding = ERLANG_TUPLE;
-       kazoo_globals.enable_legacy = SWITCH_FALSE;
-       kazoo_globals.tweaks_restore_caller_id = SWITCH_TRUE;
+
+       kazoo_globals.legacy_events = SWITCH_FALSE;
+
+       kz_set_tweak(KZ_TWEAK_INTERACTION_ID);
+       kz_set_tweak(KZ_TWEAK_EXPORT_VARS);
+       kz_set_tweak(KZ_TWEAK_SWITCH_URI);
+       kz_set_tweak(KZ_TWEAK_REPLACES_CALL_ID);
+       kz_set_tweak(KZ_TWEAK_LOOPBACK_VARS);
+       kz_set_tweak(KZ_TWEAK_CALLER_ID);
+       kz_set_tweak(KZ_TWEAK_TRANSFERS);
+       kz_set_tweak(KZ_TWEAK_BRIDGE);
+       kz_set_tweak(KZ_TWEAK_BRIDGE_REPLACES_ALEG);
+       kz_set_tweak(KZ_TWEAK_BRIDGE_REPLACES_CALL_ID);
+       kz_set_tweak(KZ_TWEAK_BRIDGE_VARIABLES);
+       kz_set_tweak(KZ_TWEAK_RESTORE_CALLER_ID_ON_BLIND_XFER);
+
 
 
        if ((child = switch_xml_child(cfg, "settings"))) {
@@ -186,12 +200,24 @@ switch_status_t kazoo_ei_config(switch_xml_t cfg) {
                                if(!strcmp(val, "map")) {
                                        kazoo_globals.json_encoding = ERLANG_MAP;
                                }
-                       } else if (!strcmp(var, "enable-legacy")) {
-                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set enable-legacy: %s\n", val);
-                               kazoo_globals.enable_legacy = switch_true(val);
-                       } else if (!strcmp(var, "tweaks-restore-caller-id")) {
-                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set tweaks-restore-caller-id: %s\n", val);
-                               kazoo_globals.tweaks_restore_caller_id = switch_true(val);
+                       } else if (!strcmp(var, "legacy-events")) {
+                               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set legacy-events: %s\n", val);
+                               kazoo_globals.legacy_events = switch_true(val);
+                       }
+               }
+       }
+
+       if ((child = switch_xml_child(cfg, "tweaks"))) {
+               for (param = switch_xml_child(child, "tweak"); param; param = param->next) {
+                       kz_tweak_t tweak = KZ_TWEAK_MAX;
+                       char *var = (char *) switch_xml_attr_soft(param, "name");
+                       char *val = (char *) switch_xml_attr_soft(param, "value");
+                       if(var && val && kz_name_tweak(var, &tweak) == SWITCH_STATUS_SUCCESS) {
+                               if(switch_true(val)) {
+                                       kz_set_tweak(tweak);
+                               } else {
+                                       kz_clear_tweak(tweak);
+                               }
                        }
                }
        }
index 094b9107514b553cee2337d9d1ea98bb5d3b99af..8d416a8317dd8aac09c6fe385383d56dc6868b38 100644 (file)
@@ -201,6 +201,8 @@ static void event_handler(switch_event_t *event) {
 
        ei_x_encode_version(ebuf);
 
+       switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Target-Node", event_binding->stream->node->peer_nodename);
+
        if(event_stream->node->legacy) {
                switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Switch-Nodename", kazoo_globals.ei_cnode.thisnodename);
                res = encode_event_old(event, ebuf);
index 9b1f06afd467cc918aaad4a46482802efe522308..a92fe49aa23ba380d69b7cc28c273f427e4473a5 100644 (file)
@@ -64,7 +64,8 @@ static char *REQUEST_ATOMS[] = {
        "fetch_reply",
        "config",
        "bgapi4",
-       "api4"
+       "api4",
+       "json_api"
 };
 
 typedef enum {
@@ -86,6 +87,7 @@ typedef enum {
        REQUEST_CONFIG,
        REQUEST_BGAPI4,
        REQUEST_API4,
+       REQUEST_JSON_API,
        REQUEST_MAX
 } request_atoms_t;
 
@@ -925,10 +927,10 @@ static switch_status_t handle_request_api4(ei_node_t *ei_node, erlang_pid *pid,
                status = api_exec_stream(cmd, arg, &stream, &reply);
 
                if (status == SWITCH_STATUS_SUCCESS) {
-                       ei_x_encode_tuple_header(buf, 2);
+                       ei_x_encode_tuple_header(rbuf, 2);
                        ei_x_encode_atom(rbuf, "ok");
                } else {
-                       ei_x_encode_tuple_header(buf, (stream.param_event ? 3 : 2));
+                       ei_x_encode_tuple_header(rbuf, (stream.param_event ? 3 : 2));
                        ei_x_encode_atom(rbuf, "error");
                }
 
@@ -951,6 +953,61 @@ static switch_status_t handle_request_api4(ei_node_t *ei_node, erlang_pid *pid,
         return SWITCH_STATUS_SUCCESS;
 }
 
+static switch_status_t handle_request_json_api(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf)
+{
+    char *arg;
+       cJSON *jcmd = NULL;
+       switch_core_session_t *session = NULL;
+       const char *uuid = NULL;
+       char *response = NULL;
+       const char *parse_end = NULL;
+       switch_status_t status = SWITCH_STATUS_SUCCESS;
+
+    if (ei_decode_string_or_binary(buf->buff, &buf->index, &arg)) {
+            return erlang_response_badarg(rbuf);
+    }
+
+    jcmd = cJSON_ParseWithOpts(arg, &parse_end, 0);
+
+       if (!jcmd) {
+           switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "json api error: %s\n", parse_end);
+               ei_x_encode_tuple_header(rbuf, 2);
+               ei_x_encode_atom(rbuf, "error");
+               ei_x_encode_tuple_header(rbuf, 2);
+               ei_x_encode_atom(rbuf, "parse_error");
+               _ei_x_encode_string(rbuf, parse_end);
+               return status;
+       }
+
+       if ((uuid = cJSON_GetObjectCstr(jcmd, "uuid"))) {
+               if (!(session = switch_core_session_locate(uuid))) {
+                       return erlang_response_baduuid(rbuf);
+               }
+       }
+
+       status = switch_json_api_execute(jcmd, session, NULL);
+    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "json api (%i): %s\n", status , arg);
+
+       response = cJSON_PrintUnformatted(jcmd);
+       ei_x_encode_tuple_header(rbuf, 2);
+       if (status == SWITCH_STATUS_SUCCESS) {
+               ei_x_encode_atom(rbuf, "ok");
+       } else {
+               ei_x_encode_atom(rbuf, "error");
+       }
+       _ei_x_encode_string(rbuf, response);
+       switch_safe_free(response);
+
+    cJSON_Delete(jcmd);
+    switch_safe_free(arg);
+
+       if (session) {
+               switch_core_session_rwunlock(session);
+       }
+
+    return SWITCH_STATUS_SUCCESS;
+}
+
 static switch_status_t handle_request_api(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) {
        char cmd[MAXATOMLEN + 1];
        char *arg;
@@ -963,7 +1020,7 @@ static switch_status_t handle_request_api(ei_node_t *ei_node, erlang_pid *pid, e
                return erlang_response_badarg(rbuf);
        }
 
-       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "exec: %s(%s)\n", cmd, arg);
+       switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "exec: %s(%s)\n", cmd, arg);
 
        if (rbuf) {
                char *reply;
@@ -1100,12 +1157,12 @@ static switch_status_t handle_kazoo_request(ei_node_t *ei_node, erlang_pid *pid,
        }
 
        if (ei_decode_atom_safe(buf->buff, &buf->index, atom)) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Recieved mod_kazoo message that did not contain a command (ensure you are using Kazoo v2.14+).\n");
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received mod_kazoo message that did not contain a command (ensure you are using Kazoo v2.14+).\n");
                return erlang_response_badarg(rbuf);
        }
 
        if (find_request(atom, &request) != SWITCH_STATUS_SUCCESS) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Recieved mod_kazoo message for unimplemented feature (ensure you are using Kazoo v2.14+): %s\n", atom);
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received mod_kazoo message for unimplemented feature (ensure you are using Kazoo v2.14+): %s\n", atom);
                return erlang_response_badarg(rbuf);
        }
 
@@ -1146,6 +1203,8 @@ static switch_status_t handle_kazoo_request(ei_node_t *ei_node, erlang_pid *pid,
                return handle_request_bgapi4(ei_node, pid, buf, rbuf);
        case REQUEST_API4:
                return handle_request_api4(ei_node, pid, buf, rbuf);
+       case REQUEST_JSON_API:
+               return handle_request_json_api(ei_node, pid, buf, rbuf);
        default:
                return erlang_response_notimplemented(rbuf);
        }
@@ -1168,7 +1227,7 @@ static switch_status_t handle_mod_kazoo_request(ei_node_t *ei_node, erlang_msg *
        ei_decode_tuple_header(buf->buff, &buf->index, &arity);
 
        if (ei_decode_atom_safe(buf->buff, &buf->index, atom)) {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Recieved erlang message tuple that did not start with an atom (ensure you are using Kazoo v2.14+).\n");
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received erlang message tuple that did not start with an atom (ensure you are using Kazoo v2.14+).\n");
                return SWITCH_STATUS_GENERR;
        }
 
@@ -1224,7 +1283,7 @@ static switch_status_t handle_mod_kazoo_request(ei_node_t *ei_node, erlang_msg *
 
                return status;
        } else {
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Recieved inappropriate erlang message (ensure you are using Kazoo v2.14+)\n");
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received inappropriate erlang message (ensure you are using Kazoo v2.14+)\n");
                return SWITCH_STATUS_GENERR;
        }
 }
@@ -1547,7 +1606,7 @@ switch_status_t new_kazoo_node(int nodefd, ErlConnect *conn) {
        ei_node->nodefd = nodefd;
        ei_node->peer_nodename = switch_core_strdup(ei_node->pool, conn->nodename);
        ei_node->created_time = switch_micro_time_now();
-       ei_node->legacy = kazoo_globals.enable_legacy;
+       ei_node->legacy = kazoo_globals.legacy_events;
        ei_node->event_stream_framing = kazoo_globals.event_stream_framing;
 
        /* store the IP and node name we are talking with */
index a1bd6a08766c3287deffa661825cae91a57bd9ef..19aa19980d9c9f59100e8534514d8c1583b84ce1 100644 (file)
 
 #define INTERACTION_VARIABLE "Call-Interaction-ID"
 
+static char *TWEAK_NAMES[] = {
+       "interaction-id",
+       "export-vars",
+       "switch-uri",
+       "replaces-call-id",
+       "loopback-vars",
+       "caller-id",
+       "transfers",
+       "bridge",
+       "bridge-replaces-aleg",
+       "bridge-replaces-call-id",
+       "bridge-variables",
+       "restore-caller-id-on-blind-xfer"
+};
+
 static const char *bridge_variables[] = {
                "Call-Control-Queue",
                "Call-Control-PID",
@@ -83,7 +98,7 @@ static void kz_tweaks_handle_bridge_variables(switch_event_t *event)
        const char *b_leg = switch_event_get_header(event, "Bridge-B-Unique-ID");
        int i;
 
-       if (kazoo_globals.enable_legacy) return;
+       if (!kz_test_tweak(KZ_TWEAK_BRIDGE_VARIABLES)) return;
 
        if (a_leg && (a_session = switch_core_session_force_locate(a_leg)) != NULL) {
                switch_channel_t *a_channel = switch_core_session_get_channel(a_session);
@@ -115,7 +130,7 @@ static void kz_tweaks_handle_bridge_variables(switch_event_t *event)
 
 }
 
-static void kz_tweaks_handle_bridge_replaces(switch_event_t *event)
+static void kz_tweaks_handle_bridge_replaces_aleg(switch_event_t *event)
 {
        switch_event_t *my_event;
 
@@ -124,7 +139,7 @@ static void kz_tweaks_handle_bridge_replaces(switch_event_t *event)
        const char *peer_uuid = switch_event_get_header(event, "Unique-ID");
        int processed = 0;
 
-       if (kazoo_globals.enable_legacy) return;
+       if (!kz_test_tweak(KZ_TWEAK_BRIDGE_REPLACES_ALEG)) return;
 
 
        if(a_leg_call_id && replaced_call_id) {
@@ -171,7 +186,7 @@ static void kz_tweaks_handle_bridge_replaces_call_id(switch_event_t *event)
        const char *a_leg_call_id =     switch_event_get_header(event, "variable_sip_replaces_a-leg");
        const char *peer_uuid = switch_event_get_header(event, "Unique-ID");
 
-       if (kazoo_globals.enable_legacy) return;
+       if (!kz_test_tweak(KZ_TWEAK_BRIDGE_REPLACES_CALL_ID)) return;
 
        if(a_leg_call_id && replaced_call_id) {
                switch_core_session_t *call_session = NULL;
@@ -196,10 +211,10 @@ static void kz_tweaks_handle_bridge_replaces_call_id(switch_event_t *event)
 
 static void kz_tweaks_channel_bridge_event_handler(switch_event_t *event)
 {
-       if (kazoo_globals.enable_legacy) return;
+       if (!kz_test_tweak(KZ_TWEAK_BRIDGE)) return;
 
        kz_tweaks_handle_bridge_replaces_call_id(event);
-       kz_tweaks_handle_bridge_replaces(event);
+       kz_tweaks_handle_bridge_replaces_aleg(event);
        kz_tweaks_handle_bridge_variables(event);
 }
 
@@ -209,7 +224,8 @@ static void kz_tweaks_channel_replaced_event_handler(switch_event_t *event)
 {
        const char *uuid = switch_event_get_header(event, "Unique-ID");
        const char *replaced_by = switch_event_get_header(event, "att_xfer_replaced_by");
-       if (kazoo_globals.enable_legacy) return;
+
+       if (!kz_test_tweak(KZ_TWEAK_TRANSFERS)) return;
 
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "REPLACED : %s , %s\n", uuid, replaced_by);
 }
@@ -219,7 +235,7 @@ static void kz_tweaks_channel_intercepted_event_handler(switch_event_t *event)
        const char *uuid = switch_event_get_header(event, "Unique-ID");
        const char *peer_uuid = switch_event_get_header(event, "intercepted_by");
 
-       if (kazoo_globals.enable_legacy) return;
+       if (!kz_test_tweak(KZ_TWEAK_TRANSFERS)) return;
 
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "INTERCEPTED : %s => %s\n", uuid, peer_uuid);
 }
@@ -238,7 +254,7 @@ static void kz_tweaks_channel_transferor_event_handler(switch_event_t *event)
        const char *func = switch_event_get_header(event, "Event-Calling-Function");
        const char *line = switch_event_get_header(event, "Event-Calling-Line-Number");
 
-       if (kazoo_globals.enable_legacy) return;
+       if (!kz_test_tweak(KZ_TWEAK_TRANSFERS)) return;
 
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR : %s , %s , %s, %s, %s , %s , %s \n", uuid, orig_call_id, dest_peer_uuid, dest_call_id, file, func, line);
        if ((uuid_session = switch_core_session_force_locate(uuid)) != NULL) {
@@ -304,7 +320,7 @@ static void kz_tweaks_channel_transferee_event_handler(switch_event_t *event)
        const char *uuid = switch_event_get_header(event, "Unique-ID");
        const char *replaced_by_uuid = switch_event_get_header(event, "att_xfer_replaced_call_id");
 
-       if (kazoo_globals.enable_legacy) return;
+       if (!kz_test_tweak(KZ_TWEAK_TRANSFERS)) return;
 
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEREE : %s replaced by %s\n", uuid, replaced_by_uuid);
 }
@@ -326,6 +342,10 @@ static switch_status_t kz_tweaks_handle_loopback(switch_core_session_t *session)
        switch_caller_profile_t *caller;
        int n = 0;
 
+       if (!kz_test_tweak(KZ_TWEAK_LOOPBACK_VARS)) {
+               return SWITCH_STATUS_SUCCESS;
+       }
+
        caller = switch_channel_get_caller_profile(channel);
        if(strncmp(caller->source, "mod_loopback", 12))
                return SWITCH_STATUS_SUCCESS;
@@ -380,12 +400,14 @@ static switch_status_t kz_tweaks_handle_loopback(switch_core_session_t *session)
         *  set Interaction-ID
         *  if we're not crossing account boundaries
         */
-       if (a_channel) {
-               const char *interaction_id = switch_channel_get_variable_dup(a_channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1);
-               const char *a_account_id  = switch_channel_get_variable_dup(a_channel, "ecallmgr_Account-ID", SWITCH_FALSE, -1);
-               const char *b_account_id  = switch_channel_get_variable_dup(channel, "ecallmgr_Account-ID", SWITCH_FALSE, -1);
-               if ((!a_account_id) || (!b_account_id) || (!strcmp(a_account_id, b_account_id))) {
-                       switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id);
+       if (kz_test_tweak(KZ_TWEAK_INTERACTION_ID)) {
+               if (a_channel) {
+                       const char *interaction_id = switch_channel_get_variable_dup(a_channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1);
+                       const char *a_account_id  = switch_channel_get_variable_dup(a_channel, "ecallmgr_Account-ID", SWITCH_FALSE, -1);
+                       const char *b_account_id  = switch_channel_get_variable_dup(channel, "ecallmgr_Account-ID", SWITCH_FALSE, -1);
+                       if ((!a_account_id) || (!b_account_id) || (!strcmp(a_account_id, b_account_id))) {
+                               switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id);
+                       }
                }
        }
 
@@ -402,18 +424,20 @@ static switch_status_t kz_tweaks_handle_loopback(switch_core_session_t *session)
 
 static void kz_tweaks_handle_caller_id(switch_core_session_t *session)
 {
-       switch_channel_t *channel = switch_core_session_get_channel(session);
-       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 (caller && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
-               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;
+       if (kz_test_tweak(KZ_TWEAK_CALLER_ID)) {
+               switch_channel_t *channel = switch_core_session_get_channel(session);
+               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 (caller && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) {
+                       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;
+                       }
                }
        }
 }
@@ -442,26 +466,28 @@ static switch_status_t kz_tweaks_handle_auth_token(switch_core_session_t *sessio
 }
 */
 
-static switch_status_t kz_tweaks_handle_nightmare_xfer(switch_core_session_t *session)
+static switch_status_t kz_tweaks_handle_nightmare_xfer_interaction_id(switch_core_session_t *session)
 {
-       switch_core_session_t *replace_session = NULL;
-       switch_channel_t *channel = switch_core_session_get_channel(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");
-       const char *partner_uuid = switch_channel_get_variable(channel, "sip_h_X-FS-Refer-Partner-UUID");
-       const char *interaction_id = switch_channel_get_variable(channel, "sip_h_X-FS-Call-Interaction-ID");
-       if(core_uuid && partner_uuid && replaced_call_id && interaction_id) {
-               switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id);
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "checking nightmare xfer tweak for %s\n", switch_channel_get_uuid(channel));
-               if ((replace_session = switch_core_session_locate(replaced_call_id))) {
-                       switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_session);
-                       switch_channel_set_variable(replaced_call_channel, INTERACTION_VARIABLE, interaction_id);
-                       switch_core_session_rwunlock(replace_session);
-               }
-               if ((replace_session = switch_core_session_locate(partner_uuid))) {
-                       switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_session);
-                       switch_channel_set_variable(replaced_call_channel, INTERACTION_VARIABLE, interaction_id);
-                       switch_core_session_rwunlock(replace_session);
+       if (kz_test_tweak(KZ_TWEAK_INTERACTION_ID)) {
+               switch_core_session_t *replace_session = NULL;
+               switch_channel_t *channel = switch_core_session_get_channel(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");
+               const char *partner_uuid = switch_channel_get_variable(channel, "sip_h_X-FS-Refer-Partner-UUID");
+               const char *interaction_id = switch_channel_get_variable(channel, "sip_h_X-FS-Call-Interaction-ID");
+               if(core_uuid && partner_uuid && replaced_call_id && interaction_id) {
+                       switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id);
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "checking nightmare xfer tweak for %s\n", switch_channel_get_uuid(channel));
+                       if ((replace_session = switch_core_session_locate(replaced_call_id))) {
+                               switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_session);
+                               switch_channel_set_variable(replaced_call_channel, INTERACTION_VARIABLE, interaction_id);
+                               switch_core_session_rwunlock(replace_session);
+                       }
+                       if ((replace_session = switch_core_session_locate(partner_uuid))) {
+                               switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_session);
+                               switch_channel_set_variable(replaced_call_channel, INTERACTION_VARIABLE, interaction_id);
+                               switch_core_session_rwunlock(replace_session);
+                       }
                }
        }
 
@@ -469,29 +495,31 @@ static switch_status_t kz_tweaks_handle_nightmare_xfer(switch_core_session_t *se
 
 }
 
-static switch_status_t kz_tweaks_handle_replaces_id(switch_core_session_t *session)
+static switch_status_t kz_tweaks_handle_replaces_call_id(switch_core_session_t *session)
 {
-       switch_core_session_t *replace_call_session = NULL;
-       switch_event_t *event;
-       switch_channel_t *channel = switch_core_session_get_channel(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))) {
-                       switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_call_session);
-                       int i;
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "setting bridge variables from %s to %s\n", replaced_call_id, switch_channel_get_uuid(channel));
-                       for(i = 0; bridge_variables[i] != NULL; i++) {
-                               const char *val = switch_channel_get_variable_dup(replaced_call_channel, bridge_variables[i], SWITCH_TRUE, -1);
-                               switch_channel_set_variable(channel, bridge_variables[i], val);
-                               switch_safe_strdup(val);
-                       }
-                       if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
-                               switch_channel_event_set_data(channel, event);
-                               switch_event_fire(&event);
+       if (kz_test_tweak(KZ_TWEAK_REPLACES_CALL_ID)) {
+               switch_core_session_t *replace_call_session = NULL;
+               switch_event_t *event;
+               switch_channel_t *channel = switch_core_session_get_channel(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))) {
+                               switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_call_session);
+                               int i;
+                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "setting bridge variables from %s to %s\n", replaced_call_id, switch_channel_get_uuid(channel));
+                               for(i = 0; bridge_variables[i] != NULL; i++) {
+                                       const char *val = switch_channel_get_variable_dup(replaced_call_channel, bridge_variables[i], SWITCH_TRUE, -1);
+                                       switch_channel_set_variable(channel, bridge_variables[i], val);
+                                       switch_safe_strdup(val);
+                               }
+                               if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) {
+                                       switch_channel_event_set_data(channel, event);
+                                       switch_event_fire(&event);
+                               }
+                               switch_core_session_rwunlock(replace_call_session);
                        }
-                       switch_core_session_rwunlock(replace_call_session);
                }
        }
 
@@ -503,11 +531,13 @@ static switch_status_t kz_tweaks_handle_replaces_id(switch_core_session_t *sessi
 static switch_status_t kz_tweaks_handle_switch_uri(switch_core_session_t *session)
 {
        switch_channel_t *channel = switch_core_session_get_channel(session);
-       const char *profile_url = switch_channel_get_variable(channel, "sofia_profile_url");
-       if(profile_url) {
-               int n = strcspn(profile_url, "@");
-               switch_channel_set_variable(channel, "Switch-URL", profile_url);
-               switch_channel_set_variable_printf(channel, "Switch-URI", "sip:%s", n > 0 ? profile_url + n + 1 : profile_url);
+       if (kz_test_tweak(KZ_TWEAK_SWITCH_URI)) {
+               const char *profile_url = switch_channel_get_variable(channel, "sofia_profile_url");
+               if(profile_url) {
+                       int n = strcspn(profile_url, "@");
+                       switch_channel_set_variable(channel, "Switch-URL", profile_url);
+                       switch_channel_set_variable_printf(channel, "Switch-URI", "sip:%s", n > 0 ? profile_url + n + 1 : profile_url);
+               }
        }
 
        return SWITCH_STATUS_SUCCESS;
@@ -518,49 +548,54 @@ static void kz_tweaks_handle_interaction_id(switch_core_session_t *session)
 {
        const char *expr = "${expr(ceil((${Event-Date-Timestamp} / 1000000) + $${UNIX_EPOCH_IN_GREGORIAN}))}-${regex(${create_uuid()}|^([^-]*)|%1)}";
        switch_channel_t *channel = switch_core_session_get_channel(session);
-       char * val = kz_expand(expr);
+       char * val = NULL;
        switch_core_session_t *peer_session = NULL;
        const char* peer_interaction_id = NULL;
 
-       if (val) {
-               switch_channel_set_variable(channel, "Original-"INTERACTION_VARIABLE, val);
-               if(switch_core_session_get_partner(session, &peer_session) == SWITCH_STATUS_SUCCESS) {
-                       switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
-                       peer_interaction_id = switch_channel_get_variable_dup(peer_channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1);
-                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "PEER_SESSION => %s\n", peer_interaction_id);
-                       if(peer_interaction_id) {
-                               switch_channel_set_variable(channel, INTERACTION_VARIABLE, peer_interaction_id);
+       if (kz_test_tweak(KZ_TWEAK_INTERACTION_ID)) {
+               val = kz_expand(expr);
+               if (val) {
+                       switch_channel_set_variable(channel, "Original-"INTERACTION_VARIABLE, val);
+                       if(switch_core_session_get_partner(session, &peer_session) == SWITCH_STATUS_SUCCESS) {
+                               switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
+                               peer_interaction_id = switch_channel_get_variable_dup(peer_channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1);
+                               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "PEER_SESSION => %s\n", peer_interaction_id);
+                               if(peer_interaction_id) {
+                                       switch_channel_set_variable(channel, INTERACTION_VARIABLE, peer_interaction_id);
+                               }
+                               switch_core_session_rwunlock(peer_session);
+                       } else if (!switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1)) {
+                               switch_channel_set_variable(channel, INTERACTION_VARIABLE, val);
                        }
-                       switch_core_session_rwunlock(peer_session);
-               } else if (!switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1)) {
-                       switch_channel_set_variable(channel, INTERACTION_VARIABLE, val);
                }
-       }
 
-       switch_safe_free(val);
+               switch_safe_free(val);
+       }
 
 }
 
 static switch_status_t kz_outgoing_channel(switch_core_session_t * session, switch_event_t * event, switch_caller_profile_t * cp, switch_core_session_t * peer_session, switch_originate_flag_t flag)
 {
-       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "GOT OUTGOING\n");
-       if (peer_session) {
-               switch_channel_t *channel = switch_core_session_get_channel(session);
-               const char* interaction_id = switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1);
-               switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "SESSION && PEER_SESSION => %s\n", interaction_id );
-               if (interaction_id) {
-                       switch_channel_set_variable(peer_channel, INTERACTION_VARIABLE, interaction_id);
+       if (kz_test_tweak(KZ_TWEAK_INTERACTION_ID)) {
+               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "GOT OUTGOING\n");
+               if (peer_session) {
+                       switch_channel_t *channel = switch_core_session_get_channel(session);
+                       const char* interaction_id = switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1);
+                       switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session);
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "SESSION && PEER_SESSION => %s\n", interaction_id );
+                       if (interaction_id) {
+                               switch_channel_set_variable(peer_channel, INTERACTION_VARIABLE, interaction_id);
+                       }
+               } else {
+                       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "NO SESSION && PEER_SESSION\n");
                }
-       } else {
-               switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "NO SESSION && PEER_SESSION\n");
        }
        return SWITCH_STATUS_SUCCESS;
 }
 
-static switch_status_t kz_tweaks_register_handle_xfer(switch_core_session_t *session)
+static switch_status_t kz_tweaks_register_handle_blind_xfer(switch_core_session_t *session)
 {
-       if (kazoo_globals.tweaks_restore_caller_id) {
+       if (kz_test_tweak(KZ_TWEAK_RESTORE_CALLER_ID_ON_BLIND_XFER)) {
                switch_channel_t *channel = switch_core_session_get_channel(session);
                switch_channel_set_variable(channel, "execute_on_blind_transfer", "kz_restore_caller_id");
        }
@@ -570,23 +605,24 @@ static switch_status_t kz_tweaks_register_handle_xfer(switch_core_session_t *ses
 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 (kz_test_tweak(KZ_TWEAK_EXPORT_VARS)) {
+               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;
-       }
+               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_channel_set_variable(channel, SWITCH_EXPORT_VARS_VARIABLE, new_exports);
 
-       switch_safe_free(new_exports_d);
+               switch_safe_free(new_exports_d);
+       }
 
 
        return SWITCH_STATUS_SUCCESS;
@@ -595,18 +631,17 @@ static switch_status_t kz_tweaks_set_export_vars(switch_core_session_t *session)
 static switch_status_t kz_tweaks_on_init(switch_core_session_t *session)
 {
        switch_channel_t *channel = switch_core_session_get_channel(session);
-       if (kazoo_globals.enable_legacy) return SWITCH_STATUS_SUCCESS;
-       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "checking tweaks for %s\n", switch_channel_get_uuid(channel));
+       switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "checking tweaks for %s\n", switch_channel_get_uuid(channel));
        switch_channel_set_flag(channel, CF_VERBOSE_EVENTS);
        switch_core_event_hook_add_outgoing_channel(session, kz_outgoing_channel);
        kz_tweaks_handle_interaction_id(session);
        kz_tweaks_handle_switch_uri(session);
        kz_tweaks_handle_caller_id(session);
 //     kz_tweaks_handle_auth_token(session);
-       kz_tweaks_handle_nightmare_xfer(session);
-       kz_tweaks_handle_replaces_id(session);
+       kz_tweaks_handle_nightmare_xfer_interaction_id(session);
+       kz_tweaks_handle_replaces_call_id(session);
        kz_tweaks_handle_loopback(session);
-       kz_tweaks_register_handle_xfer(session);
+       kz_tweaks_register_handle_blind_xfer(session);
        kz_tweaks_set_export_vars(session);
 
        return SWITCH_STATUS_SUCCESS;
@@ -693,6 +728,24 @@ void kz_tweaks_stop()
        kz_tweaks_unregister_state_handlers();
 }
 
+SWITCH_DECLARE(const char *) kz_tweak_name(kz_tweak_t tweak)
+{
+       return TWEAK_NAMES[tweak];
+}
+
+SWITCH_DECLARE(switch_status_t) kz_name_tweak(const char *name, kz_tweak_t *type)
+{
+       kz_tweak_t x;
+       for (x = 0; x < KZ_TWEAK_MAX; x++) {
+               if (!strcasecmp(name, TWEAK_NAMES[x])) {
+                       *type = x;
+                       return SWITCH_STATUS_SUCCESS;
+               }
+       }
+
+       return SWITCH_STATUS_FALSE;
+}
+
 /* For Emacs:
  * Local Variables:
  * mode:c
index bbf511a28000047841cccb2fc68799116679ec94..1fc12ba2aa2503bc3570846bc59d1b14604727fa 100644 (file)
@@ -57,6 +57,8 @@ void add_kz_endpoints(switch_loadable_module_interface_t **module_interface);
 /* kazoo_tweaks.c */
 void kz_tweaks_start();
 void kz_tweaks_stop();
+SWITCH_DECLARE(const char *) kz_tweak_name(kz_tweak_t tweak);
+SWITCH_DECLARE(switch_status_t) kz_name_tweak(const char *name, kz_tweak_t *type);
 
 /* kazoo_node.c */
 void add_kz_node(switch_loadable_module_interface_t **module_interface);