From 59551f0fd0c7351b2abd92df78d671aaa0019a82 Mon Sep 17 00:00:00 2001 From: Andrey Volk Date: Thu, 5 Mar 2020 20:48:40 +0400 Subject: [PATCH] [mod_kazoo] some fixes & enhancements * [mod_kazoo] address scan-build warnings * [mod_kazoo] don't use switch_core_session_force_locate * [mod_kazoo] add loglevel support per event * [mod_kazoo] add option to serialize as array * [mod_kazoo] handle verbose fields * [mod_kazoo] handle _body header field * [mod_kazoo] ensure raw json is valid * [mod_kazoo] encode json number encodes double as unsigned long long if possible note: file was formatted * [mod_kazoo] fix tweaks configuration * [mod_kazoo] move headers to proper place * to use Target-Node in filtering we need to add and then remove it since the next node uses the same event to build the message * [mod_kazoo] handle cleanup in new_event_stream * [mod_kazoo] do not decode _json_ headers * [mod_kazoo] add kz_cdr event * fires the event in report state * adds json serialized parts that can be included in event message * moves history funcs from kazoo_commands to kazoo_cdr * [mod_kazoo] format default configuration * [mod_kazoo] validate bracket creation * [mod_kazoo] use single fd for kz_http_put * [mod_kazoo] add uuid to kz_expand --- src/mod/event_handlers/mod_kazoo/Makefile.am | 1 + .../event_handlers/mod_kazoo/kazoo.conf.xml | 1518 +++++++++-------- src/mod/event_handlers/mod_kazoo/kazoo_api.c | 1 - src/mod/event_handlers/mod_kazoo/kazoo_cdr.c | 630 +++++++ .../event_handlers/mod_kazoo/kazoo_commands.c | 218 +-- .../event_handlers/mod_kazoo/kazoo_config.c | 17 + .../event_handlers/mod_kazoo/kazoo_dptools.c | 2 +- .../mod_kazoo/kazoo_ei_config.c | 9 +- .../event_handlers/mod_kazoo/kazoo_ei_utils.c | 622 +++---- .../mod_kazoo/kazoo_endpoints.c | 2 +- .../mod_kazoo/kazoo_event_stream.c | 39 +- .../mod_kazoo/kazoo_fetch_agent.c | 4 +- .../event_handlers/mod_kazoo/kazoo_fields.h | 6 + .../event_handlers/mod_kazoo/kazoo_message.c | 78 +- src/mod/event_handlers/mod_kazoo/kazoo_node.c | 6 +- .../event_handlers/mod_kazoo/kazoo_tweaks.c | 16 +- .../event_handlers/mod_kazoo/kazoo_utils.c | 34 +- .../event_handlers/mod_kazoo/kazoo_utils.h | 4 +- src/mod/event_handlers/mod_kazoo/mod_kazoo.c | 5 + src/mod/event_handlers/mod_kazoo/mod_kazoo.h | 3 + 20 files changed, 1961 insertions(+), 1254 deletions(-) create mode 100644 src/mod/event_handlers/mod_kazoo/kazoo_cdr.c diff --git a/src/mod/event_handlers/mod_kazoo/Makefile.am b/src/mod/event_handlers/mod_kazoo/Makefile.am index 668d9ffed2..36e7a9ea4a 100644 --- a/src/mod/event_handlers/mod_kazoo/Makefile.am +++ b/src/mod/event_handlers/mod_kazoo/Makefile.am @@ -12,6 +12,7 @@ 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_SOURCES += kazoo_cdr.c mod_kazoo_la_SOURCES += kz_node.c mod_kazoo_la_CFLAGS = $(AM_CFLAGS) @ERLANG_CFLAGS@ -D_REENTRANT -DERLANG_VERSION=@ERLANG_VERSION@ -DERLANG_MAJOR=@ERLANG_MAJOR@ -DERLANG_MINOR=@ERLANG_MINOR@ diff --git a/src/mod/event_handlers/mod_kazoo/kazoo.conf.xml b/src/mod/event_handlers/mod_kazoo/kazoo.conf.xml index a869420681..353db1b0c1 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo.conf.xml +++ b/src/mod/event_handlers/mod_kazoo/kazoo.conf.xml @@ -4,13 +4,12 @@ - + - - + + @@ -21,633 +20,662 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -674,15 +702,15 @@ - + - - - + + + - - - - - - - + + + + + + + @@ -763,7 +791,6 @@ - @@ -776,7 +803,6 @@ - @@ -840,18 +866,8 @@ - - @@ -866,12 +882,6 @@ - @@ -879,34 +889,34 @@ value="variable_endpoint_disposition|variable_originate_disposition|#FAIL" /> - - - + + + - + - - + + - - - - - - - - - - - - + + + + + + + + + + + + @@ -916,10 +926,11 @@ value="Application-Response|variable_originate_disposition|variable_endpoint_disposition|#NONE" /> - - - - + + + + @@ -930,7 +941,8 @@ - + @@ -940,7 +952,8 @@ - + @@ -950,7 +963,8 @@ - + @@ -986,9 +1000,9 @@ - - - + + + @@ -1029,31 +1043,29 @@ - - - - - - - - + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + @@ -1090,14 +1102,72 @@ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1126,10 +1196,10 @@ - - - - + + + + diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_api.c b/src/mod/event_handlers/mod_kazoo/kazoo_api.c index 955ff5c64e..180f3e3d48 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_api.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_api.c @@ -175,7 +175,6 @@ static switch_status_t api_erlang_event_filter(switch_stream_handle_t *stream) { if (++column > 2) { stream->write_function(stream, "\n"); - column = 0; } while(kazoo_globals.kazoo_var_prefixes[idx] != NULL) { diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_cdr.c b/src/mod/event_handlers/mod_kazoo/kazoo_cdr.c new file mode 100644 index 0000000000..f7b0d53df6 --- /dev/null +++ b/src/mod/event_handlers/mod_kazoo/kazoo_cdr.c @@ -0,0 +1,630 @@ +/* + * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * Copyright (C) 2005-2012, Anthony Minessale II + * + * Version: MPL 1.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application + * + * The Initial Developer of the Original Code is + * Anthony Minessale II + * Portions created by the Initial Developer are Copyright (C) + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Luis Azedo + * + * mod_hacks.c -- hacks with state handlers + * + */ +#include "mod_kazoo.h" + +#define MY_EVENT_JSON_CDR "KZ_CDR" + +#define maybe_add_json_string(_json, _name, _string) \ + if (!zstr(_string)) cJSON_AddItemToObject(_json, _name, cJSON_CreateString((char *)_string)) + +static void kz_switch_ivr_set_json_profile_data(cJSON *json, switch_caller_profile_t *caller_profile) +{ + cJSON *soft = NULL; + profile_node_t *pn = NULL; + + maybe_add_json_string(json, "Username", caller_profile->username); + maybe_add_json_string(json, "Dialplan", caller_profile->dialplan); + maybe_add_json_string(json, "ANI", caller_profile->ani); + maybe_add_json_string(json, "ANIII", caller_profile->aniii); + maybe_add_json_string(json, "Caller-ID-Name", caller_profile->caller_id_name); + maybe_add_json_string(json, "Caller-ID-Number", caller_profile->caller_id_number); + maybe_add_json_string(json, "Caller-ID-Original-Name", caller_profile->orig_caller_id_name); + maybe_add_json_string(json, "Caller-ID-Original-Number", caller_profile->orig_caller_id_number); + maybe_add_json_string(json, "Network-Address", caller_profile->network_addr); + maybe_add_json_string(json, "RDNIS", caller_profile->rdnis); + maybe_add_json_string(json, "Destination-Number", caller_profile->destination_number); + maybe_add_json_string(json, "Callee-ID-Name", caller_profile->callee_id_name); + maybe_add_json_string(json, "Callee-ID-Number", caller_profile->callee_id_number); + maybe_add_json_string(json, "UUID", caller_profile->uuid); + maybe_add_json_string(json, "Source", caller_profile->source); + maybe_add_json_string(json, "Context", caller_profile->context); + maybe_add_json_string(json, "Channel-Name", caller_profile->chan_name); + maybe_add_json_string(json, "Profile-UUID", caller_profile->uuid_str); + maybe_add_json_string(json, "Profile-Clone-Of", caller_profile->clone_of); + maybe_add_json_string(json, "Transfer-Source", caller_profile->transfer_source); + cJSON_AddItemToObject(json, "Direction", cJSON_CreateString(caller_profile->direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound")); + cJSON_AddItemToObject(json, "Logical-Direction", cJSON_CreateString(caller_profile->logical_direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound")); + + soft = cJSON_CreateObject(); + for (pn = caller_profile->soft; pn; pn = pn->next) { + maybe_add_json_string(soft, pn->var, pn->val); + } + + cJSON_AddItemToObject(json, "Directory", soft); +} + +SWITCH_DECLARE(void) kz_switch_ivr_set_json_call_flaws(cJSON *json, switch_core_session_t *session, switch_media_type_t type) +{ + const char *name = (type == SWITCH_MEDIA_TYPE_VIDEO) ? "Video" : "Audio"; + cJSON *j_stat; + switch_rtp_stats_t *stats = switch_core_media_get_stats(session, type, NULL); + + if (!stats) return; + + if (!stats->inbound.error_log && !stats->outbound.error_log) return; + + j_stat = cJSON_CreateObject(); + cJSON_AddItemToObject(json, name, j_stat); + + if (stats->inbound.error_log) { + cJSON *j_err_log, *j_err, *j_in; + switch_error_period_t *ep; + + j_in = cJSON_CreateObject(); + cJSON_AddItemToObject(j_stat, "Inbound", j_in); + + j_err_log = cJSON_CreateArray(); + cJSON_AddItemToObject(j_in, "Error-Log", j_err_log); + + for(ep = stats->inbound.error_log; ep; ep = ep->next) { + + if (!(ep->start && ep->stop)) continue; + + j_err = cJSON_CreateObject(); + + cJSON_AddItemToObject(j_err, "Start", cJSON_CreateNumber(ep->start)); + cJSON_AddItemToObject(j_err, "Stop", cJSON_CreateNumber(ep->stop)); + cJSON_AddItemToObject(j_err, "Flaws", cJSON_CreateNumber(ep->flaws)); + cJSON_AddItemToObject(j_err, "Consecutive-Flaws", cJSON_CreateNumber(ep->consecutive_flaws)); + cJSON_AddItemToObject(j_err, "Duration-MS", cJSON_CreateNumber((ep->stop - ep->start) / 1000)); + cJSON_AddItemToArray(j_err_log, j_err); + } + } + + if (stats->outbound.error_log) { + cJSON *j_err_log, *j_err, *j_out; + switch_error_period_t *ep; + + j_out = cJSON_CreateObject(); + cJSON_AddItemToObject(j_stat, "Outbound", j_out); + + j_err_log = cJSON_CreateArray(); + cJSON_AddItemToObject(j_out, "Error-Log", j_err_log); + + for(ep = stats->outbound.error_log; ep; ep = ep->next) { + + if (!(ep->start && ep->stop)) continue; + + j_err = cJSON_CreateObject(); + + cJSON_AddItemToObject(j_err, "Start", cJSON_CreateNumber(ep->start)); + cJSON_AddItemToObject(j_err, "Stop", cJSON_CreateNumber(ep->stop)); + cJSON_AddItemToObject(j_err, "Flaws", cJSON_CreateNumber(ep->flaws)); + cJSON_AddItemToObject(j_err, "Consecutive-Flaws", cJSON_CreateNumber(ep->consecutive_flaws)); + cJSON_AddItemToObject(j_err, "Duration-MS", cJSON_CreateNumber((ep->stop - ep->start) / 1000)); + cJSON_AddItemToArray(j_err_log, j_err); + } + } +} + +#define add_jstat(_j, _i, _s) \ + switch_snprintf(var_val, sizeof(var_val), "%" SWITCH_SIZE_T_FMT, _i); \ + cJSON_AddItemToObject(_j, _s, cJSON_CreateNumber(_i)) + +SWITCH_DECLARE(void) kz_switch_ivr_set_json_call_stats(cJSON *json, switch_core_session_t *session, switch_media_type_t type) +{ + const char *name = (type == SWITCH_MEDIA_TYPE_VIDEO) ? "Video" : "Audio"; + cJSON *j_stat, *j_in, *j_out; + switch_rtp_stats_t *stats = switch_core_media_get_stats(session, type, NULL); + char var_val[35] = ""; + + if (!stats) return; + + j_stat = cJSON_CreateObject(); + j_in = cJSON_CreateObject(); + j_out = cJSON_CreateObject(); + + cJSON_AddItemToObject(json, name, j_stat); + cJSON_AddItemToObject(j_stat, "Inbound", j_in); + cJSON_AddItemToObject(j_stat, "Outbound", j_out); + + stats->inbound.std_deviation = sqrt(stats->inbound.variance); + + add_jstat(j_in, stats->inbound.raw_bytes, "Raw-Bytes"); + add_jstat(j_in, stats->inbound.media_bytes, "Media-Bytes"); + add_jstat(j_in, stats->inbound.packet_count, "Packet-Count"); + add_jstat(j_in, stats->inbound.media_packet_count, "Media-Packet-Count"); + add_jstat(j_in, stats->inbound.skip_packet_count, "Skip-Packet-Count"); + add_jstat(j_in, stats->inbound.jb_packet_count, "Jitter-Packet-Count"); + add_jstat(j_in, stats->inbound.dtmf_packet_count, "DTMF-Packet-Count"); + add_jstat(j_in, stats->inbound.cng_packet_count, "CNG-Packet-Count"); + add_jstat(j_in, stats->inbound.flush_packet_count, "Flush-Packet-Count"); + add_jstat(j_in, stats->inbound.largest_jb_size, "Largest-JB-Size"); + add_jstat(j_in, stats->inbound.min_variance, "Jitter-Min-Variance"); + add_jstat(j_in, stats->inbound.max_variance, "Jitter-Max-Variance"); + add_jstat(j_in, stats->inbound.lossrate, "Jitter-Loss-Rate"); + add_jstat(j_in, stats->inbound.burstrate, "Jitter-Burst-Rate"); + add_jstat(j_in, stats->inbound.mean_interval, "Mean-Interval"); + add_jstat(j_in, stats->inbound.flaws, "Flaw-Total"); + add_jstat(j_in, stats->inbound.R, "Quality-Percentage"); + add_jstat(j_in, stats->inbound.mos, "MOS"); + + + add_jstat(j_out, stats->outbound.raw_bytes, "Raw-Bytes"); + add_jstat(j_out, stats->outbound.media_bytes, "Media-Bytes"); + add_jstat(j_out, stats->outbound.packet_count, "Packet-Count"); + add_jstat(j_out, stats->outbound.media_packet_count, "Media-Packet-Count"); + add_jstat(j_out, stats->outbound.skip_packet_count, "Skip-Packet-Count"); + add_jstat(j_out, stats->outbound.dtmf_packet_count, "DTMF-Packet-Count"); + add_jstat(j_out, stats->outbound.cng_packet_count, "CNG-Packet-Count"); + add_jstat(j_out, stats->rtcp.packet_count, "RTCP-Packet-Count"); + add_jstat(j_out, stats->rtcp.octet_count, "RTCP-Octet-Count"); +} + +static switch_status_t kz_report_channel_flaws(switch_core_session_t *session, switch_event_t *cdr_event) +{ + cJSON *callStats = cJSON_CreateObject(); + + kz_switch_ivr_set_json_call_flaws(callStats, session, SWITCH_MEDIA_TYPE_AUDIO); + kz_switch_ivr_set_json_call_flaws(callStats, session, SWITCH_MEDIA_TYPE_VIDEO); + + switch_event_add_header_string(cdr_event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, "_json_channel_media_errors", cJSON_PrintUnformatted(callStats)); + + cJSON_Delete(callStats); + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t kz_report_channel_stats(switch_core_session_t *session, switch_event_t *cdr_event) +{ + cJSON *callStats = cJSON_CreateObject(); + + kz_switch_ivr_set_json_call_stats(callStats, session, SWITCH_MEDIA_TYPE_AUDIO); + kz_switch_ivr_set_json_call_stats(callStats, session, SWITCH_MEDIA_TYPE_VIDEO); + + switch_event_add_header_string(cdr_event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, "_json_channel_stats", cJSON_PrintUnformatted(callStats)); + + cJSON_Delete(callStats); + + return SWITCH_STATUS_SUCCESS; + +} + +static switch_status_t kz_report_app_log(switch_core_session_t *session, switch_event_t *cdr_event) +{ + switch_app_log_t *ap, *app_log = switch_core_session_get_app_log(session); + cJSON *j_apps = NULL; + + if (!app_log) { + return SWITCH_STATUS_FALSE; + } + + j_apps = cJSON_CreateArray(); + + for (ap = app_log; ap; ap = ap->next) { + cJSON *j_application = cJSON_CreateObject(); + cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->app)); + cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(ap->arg)); + cJSON_AddItemToObject(j_application, "app_stamp", cJSON_CreateNumber(ap->stamp)); + cJSON_AddItemToArray(j_apps, j_application); + } + + switch_event_add_header_string(cdr_event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, "_json_application_log", cJSON_PrintUnformatted(j_apps)); + + cJSON_Delete(j_apps); + + return SWITCH_STATUS_SUCCESS; + +} + +static switch_status_t kz_report_callflow_extension(switch_caller_profile_t *caller_profile, cJSON *j_profile) +{ + cJSON *j_caller_extension, *j_caller_extension_apps, *j_application, *j_inner_extension; + if (caller_profile->caller_extension) { + switch_caller_application_t *ap; + + j_caller_extension = cJSON_CreateObject(); + j_caller_extension_apps = cJSON_CreateArray(); + + cJSON_AddItemToObject(j_profile, "extension", j_caller_extension); + + cJSON_AddItemToObject(j_caller_extension, "name", cJSON_CreateString(caller_profile->caller_extension->extension_name)); + cJSON_AddItemToObject(j_caller_extension, "number", cJSON_CreateString(caller_profile->caller_extension->extension_number)); + cJSON_AddItemToObject(j_caller_extension, "applications", j_caller_extension_apps); + + if (caller_profile->caller_extension->current_application) { + cJSON_AddItemToObject(j_caller_extension, "current_app", cJSON_CreateString(caller_profile->caller_extension->current_application->application_name)); + } + + for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) { + j_application = cJSON_CreateObject(); + + cJSON_AddItemToArray(j_caller_extension_apps, j_application); + + if (ap == caller_profile->caller_extension->current_application) { + cJSON_AddItemToObject(j_application, "last_executed", cJSON_CreateString("true")); + } + cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->application_name)); + cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(switch_str_nil(ap->application_data))); + } + + if (caller_profile->caller_extension->children) { + switch_caller_profile_t *cp = NULL; + j_inner_extension = cJSON_CreateArray(); + cJSON_AddItemToObject(j_caller_extension, "sub_extensions", j_inner_extension); + for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) { + + if (!cp->caller_extension) { + continue; + } + + j_caller_extension = cJSON_CreateObject(); + cJSON_AddItemToArray(j_inner_extension, j_caller_extension); + + cJSON_AddItemToObject(j_caller_extension, "name", cJSON_CreateString(cp->caller_extension->extension_name)); + cJSON_AddItemToObject(j_caller_extension, "number", cJSON_CreateString(cp->caller_extension->extension_number)); + + cJSON_AddItemToObject(j_caller_extension, "dialplan", cJSON_CreateString((char *)cp->dialplan)); + + if (cp->caller_extension->current_application) { + cJSON_AddItemToObject(j_caller_extension, "current_app", cJSON_CreateString(cp->caller_extension->current_application->application_name)); + } + + j_caller_extension_apps = cJSON_CreateArray(); + cJSON_AddItemToObject(j_caller_extension, "applications", j_caller_extension_apps); + for (ap = cp->caller_extension->applications; ap; ap = ap->next) { + j_application = cJSON_CreateObject(); + cJSON_AddItemToArray(j_caller_extension_apps, j_application); + + if (ap == cp->caller_extension->current_application) { + cJSON_AddItemToObject(j_application, "last_executed", cJSON_CreateString("true")); + } + cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->application_name)); + cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(switch_str_nil(ap->application_data))); + } + } + } + } + + return SWITCH_STATUS_SUCCESS; + +} + +static switch_status_t kz_report_callflow(switch_core_session_t *session, switch_event_t *cdr_event) +{ + switch_channel_t *channel = switch_core_session_get_channel(session); + switch_caller_profile_t *caller_profile; + cJSON *j_main_cp, *j_times, *j_callflow, *j_profile, *j_o; + + + caller_profile = switch_channel_get_caller_profile(channel); + + j_callflow = cJSON_CreateArray(); + + while (caller_profile) { + + j_profile = cJSON_CreateObject(); + + if (!zstr(caller_profile->dialplan)) { + cJSON_AddItemToObject(j_profile, "dialplan", cJSON_CreateString((char *)caller_profile->dialplan)); + } + + if (!zstr(caller_profile->profile_index)) { + cJSON_AddItemToObject(j_profile, "profile_index", cJSON_CreateString((char *)caller_profile->profile_index)); + } + + kz_report_callflow_extension(caller_profile, j_profile); + + j_main_cp = cJSON_CreateObject(); + cJSON_AddItemToObject(j_profile, "Caller-Profile", j_main_cp); + + kz_switch_ivr_set_json_profile_data(j_main_cp, caller_profile); + + if (caller_profile->originator_caller_profile) { + j_o = cJSON_CreateObject(); + cJSON_AddItemToObject(j_main_cp, "originator", j_o); + kz_switch_ivr_set_json_profile_data(j_o, caller_profile->originator_caller_profile); + kz_report_callflow_extension(caller_profile->originator_caller_profile, j_o); + } + + if (caller_profile->originatee_caller_profile) { + j_o = cJSON_CreateObject(); + cJSON_AddItemToObject(j_main_cp, "originatee", j_o); + kz_switch_ivr_set_json_profile_data(j_o, caller_profile->originatee_caller_profile); + kz_report_callflow_extension(caller_profile->originatee_caller_profile, j_o); + } + + if (caller_profile->times) { + j_times = cJSON_CreateObject(); + cJSON_AddItemToObject(j_profile, "Time", j_times); + cJSON_AddItemToObject(j_times, "Created", cJSON_CreateNumber(caller_profile->times->created)); + cJSON_AddItemToObject(j_times, "Profile-Created", cJSON_CreateNumber(caller_profile->times->profile_created)); + cJSON_AddItemToObject(j_times, "Progress", cJSON_CreateNumber(caller_profile->times->progress)); + cJSON_AddItemToObject(j_times, "Progress-Media", cJSON_CreateNumber(caller_profile->times->progress_media)); + cJSON_AddItemToObject(j_times, "Answered", cJSON_CreateNumber(caller_profile->times->answered)); + cJSON_AddItemToObject(j_times, "Bridged", cJSON_CreateNumber(caller_profile->times->bridged)); + cJSON_AddItemToObject(j_times, "Last-Hold", cJSON_CreateNumber(caller_profile->times->last_hold)); + cJSON_AddItemToObject(j_times, "Hold-Accumulated", cJSON_CreateNumber(caller_profile->times->hold_accum)); + cJSON_AddItemToObject(j_times, "Hangup", cJSON_CreateNumber(caller_profile->times->hungup)); + cJSON_AddItemToObject(j_times, "Resurrect", cJSON_CreateNumber(caller_profile->times->resurrected)); + cJSON_AddItemToObject(j_times, "Transfer", cJSON_CreateNumber(caller_profile->times->transferred)); + } + cJSON_AddItemToArray(j_callflow, j_profile); + caller_profile = caller_profile->next; + } + + switch_event_add_header_string(cdr_event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, "_json_callflow", cJSON_PrintUnformatted(j_callflow)); + + cJSON_Delete(j_callflow); + + + return SWITCH_STATUS_SUCCESS; + +} + + +#define ORIGINATED_LEGS_VARIABLE "originated_legs" +#define ORIGINATED_LEGS_ITEM_DELIM ';' + +#define ORIGINATE_CAUSES_VARIABLE "originate_causes" +#define ORIGINATE_CAUSES_ITEM_DELIM ';' + +static switch_status_t kz_report_originated_legs(switch_core_session_t *session, switch_event_t *cdr_event) +{ + switch_channel_t *channel = switch_core_session_get_channel(session); + cJSON *j_originated = cJSON_CreateArray(); + const char *originated_legs_var = NULL, *originate_causes_var = NULL; + int idx = 0; + + while(1) { + char *argv_leg[10] = { 0 }, *argv_cause[10] = { 0 }; + char *originated_legs, *originate_causes; + cJSON *j_originated_leg; + originated_legs_var = switch_channel_get_variable_dup(channel, ORIGINATED_LEGS_VARIABLE, SWITCH_FALSE, idx); + originate_causes_var = switch_channel_get_variable_dup(channel, ORIGINATE_CAUSES_VARIABLE, SWITCH_FALSE, idx); + + if (zstr(originated_legs_var) || zstr(originate_causes_var)) { + break; + } + + originated_legs = strdup(originated_legs_var); + originate_causes = strdup(originate_causes_var); + + switch_separate_string(originated_legs, ORIGINATED_LEGS_ITEM_DELIM, argv_leg, (sizeof(argv_leg) / sizeof(argv_leg[0]))); + switch_separate_string(originate_causes, ORIGINATE_CAUSES_ITEM_DELIM, argv_cause, (sizeof(argv_cause) / sizeof(argv_cause[0]))); + + j_originated_leg = cJSON_CreateObject(); + cJSON_AddItemToObject(j_originated_leg, "Call-ID", cJSON_CreateString(argv_leg[0])); + cJSON_AddItemToObject(j_originated_leg, "Caller-ID-Name", cJSON_CreateString(argv_leg[1])); + cJSON_AddItemToObject(j_originated_leg, "Caller-ID-Number", cJSON_CreateString(argv_leg[2])); + cJSON_AddItemToObject(j_originated_leg, "Result", cJSON_CreateString(argv_cause[1])); + + cJSON_AddItemToArray(j_originated, j_originated_leg); + + switch_safe_free(originated_legs); + switch_safe_free(originate_causes); + + idx++; + } + + switch_event_add_header_string(cdr_event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, "_json_originated_legs", cJSON_PrintUnformatted(j_originated)); + + cJSON_Delete(j_originated); + + return SWITCH_STATUS_SUCCESS; +} + +#define MAX_HISTORY 50 +#define HST_ARRAY_DELIM "|:" +#define HST_ITEM_DELIM ':' + +static void kz_report_transfer_history_item(char* value, cJSON *json) +{ + char *argv[4] = { 0 }; + char *item = strdup(value); + int argc = switch_separate_string(item, HST_ITEM_DELIM, argv, (sizeof(argv) / sizeof(argv[0]))); + cJSON *jitem = cJSON_CreateObject(); + char *epoch = NULL, *callid = NULL, *type = NULL; + int add = 0; + if(argc == 4) { + add = 1; + epoch = argv[0]; + callid = argv[1]; + type = argv[2]; + + if(!strncmp(type, "bl_xfer", 7)) { + //char *split = strchr(argv[3], '/'); + //if(split) *(split++) = '\0'; + cJSON_AddItemToObject(jitem, "Caller-Profile-ID", cJSON_CreateString(callid)); + cJSON_AddItemToObject(jitem, "Type", cJSON_CreateString("blind")); + cJSON_AddItemToObject(jitem, "Extension", cJSON_CreateString(argv[3])); + cJSON_AddItemToObject(jitem, "Timestamp", cJSON_CreateNumber(strtod(epoch, NULL))); + } else if(!strncmp(type, "att_xfer", 8)) { + char *split = strchr(argv[3], '/'); + if(split) { + *(split++) = '\0'; + cJSON_AddItemToObject(jitem, "Caller-Profile-ID", cJSON_CreateString(callid)); + cJSON_AddItemToObject(jitem, "Type", cJSON_CreateString("attended")); + cJSON_AddItemToObject(jitem, "Transferee", cJSON_CreateString(argv[3])); + cJSON_AddItemToObject(jitem, "Transferer", cJSON_CreateString(split)); + cJSON_AddItemToObject(jitem, "Timestamp", cJSON_CreateNumber(strtod(epoch, NULL))); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER TYPE '%s' NOT HANDLED => %s\n", type, item); + add = 0; + } + } else if(!strncmp(type, "uuid_br", 7)) { + cJSON_AddItemToObject(jitem, "Caller-Profile-ID", cJSON_CreateString(callid)); + cJSON_AddItemToObject(jitem, "Type", cJSON_CreateString("bridge")); + cJSON_AddItemToObject(jitem, "Other-Leg", cJSON_CreateString(argv[3])); + cJSON_AddItemToObject(jitem, "Timestamp", cJSON_CreateNumber(strtod(epoch, NULL))); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER TYPE '%s' NOT HANDLED => %s\n", type, item); + add = 0; + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER TYPE SPLIT ERROR %i => %s\n", argc, item); + } + if(add) { + cJSON_AddItemToArray(json, jitem); + } else { + cJSON_Delete(jitem); + } + switch_safe_free(item); +} + +static switch_status_t kz_report_transfer_history(switch_core_session_t *session, switch_event_t *cdr_event, const char* var_name) +{ + switch_channel_t *channel = switch_core_session_get_channel(session); + cJSON *j_transfer = NULL; + char *tmp_history = NULL, *history = NULL, *argv[MAX_HISTORY] = { 0 }; + char event_header[50]; + int n, argc = 0; + const char *transfer_var = switch_channel_get_variable_dup(channel, var_name, SWITCH_FALSE, -1); + if (zstr(transfer_var)) { + return SWITCH_STATUS_SUCCESS; + } + + if (!(tmp_history = strdup(transfer_var))) { + return SWITCH_STATUS_SUCCESS; + } + + sprintf(event_header, "_json_%s", var_name); + history = tmp_history; + j_transfer = cJSON_CreateArray(); + + if (!strncmp(history, "ARRAY::", 7)) { + history += 7; + argc = switch_separate_string_string(history, HST_ARRAY_DELIM, argv, (sizeof(argv) / sizeof(argv[0]))); + for(n=0; n < argc; n++) { + kz_report_transfer_history_item(argv[n], j_transfer); + } + switch_event_add_header_string(cdr_event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, event_header, cJSON_PrintUnformatted(j_transfer)); + } else if (strchr(history, HST_ITEM_DELIM)) { + kz_report_transfer_history_item(history, j_transfer); + switch_event_add_header_string(cdr_event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, event_header, cJSON_PrintUnformatted(j_transfer)); + } + cJSON_Delete(j_transfer); + switch_safe_free(tmp_history); + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t kz_report(switch_core_session_t *session, switch_event_t *cdr_event) +{ + kz_report_app_log(session, cdr_event); + kz_report_callflow(session, cdr_event); + kz_report_channel_stats(session, cdr_event); + kz_report_channel_flaws(session, cdr_event); + kz_report_originated_legs(session, cdr_event); + kz_report_transfer_history(session, cdr_event, SWITCH_TRANSFER_HISTORY_VARIABLE); + kz_report_transfer_history(session, cdr_event, SWITCH_TRANSFER_SOURCE_VARIABLE); + return SWITCH_STATUS_SUCCESS; +} + + +static switch_status_t kz_cdr_on_reporting(switch_core_session_t *session) +{ + switch_event_t *cdr_event = NULL; + switch_channel_t *channel = switch_core_session_get_channel(session); + + if (switch_event_create_subclass(&cdr_event, SWITCH_EVENT_CUSTOM, MY_EVENT_JSON_CDR) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "error creating event for report data!\n"); + return SWITCH_STATUS_FALSE; + } + + kz_report(session, cdr_event); + switch_channel_event_set_data(channel, cdr_event); + switch_event_fire(&cdr_event); + + return SWITCH_STATUS_SUCCESS; +} + + +static switch_state_handler_table_t kz_cdr_state_handlers = { + /*.on_init */ NULL, + /*.on_routing */ NULL, + /*.on_execute */ NULL, + /*.on_hangup */ NULL, + /*.on_exchange_media */ NULL, + /*.on_soft_execute */ NULL, + /*.on_consume_media */ NULL, + /*.on_hibernate */ NULL, + /*.on_reset */ NULL, + /*.on_park */ NULL, + /*.on_reporting */ kz_cdr_on_reporting +}; + + +static void kz_cdr_register_state_handlers() +{ + switch_core_add_state_handler(&kz_cdr_state_handlers); +} + +static void kz_cdr_unregister_state_handlers() +{ + switch_core_remove_state_handler(&kz_cdr_state_handlers); +} + +static void kz_cdr_register_events() +{ + if (switch_event_reserve_subclass(MY_EVENT_JSON_CDR) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_JSON_CDR); + } +} + +static void kz_cdr_unregister_events() +{ + switch_event_free_subclass(MY_EVENT_JSON_CDR); +} + + +void kz_cdr_start() +{ + kz_cdr_register_events(); + kz_cdr_register_state_handlers(); +} + +void kz_cdr_stop() +{ + kz_cdr_unregister_state_handlers(); + kz_cdr_unregister_events(); +} + +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: + */ diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_commands.c b/src/mod/event_handlers/mod_kazoo/kazoo_commands.c index 3286c34811..bf954d1e6c 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_commands.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_commands.c @@ -48,138 +48,45 @@ #define MAX_FIRST_OF 25 -#define MAX_HISTORY 50 -#define HST_ARRAY_DELIM "|:" -#define HST_ITEM_DELIM ':' - -static void process_history_item(char* value, cJSON *json) -{ - char *argv[4] = { 0 }; - char *item = strdup(value); - int argc = switch_separate_string(item, HST_ITEM_DELIM, argv, (sizeof(argv) / sizeof(argv[0]))); - cJSON *jitem = cJSON_CreateObject(); - char *epoch = NULL, *callid = NULL, *type = NULL; - int add = 0; - if(argc == 4) { - add = 1; - epoch = argv[0]; - callid = argv[1]; - type = argv[2]; - - if(!strncmp(type, "bl_xfer", 7)) { - char *split = strchr(argv[3], '/'); - if(split) *(split++) = '\0'; - cJSON_AddItemToObject(jitem, "Call-ID", cJSON_CreateString(callid)); - cJSON_AddItemToObject(jitem, "Type", cJSON_CreateString("blind")); - cJSON_AddItemToObject(jitem, "Extension", cJSON_CreateString(argv[3])); - } else if(!strncmp(type, "att_xfer", 8)) { - char *split = strchr(argv[3], '/'); - if(split) { - *(split++) = '\0'; - cJSON_AddItemToObject(jitem, "Call-ID", cJSON_CreateString(callid)); - cJSON_AddItemToObject(jitem, "Type", cJSON_CreateString("attended")); - cJSON_AddItemToObject(jitem, "Transferee", cJSON_CreateString(argv[3])); - cJSON_AddItemToObject(jitem, "Transferer", cJSON_CreateString(split)); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER TYPE '%s' NOT HANDLED => %s\n", type, item); - add = 0; - } - } else if(!strncmp(type, "uuid_br", 7)) { - cJSON_AddItemToObject(jitem, "Call-ID", cJSON_CreateString(callid)); - cJSON_AddItemToObject(jitem, "Type", cJSON_CreateString("bridge")); - cJSON_AddItemToObject(jitem, "Other-Leg", cJSON_CreateString(argv[3])); - - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER TYPE '%s' NOT HANDLED => %s\n", type, item); - add = 0; - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER TYPE SPLIT ERROR %i => %s\n", argc, item); - } - if(add) { - cJSON_AddItemToObject(json, epoch, jitem); - } else { - cJSON_Delete(jitem); - } - switch_safe_free(item); -} - -SWITCH_STANDARD_API(kz_json_history) -{ - char *mycmd = NULL, *argv[MAX_HISTORY] = { 0 }; - int n, argc = 0; - cJSON *json = cJSON_CreateObject(); - char* output = NULL; - switch_event_header_t *header = NULL; - if (!zstr(cmd) && (mycmd = strdup(cmd))) { - if (!strncmp(mycmd, "ARRAY::", 7)) { - mycmd += 7; - argc = switch_separate_string_string(mycmd, HST_ARRAY_DELIM, argv, (sizeof(argv) / sizeof(argv[0]))); - for(n=0; n < argc; n++) { - process_history_item(argv[n], json); - } - } else if (strchr(mycmd, HST_ITEM_DELIM)) { - process_history_item(mycmd, json); - } else if (stream->param_event) { - header = switch_event_get_header_ptr(stream->param_event, mycmd); - if (header != NULL) { - if(header->idx) { - for(n = 0; n < header->idx; n++) { - process_history_item(header->array[n], json); - } - } else { - process_history_item(header->value, json); - } - - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER HISTORY HEADER NOT FOUND => %s\n", mycmd); - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER HISTORY NOT PARSED => %s\n", mycmd); - } - } - output = cJSON_PrintUnformatted(json); - stream->write_function(stream, "%s", output); - switch_safe_free(output); - cJSON_Delete(json); - - return SWITCH_STATUS_SUCCESS; -} - SWITCH_STANDARD_API(kz_first_of) { char delim = '|'; - char *mycmd = NULL, *argv[MAX_FIRST_OF] = { 0 }; + char *mycmd = NULL, *mycmd_dup = NULL, *argv[MAX_FIRST_OF] = { 0 }; int n, argc = 0; switch_event_header_t *header = NULL; - if (!zstr(cmd) && (mycmd = strdup(cmd))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "FIRST-OF %s\n", mycmd); - if (!zstr(mycmd) && *mycmd == '^' && *(mycmd+1) == '^') { - mycmd += 2; - delim = *mycmd++; - } - argc = switch_separate_string(mycmd, delim, argv, (sizeof(argv) / sizeof(argv[0]))); - for(n=0; n < argc; n++) { - char* item = argv[n]; - if(*item == '#') { - if(*(++item) != '\0') { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "RETURNING default %s\n", item); - stream->write_function(stream, item); - break; - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "CHECKING %s\n", item); - header = switch_event_get_header_ptr(stream->param_event, item); - if(header) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "RETURNING %s : %s\n", item, header->value); - stream->write_function(stream, header->value); - break; - } + + if (zstr(cmd)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid arg\n"); + return SWITCH_STATUS_GENERR; + } + + mycmd_dup = mycmd = strdup(cmd); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "FIRST-OF %s\n", mycmd); + if (!zstr(mycmd) && *mycmd == '^' && *(mycmd+1) == '^') { + mycmd += 2; + delim = *mycmd++; + } + argc = switch_separate_string(mycmd, delim, argv, (sizeof(argv) / sizeof(argv[0]))); + for(n=0; n < argc; n++) { + char* item = argv[n]; + if(*item == '#' || *item == '!' || *item == '?') { + if(*(++item) != '\0') { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "RETURNING default %s\n", item); + stream->write_function(stream, item); + break; + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "CHECKING %s\n", item); + header = switch_event_get_header_ptr(stream->param_event, item); + if(header) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "RETURNING %s : %s\n", item, header->value); + stream->write_function(stream, header->value); + break; } } } - switch_safe_free(mycmd); + switch_safe_free(mycmd_dup); return SWITCH_STATUS_SUCCESS; } @@ -364,7 +271,6 @@ SWITCH_STANDARD_API(kz_http_put) long httpRes = 0; struct stat file_info = {0}; FILE *file_to_put = NULL; - int fd; if (session) { pool = switch_core_session_get_pool(session); @@ -390,7 +296,11 @@ SWITCH_STANDARD_API(kz_http_put) /* parse params and get profile */ url = switch_core_strdup(pool, argv[0]); if (*url == '{') { - switch_event_create_brackets(url, '{', '}', ',', ¶ms, &url, SWITCH_FALSE); + if (switch_event_create_brackets(url, '{', '}', ',', ¶ms, &url, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { + status = SWITCH_STATUS_FALSE; + stream->write_function(stream, "-ERR error parsing parameters\n"); + goto done; + } } filename = switch_core_strdup(pool, argv[1]); @@ -404,34 +314,26 @@ SWITCH_STANDARD_API(kz_http_put) } buf = switch_mprintf("Content-Type: %s", mime_type); - headers = switch_curl_slist_append(headers, buf); /* open file and get the file size */ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "opening %s for upload to %s\n", filename, url); - fd = open(filename, O_RDONLY); - if (fd == -1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "open() error: %s\n", strerror(errno)); - status = SWITCH_STATUS_FALSE; - stream->write_function(stream, "-ERR error opening file\n"); - goto done; - } - if (fstat(fd, &file_info) == -1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "fstat() error: %s\n", strerror(errno)); - stream->write_function(stream, "-ERR fstat error\n"); - close(fd); - goto done; - } - close(fd); /* libcurl requires FILE* */ file_to_put = fopen(filename, "rb"); if (!file_to_put) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "fopen() error: %s\n", strerror(errno)); + stream->write_function(stream, "-ERR error opening file\n"); status = SWITCH_STATUS_FALSE; goto done; } + if (fstat(fileno(file_to_put), &file_info) == -1) { + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "fstat() error: %s\n", strerror(errno)); + stream->write_function(stream, "-ERR fstat error\n"); + goto done; + } + curl_handle = switch_curl_easy_init(); if (!curl_handle) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "switch_curl_easy_init() failure\n"); @@ -503,13 +405,36 @@ done: SWITCH_STANDARD_API(kz_expand_api) { - if (!zstr(cmd)) { - char * val = kz_expand(cmd); - stream->write_function(stream, "+OK %s", val); - switch_safe_free(val); - } else { - stream->write_function(stream, "ERR invalid input"); + char *p = NULL, *input = NULL; + char *uuid = NULL, *mycmd; + + if (zstr(cmd)) { + stream->write_function(stream, "-ERR invalid input"); + return SWITCH_STATUS_GENERR; } + + if (!(mycmd = strdup(cmd))) { + stream->write_function(stream, "-ERR no memory"); + return SWITCH_STATUS_GENERR; + } + + if (!strncasecmp(mycmd, "uuid:", 5)) { + uuid = mycmd + 5; + if ((input = strchr(uuid, ' ')) != NULL) { + *input++ = '\0'; + } else { + stream->write_function(stream, "-ERR invalid argument"); + switch_safe_free(mycmd); + return SWITCH_STATUS_GENERR; + } + } + + p = kz_expand(input, uuid); + stream->write_function(stream, "+OK %s", p); + if (p != input) { + switch_safe_free(p); + } + switch_safe_free(mycmd); return SWITCH_STATUS_SUCCESS; } @@ -525,7 +450,6 @@ void add_kz_commands(switch_loadable_module_interface_t **module_interface) { switch_console_set_complete("add kz_uuid_setvar_encoded ::console::list_uuid"); SWITCH_ADD_API(api_interface, "kz_http_put", KZ_HTTP_PUT_DESC, kz_http_put, KZ_HTTP_PUT_SYNTAX); SWITCH_ADD_API(api_interface, "first-of", KZ_FIRST_OF_DESC, kz_first_of, KZ_FIRST_OF_SYNTAX); - SWITCH_ADD_API(api_interface, "kz_json_history", KZ_FIRST_OF_DESC, kz_json_history, KZ_FIRST_OF_SYNTAX); SWITCH_ADD_API(api_interface, "kz_expand", KZ_FIRST_OF_DESC, kz_expand_api, KZ_FIRST_OF_SYNTAX); } diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_config.c b/src/mod/event_handlers/mod_kazoo/kazoo_config.c index fcda9012ff..a64677074b 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_config.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_config.c @@ -129,6 +129,10 @@ switch_status_t kazoo_config_loglevels(switch_memory_pool_t *pool, switch_xml_t loglevels->warn_log_level = SWITCH_LOG_WARNING; loglevels->success_log_level = SWITCH_LOG_DEBUG; loglevels->time_log_level = SWITCH_LOG_DEBUG1; + loglevels->trace_log_level = SWITCH_LOG_DEBUG1; + loglevels->debug_log_level = SWITCH_LOG_DEBUG; + loglevels->error_log_level = SWITCH_LOG_ERROR; + loglevels->hashing_log_level = SWITCH_LOG_DEBUG1; if ((xml_logging = switch_xml_child(cfg, "logging")) != NULL) { for (xml_level = switch_xml_child(xml_logging, "log"); xml_level; xml_level = xml_level->next) { @@ -159,6 +163,14 @@ switch_status_t kazoo_config_loglevels(switch_memory_pool_t *pool, switch_xml_t loglevels->filtered_event_log_level = log_str2level(val); } else if (!strncmp(var, "filtered-field", 14)) { loglevels->filtered_field_log_level = log_str2level(val); + } else if (!strncmp(var, "trace", 5)) { + loglevels->trace_log_level = log_str2level(val); + } else if (!strncmp(var, "debug", 5)) { + loglevels->debug_log_level = log_str2level(val); + } else if (!strncmp(var, "error", 5)) { + loglevels->error_log_level = log_str2level(val); + } else if (!strncmp(var, "hashing", 7)) { + loglevels->hashing_log_level = log_str2level(val); } } /* xml_level for loop */ } @@ -247,6 +259,7 @@ switch_status_t kazoo_config_field(kazoo_config_ptr definitions, switch_memory_p const char *type = switch_xml_attr(cfg, "type"); const char *exclude_prefix = switch_xml_attr(cfg, "exclude-prefix"); const char *serialize_as = switch_xml_attr(cfg, "serialize-as"); + const char *as_array = switch_xml_attr(cfg, "as-array"); kazoo_field_ptr cur = (kazoo_field_ptr) switch_core_alloc(pool, sizeof(kazoo_field)); cur->in_type = FIELD_NONE; cur->out_type = JSON_NONE; @@ -292,6 +305,10 @@ switch_status_t kazoo_config_field(kazoo_config_ptr definitions, switch_memory_p } } + if(as_array) { + cur->out_type_as_array = switch_true(as_array); + } + if(exclude_prefix) cur->exclude_prefix = switch_true(exclude_prefix); diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_dptools.c b/src/mod/event_handlers/mod_kazoo/kazoo_dptools.c index 2239855464..d5bd64fa9a 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_dptools.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_dptools.c @@ -267,7 +267,7 @@ void kz_uuid_multiset(switch_core_session_t *session, const char* data, int urld if(delim != '\0') { switch_core_session_t *uuid_session = NULL; - if ((uuid_session = switch_core_session_force_locate(arg0)) != NULL) { + if ((uuid_session = switch_core_session_locate(arg0)) != NULL) { switch_channel_t *uuid_channel = switch_core_session_get_channel(uuid_session); if (arg) { char *array[256] = {0}; diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_ei_config.c b/src/mod/event_handlers/mod_kazoo/kazoo_ei_config.c index 53ed984154..8045721626 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_ei_config.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_ei_config.c @@ -238,8 +238,8 @@ switch_status_t kazoo_ei_config(switch_xml_t cfg) { } if ((child = switch_xml_child(cfg, "tweaks"))) { - char *default_tweaks = (char *) switch_xml_attr_soft(param, "default"); - if (default_tweaks) { + char *default_tweaks = (char *) switch_xml_attr_soft(child, "default"); + if (default_tweaks && !zstr(default_tweaks)) { int i, v = switch_true(default_tweaks) ? 1 : 0; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set tweak default : %s\n", default_tweaks); for (i = 0; i < KZ_TWEAK_MAX; i++) kazoo_globals.tweaks[i] = v; @@ -516,9 +516,10 @@ switch_status_t kazoo_config_events(kazoo_config_ptr definitions, switch_memory_ cur->name = switch_core_strdup(pool, var); kazoo_config_filters(pool, event, &cur->filter); kazoo_config_fields(definitions, pool, event, &cur->fields); - + if (switch_xml_child(event, "logging") != NULL) { + kazoo_config_loglevels(pool, event, &cur->logging); + } } - } return SWITCH_STATUS_SUCCESS; diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_ei_utils.c b/src/mod/event_handlers/mod_kazoo/kazoo_ei_utils.c index fb655e8860..416098b972 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_ei_utils.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_ei_utils.c @@ -54,91 +54,87 @@ #ifdef EI_DEBUG static void ei_x_print_reg_msg(ei_x_buff *buf, char *dest, int send) { - char *mbuf = NULL; - int i = 1; + char *mbuf = NULL; + int i = 1; - ei_s_print_term(&mbuf, buf->buff, &i); + ei_s_print_term(&mbuf, buf->buff, &i); - if (send) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Encoded term %s to '%s'\n", mbuf, dest); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Decoded term %s for '%s'\n", mbuf, dest); - } + if (send) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Encoded term %s to '%s'\n", mbuf, dest); + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Decoded term %s for '%s'\n", mbuf, dest); + } - free(mbuf); + free(mbuf); } static void ei_x_print_msg(ei_x_buff *buf, erlang_pid *pid, int send) { - char *pbuf = NULL; - int i = 0; - ei_x_buff pidbuf; + char *pbuf = NULL; + int i = 0; + ei_x_buff pidbuf; - ei_x_new(&pidbuf); - ei_x_encode_pid(&pidbuf, pid); + ei_x_new(&pidbuf); + ei_x_encode_pid(&pidbuf, pid); - ei_s_print_term(&pbuf, pidbuf.buff, &i); + ei_s_print_term(&pbuf, pidbuf.buff, &i); - ei_x_print_reg_msg(buf, pbuf, send); - free(pbuf); + ei_x_print_reg_msg(buf, pbuf, send); + free(pbuf); } #endif -void ei_encode_switch_event_headers(ei_x_buff *ebuf, switch_event_t *event) { +void ei_encode_switch_event_headers(ei_x_buff *ebuf, switch_event_t *event) +{ ei_encode_switch_event_headers_2(ebuf, event, 1); } -void ei_encode_switch_event_headers_2(ei_x_buff *ebuf, switch_event_t *event, int encode) { - switch_event_header_t *hp; - char *uuid = switch_event_get_header(event, "unique-id"); - int i; +void ei_encode_switch_event_headers_2(ei_x_buff *ebuf, switch_event_t *event, int encode) +{ + switch_event_header_t *hp; + char *uuid = switch_event_get_header(event, "unique-id"); + int i; - for (i = 0, hp = event->headers; hp; hp = hp->next, i++); + for (i = 0, hp = event->headers; hp; hp = hp->next, i++) + ; - if (event->body) - i++; + if (event->body) + i++; - ei_x_encode_list_header(ebuf, i + 1); + ei_x_encode_list_header(ebuf, i + 1); - if (uuid) { + if (uuid) { char *unique_id = switch_event_get_header(event, "unique-id"); ei_x_encode_binary(ebuf, unique_id, strlen(unique_id)); - } else { - ei_x_encode_atom(ebuf, "undefined"); - } + } else { + ei_x_encode_atom(ebuf, "undefined"); + } - for (hp = event->headers; hp; hp = hp->next) { - ei_x_encode_tuple_header(ebuf, 2); - ei_x_encode_binary(ebuf, hp->name, strlen(hp->name)); - if(encode) { - switch_url_decode(hp->value); - } - ei_x_encode_binary(ebuf, hp->value, strlen(hp->value)); - } + for (hp = event->headers; hp; hp = hp->next) { + ei_x_encode_tuple_header(ebuf, 2); + ei_x_encode_binary(ebuf, hp->name, strlen(hp->name)); + if (encode) { + switch_url_decode(hp->value); + } + ei_x_encode_binary(ebuf, hp->value, strlen(hp->value)); + } - if (event->body) { - ei_x_encode_tuple_header(ebuf, 2); - ei_x_encode_binary(ebuf, "body", strlen("body")); - ei_x_encode_binary(ebuf, event->body, strlen(event->body)); - } + if (event->body) { + ei_x_encode_tuple_header(ebuf, 2); + ei_x_encode_binary(ebuf, "body", strlen("body")); + ei_x_encode_binary(ebuf, event->body, strlen(event->body)); + } - ei_x_encode_empty_list(ebuf); + ei_x_encode_empty_list(ebuf); } int ei_json_child_count(cJSON *JObj) { - int mask = cJSON_False - | cJSON_True - | cJSON_NULL - | cJSON_Number - | cJSON_String - | cJSON_Array - | cJSON_Object - | cJSON_Raw; + int mask = cJSON_False | cJSON_True | cJSON_NULL | cJSON_Number | cJSON_String | cJSON_Array | cJSON_Object | cJSON_Raw; cJSON *item = JObj->child; int i = 0; - while(item) { - if(item->type & mask) + while (item) { + if (item->type & mask) i++; item = item->next; } @@ -146,154 +142,165 @@ int ei_json_child_count(cJSON *JObj) } -void ei_encode_json_array(ei_x_buff *ebuf, cJSON *JObj) { +void ei_encode_json_array(ei_x_buff *ebuf, cJSON *JObj) +{ cJSON *item; int count = ei_json_child_count(JObj); - ei_x_encode_list_header(ebuf, count); - if(count == 0) - return; + ei_x_encode_list_header(ebuf, count); + if (count == 0) + return; - item = JObj->child; - while(item) { - switch(item->type) { - case cJSON_String: - ei_x_encode_binary(ebuf, item->valuestring, strlen(item->valuestring)); - break; + item = JObj->child; + while (item) { + switch (item->type){ + case cJSON_String: + ei_x_encode_binary(ebuf, item->valuestring, strlen(item->valuestring)); + break; - case cJSON_Number: - ei_x_encode_double(ebuf, item->valuedouble); - break; + case cJSON_Number: + if ((fabs(((double) item->valueint) - item->valuedouble) <= DBL_EPSILON) && (item->valuedouble <= INT_MAX) && (item->valuedouble >= INT_MIN)) { + ei_x_encode_longlong(ebuf, item->valueint); + } else { + if (fmod(item->valuedouble, 1) == 0) { + ei_x_encode_ulonglong(ebuf, item->valuedouble); + } else { + ei_x_encode_double(ebuf, item->valuedouble); + } + } + break; - case cJSON_True: - ei_x_encode_boolean(ebuf, 1); - break; + case cJSON_True: + ei_x_encode_boolean(ebuf, 1); + break; - case cJSON_False: - ei_x_encode_boolean(ebuf, 0); - break; + case cJSON_False: + ei_x_encode_boolean(ebuf, 0); + break; - case cJSON_Object: - ei_encode_json(ebuf, item); - break; + case cJSON_Object: + ei_encode_json(ebuf, item); + break; - case cJSON_Array: - ei_encode_json_array(ebuf, item); - break; + case cJSON_Array: + ei_encode_json_array(ebuf, item); + break; - case cJSON_Raw: - { - cJSON *Decoded = cJSON_Parse(item->valuestring); - if(!Decoded) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR DECODING RAW JSON %s\n", item->valuestring); - ei_x_encode_tuple_header(ebuf, 0); - } else { - ei_encode_json(ebuf, Decoded); - cJSON_Delete(Decoded); - } - break; - } + case cJSON_Raw: { + cJSON *Decoded = cJSON_Parse(item->valuestring); + if (!Decoded) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR DECODING RAW JSON %s\n", item->valuestring); + ei_x_encode_tuple_header(ebuf, 0); + } else { + ei_encode_json(ebuf, Decoded); + cJSON_Delete(Decoded); + } + break; + } - case cJSON_NULL: - ei_x_encode_atom(ebuf, "null"); - break; + case cJSON_NULL: + ei_x_encode_atom(ebuf, "null"); + break; - default: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NOT ENCODED %i\n", item->type); - break; + default: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NOT ENCODED %i\n", item->type); + break; - } - item = item->next; - } + } + item = item->next; + } - ei_x_encode_empty_list(ebuf); + ei_x_encode_empty_list(ebuf); } -void ei_encode_json(ei_x_buff *ebuf, cJSON *JObj) { +void ei_encode_json(ei_x_buff *ebuf, cJSON *JObj) +{ cJSON *item; int count = ei_json_child_count(JObj); - if(kazoo_globals.json_encoding == ERLANG_TUPLE) { - ei_x_encode_tuple_header(ebuf, 1); - ei_x_encode_list_header(ebuf, count); + if (kazoo_globals.json_encoding == ERLANG_TUPLE) { + ei_x_encode_tuple_header(ebuf, 1); + ei_x_encode_list_header(ebuf, count); } else { ei_x_encode_map_header(ebuf, count); } - if(count == 0) - return; + if (count == 0) + return; - item = JObj->child; - while(item) { - if(kazoo_globals.json_encoding == ERLANG_TUPLE) { - ei_x_encode_tuple_header(ebuf, 2); - } - ei_x_encode_binary(ebuf, item->string, strlen(item->string)); + item = JObj->child; + while (item) { + if (kazoo_globals.json_encoding == ERLANG_TUPLE) { + ei_x_encode_tuple_header(ebuf, 2); + } + ei_x_encode_binary(ebuf, item->string, strlen(item->string)); - switch(item->type) { - case cJSON_String: - ei_x_encode_binary(ebuf, item->valuestring, strlen(item->valuestring)); - break; + switch (item->type){ + case cJSON_String: + ei_x_encode_binary(ebuf, item->valuestring, strlen(item->valuestring)); + break; - case cJSON_Number: - if ((fabs(((double)item->valueint) - item->valuedouble) <= DBL_EPSILON) - && (item->valuedouble <= INT_MAX) - && (item->valuedouble >= INT_MIN)) { - ei_x_encode_longlong(ebuf, item->valueint); - } else { - ei_x_encode_double(ebuf, item->valuedouble); - } - break; + case cJSON_Number: + if ((fabs(((double) item->valueint) - item->valuedouble) <= DBL_EPSILON) && (item->valuedouble <= INT_MAX) && (item->valuedouble >= INT_MIN)) { + ei_x_encode_longlong(ebuf, item->valueint); + } else { + if (fmod(item->valuedouble, 1) == 0) { + ei_x_encode_ulonglong(ebuf, item->valuedouble); + } else { + ei_x_encode_double(ebuf, item->valuedouble); + } + } + break; - case cJSON_True: - ei_x_encode_boolean(ebuf, 1); - break; + case cJSON_True: + ei_x_encode_boolean(ebuf, 1); + break; - case cJSON_False: - ei_x_encode_boolean(ebuf, 0); - break; + case cJSON_False: + ei_x_encode_boolean(ebuf, 0); + break; - case cJSON_Object: - ei_encode_json(ebuf, item); - break; + case cJSON_Object: + ei_encode_json(ebuf, item); + break; - case cJSON_Array: - ei_encode_json_array(ebuf, item); - break; + case cJSON_Array: + ei_encode_json_array(ebuf, item); + break; - case cJSON_Raw: - { - cJSON *Decoded = cJSON_Parse(item->valuestring); - if(!Decoded) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR DECODING RAW JSON %s\n", item->valuestring); - ei_x_encode_tuple_header(ebuf, 0); - } else { - ei_encode_json(ebuf, Decoded); - cJSON_Delete(Decoded); - } - break; - } + case cJSON_Raw: { + cJSON *Decoded = cJSON_Parse(item->valuestring); + if (!Decoded) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ERROR DECODING RAW JSON %s\n", item->valuestring); + ei_x_encode_tuple_header(ebuf, 0); + } else { + ei_encode_json(ebuf, Decoded); + cJSON_Delete(Decoded); + } + break; + } - case cJSON_NULL: - ei_x_encode_atom(ebuf, "null"); - break; + case cJSON_NULL: + ei_x_encode_atom(ebuf, "null"); + break; - default: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NOT ENCODED %i\n", item->type); - break; + default: + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "NOT ENCODED %i\n", item->type); + break; - } - item = item->next; - } + } + item = item->next; + } - if(kazoo_globals.json_encoding == ERLANG_TUPLE) { + if (kazoo_globals.json_encoding == ERLANG_TUPLE) { ei_x_encode_empty_list(ebuf); } } -void close_socket(switch_socket_t ** sock) { +void close_socket(switch_socket_t ** sock) +{ if (*sock) { switch_socket_shutdown(*sock, SWITCH_SHUTDOWN_READWRITE); switch_socket_close(*sock); @@ -301,18 +308,20 @@ void close_socket(switch_socket_t ** sock) { } } -void close_socketfd(int *sockfd) { +void close_socketfd(int *sockfd) +{ if (*sockfd) { shutdown(*sockfd, SHUT_RDWR); close(*sockfd); } } -switch_socket_t *create_socket_with_port(switch_memory_pool_t *pool, switch_port_t port) { +switch_socket_t *create_socket_with_port(switch_memory_pool_t *pool, switch_port_t port) +{ switch_sockaddr_t *sa; switch_socket_t *socket; - if(switch_sockaddr_info_get(&sa, kazoo_globals.ip, SWITCH_UNSPEC, port, 0, pool)) { + if (switch_sockaddr_info_get(&sa, kazoo_globals.ip, SWITCH_UNSPEC, port, 0, pool)) { return NULL; } @@ -328,7 +337,7 @@ switch_socket_t *create_socket_with_port(switch_memory_pool_t *pool, switch_port return NULL; } - if (switch_socket_listen(socket, 5)){ + if (switch_socket_listen(socket, 5)) { return NULL; } @@ -339,30 +348,32 @@ switch_socket_t *create_socket_with_port(switch_memory_pool_t *pool, switch_port return socket; } -switch_socket_t *create_socket(switch_memory_pool_t *pool) { +switch_socket_t *create_socket(switch_memory_pool_t *pool) +{ return create_socket_with_port(pool, 0); } -switch_status_t create_ei_cnode(const char *ip_addr, const char *name, struct ei_cnode_s *ei_cnode) { - char hostname[EI_MAXHOSTNAMELEN + 1]; - char nodename[MAXNODELEN + 1]; - char cnodename[EI_MAXALIVELEN + 1]; - char *atsign; +switch_status_t create_ei_cnode(const char *ip_addr, const char *name, struct ei_cnode_s *ei_cnode) +{ + char hostname[EI_MAXHOSTNAMELEN + 1]; + char nodename[MAXNODELEN + 1]; + char cnodename[EI_MAXALIVELEN + 1]; + char *atsign; - /* copy the erlang interface nodename into something we can modify */ - strncpy(cnodename, name, EI_MAXALIVELEN); + /* copy the erlang interface nodename into something we can modify */ + strncpy(cnodename, name, EI_MAXALIVELEN); - if ((atsign = strchr(cnodename, '@'))) { - /* we got a qualified node name, don't guess the host/domain */ - snprintf(nodename, MAXNODELEN + 1, "%s", name); - /* truncate the alivename at the @ */ - *atsign++ = '\0'; - strncpy(hostname, atsign, EI_MAXHOSTNAMELEN); - } else { - strncpy(hostname, kazoo_globals.hostname, EI_MAXHOSTNAMELEN); - snprintf(nodename, MAXNODELEN + 1, "%s@%s", name, hostname); - } + if ((atsign = strchr(cnodename, '@'))) { + /* we got a qualified node name, don't guess the host/domain */ + snprintf(nodename, MAXNODELEN + 1, "%s", name); + /* truncate the alivename at the @ */ + *atsign++ = '\0'; + strncpy(hostname, atsign, EI_MAXHOSTNAMELEN); + } else { + strncpy(hostname, kazoo_globals.hostname, EI_MAXHOSTNAMELEN); + snprintf(nodename, MAXNODELEN + 1, "%s@%s", name, hostname); + } if (kazoo_globals.ei_shortname) { char *off; @@ -373,94 +384,97 @@ switch_status_t create_ei_cnode(const char *ip_addr, const char *name, struct ei switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "creating nodename: %s\n", nodename); - /* init the ec stuff */ - if (ei_connect_xinit(ei_cnode, hostname, cnodename, nodename, (Erl_IpAddr) ip_addr, kazoo_globals.ei_cookie, 0) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to initialize the erlang interface connection structure\n"); - return SWITCH_STATUS_FALSE; - } + /* init the ec stuff */ + if (ei_connect_xinit(ei_cnode, hostname, cnodename, nodename, (Erl_IpAddr) ip_addr, kazoo_globals.ei_cookie, 0) < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to initialize the erlang interface connection structure\n"); + return SWITCH_STATUS_FALSE; + } - return SWITCH_STATUS_SUCCESS; + return SWITCH_STATUS_SUCCESS; } -switch_status_t ei_compare_pids(const erlang_pid *pid1, const erlang_pid *pid2) { - if ((!strcmp(pid1->node, pid2->node)) - && pid1->creation == pid2->creation - && pid1->num == pid2->num - && pid1->serial == pid2->serial) { - return SWITCH_STATUS_SUCCESS; - } else { - return SWITCH_STATUS_FALSE; - } +switch_status_t ei_compare_pids(const erlang_pid *pid1, const erlang_pid *pid2) +{ + if ((!strcmp(pid1->node, pid2->node)) && pid1->creation == pid2->creation && pid1->num == pid2->num && pid1->serial == pid2->serial) { + return SWITCH_STATUS_SUCCESS; + } else { + return SWITCH_STATUS_FALSE; + } } -void ei_link(ei_node_t *ei_node, erlang_pid * from, erlang_pid * to) { - char msgbuf[2048]; - char *s; - int index = 0; +void ei_link(ei_node_t *ei_node, erlang_pid * from, erlang_pid * to) +{ + char msgbuf[2048]; + char *s; + int index = 0; - index = 5; /* max sizes: */ - ei_encode_version(msgbuf, &index); /* 1 */ - ei_encode_tuple_header(msgbuf, &index, 3); - ei_encode_long(msgbuf, &index, ERL_LINK); - ei_encode_pid(msgbuf, &index, from); /* 268 */ - ei_encode_pid(msgbuf, &index, to); /* 268 */ + index = 5; /* max sizes: */ + ei_encode_version(msgbuf, &index); /* 1 */ + ei_encode_tuple_header(msgbuf, &index, 3); + ei_encode_long(msgbuf, &index, ERL_LINK); + ei_encode_pid(msgbuf, &index, from); /* 268 */ + ei_encode_pid(msgbuf, &index, to); /* 268 */ - /* 5 byte header missing */ - s = msgbuf; - put32be(s, index - 4); /* 4 */ - put8(s, ERL_PASS_THROUGH); /* 1 */ - /* sum: 542 */ + /* 5 byte header missing */ + s = msgbuf; + put32be(s, index - 4); /* 4 */ + put8(s, ERL_PASS_THROUGH); /* 1 */ + /* sum: 542 */ - if (write(ei_node->nodefd, msgbuf, index) == -1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to link to process on %s\n", ei_node->peer_nodename); - } + if (write(ei_node->nodefd, msgbuf, index) == -1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to link to process on %s\n", ei_node->peer_nodename); + } } -void ei_encode_switch_event(ei_x_buff *ebuf, switch_event_t *event) { - ei_x_encode_tuple_header(ebuf, 2); - ei_x_encode_atom(ebuf, "event"); - ei_encode_switch_event_headers(ebuf, event); +void ei_encode_switch_event(ei_x_buff *ebuf, switch_event_t *event) +{ + ei_x_encode_tuple_header(ebuf, 2); + ei_x_encode_atom(ebuf, "event"); + ei_encode_switch_event_headers(ebuf, event); } -int ei_helper_send(ei_node_t *ei_node, erlang_pid *to, ei_x_buff *buf) { - int ret = 0; +int ei_helper_send(ei_node_t *ei_node, erlang_pid *to, ei_x_buff *buf) +{ + int ret = 0; - if (ei_node->nodefd) { + if (ei_node->nodefd) { #ifdef EI_DEBUG ei_x_print_msg(buf, to, 1); #endif - ret = ei_send(ei_node->nodefd, to, buf->buff, buf->index); - } + ret = ei_send(ei_node->nodefd, to, buf->buff, buf->index); + } - return ret; + return ret; } -int ei_decode_atom_safe(char *buf, int *index, char *dst) { - int type, size; +int ei_decode_atom_safe(char *buf, int *index, char *dst) +{ + int type, size; - ei_get_type(buf, index, &type, &size); + ei_get_type(buf, index, &type, &size); if (type != ERL_ATOM_EXT) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unexpected erlang term type %d (size %d), needed atom\n", type, size); - return -1; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unexpected erlang term type %d (size %d), needed atom\n", type, size); + return -1; } else if (size > MAXATOMLEN) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Requested decoding of atom with size %d into a buffer of size %d\n", size, MAXATOMLEN); - return -1; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Requested decoding of atom with size %d into a buffer of size %d\n", size, MAXATOMLEN); + return -1; } else { return ei_decode_atom(buf, index, dst); } } -int ei_decode_string_or_binary(char *buf, int *index, char **dst) { - int type, size, res; - long len; +int ei_decode_string_or_binary(char *buf, int *index, char **dst) +{ + int type, size, res; + long len; - ei_get_type(buf, index, &type, &size); + ei_get_type(buf, index, &type, &size); - if (type != ERL_STRING_EXT && type != ERL_BINARY_EXT && type != ERL_LIST_EXT && type != ERL_NIL_EXT) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unexpected erlang term type %d (size %d), needed binary or string\n", type, size); - return -1; - } + if (type != ERL_STRING_EXT && type != ERL_BINARY_EXT && type != ERL_LIST_EXT && type != ERL_NIL_EXT) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unexpected erlang term type %d (size %d), needed binary or string\n", type, size); + return -1; + } *dst = malloc(size + 1); @@ -468,29 +482,30 @@ int ei_decode_string_or_binary(char *buf, int *index, char **dst) { res = 0; **dst = '\0'; } else if (type == ERL_BINARY_EXT) { - res = ei_decode_binary(buf, index, *dst, &len); - (*dst)[len] = '\0'; - } else { - res = ei_decode_string(buf, index, *dst); - } + res = ei_decode_binary(buf, index, *dst, &len); + (*dst)[len] = '\0'; + } else { + res = ei_decode_string(buf, index, *dst); + } - return res; + return res; } -int ei_decode_string_or_binary_limited(char *buf, int *index, int maxsize, char *dst) { - int type, size, res; - long len; +int ei_decode_string_or_binary_limited(char *buf, int *index, int maxsize, char *dst) +{ + int type, size, res; + long len; - ei_get_type(buf, index, &type, &size); + ei_get_type(buf, index, &type, &size); - if (type != ERL_STRING_EXT && type != ERL_BINARY_EXT && type != ERL_LIST_EXT && type != ERL_NIL_EXT) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unexpected erlang term type %d (size %d), needed binary or string\n", type, size); - return -1; - } + if (type != ERL_STRING_EXT && type != ERL_BINARY_EXT && type != ERL_LIST_EXT && type != ERL_NIL_EXT) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unexpected erlang term type %d (size %d), needed binary or string\n", type, size); + return -1; + } if (size > maxsize) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Requested decoding of %s with size %d into a buffer of size %d\n", - type == ERL_BINARY_EXT ? "binary" : "string", size, maxsize); + type == ERL_BINARY_EXT ? "binary" : "string", size, maxsize); return -1; } @@ -498,21 +513,21 @@ int ei_decode_string_or_binary_limited(char *buf, int *index, int maxsize, char res = 0; *dst = '\0'; } else if (type == ERL_BINARY_EXT) { - res = ei_decode_binary(buf, index, dst, &len); - dst[len] = '\0'; /* binaries aren't null terminated */ - } else { - res = ei_decode_string(buf, index, dst); - } + res = ei_decode_binary(buf, index, dst, &len); + dst[len] = '\0'; /* binaries aren't null terminated */ + } else { + res = ei_decode_string(buf, index, dst); + } - return res; + return res; } - -switch_status_t create_acceptor() { +switch_status_t create_acceptor() +{ switch_sockaddr_t *sa; uint16_t port; - char ipbuf[48]; - const char *ip_addr; + char ipbuf[48]; + const char *ip_addr; /* if the config has specified an erlang release compatibility then pass that along to the erlang interface */ if (kazoo_globals.ei_compat_rel) { @@ -527,7 +542,7 @@ switch_status_t create_acceptor() { switch_socket_addr_get(&sa, SWITCH_FALSE, kazoo_globals.acceptor); port = switch_sockaddr_get_port(sa); - ip_addr = switch_get_addr(ipbuf, sizeof (ipbuf), sa); + ip_addr = switch_get_addr(ipbuf, sizeof(ipbuf), sa); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Erlang connection acceptor listening on %s:%u\n", ip_addr, port); @@ -541,7 +556,7 @@ switch_status_t create_acceptor() { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to publish port to epmd, trying to start epmd via system()\n"); if (system("fs_epmd -daemon")) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, - "Failed to start epmd manually! Is epmd in $PATH? If not, start it yourself or run an erl shell with -sname or -name\n"); + "Failed to start epmd manually! Is epmd in $PATH? If not, start it yourself or run an erl shell with -sname or -name\n"); return SWITCH_STATUS_SOCKERR; } switch_yield(100000); @@ -551,12 +566,14 @@ switch_status_t create_acceptor() { } } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connected to epmd and published erlang cnode name %s at port %d\n", kazoo_globals.ei_cnode.thisnodename, port); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Connected to epmd and published erlang cnode name %s at port %d\n", kazoo_globals.ei_cnode.thisnodename, + port); return SWITCH_STATUS_SUCCESS; } -switch_hash_t *create_default_filter() { +switch_hash_t *create_default_filter() +{ switch_hash_t *filter; switch_core_hash_init(&filter); @@ -904,7 +921,7 @@ static void fetch_config_handlers(switch_memory_pool_t *pool) static void *SWITCH_THREAD_FUNC fetch_config_exec(switch_thread_t *thread, void *obj) { - switch_memory_pool_t *pool = (switch_memory_pool_t *)obj; + switch_memory_pool_t *pool = (switch_memory_pool_t *) obj; fetch_config_filters(pool); fetch_config_handlers(pool); @@ -913,13 +930,13 @@ static void *SWITCH_THREAD_FUNC fetch_config_exec(switch_thread_t *thread, void return NULL; } -void fetch_config() { +void fetch_config() +{ switch_memory_pool_t *pool; switch_thread_t *thread; switch_threadattr_t *thd_attr = NULL; switch_uuid_t uuid; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "fetching kazoo config\n"); switch_core_new_memory_pool(&pool); @@ -935,35 +952,35 @@ void fetch_config() { #ifdef WITH_KAZOO_ERL_SHUTDOWN #if (ERLANG_MAJOR == 10 && ERLANG_MINOR >= 3) || ERLANG_MAJOR >= 11 - typedef struct ei_mutex_s { - #ifdef __WIN32__ - HANDLE lock; - #elif VXWORKS - SEM_ID lock; - #else /* unix */ - #if defined(HAVE_MIT_PTHREAD_H) || defined(HAVE_PTHREAD_H) - pthread_mutex_t *lock; - #else /* ! (HAVE_MIT_PTHREAD_H || HAVE_PTHREAD_H) */ - void *dummy; /* Actually never used */ - #endif /* ! (HAVE_MIT_PTHREAD_H || HAVE_PTHREAD_H) */ - #endif /* unix */ - } ei_mutex_t; +typedef struct ei_mutex_s { +#ifdef __WIN32__ + HANDLE lock; +#elif VXWORKS + SEM_ID lock; +#else /* unix */ +#if defined(HAVE_MIT_PTHREAD_H) || defined(HAVE_PTHREAD_H) + pthread_mutex_t *lock; +#else /* ! (HAVE_MIT_PTHREAD_H || HAVE_PTHREAD_H) */ + void *dummy; /* Actually never used */ +#endif /* ! (HAVE_MIT_PTHREAD_H || HAVE_PTHREAD_H) */ +#endif /* unix */ +}ei_mutex_t; - typedef struct ei_socket_info_s { - int socket; - ei_socket_callbacks *cbs; - void *ctx; - int dist_version; - ei_cnode cnode; /* A copy, not a pointer. We don't know when freed */ - char cookie[EI_MAX_COOKIE_SIZE+1]; - } ei_socket_info; +typedef struct ei_socket_info_s { + int socket; + ei_socket_callbacks *cbs; + void *ctx; + int dist_version; + ei_cnode cnode; /* A copy, not a pointer. We don't know when freed */ + char cookie[EI_MAX_COOKIE_SIZE+1]; +}ei_socket_info; - extern ei_socket_info *ei_sockets; - extern ei_mutex_t* ei_sockets_lock; - extern int ei_n_sockets; - extern int ei_sz_sockets; +extern ei_socket_info *ei_sockets; +extern ei_mutex_t* ei_sockets_lock; +extern int ei_n_sockets; +extern int ei_sz_sockets; - int ei_mutex_free(ei_mutex_t *l, int nblock); +int ei_mutex_free(ei_mutex_t *l, int nblock); #endif #endif @@ -988,10 +1005,11 @@ void kz_erl_shutdown() #endif } -SWITCH_MODULE_RUNTIME_FUNCTION(mod_kazoo_runtime) { +SWITCH_MODULE_RUNTIME_FUNCTION(mod_kazoo_runtime) +{ switch_os_socket_t os_socket; - if(create_acceptor() != SWITCH_STATUS_SUCCESS) { + if (create_acceptor() != SWITCH_STATUS_SUCCESS) { // TODO: what would we need to clean up here switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to create erlang connection acceptor!\n"); close_socket(&kazoo_globals.acceptor); @@ -1018,7 +1036,7 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_kazoo_runtime) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Erlang connection acceptor socket error %d %d\n", erl_errno, errno); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, - "Erlang node connection failed - ensure your cookie matches '%s' and you are using a good nodename\n", kazoo_globals.ei_cookie); + "Erlang node connection failed - ensure your cookie matches '%s' and you are using a good nodename\n", kazoo_globals.ei_cookie); } continue; } diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_endpoints.c b/src/mod/event_handlers/mod_kazoo/kazoo_endpoints.c index bec5b5e1ea..2e111db3af 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_endpoints.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_endpoints.c @@ -271,7 +271,7 @@ static switch_call_cause_t kz_endpoint_outgoing_channel(switch_core_session_t *s } else if(var_event) { const char* uuid_e_session = switch_event_get_header(var_event, "ent_originate_aleg_uuid"); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHECKING ORIGINATE-UUID : %s\n", uuid_e_session); - if (uuid_e_session && (e_session = switch_core_session_force_locate(uuid_e_session)) != NULL) { + if (uuid_e_session && (e_session = switch_core_session_locate(uuid_e_session)) != NULL) { a_session = e_session; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FOUND ORIGINATE-UUID : %s\n", uuid_e_session); } diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_event_stream.c b/src/mod/event_handlers/mod_kazoo/kazoo_event_stream.c index c2a53933ea..4f0148340d 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_event_stream.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_event_stream.c @@ -202,14 +202,17 @@ 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); + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Switch-Nodename", kazoo_globals.ei_cnode.thisnodename); 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); } else { res = encode_event_new(event, ebuf); } + switch_event_del_header(event, "Switch-Nodename"); + switch_event_del_header(event, "Target-Node"); + if(!res) { ei_x_free(ebuf); switch_safe_free(ebuf); @@ -391,7 +394,7 @@ ei_event_stream_t *new_event_stream(ei_node_t *ei_node, const erlang_pid *from) /* from the memory pool, allocate the event stream structure */ if (!(event_stream = switch_core_alloc(pool, sizeof (*event_stream)))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Out of memory: I may have Alzheimers but at least I dont have Alzheimers.\n"); - return NULL; + goto cleanup; } /* prepare the event stream */ @@ -408,28 +411,24 @@ ei_event_stream_t *new_event_stream(ei_node_t *ei_node, const erlang_pid *from) /* create a socket for accepting the event stream client */ if (!(event_stream->acceptor = create_socket(pool))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Like car accidents, most hardware problems are due to driver error.\n"); - /* TODO: clean up */ - return NULL; + goto cleanup; } if (switch_socket_opt_set(event_stream->acceptor, SWITCH_SO_NONBLOCK, TRUE)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Hey, it compiles!\n"); - /* TODO: clean up */ - return NULL; + goto cleanup; } /* create a pollset so we can efficiently check for new client connections */ if (switch_pollset_create(&event_stream->pollset, 1000, pool, 0) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "My software never has bugs. It just develops random features.\n"); - /* TODO: clean up */ - return NULL; + goto cleanup; } switch_socket_create_pollfd(&event_stream->pollfd, event_stream->acceptor, SWITCH_POLLIN | SWITCH_POLLERR, NULL, pool); if (switch_pollset_add(event_stream->pollset, event_stream->pollfd) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "If you saw a heat wave, would you wave back?\n"); - /* TODO: clean up */ - return NULL; + goto cleanup; } switch_mutex_init(&event_stream->socket_mutex, SWITCH_MUTEX_DEFAULT, pool); @@ -454,6 +453,26 @@ ei_event_stream_t *new_event_stream(ei_node_t *ei_node, const erlang_pid *from) switch_thread_create(&thread, thd_attr, event_stream_loop, event_stream, event_stream->pool); return event_stream; + +cleanup: + + if (event_stream) { + /* remove the acceptor pollset */ + if (event_stream->pollset) { + switch_pollset_remove(event_stream->pollset, event_stream->pollfd); + } + + /* close any open sockets */ + if (event_stream->acceptor) { + close_socket(&event_stream->acceptor); + } + } + + /* clean up the memory */ + switch_core_destroy_memory_pool(&pool); + + return NULL; + } unsigned long get_stream_port(const ei_event_stream_t *event_stream) { diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_fetch_agent.c b/src/mod/event_handlers/mod_kazoo/kazoo_fetch_agent.c index f48660d6eb..0b9efe45d0 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_fetch_agent.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_fetch_agent.c @@ -154,6 +154,8 @@ static switch_xml_t fetch_handler(const char *section, const char *tag_name, con } } + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Switch-Nodename", kazoo_globals.ei_cnode.thisnodename); + /* prepare the reply collector */ switch_uuid_get(&uuid); switch_uuid_format(reply.uuid_str, &uuid); @@ -165,7 +167,7 @@ static switch_xml_t fetch_handler(const char *section, const char *tag_name, con for(i = 0; fetch_uuid_sources[i] != NULL; i++) { if((fetch_call_id = switch_event_get_header(event, fetch_uuid_sources[i])) != NULL) { switch_core_session_t *session = NULL; - if((session = switch_core_session_force_locate(fetch_call_id)) != NULL) { + if((session = switch_core_session_locate(fetch_call_id)) != NULL) { switch_channel_t *channel = switch_core_session_get_channel(session); uint32_t verbose = switch_channel_test_flag(channel, CF_VERBOSE_EVENTS); switch_channel_set_flag(channel, CF_VERBOSE_EVENTS); diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_fields.h b/src/mod/event_handlers/mod_kazoo/kazoo_fields.h index 6c8111bfe4..8d17378768 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_fields.h +++ b/src/mod/event_handlers/mod_kazoo/kazoo_fields.h @@ -55,6 +55,10 @@ struct kazoo_log_levels switch_log_level_t time_log_level; switch_log_level_t filtered_event_log_level; switch_log_level_t filtered_field_log_level; + switch_log_level_t trace_log_level; + switch_log_level_t debug_log_level; + switch_log_level_t error_log_level; + switch_log_level_t hashing_log_level; }; @@ -138,6 +142,7 @@ struct kazoo_field_t { switch_bool_t exclude_prefix; kazoo_field_type in_type; kazoo_json_field_type out_type; + int out_type_as_array; kazoo_filter_ptr filter; kazoo_definition_ptr ref; @@ -162,6 +167,7 @@ struct kazoo_event { char *name; kazoo_fields_ptr fields; kazoo_filter_ptr filter; + kazoo_loglevels_ptr logging; kazoo_event_t* next; }; diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_message.c b/src/mod/event_handlers/mod_kazoo/kazoo_message.c index a35dfab080..e43d656b4c 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_message.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_message.c @@ -45,7 +45,7 @@ void kazoo_cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) cJSON_AddItemToObject(object, string, item); } -static int inline filter_compare(switch_event_t* evt, kazoo_filter_ptr filter) +static int inline filter_compare(switch_event_t* evt, kazoo_filter_ptr filter, kazoo_logging_ptr logging) { switch_event_header_t *header; int hasValue = 0, n; @@ -55,6 +55,7 @@ static int inline filter_compare(switch_event_t* evt, kazoo_filter_ptr filter) case FILTER_COMPARE_EXISTS: hasValue = switch_event_get_header(evt, filter->name) != NULL ? 1 : 0; + switch_log_printf(SWITCH_CHANNEL_LOG, logging->levels->trace_log_level, "profile[%s] event %s checking if %s exists => %s\n", logging->profile_name, logging->event_name, filter->name, hasValue ? "true" : "false"); break; case FILTER_COMPARE_VALUE: @@ -64,6 +65,7 @@ static int inline filter_compare(switch_event_t* evt, kazoo_filter_ptr filter) value = switch_event_get_header(evt, filter->name); } hasValue = value ? !strcmp(value, filter->value) : 0; + switch_log_printf(SWITCH_CHANNEL_LOG, logging->levels->trace_log_level, "profile[%s] event %s compare value %s to %s => %s == %s => %s\n", logging->profile_name, logging->event_name, filter->name, filter->value, value, filter->value, hasValue ? "true" : "false"); break; case FILTER_COMPARE_FIELD: @@ -73,6 +75,7 @@ static int inline filter_compare(switch_event_t* evt, kazoo_filter_ptr filter) value = switch_event_get_header(evt, filter->name); } hasValue = value ? !strcmp(value, switch_event_get_header_nil(evt, filter->value)) : 0; + switch_log_printf(SWITCH_CHANNEL_LOG, logging->levels->trace_log_level, "profile[%s] event %s compare field %s to %s => %s == %s => %s\n", logging->profile_name, logging->event_name, filter->name, filter->value, value, switch_event_get_header_nil(evt, filter->value), hasValue ? "true" : "false"); break; case FILTER_COMPARE_PREFIX: @@ -112,10 +115,10 @@ static int inline filter_compare(switch_event_t* evt, kazoo_filter_ptr filter) return hasValue; } -static kazoo_filter_ptr inline filter_event(switch_event_t* evt, kazoo_filter_ptr filter) +static kazoo_filter_ptr inline filter_event(switch_event_t* evt, kazoo_filter_ptr filter, kazoo_logging_ptr logging) { while(filter) { - int hasValue = filter_compare(evt, filter); + int hasValue = filter_compare(evt, filter, logging); if(filter->type == FILTER_EXCLUDE) { if(hasValue) break; @@ -132,31 +135,37 @@ static void kazoo_event_init_json_fields(switch_event_t *event, cJSON *json) { switch_event_header_t *hp; for (hp = event->headers; hp; hp = hp->next) { - if (hp->idx) { - cJSON *a = cJSON_CreateArray(); - int i; + if (strncmp(hp->name, "_json_", 6)) { + if (hp->idx) { + cJSON *a = cJSON_CreateArray(); + int i; - for(i = 0; i < hp->idx; i++) { - cJSON_AddItemToArray(a, cJSON_CreateString(hp->array[i])); + for(i = 0; i < hp->idx; i++) { + cJSON_AddItemToArray(a, cJSON_CreateString(hp->array[i])); + } + + cJSON_AddItemToObject(json, hp->name, a); + + } else { + cJSON_AddItemToObject(json, hp->name, cJSON_CreateString(hp->value)); } - - cJSON_AddItemToObject(json, hp->name, a); - - } else { - cJSON_AddItemToObject(json, hp->name, cJSON_CreateString(hp->value)); } } } static switch_status_t kazoo_event_init_json(kazoo_fields_ptr fields1, kazoo_fields_ptr fields2, switch_event_t* evt, cJSON** clone) { - switch_status_t status; + switch_status_t status = SWITCH_STATUS_SUCCESS; if( (fields2 && fields2->verbose) || (fields1 && fields1->verbose) || ( (!fields2) && (!fields1)) ) { - status = switch_event_serialize_json_obj(evt, clone); + *clone = cJSON_CreateObject(); + if((*clone) == NULL) { + status = SWITCH_STATUS_GENERR; + } else { + kazoo_event_init_json_fields(evt, *clone); + } } else { - status = SWITCH_STATUS_SUCCESS; *clone = cJSON_CreateObject(); if((*clone) == NULL) { status = SWITCH_STATUS_GENERR; @@ -185,7 +194,11 @@ static cJSON * kazoo_event_json_value(kazoo_json_field_type type, const char *va break; case JSON_RAW: - item = cJSON_CreateRaw(value); + item = cJSON_Parse(value); + if (!item) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "parse from raw error!\n"); + item = cJSON_CreateRaw(value); + } break; default: @@ -210,18 +223,24 @@ cJSON * kazoo_event_add_field_to_json(cJSON *dst, switch_event_t *src, kazoo_fie { switch_event_header_t *header; char *expanded; - uint i, n; + int i, n; cJSON *item = NULL; switch(field->in_type) { case FIELD_COPY: - if((header = switch_event_get_header_ptr(src, field->name)) != NULL) { + if (!strcmp(field->name, "_body")) { + item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, src->body); + } else if((header = switch_event_get_header_ptr(src, field->name)) != NULL) { if (header->idx) { item = cJSON_CreateArray(); for(i = 0; i < header->idx; i++) { cJSON_AddItemToArray(item, kazoo_event_json_value(field->out_type, header->array[i])); } kazoo_cJSON_AddItemToObject(dst, field->as ? field->as : field->name, item); + } else if (field->out_type_as_array) { + item = cJSON_CreateArray(); + cJSON_AddItemToArray(item, kazoo_event_json_value(field->out_type, header->value)); + kazoo_cJSON_AddItemToObject(dst, field->as ? field->as : field->name, item); } else { item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, header->value); } @@ -299,7 +318,7 @@ static switch_status_t kazoo_event_add_fields_to_json(kazoo_logging_ptr logging, while(field) { if(field->in_type == FIELD_REFERENCE) { if(field->ref) { - if((filter = filter_event(src, field->ref->filter)) != NULL) { + if((filter = filter_event(src, field->ref->filter, logging)) != NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, logging->levels->filtered_field_log_level, "profile[%s] event %s, referenced field %s filtered by settings %s : %s\n", logging->profile_name, logging->event_name, field->ref->name, filter->name, filter->value); } else { kazoo_event_add_fields_to_json(logging, dst, src, field->ref->head); @@ -308,7 +327,7 @@ static switch_status_t kazoo_event_add_fields_to_json(kazoo_logging_ptr logging, switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "profile[%s] event %s, referenced field %s not found\n", logging->profile_name, logging->event_name, field->name); } } else { - if((filter = filter_event(src, field->filter)) != NULL) { + if((filter = filter_event(src, field->filter, logging)) != NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, logging->levels->filtered_field_log_level, "profile[%s] event %s, field %s filtered by settings %s : %s\n", logging->profile_name, logging->event_name, field->name, filter->name, filter->value); } else { item = kazoo_event_add_field_to_json(dst, src, field); @@ -351,12 +370,9 @@ kazoo_message_ptr kazoo_message_create_event(switch_event_t* evt, kazoo_event_pt kazoo_logging_t logging; logging.levels = profile->logging; - logging.event_name = switch_event_get_header_nil(evt, "Event-Name"); + logging.event_name = evt->subclass_name ? evt->subclass_name : switch_event_get_header_nil(evt, "Event-Name"); logging.profile_name = profile->name; - switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM, "Switch-Nodename", kazoo_globals.ei_cnode.thisnodename); - - message = malloc(sizeof(kazoo_message_t)); if(message == NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error allocating memory for serializing event to json\n"); @@ -366,15 +382,19 @@ kazoo_message_ptr kazoo_message_create_event(switch_event_t* evt, kazoo_event_pt if(profile->filter) { // filtering - if((filtered = filter_event(evt, profile->filter)) != NULL) { + if((filtered = filter_event(evt, profile->filter, &logging)) != NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, logging.levels->filtered_event_log_level, "profile[%s] event %s filtered by profile settings %s : %s\n", logging.profile_name, logging.event_name, filtered->name, filtered->value); kazoo_message_destroy(&message); return NULL; } } - if(event && event->filter) { - if((filtered = filter_event(evt, event->filter)) != NULL) { + if (event->logging) { + logging.levels = event->logging; + } + + if (event && event->filter) { + if((filtered = filter_event(evt, event->filter, &logging)) != NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, logging.levels->filtered_event_log_level, "profile[%s] event %s filtered by event settings %s : %s\n", logging.profile_name, logging.event_name, filtered->name, filtered->value); kazoo_message_destroy(&message); return NULL; @@ -409,8 +429,6 @@ kazoo_message_ptr kazoo_message_create_fetch(switch_event_t* evt, kazoo_fetch_pr logging.event_name = switch_event_get_header_nil(evt, "Event-Name"); logging.profile_name = profile->name; - switch_event_add_header_string(evt, SWITCH_STACK_BOTTOM, "Switch-Nodename", kazoo_globals.ei_cnode.thisnodename); - message = malloc(sizeof(kazoo_message_t)); if(message == NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error allocating memory for serializing event to json\n"); diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_node.c b/src/mod/event_handlers/mod_kazoo/kazoo_node.c index e11a48d6ac..15f5ba9224 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_node.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_node.c @@ -208,15 +208,13 @@ SWITCH_DECLARE(switch_status_t) kazoo_api_execute(const char *cmd, const char *a char *arg_used; char *cmd_used; int fire_event = 0; - char *arg_expanded; + char *arg_expanded = NULL; switch_event_t* evt; switch_assert(stream != NULL); switch_assert(stream->data != NULL); switch_assert(stream->write_function != NULL); - arg_expanded = (char *) arg; - switch_event_create(&evt, SWITCH_EVENT_GENERAL); arg_expanded = switch_event_expand_headers(evt, arg); switch_event_destroy(&evt); @@ -507,7 +505,7 @@ static switch_status_t build_event(switch_event_t *event, ei_x_buff * buf) { if(!strcasecmp(key, "Call-ID")) { switch_core_session_t *session = NULL; if(!zstr(value)) { - if ((session = switch_core_session_force_locate(value)) != NULL) { + if ((session = switch_core_session_locate(value)) != NULL) { switch_channel_t *channel = switch_core_session_get_channel(session); switch_channel_event_set_data(channel, event); switch_core_session_rwunlock(session); diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_tweaks.c b/src/mod/event_handlers/mod_kazoo/kazoo_tweaks.c index 2afcdf1a6a..8b1d19d89c 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_tweaks.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_tweaks.c @@ -102,10 +102,10 @@ static void kz_tweaks_handle_bridge_variables(switch_event_t *event) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "tweak bridge event handler: variables : %s , %s\n", a_leg, b_leg); - if (a_leg && (a_session = switch_core_session_force_locate(a_leg)) != NULL) { + if (a_leg && (a_session = switch_core_session_locate(a_leg)) != NULL) { switch_channel_t *a_channel = switch_core_session_get_channel(a_session); if(switch_channel_get_variable_dup(a_channel, bridge_variables[0], SWITCH_FALSE, -1) == NULL) { - if(b_leg && (b_session = switch_core_session_force_locate(b_leg)) != NULL) { + if(b_leg && (b_session = switch_core_session_locate(b_leg)) != NULL) { switch_channel_t *b_channel = switch_core_session_get_channel(b_session); for(i = 0; bridge_variables[i] != NULL; i++) { const char *val = switch_channel_get_variable_dup(b_channel, bridge_variables[i], SWITCH_FALSE, -1); @@ -114,7 +114,7 @@ static void kz_tweaks_handle_bridge_variables(switch_event_t *event) switch_core_session_rwunlock(b_session); } } else { - if(b_leg && (b_session = switch_core_session_force_locate(b_leg)) != NULL) { + if(b_leg && (b_session = switch_core_session_locate(b_leg)) != NULL) { switch_channel_t *b_channel = switch_core_session_get_channel(b_session); if(switch_channel_get_variable_dup(b_channel, bridge_variables[0], SWITCH_FALSE, -1) == NULL) { for(i = 0; bridge_variables[i] != NULL; i++) { @@ -193,7 +193,7 @@ static void kz_tweaks_handle_bridge_replaces_call_id(switch_event_t *event) if(a_leg_call_id && replaced_call_id) { switch_core_session_t *call_session = NULL; const char *call_id = switch_event_get_header(event, "Bridge-B-Unique-ID"); - if (call_id && (call_session = switch_core_session_force_locate(call_id)) != NULL) { + if (call_id && (call_session = switch_core_session_locate(call_id)) != NULL) { switch_channel_t *call_channel = switch_core_session_get_channel(call_session); if (switch_event_create(&my_event, SWITCH_EVENT_CHANNEL_BRIDGE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(my_event, SWITCH_STACK_BOTTOM, "Bridge-A-Unique-ID", switch_core_session_get_uuid(call_session)); @@ -259,13 +259,13 @@ static void kz_tweaks_channel_transferor_event_handler(switch_event_t *event) 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) { + if ((uuid_session = switch_core_session_locate(uuid)) != NULL) { switch_channel_t *uuid_channel = switch_core_session_get_channel(uuid_session); const char* interaction_id = switch_channel_get_variable_dup(uuid_channel, INTERACTION_VARIABLE, SWITCH_TRUE, -1); // set to uuid & peer_uuid if(interaction_id != NULL) { switch_core_session_t *session = NULL; - if(dest_call_id && (session = switch_core_session_force_locate(dest_call_id)) != NULL) { + if(dest_call_id && (session = switch_core_session_locate(dest_call_id)) != NULL) { switch_channel_t *channel = switch_core_session_get_channel(session); const char* prv_interaction_id = switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_TRUE, -1); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "LOCATING UUID PRV : %s : %s\n", prv_interaction_id, interaction_id); @@ -279,7 +279,7 @@ static void kz_tweaks_channel_transferor_event_handler(switch_event_t *event) } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR NO UUID SESSION: %s , %s , %s \n", uuid, dest_call_id, dest_peer_uuid); } - if(dest_peer_uuid && (session = switch_core_session_force_locate(dest_peer_uuid)) != NULL) { + if(dest_peer_uuid && (session = switch_core_session_locate(dest_peer_uuid)) != NULL) { switch_channel_t *channel = switch_core_session_get_channel(session); const char* prv_interaction_id = switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_TRUE, -1); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "LOCATING PEER UUID PRV : %s : %s\n", prv_interaction_id, interaction_id); @@ -293,7 +293,7 @@ static void kz_tweaks_channel_transferor_event_handler(switch_event_t *event) } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR NO PEER SESSION: %s , %s , %s \n", uuid, dest_call_id, dest_peer_uuid); } - if(orig_call_id && (session = switch_core_session_force_locate(orig_call_id)) != NULL) { + if(orig_call_id && (session = switch_core_session_locate(orig_call_id)) != NULL) { switch_channel_t *channel = switch_core_session_get_channel(session); const char* prv_interaction_id = switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_TRUE, -1); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "LOCATING PEER UUID PRV : %s : %s\n", prv_interaction_id, interaction_id); diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_utils.c b/src/mod/event_handlers/mod_kazoo/kazoo_utils.c index 34b33c8ae1..1986f81717 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_utils.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_utils.c @@ -386,7 +386,6 @@ SWITCH_DECLARE(char *) kz_event_expand_headers_check(switch_event_t *event, cons switch_safe_free(expanded_sub_val); sub_val = NULL; vname = NULL; - vtype = 0; br = 0; } @@ -438,21 +437,18 @@ SWITCH_DECLARE(char *) kz_event_expand_headers_pool(switch_memory_pool_t *pool, return dup; } -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; -} - -SWITCH_DECLARE(char *) kz_expand(const char *in) +SWITCH_DECLARE(char *) kz_expand(const char *in, const char *uuid) { switch_event_t *event = NULL; char *ret = NULL; kz_switch_core_base_headers_for_expand(&event); + if (uuid != NULL) { + switch_core_session_t *nsession = NULL; + if ((nsession = switch_core_session_locate(uuid))) { + switch_channel_event_set_data(switch_core_session_get_channel(nsession), event); + switch_core_session_rwunlock(nsession); + } + } ret = kz_event_expand_headers_check(event, in, NULL, NULL, 0); switch_event_destroy(&event); return ret; @@ -463,7 +459,7 @@ SWITCH_DECLARE(char *) kz_expand_pool(switch_memory_pool_t *pool, const char *in char *expanded; char *dup = NULL; - if(!(expanded = kz_expand(in))) { + if(!(expanded = kz_expand(in, NULL))) { return NULL; } dup = switch_core_strdup(pool, expanded); @@ -584,12 +580,14 @@ void kz_event_decode(switch_event_t *event) switch_event_header_t *hp; int i; for (hp = event->headers; hp; hp = hp->next) { - if (hp->idx) { - for(i = 0; i < hp->idx; i++) { - switch_url_decode(hp->array[i]); + if (strncmp(hp->name, "_json_", 6)) { + if (hp->idx) { + for(i = 0; i < hp->idx; i++) { + switch_url_decode(hp->array[i]); + } + } else { + switch_url_decode(hp->value); } - } else { - switch_url_decode(hp->value); } } } diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_utils.h b/src/mod/event_handlers/mod_kazoo/kazoo_utils.h index c5ddc3e037..cb5549c760 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_utils.h +++ b/src/mod/event_handlers/mod_kazoo/kazoo_utils.h @@ -26,9 +26,7 @@ SWITCH_DECLARE(char *) kz_event_expand_headers(switch_event_t *event, const char SWITCH_DECLARE(char *) kz_event_expand_headers_pool(switch_memory_pool_t *pool, switch_event_t *event, char *val); -SWITCH_DECLARE(char *) kz_event_expand(const char *in); - -SWITCH_DECLARE(char *) kz_expand(const char *in); +SWITCH_DECLARE(char *) kz_expand(const char *in, const char *uuid); SWITCH_DECLARE(char *) kz_expand_pool(switch_memory_pool_t *pool, const char *in); diff --git a/src/mod/event_handlers/mod_kazoo/mod_kazoo.c b/src/mod/event_handlers/mod_kazoo/mod_kazoo.c index 93ccb5aaf8..15b8fb469c 100644 --- a/src/mod/event_handlers/mod_kazoo/mod_kazoo.c +++ b/src/mod/event_handlers/mod_kazoo/mod_kazoo.c @@ -79,6 +79,9 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_kazoo_load) /* add tweaks */ kz_tweaks_start(); + /* add our cdr */ + kz_cdr_start(); + /* indicate that the module should continue to be loaded */ return SWITCH_STATUS_SUCCESS; } @@ -88,6 +91,8 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_kazoo_shutdown) { remove_cli_api(); + kz_cdr_stop(); + kz_tweaks_stop(); /* stop taking new requests and start shuting down the threads */ diff --git a/src/mod/event_handlers/mod_kazoo/mod_kazoo.h b/src/mod/event_handlers/mod_kazoo/mod_kazoo.h index c9f16f4826..37fdd861e7 100644 --- a/src/mod/event_handlers/mod_kazoo/mod_kazoo.h +++ b/src/mod/event_handlers/mod_kazoo/mod_kazoo.h @@ -58,6 +58,9 @@ switch_status_t kz_json_api(const char * command, cJSON *args, cJSON **res); /* kazoo_endpoints.c */ void add_kz_endpoints(switch_loadable_module_interface_t **module_interface); +/* kazoo_cdr.c */ +void kz_cdr_start(); +void kz_cdr_stop(); /* kazoo_tweaks.c */ void kz_tweaks_start();