From 87bb7cb5fb6f9fc2ef288b5c3560a85366acead4 Mon Sep 17 00:00:00 2001 From: Mike Jerris Date: Thu, 25 Jan 2018 15:51:44 -0600 Subject: [PATCH] Revert "FS-10820 [mod_kazoo] eventstream configuration" This reverts commit bb4499ec24bd7a5cadb90eab1b1a05515d38eaa2. This commit breaks the build. Please correct and re-submit --- src/mod/event_handlers/mod_kazoo/Makefile.am | 14 +- .../event_handlers/mod_kazoo/kazoo.conf.xml | 953 ----------------- src/mod/event_handlers/mod_kazoo/kazoo_api.c | 396 ------- .../event_handlers/mod_kazoo/kazoo_commands.c | 21 +- .../event_handlers/mod_kazoo/kazoo_config.c | 535 ---------- .../event_handlers/mod_kazoo/kazoo_config.h | 62 -- .../event_handlers/mod_kazoo/kazoo_dptools.c | 199 +--- src/mod/event_handlers/mod_kazoo/kazoo_ei.h | 262 ----- .../mod_kazoo/kazoo_ei_config.c | 543 ---------- .../event_handlers/mod_kazoo/kazoo_ei_utils.c | 996 ------------------ .../mod_kazoo/kazoo_event_stream.c | 235 ++--- .../mod_kazoo/kazoo_fetch_agent.c | 180 +--- .../event_handlers/mod_kazoo/kazoo_fields.h | 195 ---- .../event_handlers/mod_kazoo/kazoo_message.c | 458 -------- .../event_handlers/mod_kazoo/kazoo_message.h | 65 -- src/mod/event_handlers/mod_kazoo/kazoo_node.c | 221 +--- .../event_handlers/mod_kazoo/kazoo_tweaks.c | 502 --------- .../event_handlers/mod_kazoo/kazoo_utils.c | 701 ++++++++++-- src/mod/event_handlers/mod_kazoo/mod_kazoo.c | 687 +++++++++++- src/mod/event_handlers/mod_kazoo/mod_kazoo.h | 163 ++- 20 files changed, 1670 insertions(+), 5718 deletions(-) delete mode 100644 src/mod/event_handlers/mod_kazoo/kazoo.conf.xml delete mode 100644 src/mod/event_handlers/mod_kazoo/kazoo_api.c delete mode 100644 src/mod/event_handlers/mod_kazoo/kazoo_config.c delete mode 100644 src/mod/event_handlers/mod_kazoo/kazoo_config.h delete mode 100644 src/mod/event_handlers/mod_kazoo/kazoo_ei.h delete mode 100644 src/mod/event_handlers/mod_kazoo/kazoo_ei_config.c delete mode 100644 src/mod/event_handlers/mod_kazoo/kazoo_ei_utils.c delete mode 100644 src/mod/event_handlers/mod_kazoo/kazoo_fields.h delete mode 100644 src/mod/event_handlers/mod_kazoo/kazoo_message.c delete mode 100644 src/mod/event_handlers/mod_kazoo/kazoo_message.h delete mode 100644 src/mod/event_handlers/mod_kazoo/kazoo_tweaks.c diff --git a/src/mod/event_handlers/mod_kazoo/Makefile.am b/src/mod/event_handlers/mod_kazoo/Makefile.am index ed2eec7b9c..53fd7112e1 100644 --- a/src/mod/event_handlers/mod_kazoo/Makefile.am +++ b/src/mod/event_handlers/mod_kazoo/Makefile.am @@ -4,23 +4,11 @@ MODNAME=mod_kazoo if HAVE_ERLANG mod_LTLIBRARIES = mod_kazoo.la -mod_kazoo_la_SOURCES = mod_kazoo.c kazoo_utils.c kazoo_dptools.c kazoo_tweaks.c -mod_kazoo_la_SOURCES += kazoo_api.c kazoo_commands.c kazoo_config.c -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 = mod_kazoo.c kazoo_utils.c kazoo_node.c kazoo_event_stream.c kazoo_fetch_agent.c kazoo_commands.c kazoo_dptools.c mod_kazoo_la_CFLAGS = $(AM_CFLAGS) @ERLANG_CFLAGS@ -D_REENTRANT mod_kazoo_la_LIBADD = $(switch_builddir)/libfreeswitch.la mod_kazoo_la_LDFLAGS = -avoid-version -module -no-undefined -shared @ERLANG_LDFLAGS@ -mod_kazoo.la: kazoo_definitions.h $(mod_kazoo_la_OBJECTS) $(mod_kazoo_la_DEPENDENCIES) $(EXTRA_mod_kazoo_la_DEPENDENCIES) - $(AM_V_CCLD)$(mod_kazoo_la_LINK) $(am_mod_kazoo_la_rpath) $(mod_kazoo_la_OBJECTS) $(mod_kazoo_la_LIBADD) $(LIBS) - - -kazoo_definitions.h: - xxd -i kazoo.conf.xml > kazoo_definitions.h - else install: error all: error diff --git a/src/mod/event_handlers/mod_kazoo/kazoo.conf.xml b/src/mod/event_handlers/mod_kazoo/kazoo.conf.xml deleted file mode 100644 index 7a5fdb4c7b..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo.conf.xml +++ /dev/null @@ -1,953 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_api.c b/src/mod/event_handlers/mod_kazoo/kazoo_api.c deleted file mode 100644 index 09d3d05419..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_api.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * 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): - * - * Karl Anderson - * Darren Schreiber - * - * - * mod_kazoo.c -- Socket Controlled Event Handler - * - */ -#include "mod_kazoo.h" - -#define KAZOO_DESC "kazoo information" -#define KAZOO_SYNTAX " []" - -#define API_COMMAND_DISCONNECT 0 -#define API_COMMAND_REMOTE_IP 1 -#define API_COMMAND_STREAMS 2 -#define API_COMMAND_BINDINGS 3 - - -static switch_status_t api_erlang_status(switch_stream_handle_t *stream) { - switch_sockaddr_t *sa; - uint16_t port; - char ipbuf[48]; - const char *ip_addr; - ei_node_t *ei_node; - - 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); - - stream->write_function(stream, "Running %s\n", VERSION); - stream->write_function(stream, "Listening for new Erlang connections on %s:%u with cookie %s\n", ip_addr, port, kazoo_globals.ei_cookie); - stream->write_function(stream, "Registered as Erlang node %s, visible as %s\n", kazoo_globals.ei_cnode.thisnodename, kazoo_globals.ei_cnode.thisalivename); - - if (kazoo_globals.ei_compat_rel) { - stream->write_function(stream, "Using Erlang compatibility mode: %d\n", kazoo_globals.ei_compat_rel); - } - - switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock); - ei_node = kazoo_globals.ei_nodes; - if (!ei_node) { - stream->write_function(stream, "No erlang nodes connected\n"); - } else { - stream->write_function(stream, "Connected to:\n"); - while(ei_node != NULL) { - unsigned int year, day, hour, min, sec, delta; - - delta = (switch_micro_time_now() - ei_node->created_time) / 1000000; - sec = delta % 60; - min = delta / 60 % 60; - hour = delta / 3600 % 24; - day = delta / 86400 % 7; - year = delta / 31556926 % 12; - stream->write_function(stream, " %s (%s:%d) up %d years, %d days, %d hours, %d minutes, %d seconds\n" - ,ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port, year, day, hour, min, sec); - ei_node = ei_node->next; - } - } - switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t api_erlang_event_filter(switch_stream_handle_t *stream) { - switch_hash_index_t *hi = NULL; - int column = 0; - - for (hi = (switch_hash_index_t *)switch_core_hash_first_iter(kazoo_globals.event_filter, hi); hi; hi = switch_core_hash_next(&hi)) { - const void *key; - void *val; - switch_core_hash_this(hi, &key, NULL, &val); - stream->write_function(stream, "%-50s", (char *)key); - if (++column > 2) { - stream->write_function(stream, "\n"); - column = 0; - } - } - - if (++column > 2) { - stream->write_function(stream, "\n"); - column = 0; - } - - stream->write_function(stream, "%-50s", kazoo_globals.kazoo_var_prefix); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t api_erlang_nodes_list(switch_stream_handle_t *stream) { - ei_node_t *ei_node; - - switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock); - ei_node = kazoo_globals.ei_nodes; - while(ei_node != NULL) { - stream->write_function(stream, "%s (%s)\n", ei_node->peer_nodename, ei_node->remote_ip); - ei_node = ei_node->next; - } - switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t api_erlang_nodes_count(switch_stream_handle_t *stream) { - ei_node_t *ei_node; - int count = 0; - - switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock); - ei_node = kazoo_globals.ei_nodes; - while(ei_node != NULL) { - count++; - ei_node = ei_node->next; - } - switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); - - stream->write_function(stream, "%d\n", count); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t api_complete_erlang_node(const char *line, const char *cursor, switch_console_callback_match_t **matches) { - switch_console_callback_match_t *my_matches = NULL; - switch_status_t status = SWITCH_STATUS_FALSE; - ei_node_t *ei_node; - - switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock); - ei_node = kazoo_globals.ei_nodes; - while(ei_node != NULL) { - switch_console_push_match(&my_matches, ei_node->peer_nodename); - ei_node = ei_node->next; - } - switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); - - if (my_matches) { - *matches = my_matches; - status = SWITCH_STATUS_SUCCESS; - } - - return status; -} - -static switch_status_t handle_node_api_event_stream(ei_event_stream_t *event_stream, switch_stream_handle_t *stream) { - ei_event_binding_t *binding; - int column = 0; - - switch_mutex_lock(event_stream->socket_mutex); - if (event_stream->connected == SWITCH_FALSE) { - switch_sockaddr_t *sa; - uint16_t port; - char ipbuf[48] = {0}; - const char *ip_addr; - - switch_socket_addr_get(&sa, SWITCH_TRUE, event_stream->acceptor); - port = switch_sockaddr_get_port(sa); - ip_addr = switch_get_addr(ipbuf, sizeof (ipbuf), sa); - - if (zstr(ip_addr)) { - ip_addr = kazoo_globals.ip; - } - - stream->write_function(stream, "%s:%d -> disconnected\n" - ,ip_addr, port); - } else { - stream->write_function(stream, "%s:%d -> %s:%d\n" - ,event_stream->local_ip, event_stream->local_port - ,event_stream->remote_ip, event_stream->remote_port); - } - - binding = event_stream->bindings; - while(binding != NULL) { - if (binding->type == SWITCH_EVENT_CUSTOM) { - stream->write_function(stream, "CUSTOM %-43s", binding->subclass_name); - } else { - stream->write_function(stream, "%-50s", switch_event_name(binding->type)); - } - - if (++column > 2) { - stream->write_function(stream, "\n"); - column = 0; - } - - binding = binding->next; - } - switch_mutex_unlock(event_stream->socket_mutex); - - if (!column) { - stream->write_function(stream, "\n"); - } else { - stream->write_function(stream, "\n\n"); - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t handle_node_api_event_streams(ei_node_t *ei_node, switch_stream_handle_t *stream) { - ei_event_stream_t *event_stream; - - switch_mutex_lock(ei_node->event_streams_mutex); - event_stream = ei_node->event_streams; - while(event_stream != NULL) { - handle_node_api_event_stream(event_stream, stream); - event_stream = event_stream->next; - } - switch_mutex_unlock(ei_node->event_streams_mutex); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t handle_node_api_command(ei_node_t *ei_node, switch_stream_handle_t *stream, uint32_t command) { - unsigned int year, day, hour, min, sec, delta; - - switch (command) { - case API_COMMAND_DISCONNECT: - stream->write_function(stream, "Disconnecting erlang node %s at managers request\n", ei_node->peer_nodename); - switch_clear_flag(ei_node, LFLAG_RUNNING); - break; - case API_COMMAND_REMOTE_IP: - delta = (switch_micro_time_now() - ei_node->created_time) / 1000000; - sec = delta % 60; - min = delta / 60 % 60; - hour = delta / 3600 % 24; - day = delta / 86400 % 7; - year = delta / 31556926 % 12; - - stream->write_function(stream, "Uptime %d years, %d days, %d hours, %d minutes, %d seconds\n", year, day, hour, min, sec); - stream->write_function(stream, "Local Address %s:%d\n", ei_node->local_ip, ei_node->local_port); - stream->write_function(stream, "Remote Address %s:%d\n", ei_node->remote_ip, ei_node->remote_port); - break; - case API_COMMAND_STREAMS: - handle_node_api_event_streams(ei_node, stream); - break; - case API_COMMAND_BINDINGS: - handle_api_command_streams(ei_node, stream); - break; - default: - break; - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t api_erlang_node_command(switch_stream_handle_t *stream, const char *nodename, uint32_t command) { - ei_node_t *ei_node; - - switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock); - ei_node = kazoo_globals.ei_nodes; - while(ei_node != NULL) { - int length = strlen(ei_node->peer_nodename); - - if (!strncmp(ei_node->peer_nodename, nodename, length)) { - handle_node_api_command(ei_node, stream, command); - switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); - return SWITCH_STATUS_SUCCESS; - } - - ei_node = ei_node->next; - } - switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); - - return SWITCH_STATUS_NOTFOUND; -} - -SWITCH_STANDARD_API(exec_api_cmd) -{ - char *argv[1024] = { 0 }; - int unknown_command = 1, argc = 0; - char *mycmd = NULL; - - const char *usage_string = "USAGE:\n" - "--------------------------------------------------------------------------------------------------------------------\n" - "erlang status - provides an overview of the current status\n" - "erlang event_filter - lists the event headers that will be sent to Erlang nodes\n" - "erlang nodes list - lists connected Erlang nodes (usefull for monitoring tools)\n" - "erlang nodes count - provides a count of connected Erlang nodes (usefull for monitoring tools)\n" - "erlang node disconnect - disconnects an Erlang node\n" - "erlang node connection - Shows the connection info\n" - "erlang node event_streams - lists the event streams for an Erlang node\n" - "erlang node fetch_bindings - lists the XML fetch bindings for an Erlang node\n" - "---------------------------------------------------------------------------------------------------------------------\n"; - - if (zstr(cmd)) { - stream->write_function(stream, "%s", usage_string); - return SWITCH_STATUS_SUCCESS; - } - - if (!(mycmd = strdup(cmd))) { - return SWITCH_STATUS_MEMERR; - } - - if (!(argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { - stream->write_function(stream, "%s", usage_string); - switch_safe_free(mycmd); - return SWITCH_STATUS_SUCCESS; - } - - if (zstr(argv[0])) { - stream->write_function(stream, "%s", usage_string); - switch_safe_free(mycmd); - return SWITCH_STATUS_SUCCESS; - } - - if (!strncmp(argv[0], "status", 6)) { - unknown_command = 0; - api_erlang_status(stream); - } else if (!strncmp(argv[0], "event_filter", 6)) { - unknown_command = 0; - api_erlang_event_filter(stream); - } else if (!strncmp(argv[0], "nodes", 6) && !zstr(argv[1])) { - if (!strncmp(argv[1], "list", 6)) { - unknown_command = 0; - api_erlang_nodes_list(stream); - } else if (!strncmp(argv[1], "count", 6)) { - unknown_command = 0; - api_erlang_nodes_count(stream); - } - } else if (!strncmp(argv[0], "node", 6) && !zstr(argv[1]) && !zstr(argv[2])) { - if (!strncmp(argv[2], "disconnect", 6)) { - unknown_command = 0; - api_erlang_node_command(stream, argv[1], API_COMMAND_DISCONNECT); - } else if (!strncmp(argv[2], "connection", 2)) { - unknown_command = 0; - api_erlang_node_command(stream, argv[1], API_COMMAND_REMOTE_IP); - } else if (!strncmp(argv[2], "event_streams", 6)) { - unknown_command = 0; - api_erlang_node_command(stream, argv[1], API_COMMAND_STREAMS); - } else if (!strncmp(argv[2], "fetch_bindings", 6)) { - unknown_command = 0; - api_erlang_node_command(stream, argv[1], API_COMMAND_BINDINGS); - } - } - - if (unknown_command) { - stream->write_function(stream, "%s", usage_string); - } - - switch_safe_free(mycmd); - return SWITCH_STATUS_SUCCESS; -} - -void add_cli_api(switch_loadable_module_interface_t **module_interface, switch_api_interface_t *api_interface) -{ - SWITCH_ADD_API(api_interface, "erlang", KAZOO_DESC, exec_api_cmd, KAZOO_SYNTAX); - switch_console_set_complete("add erlang status"); - switch_console_set_complete("add erlang event_filter"); - switch_console_set_complete("add erlang nodes list"); - switch_console_set_complete("add erlang nodes count"); - switch_console_set_complete("add erlang node ::erlang::node disconnect"); - switch_console_set_complete("add erlang node ::erlang::node connection"); - switch_console_set_complete("add erlang node ::erlang::node event_streams"); - switch_console_set_complete("add erlang node ::erlang::node fetch_bindings"); - switch_console_add_complete_func("::erlang::node", api_complete_erlang_node); - -} - -void remove_cli_api() -{ - switch_console_set_complete("del erlang"); - switch_console_del_complete_func("::erlang::node"); - -} - - -/* 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 5002558398..2494bb9495 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_commands.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_commands.c @@ -31,7 +31,6 @@ * */ #include "mod_kazoo.h" -#include #include #define UUID_SET_DESC "Set a variable" @@ -159,11 +158,6 @@ SWITCH_STANDARD_API(uuid_setvar_multi_function) { return SWITCH_STATUS_SUCCESS; } -static size_t body_callback(char *buffer, size_t size, size_t nitems, void *userdata) -{ - return size * nitems; -} - static size_t header_callback(char *buffer, size_t size, size_t nitems, void *userdata) { switch_event_t* event = (switch_event_t*)userdata; @@ -188,7 +182,6 @@ SWITCH_STANDARD_API(kz_http_put) switch_event_t *params = NULL; char *url = NULL; char *filename = NULL; - int delete = 0; switch_curl_slist_t *headers = NULL; /* optional linked-list of HTTP headers */ char *ext; /* file extension, used for MIME type identification */ @@ -286,8 +279,6 @@ SWITCH_STANDARD_API(kz_http_put) switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-http-cache/1.0"); switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, stream->param_event); switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_callback); - switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, body_callback); - switch_curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L); switch_curl_easy_perform(curl_handle); switch_curl_easy_getinfo(curl_handle, CURLINFO_RESPONSE_CODE, &httpRes); @@ -295,24 +286,22 @@ SWITCH_STANDARD_API(kz_http_put) if (httpRes == 200 || httpRes == 201 || httpRes == 202 || httpRes == 204) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s saved to %s\n", filename, url); - switch_event_add_header(stream->param_event, SWITCH_STACK_BOTTOM, "API-Output", "%s saved to %s", filename, url); - stream->write_function(stream, "+OK %s saved to %s", filename, url); - delete = 1; + switch_event_add_header(stream->param_event, SWITCH_STACK_BOTTOM, "API-Output", "%s saved to %s\n", filename, url); + stream->write_function(stream, "+OK\n"); } else { error = switch_mprintf("Received HTTP error %ld trying to save %s to %s", httpRes, filename, url); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s\n", error); switch_event_add_header(stream->param_event, SWITCH_STACK_BOTTOM, "API-Error", "%s", error); switch_event_add_header(stream->param_event, SWITCH_STACK_BOTTOM, "API-HTTP-Error", "%ld", httpRes); - stream->write_function(stream, "-ERR %s", error); + stream->write_function(stream, "-ERR "); + stream->write_function(stream, error); + stream->write_function(stream, "\n"); status = SWITCH_STATUS_GENERR; } done: if (file_to_put) { fclose(file_to_put); - if(delete && kazoo_globals.delete_file_after_put) { - remove(filename); - } } if (headers) { diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_config.c b/src/mod/event_handlers/mod_kazoo/kazoo_config.c deleted file mode 100644 index f953bfc391..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_config.c +++ /dev/null @@ -1,535 +0,0 @@ -/* -* 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. -* -* Based on mod_skel by -* Anthony Minessale II -* -* Contributor(s): -* -* Daniel Bryars -* Tim Brown -* Anthony Minessale II -* William King -* Mike Jerris -* -* kazoo.c -- Sends FreeSWITCH events to an AMQP broker -* -*/ - -#include "mod_kazoo.h" - -static const char *LOG_LEVEL_NAMES[] = { - "SWITCH_LOG_DEBUG10", - "SWITCH_LOG_DEBUG9", - "SWITCH_LOG_DEBUG8", - "SWITCH_LOG_DEBUG7", - "SWITCH_LOG_DEBUG6", - "SWITCH_LOG_DEBUG5", - "SWITCH_LOG_DEBUG4", - "SWITCH_LOG_DEBUG3", - "SWITCH_LOG_DEBUG2", - "SWITCH_LOG_DEBUG1", - "SWITCH_LOG_DEBUG", - "SWITCH_LOG_INFO", - "SWITCH_LOG_NOTICE", - "SWITCH_LOG_WARNING", - "SWITCH_LOG_ERROR", - "SWITCH_LOG_CRIT", - "SWITCH_LOG_ALERT", - "SWITCH_LOG_CONSOLE", - "SWITCH_LOG_INVALID", - "SWITCH_LOG_UNINIT", - NULL -}; - -static const switch_log_level_t LOG_LEVEL_VALUES[] = { - SWITCH_LOG_DEBUG10, - SWITCH_LOG_DEBUG9, - SWITCH_LOG_DEBUG8, - SWITCH_LOG_DEBUG7, - SWITCH_LOG_DEBUG6, - SWITCH_LOG_DEBUG5, - SWITCH_LOG_DEBUG4, - SWITCH_LOG_DEBUG3, - SWITCH_LOG_DEBUG2, - SWITCH_LOG_DEBUG1, - SWITCH_LOG_DEBUG, - SWITCH_LOG_INFO, - SWITCH_LOG_NOTICE, - SWITCH_LOG_WARNING, - SWITCH_LOG_ERROR, - SWITCH_LOG_CRIT, - SWITCH_LOG_ALERT, - SWITCH_LOG_CONSOLE, - SWITCH_LOG_INVALID, - SWITCH_LOG_UNINIT -}; - -switch_log_level_t log_str2level(const char *str) -{ - int x = 0; - switch_log_level_t level = SWITCH_LOG_INVALID; - - if (switch_is_number(str)) { - x = atoi(str); - - if (x > SWITCH_LOG_INVALID) { - return SWITCH_LOG_INVALID - 1; - } else if (x < 0) { - return 0; - } else { - return x; - } - } - - - for (x = 0;; x++) { - if (!LOG_LEVEL_NAMES[x]) { - break; - } - - if (!strcasecmp(LOG_LEVEL_NAMES[x], str)) { - level = LOG_LEVEL_VALUES[x]; //(switch_log_level_t) x; - break; - } - } - - return level; -} - -switch_status_t kazoo_config_loglevels(switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_loglevels_ptr *ptr) -{ - switch_xml_t xml_level, xml_logging; - kazoo_loglevels_ptr loglevels = (kazoo_loglevels_ptr) switch_core_alloc(pool, sizeof(kazoo_loglevels_t)); - - loglevels->failed_log_level = SWITCH_LOG_ALERT; - loglevels->filtered_event_log_level = SWITCH_LOG_DEBUG1; - loglevels->filtered_field_log_level = SWITCH_LOG_DEBUG1; - loglevels->info_log_level = SWITCH_LOG_INFO; - loglevels->warn_log_level = SWITCH_LOG_WARNING; - loglevels->success_log_level = SWITCH_LOG_DEBUG; - loglevels->time_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) { - char *var = (char *) switch_xml_attr_soft(xml_level, "name"); - char *val = (char *) switch_xml_attr_soft(xml_level, "value"); - - if (!var) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "logging param missing 'name' attribute\n"); - continue; - } - - if (!val) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "logging param[%s] missing 'value' attribute\n", var); - continue; - } - - if (!strncmp(var, "success", 7)) { - loglevels->success_log_level = log_str2level(val); - } else if (!strncmp(var, "failed", 6)) { - loglevels->failed_log_level = log_str2level(val); - } else if (!strncmp(var, "info", 4)) { - loglevels->info_log_level = log_str2level(val); - } else if (!strncmp(var, "warn", 4)) { - loglevels->warn_log_level = log_str2level(val); - } else if (!strncmp(var, "time", 4)) { - loglevels->time_log_level = log_str2level(val); - } else if (!strncmp(var, "filtered-event", 14)) { - loglevels->filtered_event_log_level = log_str2level(val); - } else if (!strncmp(var, "filtered-field", 14)) { - loglevels->filtered_field_log_level = log_str2level(val); - } - } /* xml_level for loop */ - } - - *ptr = loglevels; - return SWITCH_STATUS_SUCCESS; - -} - -switch_status_t kazoo_config_filters(switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_filter_ptr *ptr) -{ - switch_xml_t filters, filter; -// char *routing_key = NULL; - kazoo_filter_ptr root = NULL, prv = NULL, cur = NULL; - - - if ((filters = switch_xml_child(cfg, "filters")) != NULL) { - for (filter = switch_xml_child(filters, "filter"); filter; filter = filter->next) { - const char *var = switch_xml_attr(filter, "name"); - const char *val = switch_xml_attr(filter, "value"); - const char *type = switch_xml_attr(filter, "type"); - const char *compare = switch_xml_attr(filter, "compare"); - cur = (kazoo_filter_ptr) switch_core_alloc(pool, sizeof(kazoo_filter)); - memset(cur, 0, sizeof(kazoo_filter)); - if(prv == NULL) { - root = prv = cur; - } else { - prv->next = cur; - prv = cur; - } - cur->type = FILTER_EXCLUDE; - cur->compare = FILTER_COMPARE_VALUE; - - if(var) - cur->name = switch_core_strdup(pool, var); - - if(val) - cur->value = switch_core_strdup(pool, val); - - if(type) { - if (!strncmp(type, "exclude", 7)) { - cur->type = FILTER_EXCLUDE; - } else if (!strncmp(type, "include", 7)) { - cur->type = FILTER_INCLUDE; - } - } - - if(compare) { - if (!strncmp(compare, "value", 7)) { - cur->compare = FILTER_COMPARE_VALUE; - } else if (!strncmp(compare, "prefix", 6)) { - cur->compare = FILTER_COMPARE_PREFIX; - } else if (!strncmp(compare, "list", 4)) { - cur->compare = FILTER_COMPARE_LIST; - } else if (!strncmp(compare, "exists", 6)) { - cur->compare = FILTER_COMPARE_EXISTS; - } else if (!strncmp(compare, "regex", 5)) { - cur->compare = FILTER_COMPARE_REGEX; - } - } - - if(cur->value == NULL) - cur->compare = FILTER_COMPARE_EXISTS; - - if(cur->compare == FILTER_COMPARE_LIST) { - cur->list.size = switch_separate_string(cur->value, '|', cur->list.value, MAX_LIST_FIELDS); - } - - } - - } - - *ptr = root; - - return SWITCH_STATUS_SUCCESS; - -} - -switch_status_t kazoo_config_field(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_field_ptr *ptr) -{ - const char *var = switch_xml_attr(cfg, "name"); - const char *val = switch_xml_attr(cfg, "value"); - const char *as = switch_xml_attr(cfg, "as"); - 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"); - kazoo_field_ptr cur = (kazoo_field_ptr) switch_core_alloc(pool, sizeof(kazoo_field)); - cur->in_type = FIELD_NONE; - cur->out_type = JSON_NONE; - - if(var) - cur->name = switch_core_strdup(pool, var); - - if(val) - cur->value = switch_core_strdup(pool, val); - - if(as) - cur->as = switch_core_strdup(pool, as); - - if(type) { - if (!strncmp(type, "copy", 4)) { - cur->in_type = FIELD_COPY; - } else if (!strncmp(type, "static", 6)) { - cur->in_type = FIELD_STATIC; - } else if (!strncmp(type, "first-of", 8)) { - cur->in_type = FIELD_FIRST_OF; - } else if (!strncmp(type, "expand", 6)) { - cur->in_type = FIELD_EXPAND; - } else if (!strncmp(type, "prefix", 10)) { - cur->in_type = FIELD_PREFIX; - } else if (!strncmp(type, "group", 5)) { - cur->in_type = FIELD_GROUP; - } else if (!strncmp(type, "reference", 9)) { - cur->in_type = FIELD_REFERENCE; - } - } - - if(serialize_as) { - if (!strncmp(serialize_as, "string", 5)) { - cur->out_type = JSON_STRING; - } else if (!strncmp(serialize_as, "number", 6)) { - cur->out_type = JSON_NUMBER; - } else if (!strncmp(serialize_as, "boolean", 7)) { - cur->out_type = JSON_BOOLEAN; - } else if (!strncmp(serialize_as, "object", 6)) { - cur->out_type = JSON_OBJECT; - } else if (!strncmp(serialize_as, "raw", 6)) { - cur->out_type = JSON_RAW; - } - } - - if(exclude_prefix) - cur->exclude_prefix = switch_true(exclude_prefix); - - kazoo_config_filters(pool, cfg, &cur->filter); - kazoo_config_fields(definitions, pool, cfg, &cur->children); - - if(cur->children != NULL - && (cur->in_type == FIELD_STATIC) - && (cur->out_type == JSON_NONE) - ) { - cur->out_type = JSON_OBJECT; - } - if(cur->in_type == FIELD_NONE) { - cur->in_type = FIELD_COPY; - } - - if(cur->out_type == JSON_NONE) { - cur->out_type = JSON_STRING; - } - - if(cur->in_type == FIELD_FIRST_OF) { - cur->list.size = switch_separate_string(cur->value, '|', cur->list.value, MAX_LIST_FIELDS); - } - - if(cur->in_type == FIELD_REFERENCE) { - cur->ref = (kazoo_definition_ptr)switch_core_hash_find(definitions->hash, cur->name); - if(cur->ref == NULL) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "referenced field %s not found\n", cur->name); - } - } - - *ptr = cur; - - return SWITCH_STATUS_SUCCESS; - -} - -switch_status_t kazoo_config_fields_loop(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_field_ptr *ptr) -{ - switch_xml_t field; - kazoo_field_ptr root = NULL, prv = NULL; - - - for (field = switch_xml_child(cfg, "field"); field; field = field->next) { - kazoo_field_ptr cur = NULL; - kazoo_config_field(definitions, pool, field, &cur); - if(root == NULL) { - root = prv = cur; - } else { - prv->next = cur; - prv = cur; - } - } - - *ptr = root; - - return SWITCH_STATUS_SUCCESS; - -} - -switch_status_t kazoo_config_fields(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_fields_ptr *ptr) -{ - switch_xml_t fields; -// char *routing_key = NULL; - kazoo_fields_ptr root = NULL; - - - if ((fields = switch_xml_child(cfg, "fields")) != NULL) { - const char *verbose = switch_xml_attr(fields, "verbose"); - root = (kazoo_fields_ptr) switch_core_alloc(pool, sizeof(kazoo_fields)); - root->verbose = SWITCH_TRUE; - if(verbose) { - root->verbose = switch_true(verbose); - } - - kazoo_config_fields_loop(definitions, pool, fields, &root->head); - - } - - *ptr = root; - - return SWITCH_STATUS_SUCCESS; - -} - -kazoo_config_ptr kazoo_config_event_handlers(kazoo_config_ptr definitions, switch_xml_t cfg) -{ - switch_xml_t xml_profiles = NULL, xml_profile = NULL; - kazoo_config_ptr profiles = NULL; - switch_memory_pool_t *pool = NULL; - - if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "error creating memory pool for producers\n"); - return NULL; - } - - profiles = switch_core_alloc(pool, sizeof(kazoo_config)); - profiles->pool = pool; - switch_core_hash_init(&profiles->hash); - - if ((xml_profiles = switch_xml_child(cfg, "event-handlers"))) { - if ((xml_profile = switch_xml_child(xml_profiles, "profile"))) { - for (; xml_profile; xml_profile = xml_profile->next) { - const char *name = switch_xml_attr(xml_profile, "name"); - if(name == NULL) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing attr name\n" ); - continue; - } - kazoo_config_event_handler(definitions, profiles, xml_profile, NULL); - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unable to locate a event-handler profile for kazoo\n" ); - } - } else { - destroy_config(&profiles); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to locate event-handlers section for kazoo\n" ); - } - - return profiles; - -} - -kazoo_config_ptr kazoo_config_fetch_handlers(kazoo_config_ptr definitions, switch_xml_t cfg) -{ - switch_xml_t xml_profiles = NULL, xml_profile = NULL; - kazoo_config_ptr profiles = NULL; - switch_memory_pool_t *pool = NULL; - - if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "error creating memory pool for producers\n"); - return NULL; - } - - profiles = switch_core_alloc(pool, sizeof(kazoo_config)); - profiles->pool = pool; - switch_core_hash_init(&profiles->hash); - - if ((xml_profiles = switch_xml_child(cfg, "fetch-handlers"))) { - if ((xml_profile = switch_xml_child(xml_profiles, "profile"))) { - for (; xml_profile; xml_profile = xml_profile->next) { - const char *name = switch_xml_attr(xml_profile, "name"); - if(name == NULL) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing attr name\n" ); - continue; - } - kazoo_config_fetch_handler(definitions, profiles, xml_profile, NULL); - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unable to locate a fetch-handler profile for kazoo\n" ); - } - } else { - destroy_config(&profiles); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unable to locate fetch-handlers section for kazoo\n" ); - } - - return profiles; - -} - - -switch_status_t kazoo_config_definition(kazoo_config_ptr root, switch_xml_t cfg) -{ - kazoo_definition_ptr definition = NULL; - char *name = (char *) switch_xml_attr_soft(cfg, "name"); - - if (zstr(name)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to load kazoo profile. Check definition missing name attr\n"); - return SWITCH_STATUS_GENERR; - } - - definition = switch_core_alloc(root->pool, sizeof(kazoo_definition)); - definition->name = switch_core_strdup(root->pool, name); - - kazoo_config_filters(root->pool, cfg, &definition->filter); - kazoo_config_fields_loop(root, root->pool, cfg, &definition->head); - - if ( switch_core_hash_insert(root->hash, name, (void *) definition) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to insert new definition [%s] into kazoo definitions hash\n", name); - return SWITCH_STATUS_GENERR; - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Definition[%s] Successfully configured\n", definition->name); - return SWITCH_STATUS_SUCCESS; -} - -kazoo_config_ptr kazoo_config_definitions(switch_xml_t cfg) -{ - switch_xml_t xml_definitions = NULL, xml_definition = NULL; - kazoo_config_ptr definitions = NULL; - switch_memory_pool_t *pool = NULL; - - if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "error creating memory pool for definitions\n"); - return NULL; - } - - definitions = switch_core_alloc(pool, sizeof(kazoo_config)); - definitions->pool = pool; - switch_core_hash_init(&definitions->hash); - - if ((xml_definitions = switch_xml_child(cfg, "definitions"))) { - if ((xml_definition = switch_xml_child(xml_definitions, "definition"))) { - for (; xml_definition; xml_definition = xml_definition->next) { - kazoo_config_definition(definitions, xml_definition); - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "no definitions for kazoo\n" ); - } - } else { - destroy_config(&definitions); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "no definitions section for kazoo\n" ); - } - - return definitions; -} - -void destroy_config(kazoo_config_ptr *ptr) -{ - kazoo_config_ptr config = NULL; - switch_memory_pool_t *pool; - - if (!ptr || !*ptr) { - return; - } - config = *ptr; - pool = config->pool; - - switch_core_hash_destroy(&(config->hash)); - switch_core_destroy_memory_pool(&pool); - - *ptr = NULL; -} - -/* 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_config.h b/src/mod/event_handlers/mod_kazoo/kazoo_config.h deleted file mode 100644 index cb6c92ba59..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_config.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -* 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. -* -* Based on mod_skel by -* Anthony Minessale II -* -* Contributor(s): -* -* Daniel Bryars -* Tim Brown -* Anthony Minessale II -* William King -* Mike Jerris -* -* kazoo.c -- Sends FreeSWITCH events to an AMQP broker -* -*/ - -#ifndef KAZOO_CONFIG_H -#define KAZOO_CONFIG_H - -#include - - -struct kazoo_config_t { - switch_hash_t *hash; - switch_memory_pool_t *pool; -}; - -switch_status_t kazoo_config_loglevels(switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_loglevels_ptr *ptr); -switch_status_t kazoo_config_filters(switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_filter_ptr *ptr); -switch_status_t kazoo_config_fields(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_fields_ptr *ptr); - -switch_status_t kazoo_config_event_handler(kazoo_config_ptr definitions, kazoo_config_ptr root, switch_xml_t cfg, kazoo_event_profile_ptr *ptr); -switch_status_t kazoo_config_fetch_handler(kazoo_config_ptr definitions, kazoo_config_ptr root, switch_xml_t cfg, kazoo_fetch_profile_ptr *ptr); -kazoo_config_ptr kazoo_config_event_handlers(kazoo_config_ptr definitions, switch_xml_t cfg); -kazoo_config_ptr kazoo_config_fetch_handlers(kazoo_config_ptr definitions, switch_xml_t cfg); -kazoo_config_ptr kazoo_config_definitions(switch_xml_t cfg); -void destroy_config(kazoo_config_ptr *ptr); - -#endif /* KAZOO_CONFIG_H */ - diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_dptools.c b/src/mod/event_handlers/mod_kazoo/kazoo_dptools.c index bf90626564..0ea4cf6f2c 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_dptools.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_dptools.c @@ -52,14 +52,6 @@ #define EXPORT_LONG_DESC "Export many channel variables for the channel calling the application" #define EXPORT_SYNTAX "[^^]= =" -#define PREFIX_UNSET_SHORT_DESC "clear variables by prefix" -#define PREFIX_UNSET_LONG_DESC "clears the channel variables that start with prefix supplied" -#define PREFIX_UNSET_SYNTAX "" - -#define UUID_MULTISET_SHORT_DESC "Set many channel variables" -#define UUID_MULTISET_LONG_DESC "Set many channel variables for a specific channel" -#define UUID_MULTISET_SYNTAX " [^^]= =" - static void base_set (switch_core_session_t *session, const char *data, switch_stack_t stack) { char *var, *val = NULL; @@ -107,22 +99,6 @@ static void base_set (switch_core_session_t *session, const char *data, switch_s } } -static int kz_is_exported(switch_core_session_t *session, char *varname) -{ - char *array[256] = {0}; - int i, argc; - switch_channel_t *channel = switch_core_session_get_channel(session); - const char *exports = switch_channel_get_variable(channel, SWITCH_EXPORT_VARS_VARIABLE); - char *arg = switch_core_session_strdup(session, exports); - argc = switch_split(arg, ',', array); - for(i=0; i < argc; i++) { - if(!strcasecmp(array[i], varname)) - return 1; - } - - return 0; -} - static void base_export (switch_core_session_t *session, const char *data, switch_stack_t stack) { char *var, *val = NULL; @@ -145,52 +121,20 @@ static void base_export (switch_core_session_t *session, const char *data, switc } } - if(!kz_is_exported(session, var)) { - if (val) { - expanded = switch_channel_expand_variables(channel, val); - } + if (val) { + expanded = switch_channel_expand_variables(channel, val); + } - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s EXPORT [%s]=[%s]\n", switch_channel_get_name(channel), var, - expanded ? expanded : "UNDEF"); - switch_channel_export_variable_var_check(channel, var, expanded, SWITCH_EXPORT_VARS_VARIABLE, SWITCH_FALSE); + switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s EXPORT [%s]=[%s]\n", switch_channel_get_name(channel), var, + expanded ? expanded : "UNDEF"); + switch_channel_export_variable_var_check(channel, var, expanded, SWITCH_EXPORT_VARS_VARIABLE, SWITCH_FALSE); - if (expanded && expanded != val) { - switch_safe_free(expanded); - } - } else { - switch_channel_set_variable(channel, var, val); + if (expanded && expanded != val) { + switch_safe_free(expanded); } } } -SWITCH_STANDARD_APP(prefix_unset_function) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_event_header_t *ei = NULL; - switch_event_t *clear; - char *arg = (char *) data; - - if(switch_event_create(&clear, SWITCH_EVENT_CLONE) != SWITCH_STATUS_SUCCESS) { - return; - } - - for (ei = switch_channel_variable_first(channel); ei; ei = ei->next) { - const char *name = ei->name; - char *value = ei->value; - if (!strncasecmp(name, arg, strlen(arg))) { - switch_event_add_header_string(clear, SWITCH_STACK_BOTTOM, name, value); - } - } - - switch_channel_variable_last(channel); - for (ei = clear->headers; ei; ei = ei->next) { - char *varname = ei->name; - switch_channel_set_variable(channel, varname, NULL); - } - - switch_event_destroy(&clear); -} - SWITCH_STANDARD_APP(multiset_function) { char delim = ' '; char *arg = (char *) data; @@ -201,79 +145,25 @@ SWITCH_STANDARD_APP(multiset_function) { delim = *arg++; } - if(delim != '\0') { + if (arg) { switch_channel_t *channel = switch_core_session_get_channel(session); - if (arg) { - char *array[256] = {0}; - int i, argc; + char *array[256] = {0}; + int i, argc; - arg = switch_core_session_strdup(session, arg); - argc = switch_split(arg, delim, array); + arg = switch_core_session_strdup(session, arg); + argc = switch_split(arg, delim, array); - for(i = 0; i < argc; i++) { - base_set(session, array[i], SWITCH_STACK_BOTTOM); - } + for(i = 0; i < argc; i++) { + base_set(session, array[i], SWITCH_STACK_BOTTOM); } + if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { switch_channel_event_set_data(channel, event); switch_event_fire(&event); } + } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "multiset with empty args\n"); - } -} - -SWITCH_STANDARD_APP(uuid_multiset_function) { - - char delim = ' '; - char *arg0 = (char *) data; - char *arg = strchr(arg0, ' '); - switch_event_t *event; - - - if(arg == NULL) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "uuid_multiset with invalid args\n"); - return; - } - *arg = '\0'; - arg++; - - if(zstr(arg0)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "uuid_multiset with invalid uuid\n"); - return; - } - - - if (!zstr(arg) && *arg == '^' && *(arg+1) == '^') { - arg += 2; - delim = *arg++; - } - - if(delim != '\0') { - switch_core_session_t *uuid_session = NULL; - if ((uuid_session = switch_core_session_force_locate(arg0)) != NULL) { - switch_channel_t *uuid_channel = switch_core_session_get_channel(uuid_session); - if (arg) { - char *array[256] = {0}; - int i, argc; - - arg = switch_core_session_strdup(session, arg); - argc = switch_split(arg, delim, array); - - for(i = 0; i < argc; i++) { - base_set(uuid_session, array[i], SWITCH_STACK_BOTTOM); - } - } - if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(uuid_channel, event); - switch_event_fire(&event); - } - switch_core_session_rwunlock(uuid_session); - } else { - base_set(session, data, SWITCH_STACK_BOTTOM); - } - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "multiset with empty args\n"); + base_set(session, data, SWITCH_STACK_BOTTOM); } } @@ -315,23 +205,19 @@ SWITCH_STANDARD_APP(multiunset_function) { delim = *arg++; } - if(delim != '\0') { - if (arg) { - char *array[256] = {0}; - int i, argc; + if (arg) { + char *array[256] = {0}; + int i, argc; - arg = switch_core_session_strdup(session, arg); - argc = switch_split(arg, delim, array); + arg = switch_core_session_strdup(session, arg); + argc = switch_split(arg, delim, array); - for(i = 0; i < argc; i++) { - switch_channel_set_variable(switch_core_session_get_channel(session), array[i], NULL); - } - - } else { - switch_channel_set_variable(switch_core_session_get_channel(session), arg, NULL); + for(i = 0; i < argc; i++) { + switch_channel_set_variable(switch_core_session_get_channel(session), array[i], NULL); } + } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "multiunset with empty args\n"); + switch_channel_set_variable(switch_core_session_get_channel(session), arg, NULL); } } @@ -344,22 +230,18 @@ SWITCH_STANDARD_APP(export_function) { delim = *arg++; } - if(delim != '\0') { - if (arg) { - char *array[256] = {0}; - int i, argc; + if (arg) { + char *array[256] = {0}; + int i, argc; - arg = switch_core_session_strdup(session, arg); - argc = switch_split(arg, delim, array); + arg = switch_core_session_strdup(session, arg); + argc = switch_split(arg, delim, array); - for(i = 0; i < argc; i++) { - base_export(session, array[i], SWITCH_STACK_BOTTOM); - } - } else { - base_export(session, data, SWITCH_STACK_BOTTOM); - } + for(i = 0; i < argc; i++) { + base_export(session, array[i], SWITCH_STACK_BOTTOM); + } } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "export with empty args\n"); + base_export(session, data, SWITCH_STACK_BOTTOM); } } @@ -372,11 +254,6 @@ void add_kz_dptools(switch_loadable_module_interface_t **module_interface, switc SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); SWITCH_ADD_APP(app_interface, "kz_multiunset", MULTISET_SHORT_DESC, MULTISET_LONG_DESC, multiunset_function, MULTIUNSET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); - SWITCH_ADD_APP(app_interface, "kz_export", EXPORT_SHORT_DESC, EXPORT_LONG_DESC, export_function, EXPORT_SYNTAX, - SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); - SWITCH_ADD_APP(app_interface, "kz_prefix_unset", PREFIX_UNSET_SHORT_DESC, PREFIX_UNSET_LONG_DESC, prefix_unset_function, PREFIX_UNSET_SYNTAX, - SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); - SWITCH_ADD_APP(app_interface, "kz_uuid_multiset", UUID_MULTISET_SHORT_DESC, UUID_MULTISET_LONG_DESC, uuid_multiset_function, UUID_MULTISET_SYNTAX, - SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); - + SWITCH_ADD_APP(app_interface, "kz_export", EXPORT_SHORT_DESC, EXPORT_LONG_DESC, export_function, EXPORT_SYNTAX, + SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); } diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_ei.h b/src/mod/event_handlers/mod_kazoo/kazoo_ei.h deleted file mode 100644 index c317b617be..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_ei.h +++ /dev/null @@ -1,262 +0,0 @@ -#ifndef KAZOO_EI_H -#define KAZOO_EI_H - -#include -#include - -#define MODNAME "mod_kazoo" -#define BUNDLE "community" -#define RELEASE "v1.5.0-1" -#define VERSION "mod_kazoo v1.5.0-1 community" - -typedef enum {KAZOO_FETCH_PROFILE, KAZOO_EVENT_PROFILE} kazoo_profile_type; - -typedef enum {ERLANG_TUPLE, ERLANG_MAP} kazoo_json_term; - -typedef struct ei_xml_agent_s ei_xml_agent_t; -typedef ei_xml_agent_t *ei_xml_agent_ptr; - -typedef struct kazoo_event kazoo_event_t; -typedef kazoo_event_t *kazoo_event_ptr; - -typedef struct kazoo_event_profile kazoo_event_profile_t; -typedef kazoo_event_profile_t *kazoo_event_profile_ptr; - -typedef struct kazoo_fetch_profile kazoo_fetch_profile_t; -typedef kazoo_fetch_profile_t *kazoo_fetch_profile_ptr; - -typedef struct kazoo_config_t kazoo_config; -typedef kazoo_config *kazoo_config_ptr; - -#include "kazoo_fields.h" -#include "kazoo_config.h" - -struct ei_send_msg_s { - ei_x_buff buf; - erlang_pid pid; -}; -typedef struct ei_send_msg_s ei_send_msg_t; - -struct ei_received_msg_s { - ei_x_buff buf; - erlang_msg msg; -}; -typedef struct ei_received_msg_s ei_received_msg_t; - - -typedef struct ei_event_stream_s ei_event_stream_t; -typedef struct ei_node_s ei_node_t; - -struct ei_event_binding_s { - char id[SWITCH_UUID_FORMATTED_LENGTH + 1]; - switch_event_node_t *node; - switch_event_types_t type; - const char *subclass_name; - ei_event_stream_t* stream; - kazoo_event_ptr event; - - struct ei_event_binding_s *next; -}; -typedef struct ei_event_binding_s ei_event_binding_t; - -struct ei_event_stream_s { - switch_memory_pool_t *pool; - ei_event_binding_t *bindings; - switch_queue_t *queue; - switch_socket_t *acceptor; - switch_pollset_t *pollset; - switch_pollfd_t *pollfd; - switch_socket_t *socket; - switch_mutex_t *socket_mutex; - switch_bool_t connected; - char remote_ip[48]; - uint16_t remote_port; - char local_ip[48]; - uint16_t local_port; - erlang_pid pid; - uint32_t flags; - ei_node_t *node; - struct ei_event_stream_s *next; -}; - -struct ei_node_s { - int nodefd; - switch_atomic_t pending_bgapi; - switch_atomic_t receive_handlers; - switch_memory_pool_t *pool; - ei_event_stream_t *event_streams; - switch_mutex_t *event_streams_mutex; - switch_queue_t *send_msgs; - switch_queue_t *received_msgs; - char *peer_nodename; - switch_time_t created_time; - switch_socket_t *socket; - char remote_ip[48]; - uint16_t remote_port; - char local_ip[48]; - uint16_t local_port; - uint32_t flags; - int legacy; - struct ei_node_s *next; -}; - - -struct xml_fetch_reply_s { - char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; - char *xml_str; - struct xml_fetch_reply_s *next; -}; -typedef struct xml_fetch_reply_s xml_fetch_reply_t; - -struct fetch_handler_s { - erlang_pid pid; - struct fetch_handler_s *next; -}; -typedef struct fetch_handler_s fetch_handler_t; - -struct ei_xml_client_s { - ei_node_t *ei_node; - fetch_handler_t *fetch_handlers; - struct ei_xml_client_s *next; -}; -typedef struct ei_xml_client_s ei_xml_client_t; - -struct ei_xml_agent_s { - switch_memory_pool_t *pool; - switch_xml_section_t section; - switch_thread_rwlock_t *lock; - ei_xml_client_t *clients; - switch_mutex_t *current_client_mutex; - ei_xml_client_t *current_client; - switch_mutex_t *replies_mutex; - switch_thread_cond_t *new_reply; - xml_fetch_reply_t *replies; - kazoo_fetch_profile_ptr profile; - -}; - -struct globals_s { - switch_memory_pool_t *pool; - switch_atomic_t threads; - switch_socket_t *acceptor; - struct ei_cnode_s ei_cnode; - switch_thread_rwlock_t *ei_nodes_lock; - ei_node_t *ei_nodes; - - switch_xml_binding_t *config_fetch_binding; - switch_xml_binding_t *directory_fetch_binding; - switch_xml_binding_t *dialplan_fetch_binding; - switch_xml_binding_t *channels_fetch_binding; - switch_xml_binding_t *languages_fetch_binding; - switch_xml_binding_t *chatplan_fetch_binding; - - switch_hash_t *event_filter; - int epmdfd; - int num_worker_threads; - switch_bool_t nat_map; - switch_bool_t ei_shortname; - int ei_compat_rel; - char *ip; - char *hostname; - char *ei_cookie; - char *ei_nodename; - char *kazoo_var_prefix; - int var_prefix_length; - uint32_t flags; - int send_all_headers; - int send_all_private_headers; - int connection_timeout; - int receive_timeout; - int receive_msg_preallocate; - int event_stream_preallocate; - int send_msg_batch; - short event_stream_framing; - switch_port_t port; - int config_fetched; - int io_fault_tolerance; - kazoo_event_profile_ptr events; - kazoo_config_ptr definitions; - kazoo_config_ptr event_handlers; - kazoo_config_ptr fetch_handlers; - kazoo_json_term json_encoding; - - int delete_file_after_put; - int enable_legacy; - -}; -typedef struct globals_s globals_t; -extern globals_t kazoo_globals; - -/* kazoo_event_stream.c */ -ei_event_stream_t *find_event_stream(ei_event_stream_t *event_streams, const erlang_pid *from); - -//ei_event_stream_t *new_event_stream(ei_event_stream_t **event_streams, const erlang_pid *from); -ei_event_stream_t *new_event_stream(ei_node_t *ei_node, const erlang_pid *from); - - -switch_status_t remove_event_stream(ei_event_stream_t **event_streams, const erlang_pid *from); -switch_status_t remove_event_streams(ei_event_stream_t **event_streams); -unsigned long get_stream_port(const ei_event_stream_t *event_stream); -switch_status_t add_event_binding(ei_event_stream_t *event_stream, const char *event_name); -//switch_status_t add_event_binding(ei_event_stream_t *event_stream, const switch_event_types_t event_type, const char *subclass_name); -switch_status_t remove_event_binding(ei_event_stream_t *event_stream, const switch_event_types_t event_type, const char *subclass_name); -switch_status_t remove_event_bindings(ei_event_stream_t *event_stream); - -/* kazoo_node.c */ -switch_status_t new_kazoo_node(int nodefd, ErlConnect *conn); - -/* kazoo_ei_utils.c */ -void close_socket(switch_socket_t **sock); -void close_socketfd(int *sockfd); -switch_socket_t *create_socket_with_port(switch_memory_pool_t *pool, switch_port_t port); -switch_socket_t *create_socket(switch_memory_pool_t *pool); -switch_status_t create_ei_cnode(const char *ip_addr, const char *name, struct ei_cnode_s *ei_cnode); -switch_status_t ei_compare_pids(const erlang_pid *pid1, const erlang_pid *pid2); -void ei_encode_switch_event_headers(ei_x_buff *ebuf, switch_event_t *event); -void ei_encode_switch_event_headers_2(ei_x_buff *ebuf, switch_event_t *event, int decode); -void ei_encode_json(ei_x_buff *ebuf, cJSON *JObj); -void ei_link(ei_node_t *ei_node, erlang_pid * from, erlang_pid * to); -void ei_encode_switch_event(ei_x_buff * ebuf, switch_event_t *event); -int ei_helper_send(ei_node_t *ei_node, erlang_pid* to, ei_x_buff *buf); -int ei_decode_atom_safe(char *buf, int *index, char *dst); -int ei_decode_string_or_binary_limited(char *buf, int *index, int maxsize, char *dst); -int ei_decode_string_or_binary(char *buf, int *index, char **dst); -switch_status_t create_acceptor(); -switch_hash_t *create_default_filter(); - -void fetch_config(); - -switch_status_t kazoo_load_config(); -void kazoo_destroy_config(); - - -#define _ei_x_encode_string(buf, string) { ei_x_encode_binary(buf, string, strlen(string)); } - -/* kazoo_fetch_agent.c */ -switch_status_t bind_fetch_agents(); -switch_status_t unbind_fetch_agents(); -switch_status_t remove_xml_clients(ei_node_t *ei_node); -switch_status_t add_fetch_handler(ei_node_t *ei_node, erlang_pid *from, switch_xml_binding_t *binding); -switch_status_t remove_fetch_handlers(ei_node_t *ei_node, erlang_pid *from); -switch_status_t fetch_reply(char *uuid_str, char *xml_str, switch_xml_binding_t *binding); -switch_status_t handle_api_command_streams(ei_node_t *ei_node, switch_stream_handle_t *stream); - -void bind_event_profiles(kazoo_event_ptr event); -void rebind_fetch_profiles(kazoo_config_ptr fetch_handlers); -switch_status_t kazoo_config_handlers(switch_xml_t cfg); - -/* runtime */ -SWITCH_MODULE_RUNTIME_FUNCTION(mod_kazoo_runtime); - -#endif /* KAZOO_EI_H */ - -/* 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_ei_config.c b/src/mod/event_handlers/mod_kazoo/kazoo_ei_config.c deleted file mode 100644 index 7eb93af5d8..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_ei_config.c +++ /dev/null @@ -1,543 +0,0 @@ -/* -* 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. -* -* Based on mod_skel by -* Anthony Minessale II -* -* Contributor(s): -* -* Daniel Bryars -* Tim Brown -* Anthony Minessale II -* William King -* Mike Jerris -* -* kazoo.c -- Sends FreeSWITCH events to an AMQP broker -* -*/ - -#include "mod_kazoo.h" -#include "kazoo_definitions.h" - -#define KAZOO_DECLARE_GLOBAL_STRING_FUNC(fname, vname) static void __attribute__((__unused__)) fname(const char *string) { if (!string) return;\ - if (vname) {free(vname); vname = NULL;}vname = strdup(string);} static void fname(const char *string) - -KAZOO_DECLARE_GLOBAL_STRING_FUNC(set_pref_ip, kazoo_globals.ip); -KAZOO_DECLARE_GLOBAL_STRING_FUNC(set_pref_ei_cookie, kazoo_globals.ei_cookie); -KAZOO_DECLARE_GLOBAL_STRING_FUNC(set_pref_ei_nodename, kazoo_globals.ei_nodename); -KAZOO_DECLARE_GLOBAL_STRING_FUNC(set_pref_kazoo_var_prefix, kazoo_globals.kazoo_var_prefix); - -static int read_cookie_from_file(char *filename) { - int fd; - char cookie[MAXATOMLEN + 1]; - char *end; - struct stat buf; - ssize_t res; - - if (!stat(filename, &buf)) { - if ((buf.st_mode & S_IRWXG) || (buf.st_mode & S_IRWXO)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s must only be accessible by owner only.\n", filename); - return 2; - } - if (buf.st_size > MAXATOMLEN) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s contains a cookie larger than the maximum atom size of %d.\n", filename, MAXATOMLEN); - return 2; - } - fd = open(filename, O_RDONLY); - if (fd < 1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to open cookie file %s : %d.\n", filename, errno); - return 2; - } - - if ((res = read(fd, cookie, MAXATOMLEN)) < 1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to read cookie file %s : %d.\n", filename, errno); - } - - cookie[MAXATOMLEN] = '\0'; - - /* replace any end of line characters with a null */ - if ((end = strchr(cookie, '\n'))) { - *end = '\0'; - } - - if ((end = strchr(cookie, '\r'))) { - *end = '\0'; - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set cookie from file %s: %s\n", filename, cookie); - - set_pref_ei_cookie(cookie); - return 0; - } else { - /* don't error here, because we might be blindly trying to read $HOME/.erlang.cookie, and that can fail silently */ - return 1; - } -} - - -switch_status_t kazoo_ei_config(switch_xml_t cfg) { - switch_xml_t child, param; - kazoo_globals.send_all_headers = 0; - kazoo_globals.send_all_private_headers = 1; - kazoo_globals.connection_timeout = 500; - kazoo_globals.receive_timeout = 200; - kazoo_globals.receive_msg_preallocate = 2000; - kazoo_globals.event_stream_preallocate = 4000; - kazoo_globals.send_msg_batch = 10; - kazoo_globals.event_stream_framing = 2; - kazoo_globals.port = 0; - kazoo_globals.io_fault_tolerance = 10; - kazoo_globals.json_encoding = ERLANG_TUPLE; - kazoo_globals.enable_legacy = SWITCH_TRUE; - kazoo_globals.delete_file_after_put = SWITCH_TRUE; - - if ((child = switch_xml_child(cfg, "settings"))) { - for (param = switch_xml_child(child, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - if (!strcmp(var, "listen-ip")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set bind ip address: %s\n", val); - set_pref_ip(val); - } else if (!strcmp(var, "listen-port")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set bind port: %s\n", val); - kazoo_globals.port = atoi(val); - } else if (!strcmp(var, "cookie")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set cookie: %s\n", val); - set_pref_ei_cookie(val); - } else if (!strcmp(var, "cookie-file")) { - if (read_cookie_from_file(val) == 1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to read cookie from %s\n", val); - } - } else if (!strcmp(var, "nodename")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set node name: %s\n", val); - set_pref_ei_nodename(val); - } else if (!strcmp(var, "shortname")) { - kazoo_globals.ei_shortname = switch_true(val); - } else if (!strcmp(var, "kazoo-var-prefix")) { - set_pref_kazoo_var_prefix(val); - } else if (!strcmp(var, "compat-rel")) { - if (atoi(val) >= 7) - kazoo_globals.ei_compat_rel = atoi(val); - else - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid compatibility release '%s' specified\n", val); - } else if (!strcmp(var, "nat-map")) { - kazoo_globals.nat_map = switch_true(val); - } else if (!strcmp(var, "send-all-headers")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-all-headers: %s\n", val); - kazoo_globals.send_all_headers = switch_true(val); - } else if (!strcmp(var, "send-all-private-headers")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-all-private-headers: %s\n", val); - kazoo_globals.send_all_private_headers = switch_true(val); - } else if (!strcmp(var, "connection-timeout")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set connection-timeout: %s\n", val); - kazoo_globals.connection_timeout = atoi(val); - } else if (!strcmp(var, "receive-timeout")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set receive-timeout: %s\n", val); - kazoo_globals.receive_timeout = atoi(val); - } else if (!strcmp(var, "receive-msg-preallocate")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set receive-msg-preallocate: %s\n", val); - kazoo_globals.receive_msg_preallocate = atoi(val); - } else if (!strcmp(var, "event-stream-preallocate")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set event-stream-preallocate: %s\n", val); - kazoo_globals.event_stream_preallocate = atoi(val); - } else if (!strcmp(var, "send-msg-batch-size")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-msg-batch-size: %s\n", val); - kazoo_globals.send_msg_batch = atoi(val); - } else if (!strcmp(var, "event-stream-framing")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set event-stream-framing: %s\n", val); - kazoo_globals.event_stream_framing = atoi(val); - } else if (!strcmp(var, "io-fault-tolerance")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set io-fault-tolerance: %s\n", val); - kazoo_globals.io_fault_tolerance = atoi(val); - } else if (!strcmp(var, "num-worker-threads")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set num-worker-threads: %s\n", val); - kazoo_globals.num_worker_threads = atoi(val); - } else if (!strcmp(var, "json-term-encoding")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set json-term-encoding: %s\n", val); - if(!strcmp(val, "map")) { - kazoo_globals.json_encoding = ERLANG_MAP; - } - } else if (!strcmp(var, "enable-legacy")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set enable-legacy: %s\n", val); - kazoo_globals.enable_legacy = switch_true(val); - } else if (!strcmp(var, "delete-file-after-put")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set delete-file-after-put: %s\n", val); - kazoo_globals.delete_file_after_put = switch_true(val); - } - } - } - - if ((child = switch_xml_child(cfg, "event-filter"))) { - switch_hash_t *filter; - - switch_core_hash_init(&filter); - for (param = switch_xml_child(child, "header"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - switch_core_hash_insert(filter, var, "1"); - } - kazoo_globals.event_filter = filter; - } - - if (kazoo_globals.receive_msg_preallocate < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid receive message preallocate value, disabled\n"); - kazoo_globals.receive_msg_preallocate = 0; - } - - if (kazoo_globals.event_stream_preallocate < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid event stream preallocate value, disabled\n"); - kazoo_globals.event_stream_preallocate = 0; - } - - if (kazoo_globals.send_msg_batch < 1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid send message batch size, reverting to default\n"); - kazoo_globals.send_msg_batch = 10; - } - - if (kazoo_globals.io_fault_tolerance < 1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid I/O fault tolerance, reverting to default\n"); - kazoo_globals.io_fault_tolerance = 10; - } - - if (!kazoo_globals.event_filter) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Event filter not found in configuration, using default\n"); - kazoo_globals.event_filter = create_default_filter(); - } - - if (kazoo_globals.event_stream_framing < 1 || kazoo_globals.event_stream_framing > 4) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid event stream framing value, using default\n"); - kazoo_globals.event_stream_framing = 2; - } - - if (zstr(kazoo_globals.kazoo_var_prefix)) { - set_pref_kazoo_var_prefix("variable_ecallmgr*"); - kazoo_globals.var_prefix_length = 17; //ignore the * - } else { - /* we could use the global pool but then we would have to conditionally - * free the pointer if it was not drawn from the XML */ - char *buf; - int size = switch_snprintf(NULL, 0, "variable_%s*", kazoo_globals.kazoo_var_prefix) + 1; - - switch_malloc(buf, size); - switch_snprintf(buf, size, "variable_%s*", kazoo_globals.kazoo_var_prefix); - switch_safe_free(kazoo_globals.kazoo_var_prefix); - kazoo_globals.kazoo_var_prefix = buf; - kazoo_globals.var_prefix_length = size - 2; //ignore the * - } - - if (!kazoo_globals.num_worker_threads) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Number of worker threads not found in configuration, using default\n"); - kazoo_globals.num_worker_threads = 10; - } - - if (zstr(kazoo_globals.ip)) { - set_pref_ip("0.0.0.0"); - } - - if (zstr(kazoo_globals.ei_cookie)) { - int res; - char *home_dir = getenv("HOME"); - char path_buf[1024]; - - if (!zstr(home_dir)) { - /* $HOME/.erlang.cookie */ - switch_snprintf(path_buf, sizeof (path_buf), "%s%s%s", home_dir, SWITCH_PATH_SEPARATOR, ".erlang.cookie"); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Checking for cookie at path: %s\n", path_buf); - - res = read_cookie_from_file(path_buf); - if (res) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No cookie or valid cookie file specified, using default cookie\n"); - set_pref_ei_cookie("ClueCon"); - } - } - } - - if (!kazoo_globals.ei_nodename) { - set_pref_ei_nodename("freeswitch"); - } - - if (!kazoo_globals.nat_map) { - kazoo_globals.nat_map = 0; - } - - return SWITCH_STATUS_SUCCESS; -} - -switch_status_t kazoo_config_handlers(switch_xml_t cfg) -{ - switch_xml_t def; - char* xml = NULL; - kazoo_config_ptr definitions, fetch_handlers, event_handlers; - kazoo_event_profile_ptr events; - - xml = strndup((char*)kazoo_conf_xml, kazoo_conf_xml_len); - def = switch_xml_parse_str_dup(xml); - - kz_xml_process(def); - kz_xml_process(cfg); - - definitions = kazoo_config_definitions(cfg); - if(definitions == NULL) { - definitions = kazoo_config_definitions(def); - } - - fetch_handlers = kazoo_config_fetch_handlers(definitions, cfg); - if(fetch_handlers == NULL) { - fetch_handlers = kazoo_config_fetch_handlers(definitions, def); - } - - event_handlers = kazoo_config_event_handlers(definitions, cfg); - if(event_handlers == NULL) { - event_handlers = kazoo_config_event_handlers(definitions, def); - } - - if(event_handlers != NULL) { - events = (kazoo_event_profile_ptr) switch_core_hash_find(event_handlers->hash, "default"); - } - - if(events == NULL) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to get default handler for events\n"); - destroy_config(&event_handlers); - destroy_config(&fetch_handlers); - destroy_config(&definitions); - switch_xml_free(def); - switch_safe_free(xml); - return SWITCH_STATUS_GENERR; - } - - bind_event_profiles(events->events); - kazoo_globals.events = events; - - destroy_config(&kazoo_globals.event_handlers); - kazoo_globals.event_handlers = event_handlers; - - rebind_fetch_profiles(fetch_handlers); - destroy_config(&kazoo_globals.fetch_handlers); - kazoo_globals.fetch_handlers = fetch_handlers; - - destroy_config(&kazoo_globals.definitions); - kazoo_globals.definitions = definitions; - - - switch_xml_free(def); - switch_safe_free(xml); - - return SWITCH_STATUS_SUCCESS; -} - -switch_status_t kazoo_load_config() -{ - char *cf = "kazoo.conf"; - switch_xml_t cfg, xml; - if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open configuration file %s\n", cf); - return SWITCH_STATUS_FALSE; - } else { - kazoo_ei_config(cfg); - kazoo_config_handlers(cfg); - switch_xml_free(xml); - } - - return SWITCH_STATUS_SUCCESS; -} - -void kazoo_destroy_config() -{ - destroy_config(&kazoo_globals.event_handlers); - destroy_config(&kazoo_globals.fetch_handlers); - destroy_config(&kazoo_globals.definitions); -} - -switch_status_t kazoo_config_events(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_event_profile_ptr profile) -{ - switch_xml_t events, event; - kazoo_event_ptr prv = NULL, cur = NULL; - - - if ((events = switch_xml_child(cfg, "events")) != NULL) { - for (event = switch_xml_child(events, "event"); event; event = event->next) { - const char *var = switch_xml_attr(event, "name"); - cur = (kazoo_event_ptr) switch_core_alloc(pool, sizeof(kazoo_event_t)); - memset(cur, 0, sizeof(kazoo_event_t)); - if(prv == NULL) { - profile->events = prv = cur; - } else { - prv->next = cur; - prv = cur; - } - cur->profile = profile; - cur->name = switch_core_strdup(pool, var); - kazoo_config_filters(pool, event, &cur->filter); - kazoo_config_fields(definitions, pool, event, &cur->fields); - - } - - } - - return SWITCH_STATUS_SUCCESS; - -} - - -switch_status_t kazoo_config_fetch_handler(kazoo_config_ptr definitions, kazoo_config_ptr root, switch_xml_t cfg, kazoo_fetch_profile_ptr *ptr) -{ - kazoo_fetch_profile_ptr profile = NULL; - switch_xml_t params, param; - switch_xml_section_t fetch_section; - int fetch_timeout = 2000000; - switch_memory_pool_t *pool = NULL; - - char *name = (char *) switch_xml_attr_soft(cfg, "name"); - if (zstr(name)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing name in profile\n"); - return SWITCH_STATUS_GENERR; - } - - if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error allocation pool for new profile : %s\n", name); - return SWITCH_STATUS_GENERR; - } - - profile = switch_core_alloc(pool, sizeof(kazoo_fetch_profile_t)); - profile->pool = pool; - profile->root = root; - profile->name = switch_core_strdup(profile->pool, name); - - fetch_section = switch_xml_parse_section_string(name); - - if ((params = switch_xml_child(cfg, "params")) != NULL) { - for (param = switch_xml_child(params, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - if (!var) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile[%s] param missing 'name' attribute\n", name); - continue; - } - - if (!val) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Profile[%s] param[%s] missing 'value' attribute\n", name, var); - continue; - } - - if (!strncmp(var, "fetch-timeout", 13)) { - fetch_timeout = atoi(val); - } else if (!strncmp(var, "fetch-section", 13)) { - fetch_section = switch_xml_parse_section_string(val); - } - } - } - - if (fetch_section == SWITCH_XML_SECTION_RESULT) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Fetch Profile[%s] invalid fetch-section: %s\n", name, switch_xml_toxml(cfg, SWITCH_FALSE)); - goto err; - } - - - profile->fetch_timeout = fetch_timeout; - profile->section = fetch_section; - kazoo_config_fields(definitions, pool, cfg, &profile->fields); - kazoo_config_loglevels(pool, cfg, &profile->logging); - - if(root) { - if ( switch_core_hash_insert(root->hash, name, (void *) profile) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to insert new fetch profile [%s] into kazoo profile hash\n", name); - goto err; - } - } - - if(ptr) - *ptr = profile; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "fetch handler profile %s successfully configured\n", name); - return SWITCH_STATUS_SUCCESS; - - err: - /* Cleanup */ - if(pool) { - switch_core_destroy_memory_pool(&pool); - } - return SWITCH_STATUS_GENERR; - -} - -switch_status_t kazoo_config_event_handler(kazoo_config_ptr definitions, kazoo_config_ptr root, switch_xml_t cfg, kazoo_event_profile_ptr *ptr) -{ - kazoo_event_profile_ptr profile = NULL; - switch_memory_pool_t *pool = NULL; - - char *name = (char *) switch_xml_attr_soft(cfg, "name"); - if (zstr(name)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "missing name in profile\n"); - return SWITCH_STATUS_GENERR; - } - - if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error allocation pool for new profile : %s\n", name); - return SWITCH_STATUS_GENERR; - } - - profile = switch_core_alloc(pool, sizeof(kazoo_event_profile_t)); - profile->pool = pool; - profile->root = root; - profile->name = switch_core_strdup(profile->pool, name); - - kazoo_config_filters(pool, cfg, &profile->filter); - kazoo_config_fields(definitions, pool, cfg, &profile->fields); - kazoo_config_events(definitions, pool, cfg, profile); - kazoo_config_loglevels(pool, cfg, &profile->logging); - - if(root) { - if ( switch_core_hash_insert(root->hash, name, (void *) profile) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to insert new profile [%s] into kazoo profile hash\n", name); - goto err; - } - } - - if(ptr) - *ptr = profile; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "event handler profile %s successfully configured\n", name); - return SWITCH_STATUS_SUCCESS; - - err: - /* Cleanup */ - if(pool) { - switch_core_destroy_memory_pool(&pool); - } - return SWITCH_STATUS_GENERR; - -} - - - -/* 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_ei_utils.c b/src/mod/event_handlers/mod_kazoo/kazoo_ei_utils.c deleted file mode 100644 index 96381f9b24..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_ei_utils.c +++ /dev/null @@ -1,996 +0,0 @@ -/* - * 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): - * - * Anthony Minessale II - * Andrew Thompson - * Rob Charlton - * Karl Anderson - * - * Original from mod_erlang_event. - * ei_helpers.c -- helper functions for ei - * - */ -#include "mod_kazoo.h" - -/* Stolen from code added to ei in R12B-5. - * Since not everyone has this version yet; - * provide our own version. - * */ - -#define put8(s,n) do { \ - (s)[0] = (char)((n) & 0xff); \ - (s) += 1; \ - } while (0) - -#define put32be(s,n) do { \ - (s)[0] = ((n) >> 24) & 0xff; \ - (s)[1] = ((n) >> 16) & 0xff; \ - (s)[2] = ((n) >> 8) & 0xff; \ - (s)[3] = (n) & 0xff; \ - (s) += 4; \ - } while (0) - -#ifdef EI_DEBUG -static void ei_x_print_reg_msg(ei_x_buff *buf, char *dest, int send) { - char *mbuf = NULL; - int i = 1; - - 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); - } - - 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; - - ei_x_new(&pidbuf); - ei_x_encode_pid(&pidbuf, pid); - - ei_s_print_term(&pbuf, pidbuf.buff, &i); - - 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) { - 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; - - for (i = 0, hp = event->headers; hp; hp = hp->next, i++); - - if (event->body) - i++; - - ei_x_encode_list_header(ebuf, i + 1); - - 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"); - } - - 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)); - } - - 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; - - cJSON *item = JObj->child; - int i = 0; - while(item) { - if(item->type & mask) - i++; - item = item->next; - } - return i; - -} - -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; - - 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_True: - ei_x_encode_boolean(ebuf, 1); - break; - - case cJSON_False: - ei_x_encode_boolean(ebuf, 0); - break; - - case cJSON_Object: - ei_encode_json(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_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; - - } - item = item->next; - } - - ei_x_encode_empty_list(ebuf); - -} - -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); - } else { - ei_x_encode_map_header(ebuf, count); - } - - 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)); - - 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_True: - ei_x_encode_boolean(ebuf, 1); - break; - - case cJSON_False: - ei_x_encode_boolean(ebuf, 0); - break; - - case cJSON_Object: - ei_encode_json(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_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; - - } - item = item->next; - } - - if(kazoo_globals.json_encoding == ERLANG_TUPLE) { - ei_x_encode_empty_list(ebuf); - } - -} - -void close_socket(switch_socket_t ** sock) { - if (*sock) { - switch_socket_shutdown(*sock, SWITCH_SHUTDOWN_READWRITE); - switch_socket_close(*sock); - *sock = NULL; - } -} - -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_sockaddr_t *sa; - switch_socket_t *socket; - - if(switch_sockaddr_info_get(&sa, kazoo_globals.ip, SWITCH_UNSPEC, port, 0, pool)) { - return NULL; - } - - if (switch_socket_create(&socket, switch_sockaddr_get_family(sa), SOCK_STREAM, SWITCH_PROTO_TCP, pool)) { - return NULL; - } - - if (switch_socket_opt_set(socket, SWITCH_SO_REUSEADDR, 1)) { - return NULL; - } - - if (switch_socket_bind(socket, sa)) { - return NULL; - } - - if (switch_socket_listen(socket, 5)){ - return NULL; - } - - switch_getnameinfo(&kazoo_globals.hostname, sa, 0); - - if (kazoo_globals.nat_map && switch_nat_get_type()) { - switch_nat_add_mapping(port, SWITCH_NAT_TCP, NULL, SWITCH_FALSE); - } - - return socket; -} - -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]; - //EI_MAX_COOKIE_SIZE+1 - char *atsign; - - /* 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", kazoo_globals.ei_nodename); - /* truncate the alivename at the @ */ - *atsign = '\0'; - } else { - if (zstr(kazoo_globals.hostname) || !strncasecmp(kazoo_globals.ip, "0.0.0.0", 7) || !strncasecmp(kazoo_globals.ip, "::", 2)) { - memcpy(hostname, switch_core_get_hostname(), EI_MAXHOSTNAMELEN); - } else { - memcpy(hostname, kazoo_globals.hostname, EI_MAXHOSTNAMELEN); - } - - snprintf(nodename, MAXNODELEN + 1, "%s@%s", kazoo_globals.ei_nodename, hostname); - } - - if (kazoo_globals.ei_shortname) { - char *off; - if ((off = strchr(nodename, '.'))) { - *off = '\0'; - } - } - - /* 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; -} - -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; - - 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 */ - - 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); -} - -int ei_helper_send(ei_node_t *ei_node, erlang_pid *to, ei_x_buff *buf) { - int ret = 0; - - 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); - } - - return ret; -} - -int ei_decode_atom_safe(char *buf, int *index, char *dst) { - int 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; - } 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; - } 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; - - ei_get_type(buf, index, &type, &size); - - if (type != ERL_STRING_EXT && type != ERL_BINARY_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); - - if (type == ERL_NIL_EXT) { - 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); - } - - return res; -} - -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); - - if (type != ERL_STRING_EXT && type != ERL_BINARY_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); - return -1; - } - - if (type == ERL_NIL_EXT) { - 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); - } - - return res; -} - - -switch_status_t create_acceptor() { - switch_sockaddr_t *sa; - uint16_t port; - 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) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Compatability with OTP R%d requested\n", kazoo_globals.ei_compat_rel); - ei_set_compat_rel(kazoo_globals.ei_compat_rel); - } - - if (!(kazoo_globals.acceptor = create_socket_with_port(kazoo_globals.pool, kazoo_globals.port))) { - return SWITCH_STATUS_SOCKERR; - } - - 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); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Erlang connection acceptor listening on %s:%u\n", ip_addr, port); - - /* try to initialize the erlang interface */ - if (create_ei_cnode(ip_addr, kazoo_globals.ei_nodename, &kazoo_globals.ei_cnode) != SWITCH_STATUS_SUCCESS) { - return SWITCH_STATUS_SOCKERR; - } - - /* tell the erlang port manager where we can be reached. this returns a file descriptor pointing to epmd or -1 */ - if ((kazoo_globals.epmdfd = ei_publish(&kazoo_globals.ei_cnode, port)) == -1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to publish port to epmd, trying to start epmd via system()\n"); - if (system("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"); - return SWITCH_STATUS_SOCKERR; - } - switch_yield(100000); - if ((kazoo_globals.epmdfd = ei_publish(&kazoo_globals.ei_cnode, port)) == -1) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to publish port to epmd AGAIN\n"); - return SWITCH_STATUS_SOCKERR; - } - } - - 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 *filter; - - switch_core_hash_init(&filter); - - switch_core_hash_insert(filter, "Acquired-UUID", "1"); - switch_core_hash_insert(filter, "action", "1"); - switch_core_hash_insert(filter, "Action", "1"); - switch_core_hash_insert(filter, "alt_event_type", "1"); - switch_core_hash_insert(filter, "Answer-State", "1"); - switch_core_hash_insert(filter, "Application", "1"); - switch_core_hash_insert(filter, "Application-Data", "1"); - switch_core_hash_insert(filter, "Application-Name", "1"); - switch_core_hash_insert(filter, "Application-Response", "1"); - switch_core_hash_insert(filter, "att_xfer_replaced_by", "1"); - switch_core_hash_insert(filter, "Auth-Method", "1"); - switch_core_hash_insert(filter, "Auth-Realm", "1"); - switch_core_hash_insert(filter, "Auth-User", "1"); - switch_core_hash_insert(filter, "Bridge-A-Unique-ID", "1"); - switch_core_hash_insert(filter, "Bridge-B-Unique-ID", "1"); - switch_core_hash_insert(filter, "Call-Direction", "1"); - switch_core_hash_insert(filter, "Caller-Callee-ID-Name", "1"); - switch_core_hash_insert(filter, "Caller-Callee-ID-Number", "1"); - switch_core_hash_insert(filter, "Caller-Caller-ID-Name", "1"); - switch_core_hash_insert(filter, "Caller-Caller-ID-Number", "1"); - switch_core_hash_insert(filter, "Caller-Screen-Bit", "1"); - switch_core_hash_insert(filter, "Caller-Privacy-Hide-Name", "1"); - switch_core_hash_insert(filter, "Caller-Privacy-Hide-Number", "1"); - switch_core_hash_insert(filter, "Caller-Context", "1"); - switch_core_hash_insert(filter, "Caller-Controls", "1"); - switch_core_hash_insert(filter, "Caller-Destination-Number", "1"); - switch_core_hash_insert(filter, "Caller-Dialplan", "1"); - switch_core_hash_insert(filter, "Caller-Network-Addr", "1"); - switch_core_hash_insert(filter, "Caller-Unique-ID", "1"); - switch_core_hash_insert(filter, "Call-ID", "1"); - switch_core_hash_insert(filter, "Channel-Call-State", "1"); - switch_core_hash_insert(filter, "Channel-Call-UUID", "1"); - switch_core_hash_insert(filter, "Channel-Presence-ID", "1"); - switch_core_hash_insert(filter, "Channel-State", "1"); - switch_core_hash_insert(filter, "Chat-Permissions", "1"); - switch_core_hash_insert(filter, "Conference-Name", "1"); - switch_core_hash_insert(filter, "Conference-Profile-Name", "1"); - switch_core_hash_insert(filter, "Conference-Unique-ID", "1"); - switch_core_hash_insert(filter, "contact", "1"); - switch_core_hash_insert(filter, "Detected-Tone", "1"); - switch_core_hash_insert(filter, "dialog_state", "1"); - switch_core_hash_insert(filter, "direction", "1"); - switch_core_hash_insert(filter, "Distributed-From", "1"); - switch_core_hash_insert(filter, "DTMF-Digit", "1"); - switch_core_hash_insert(filter, "DTMF-Duration", "1"); - switch_core_hash_insert(filter, "Event-Date-Timestamp", "1"); - switch_core_hash_insert(filter, "Event-Name", "1"); - switch_core_hash_insert(filter, "Event-Subclass", "1"); - switch_core_hash_insert(filter, "expires", "1"); - switch_core_hash_insert(filter, "Expires", "1"); - switch_core_hash_insert(filter, "Ext-SIP-IP", "1"); - switch_core_hash_insert(filter, "File", "1"); - switch_core_hash_insert(filter, "FreeSWITCH-Hostname", "1"); - switch_core_hash_insert(filter, "from", "1"); - switch_core_hash_insert(filter, "Hunt-Destination-Number", "1"); - switch_core_hash_insert(filter, "ip", "1"); - switch_core_hash_insert(filter, "Message-Account", "1"); - switch_core_hash_insert(filter, "metadata", "1"); - switch_core_hash_insert(filter, "old_node_channel_uuid", "1"); - switch_core_hash_insert(filter, "Other-Leg-Callee-ID-Name", "1"); - switch_core_hash_insert(filter, "Other-Leg-Callee-ID-Number", "1"); - switch_core_hash_insert(filter, "Other-Leg-Caller-ID-Name", "1"); - switch_core_hash_insert(filter, "Other-Leg-Caller-ID-Number", "1"); - switch_core_hash_insert(filter, "Other-Leg-Destination-Number", "1"); - switch_core_hash_insert(filter, "Other-Leg-Direction", "1"); - switch_core_hash_insert(filter, "Other-Leg-Unique-ID", "1"); - switch_core_hash_insert(filter, "Other-Leg-Channel-Name", "1"); - switch_core_hash_insert(filter, "Participant-Type", "1"); - switch_core_hash_insert(filter, "Path", "1"); - switch_core_hash_insert(filter, "profile_name", "1"); - switch_core_hash_insert(filter, "Profiles", "1"); - switch_core_hash_insert(filter, "proto-specific-event-name", "1"); - switch_core_hash_insert(filter, "Raw-Application-Data", "1"); - switch_core_hash_insert(filter, "realm", "1"); - switch_core_hash_insert(filter, "Resigning-UUID", "1"); - switch_core_hash_insert(filter, "set", "1"); - switch_core_hash_insert(filter, "sip_auto_answer", "1"); - switch_core_hash_insert(filter, "sip_auth_method", "1"); - switch_core_hash_insert(filter, "sip_from_host", "1"); - switch_core_hash_insert(filter, "sip_from_user", "1"); - switch_core_hash_insert(filter, "sip_to_host", "1"); - switch_core_hash_insert(filter, "sip_to_user", "1"); - switch_core_hash_insert(filter, "sub-call-id", "1"); - switch_core_hash_insert(filter, "technology", "1"); - switch_core_hash_insert(filter, "to", "1"); - switch_core_hash_insert(filter, "Unique-ID", "1"); - switch_core_hash_insert(filter, "URL", "1"); - switch_core_hash_insert(filter, "username", "1"); - switch_core_hash_insert(filter, "variable_channel_is_moving", "1"); - switch_core_hash_insert(filter, "variable_collected_digits", "1"); - switch_core_hash_insert(filter, "variable_current_application", "1"); - switch_core_hash_insert(filter, "variable_current_application_data", "1"); - switch_core_hash_insert(filter, "variable_domain_name", "1"); - switch_core_hash_insert(filter, "variable_effective_caller_id_name", "1"); - switch_core_hash_insert(filter, "variable_effective_caller_id_number", "1"); - switch_core_hash_insert(filter, "variable_holding_uuid", "1"); - switch_core_hash_insert(filter, "variable_hold_music", "1"); - switch_core_hash_insert(filter, "variable_media_group_id", "1"); - switch_core_hash_insert(filter, "variable_originate_disposition", "1"); - switch_core_hash_insert(filter, "variable_origination_uuid", "1"); - switch_core_hash_insert(filter, "variable_playback_terminator_used", "1"); - switch_core_hash_insert(filter, "variable_presence_id", "1"); - switch_core_hash_insert(filter, "variable_record_ms", "1"); - switch_core_hash_insert(filter, "variable_recovered", "1"); - switch_core_hash_insert(filter, "variable_silence_hits_exhausted", "1"); - switch_core_hash_insert(filter, "variable_sip_auth_realm", "1"); - switch_core_hash_insert(filter, "variable_sip_from_host", "1"); - switch_core_hash_insert(filter, "variable_sip_from_user", "1"); - switch_core_hash_insert(filter, "variable_sip_from_tag", "1"); - switch_core_hash_insert(filter, "variable_sip_h_X-AUTH-IP", "1"); - switch_core_hash_insert(filter, "variable_sip_received_ip", "1"); - switch_core_hash_insert(filter, "variable_sip_to_host", "1"); - switch_core_hash_insert(filter, "variable_sip_to_user", "1"); - switch_core_hash_insert(filter, "variable_sip_to_tag", "1"); - switch_core_hash_insert(filter, "variable_sofia_profile_name", "1"); - switch_core_hash_insert(filter, "variable_transfer_history", "1"); - switch_core_hash_insert(filter, "variable_user_name", "1"); - switch_core_hash_insert(filter, "variable_endpoint_disposition", "1"); - switch_core_hash_insert(filter, "variable_originate_disposition", "1"); - switch_core_hash_insert(filter, "variable_bridge_hangup_cause", "1"); - switch_core_hash_insert(filter, "variable_hangup_cause", "1"); - switch_core_hash_insert(filter, "variable_last_bridge_proto_specific_hangup_cause", "1"); - switch_core_hash_insert(filter, "variable_proto_specific_hangup_cause", "1"); - switch_core_hash_insert(filter, "VM-Call-ID", "1"); - switch_core_hash_insert(filter, "VM-sub-call-id", "1"); - switch_core_hash_insert(filter, "whistle_application_name", "1"); - switch_core_hash_insert(filter, "whistle_application_response", "1"); - switch_core_hash_insert(filter, "whistle_event_name", "1"); - switch_core_hash_insert(filter, "kazoo_application_name", "1"); - switch_core_hash_insert(filter, "kazoo_application_response", "1"); - switch_core_hash_insert(filter, "kazoo_event_name", "1"); - switch_core_hash_insert(filter, "sip_auto_answer_notify", "1"); - switch_core_hash_insert(filter, "eavesdrop_group", "1"); - switch_core_hash_insert(filter, "origination_caller_id_name", "1"); - switch_core_hash_insert(filter, "origination_caller_id_number", "1"); - switch_core_hash_insert(filter, "origination_callee_id_name", "1"); - switch_core_hash_insert(filter, "origination_callee_id_number", "1"); - switch_core_hash_insert(filter, "sip_auth_username", "1"); - switch_core_hash_insert(filter, "sip_auth_password", "1"); - switch_core_hash_insert(filter, "effective_caller_id_name", "1"); - switch_core_hash_insert(filter, "effective_caller_id_number", "1"); - switch_core_hash_insert(filter, "effective_callee_id_name", "1"); - switch_core_hash_insert(filter, "effective_callee_id_number", "1"); - switch_core_hash_insert(filter, "variable_destination_number", "1"); - switch_core_hash_insert(filter, "variable_effective_callee_id_name", "1"); - switch_core_hash_insert(filter, "variable_effective_callee_id_number", "1"); - switch_core_hash_insert(filter, "variable_record_silence_hits", "1"); - switch_core_hash_insert(filter, "variable_refer_uuid", "1"); - switch_core_hash_insert(filter, "variable_sip_call_id", "1"); - switch_core_hash_insert(filter, "variable_sip_h_Referred-By", "1"); - switch_core_hash_insert(filter, "variable_sip_h_X-AUTH-PORT", "1"); - switch_core_hash_insert(filter, "variable_sip_loopback_req_uri", "1"); - switch_core_hash_insert(filter, "variable_sip_received_port", "1"); - switch_core_hash_insert(filter, "variable_sip_refer_to", "1"); - switch_core_hash_insert(filter, "variable_sip_req_host", "1"); - switch_core_hash_insert(filter, "variable_sip_req_uri", "1"); - switch_core_hash_insert(filter, "variable_transfer_source", "1"); - switch_core_hash_insert(filter, "variable_uuid", "1"); - - /* Registration headers */ - switch_core_hash_insert(filter, "call-id", "1"); - switch_core_hash_insert(filter, "profile-name", "1"); - switch_core_hash_insert(filter, "from-user", "1"); - switch_core_hash_insert(filter, "from-host", "1"); - switch_core_hash_insert(filter, "presence-hosts", "1"); - switch_core_hash_insert(filter, "contact", "1"); - switch_core_hash_insert(filter, "rpid", "1"); - switch_core_hash_insert(filter, "status", "1"); - switch_core_hash_insert(filter, "expires", "1"); - switch_core_hash_insert(filter, "to-user", "1"); - switch_core_hash_insert(filter, "to-host", "1"); - switch_core_hash_insert(filter, "network-ip", "1"); - switch_core_hash_insert(filter, "network-port", "1"); - switch_core_hash_insert(filter, "username", "1"); - switch_core_hash_insert(filter, "realm", "1"); - switch_core_hash_insert(filter, "user-agent", "1"); - - switch_core_hash_insert(filter, "Hangup-Cause", "1"); - switch_core_hash_insert(filter, "Unique-ID", "1"); - switch_core_hash_insert(filter, "variable_switch_r_sdp", "1"); - switch_core_hash_insert(filter, "variable_rtp_local_sdp_str", "1"); - switch_core_hash_insert(filter, "variable_sip_to_uri", "1"); - switch_core_hash_insert(filter, "variable_sip_from_uri", "1"); - switch_core_hash_insert(filter, "variable_sip_user_agent", "1"); - switch_core_hash_insert(filter, "variable_duration", "1"); - switch_core_hash_insert(filter, "variable_billsec", "1"); - switch_core_hash_insert(filter, "variable_billmsec", "1"); - switch_core_hash_insert(filter, "variable_progresssec", "1"); - switch_core_hash_insert(filter, "variable_progress_uepoch", "1"); - switch_core_hash_insert(filter, "variable_progress_media_uepoch", "1"); - switch_core_hash_insert(filter, "variable_start_uepoch", "1"); - switch_core_hash_insert(filter, "variable_digits_dialed", "1"); - switch_core_hash_insert(filter, "Member-ID", "1"); - switch_core_hash_insert(filter, "Floor", "1"); - switch_core_hash_insert(filter, "Video", "1"); - switch_core_hash_insert(filter, "Hear", "1"); - switch_core_hash_insert(filter, "Speak", "1"); - switch_core_hash_insert(filter, "Talking", "1"); - switch_core_hash_insert(filter, "Current-Energy", "1"); - switch_core_hash_insert(filter, "Energy-Level", "1"); - switch_core_hash_insert(filter, "Mute-Detect", "1"); - - /* RTMP headers */ - switch_core_hash_insert(filter, "RTMP-Session-ID", "1"); - switch_core_hash_insert(filter, "RTMP-Profile", "1"); - switch_core_hash_insert(filter, "RTMP-Flash-Version", "1"); - switch_core_hash_insert(filter, "RTMP-SWF-URL", "1"); - switch_core_hash_insert(filter, "RTMP-TC-URL", "1"); - switch_core_hash_insert(filter, "RTMP-Page-URL", "1"); - switch_core_hash_insert(filter, "User", "1"); - switch_core_hash_insert(filter, "Domain", "1"); - - /* Fax headers */ - switch_core_hash_insert(filter, "variable_fax_bad_rows", "1"); - switch_core_hash_insert(filter, "variable_fax_document_total_pages", "1"); - switch_core_hash_insert(filter, "variable_fax_document_transferred_pages", "1"); - switch_core_hash_insert(filter, "variable_fax_ecm_used", "1"); - switch_core_hash_insert(filter, "variable_fax_result_code", "1"); - switch_core_hash_insert(filter, "variable_fax_result_text", "1"); - switch_core_hash_insert(filter, "variable_fax_success", "1"); - switch_core_hash_insert(filter, "variable_fax_transfer_rate", "1"); - switch_core_hash_insert(filter, "variable_fax_local_station_id", "1"); - switch_core_hash_insert(filter, "variable_fax_remote_station_id", "1"); - switch_core_hash_insert(filter, "variable_fax_remote_country", "1"); - switch_core_hash_insert(filter, "variable_fax_remote_vendor", "1"); - switch_core_hash_insert(filter, "variable_fax_remote_model", "1"); - switch_core_hash_insert(filter, "variable_fax_image_resolution", "1"); - switch_core_hash_insert(filter, "variable_fax_file_image_resolution", "1"); - switch_core_hash_insert(filter, "variable_fax_image_size", "1"); - switch_core_hash_insert(filter, "variable_fax_image_pixel_size", "1"); - switch_core_hash_insert(filter, "variable_fax_file_image_pixel_size", "1"); - switch_core_hash_insert(filter, "variable_fax_longest_bad_row_run", "1"); - switch_core_hash_insert(filter, "variable_fax_encoding", "1"); - switch_core_hash_insert(filter, "variable_fax_encoding_name", "1"); - switch_core_hash_insert(filter, "variable_fax_header", "1"); - switch_core_hash_insert(filter, "variable_fax_ident", "1"); - switch_core_hash_insert(filter, "variable_fax_timezone", "1"); - switch_core_hash_insert(filter, "variable_fax_doc_id", "1"); - switch_core_hash_insert(filter, "variable_fax_doc_database", "1"); - switch_core_hash_insert(filter, "variable_has_t38", "1"); - - /* Secure headers */ - switch_core_hash_insert(filter, "variable_sdp_secure_savp_only", "1"); - switch_core_hash_insert(filter, "variable_rtp_has_crypto", "1"); - switch_core_hash_insert(filter, "variable_rtp_secure_media", "1"); - switch_core_hash_insert(filter, "variable_rtp_secure_media_confirmed", "1"); - switch_core_hash_insert(filter, "variable_rtp_secure_media_confirmed_audio", "1"); - switch_core_hash_insert(filter, "variable_rtp_secure_media_confirmed_video", "1"); - switch_core_hash_insert(filter, "variable_zrtp_secure_media", "1"); - switch_core_hash_insert(filter, "variable_zrtp_secure_media_confirmed", "1"); - switch_core_hash_insert(filter, "variable_zrtp_secure_media_confirmed_audio", "1"); - switch_core_hash_insert(filter, "variable_zrtp_secure_media_confirmed_video", "1"); - switch_core_hash_insert(filter, "sdp_secure_savp_only", "1"); - switch_core_hash_insert(filter, "rtp_has_crypto", "1"); - switch_core_hash_insert(filter, "rtp_secure_media", "1"); - switch_core_hash_insert(filter, "rtp_secure_media_confirmed", "1"); - switch_core_hash_insert(filter, "rtp_secure_media_confirmed_audio", "1"); - switch_core_hash_insert(filter, "rtp_secure_media_confirmed_video", "1"); - switch_core_hash_insert(filter, "zrtp_secure_media", "1"); - switch_core_hash_insert(filter, "zrtp_secure_media_confirmed", "1"); - switch_core_hash_insert(filter, "zrtp_secure_media_confirmed_audio", "1"); - switch_core_hash_insert(filter, "zrtp_secure_media_confirmed_video", "1"); - - /* Device Redirect headers */ - switch_core_hash_insert(filter, "variable_last_bridge_hangup_cause", "1"); - switch_core_hash_insert(filter, "variable_sip_redirected_by", "1"); - switch_core_hash_insert(filter, "intercepted_by", "1"); - switch_core_hash_insert(filter, "variable_bridge_uuid", "1"); - switch_core_hash_insert(filter, "Record-File-Path", "1"); - - /* Loopback headers */ - switch_core_hash_insert(filter, "variable_loopback_bowout_on_execute", "1"); - switch_core_hash_insert(filter, "variable_loopback_bowout", "1"); - switch_core_hash_insert(filter, "variable_other_loopback_leg_uuid", "1"); - switch_core_hash_insert(filter, "variable_loopback_leg", "1"); - switch_core_hash_insert(filter, "variable_is_loopback", "1"); - - // SMS - switch_core_hash_insert(filter, "Message-ID", "1"); - switch_core_hash_insert(filter, "Delivery-Failure", "1"); - switch_core_hash_insert(filter, "Delivery-Result-Code", "1"); - - return filter; -} - -static void fetch_config_filters(switch_memory_pool_t *pool) -{ - char *cf = "kazoo.conf"; - switch_xml_t cfg, xml, child, param; - switch_event_t *params; - - switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS); - switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Action", "request-filter"); - - if (!(xml = switch_xml_open_cfg(cf, &cfg, params))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open configuration file %s\n", cf); - } else if ((child = switch_xml_child(cfg, "event-filter"))) { - switch_hash_t *filter; - switch_hash_t *old_filter; - - switch_core_hash_init(&filter); - for (param = switch_xml_child(child, "header"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - switch_core_hash_insert(filter, var, "1"); - } - - old_filter = kazoo_globals.event_filter; - kazoo_globals.event_filter = filter; - if (old_filter) { - switch_core_hash_destroy(&old_filter); - } - - kazoo_globals.config_fetched = 1; - switch_xml_free(xml); - } - -} - -static void fetch_config_handlers(switch_memory_pool_t *pool) -{ - char *cf = "kazoo.conf"; - switch_xml_t cfg, xml; - switch_event_t *params; - - switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS); - switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Action", "request-handlers"); - - if (!(xml = switch_xml_open_cfg(cf, &cfg, params))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open configuration file %s\n", cf); - } else { - kazoo_config_handlers(cfg); - kazoo_globals.config_fetched = 1; - switch_xml_free(xml); - } - -} - -static void *SWITCH_THREAD_FUNC fetch_config_exec(switch_thread_t *thread, void *obj) -{ - switch_memory_pool_t *pool = (switch_memory_pool_t *)obj; - fetch_config_filters(pool); - fetch_config_handlers(pool); - - kazoo_globals.config_fetched = 1; - - return NULL; -} - -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); - - switch_threadattr_create(&thd_attr, pool); - switch_threadattr_detach_set(thd_attr, 1); - switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - - switch_uuid_get(&uuid); - switch_thread_create(&thread, thd_attr, fetch_config_exec, pool, pool); - -} - - -SWITCH_MODULE_RUNTIME_FUNCTION(mod_kazoo_runtime) { - switch_os_socket_t os_socket; - - 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); - return SWITCH_STATUS_TERM; - } - - switch_atomic_inc(&kazoo_globals.threads); - switch_os_sock_get(&os_socket, kazoo_globals.acceptor); - - while (switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) { - int nodefd; - ErlConnect conn; - - /* zero out errno because ei_accept doesn't differentiate between a */ - /* failed authentication or a socket failure, or a client version */ - /* mismatch or a godzilla attack (and a godzilla attack is highly likely) */ - errno = 0; - - /* wait here for an erlang node to connect, timming out to check if our module is still running every now-and-again */ - if ((nodefd = ei_accept_tmo(&kazoo_globals.ei_cnode, (int) os_socket, &conn, kazoo_globals.connection_timeout)) == ERL_ERROR) { - if (erl_errno == ETIMEDOUT) { - continue; - } else if (errno) { - 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); - } - continue; - } - - if (!switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) { - break; - } - - /* NEW ERLANG NODE CONNECTION! Hello friend! */ - new_kazoo_node(nodefd, &conn); - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Erlang connection acceptor shut down\n"); - - switch_atomic_dec(&kazoo_globals.threads); - - return SWITCH_STATUS_TERM; -} - -/* 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_event_stream.c b/src/mod/event_handlers/mod_kazoo/kazoo_event_stream.c index b52b6d4b81..3ca0e3acc7 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_event_stream.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_event_stream.c @@ -48,8 +48,7 @@ static char *my_dup(const char *s) { static const char* private_headers[] = {"variable_sip_h_", "sip_h_", "P-", "X-"}; static int is_private_header(const char *name) { - int i; - for(i=0; i < 4; i++) { + for(int i=0; i < 4; i++) { if(!strncmp(name, private_headers[i], strlen(private_headers[i]))) { return 1; } @@ -103,105 +102,51 @@ static switch_status_t kazoo_event_dup(switch_event_t **clone, switch_event_t *e return SWITCH_STATUS_SUCCESS; } -static int encode_event_old(switch_event_t *event, ei_x_buff *ebuf) { - switch_event_t *clone = NULL; - - if (kazoo_event_dup(&clone, event, kazoo_globals.event_filter) != SWITCH_STATUS_SUCCESS) { - return 0; - } - - ei_encode_switch_event(ebuf, clone); - - switch_event_destroy(&clone); - - return 1; -} - -static int encode_event_new(switch_event_t *event, ei_x_buff *ebuf) { - kazoo_message_ptr msg = NULL; - ei_event_binding_t *event_binding = (ei_event_binding_t *) event->bind_user_data; - - msg = kazoo_message_create_event(event, event_binding->event, kazoo_globals.events); - - if(msg == NULL) { - return 0; - } - - ei_x_encode_tuple_header(ebuf, 2); - ei_x_encode_atom(ebuf, "event"); - ei_encode_json(ebuf, msg->JObj); - - kazoo_message_destroy(&msg); - - return 1; -} - -/* - * event_handler is duplicated when there are 2+ nodes connected - * with the same bindings - * we should maintain a list of event_streams in event_binding struct - * and build a ref count in the message - * - */ static void event_handler(switch_event_t *event) { - ei_event_binding_t *event_binding = (ei_event_binding_t *) event->bind_user_data; - ei_event_stream_t *event_stream = event_binding->stream; - ei_x_buff *ebuf = NULL; - int res = 0; + switch_event_t *clone = NULL; + ei_event_stream_t *event_stream = (ei_event_stream_t *) event->bind_user_data; /* if mod_kazoo or the event stream isn't running dont push a new event */ if (!switch_test_flag(event_stream, LFLAG_RUNNING) || !switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) { return; } - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Switch-Nodename", kazoo_globals.ei_cnode.thisnodename); + if (event->event_id == SWITCH_EVENT_CUSTOM) { + ei_event_binding_t *event_binding = event_stream->bindings; + unsigned short int found = 0; - switch_malloc(ebuf, sizeof(*ebuf)); - if(ebuf == NULL) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not allocate erlang buffer for mod_kazoo message\n"); - return; - } - memset(ebuf, 0, sizeof(*ebuf)); - - if(kazoo_globals.event_stream_preallocate > 0) { - ebuf->buff = malloc(kazoo_globals.event_stream_preallocate); - ebuf->buffsz = kazoo_globals.event_stream_preallocate; - ebuf->index = 0; - if(ebuf->buff == NULL) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not pre-allocate memory for mod_kazoo message\n"); - switch_safe_free(ebuf); + if (!event->subclass_name) { + return; + } + + while(event_binding != NULL) { + if (event_binding->type == SWITCH_EVENT_CUSTOM) { + if(event_binding->subclass_name + && !strcmp(event->subclass_name, event_binding->subclass_name)) { + found = 1; + break; + } + } + event_binding = event_binding->next; + } + + if (!found) { return; } - ei_x_encode_version(ebuf); - } else { - ei_x_new_with_version(ebuf); } - - if(event_stream->node->legacy) { - res = encode_event_old(event, ebuf); - } else { - res = encode_event_new(event, ebuf); - } - - if(!res) { - ei_x_free(ebuf); - switch_safe_free(ebuf); - return; - } - - if (kazoo_globals.event_stream_preallocate > 0 && ebuf->buffsz > kazoo_globals.event_stream_preallocate) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "increased event stream buffer size to %d\n", ebuf->buffsz); - } - - if (switch_queue_trypush(event_stream->queue, ebuf) != SWITCH_STATUS_SUCCESS) { + /* try to clone the event and push it to the event stream thread */ + /* TODO: someday maybe the filter comes from the event_stream (set during init only) + * and is per-binding so we only send headers that a process requests */ + if (kazoo_event_dup(&clone, event, kazoo_globals.event_filter) == SWITCH_STATUS_SUCCESS) { + if (switch_queue_trypush(event_stream->queue, clone) != SWITCH_STATUS_SUCCESS) { /* if we couldn't place the cloned event into the listeners */ /* event queue make sure we destroy it, real good like */ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error placing the event in the listeners queue\n"); - ei_x_free(ebuf); - switch_safe_free(ebuf); + switch_event_destroy(&clone); + } + } else { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory error: Have a good trip? See you next fall!\n"); } - } static void *SWITCH_THREAD_FUNC event_stream_loop(switch_thread_t *thread, void *obj) { @@ -233,8 +178,7 @@ static void *SWITCH_THREAD_FUNC event_stream_loop(switch_thread_t *thread, void /* check if a new connection is pending */ if (switch_pollset_poll(event_stream->pollset, 0, &numfds, &fds) == SWITCH_STATUS_SUCCESS) { - int32_t i; - for (i = 0; i < numfds; i++) { + for (int32_t i = 0; i < numfds; i++) { switch_socket_t *newsocket; /* accept the new client connection */ @@ -273,25 +217,46 @@ static void *SWITCH_THREAD_FUNC event_stream_loop(switch_thread_t *thread, void } /* if there was an event waiting in our queue send it to the client */ - if (switch_queue_pop_timeout(event_stream->queue, &pop, 200000) == SWITCH_STATUS_SUCCESS) { - ei_x_buff *ebuf = (ei_x_buff *) pop; + if (switch_queue_pop_timeout(event_stream->queue, &pop, 500000) == SWITCH_STATUS_SUCCESS) { + switch_event_t *event = (switch_event_t *) pop; if (event_stream->socket) { + ei_x_buff ebuf; char byte; short i = event_stream_framing; switch_size_t size = 1; + if(kazoo_globals.event_stream_preallocate > 0) { + ebuf.buff = malloc(kazoo_globals.event_stream_preallocate); + ebuf.buffsz = kazoo_globals.event_stream_preallocate; + ebuf.index = 0; + if(ebuf.buff == NULL) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not pre-allocate memory for mod_kazoo message\n"); + break; + } + ei_x_encode_version(&ebuf); + } else { + ei_x_new_with_version(&ebuf); + } + + ei_encode_switch_event(&ebuf, event); + + if (kazoo_globals.event_stream_preallocate > 0 && ebuf.buffsz > kazoo_globals.event_stream_preallocate) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "increased event stream buffer size to %d\n", ebuf.buffsz); + } + while (i) { - byte = ebuf->index >> (8 * --i); + byte = ebuf.index >> (8 * --i); switch_socket_send(event_stream->socket, &byte, &size); } - size = (switch_size_t)ebuf->index; - switch_socket_send(event_stream->socket, ebuf->buff, &size); + size = (switch_size_t)ebuf.index; + switch_socket_send(event_stream->socket, ebuf.buff, &size); + + ei_x_free(&ebuf); } - ei_x_free(ebuf); - switch_safe_free(ebuf); + switch_event_destroy(&event); } } @@ -332,12 +297,11 @@ static void *SWITCH_THREAD_FUNC event_stream_loop(switch_thread_t *thread, void return NULL; } -ei_event_stream_t *new_event_stream(ei_node_t *ei_node, const erlang_pid *from) { +ei_event_stream_t *new_event_stream(ei_event_stream_t **event_streams, const erlang_pid *from) { switch_thread_t *thread; switch_threadattr_t *thd_attr = NULL; switch_memory_pool_t *pool = NULL; ei_event_stream_t *event_stream; - ei_event_stream_t **event_streams = &ei_node->event_streams; /* create memory pool for this event stream */ if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { @@ -356,7 +320,6 @@ ei_event_stream_t *new_event_stream(ei_node_t *ei_node, const erlang_pid *from) event_stream->bindings = NULL; event_stream->pool = pool; event_stream->connected = SWITCH_FALSE; - event_stream->node = ei_node; memcpy(&event_stream->pid, from, sizeof(erlang_pid)); switch_queue_create(&event_stream->queue, MAX_QUEUE_LEN, pool); @@ -480,68 +443,17 @@ switch_status_t remove_event_streams(ei_event_stream_t **event_streams) { return SWITCH_STATUS_SUCCESS; } -void bind_event_profile(ei_event_binding_t *event_binding, kazoo_event_ptr event) -{ - switch_event_types_t event_type; - while(event != NULL) { - if (switch_name_event(event->name, &event_type) != SWITCH_STATUS_SUCCESS) { - event_type = SWITCH_EVENT_CUSTOM; - } - if(event_binding->type != SWITCH_EVENT_CUSTOM - && event_binding->type == event_type) { - break; - } - if (event_binding->type == SWITCH_EVENT_CUSTOM - && event_binding->type == event_type - && !strcasecmp(event_binding->subclass_name, event->name)) { - break; - } - event = event->next; - } - event_binding->event = event; - if(event == NULL) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "EVENT BINDING ERROR %s - %s\n",switch_event_name(event_binding->type), event_binding->subclass_name); - } -} - -void bind_event_profiles(kazoo_event_ptr event) -{ - ei_node_t *ei_node = kazoo_globals.ei_nodes; - while(ei_node) { - ei_event_stream_t *event_streams = ei_node->event_streams; - while(event_streams) { - ei_event_binding_t *bindings = event_streams->bindings; - while(bindings) { - bind_event_profile(bindings, event); - bindings = bindings->next; - } - event_streams = event_streams->next; - } - ei_node = ei_node->next; - } -} - -switch_status_t add_event_binding(ei_event_stream_t *event_stream, const char *event_name) { +switch_status_t add_event_binding(ei_event_stream_t *event_stream, const switch_event_types_t event_type, const char *subclass_name) { ei_event_binding_t *event_binding = event_stream->bindings; - switch_event_types_t event_type; - - if(!strcasecmp(event_name, "CUSTOM")) { - return SWITCH_STATUS_SUCCESS; - } - - if (switch_name_event(event_name, &event_type) != SWITCH_STATUS_SUCCESS) { - event_type = SWITCH_EVENT_CUSTOM; - } /* check if the event binding already exists, ignore if so */ while(event_binding != NULL) { if (event_binding->type == SWITCH_EVENT_CUSTOM) { - if(event_type == SWITCH_EVENT_CUSTOM - && event_name - && event_binding->subclass_name - && !strcasecmp(event_name, event_binding->subclass_name)) { - return SWITCH_STATUS_SUCCESS; - } + if(subclass_name + && event_binding->subclass_name + && !strcmp(subclass_name, event_binding->subclass_name)) { + return SWITCH_STATUS_SUCCESS; + } } else if (event_binding->type == event_type) { return SWITCH_STATUS_SUCCESS; } @@ -555,21 +467,18 @@ switch_status_t add_event_binding(ei_event_stream_t *event_stream, const char *e } /* prepare the event binding struct */ - event_binding->stream = event_stream; event_binding->type = event_type; - if(event_binding->type == SWITCH_EVENT_CUSTOM) { - event_binding->subclass_name = switch_core_strdup(event_stream->pool, event_name); + if (!subclass_name || zstr(subclass_name)) { + event_binding->subclass_name = NULL; } else { - event_binding->subclass_name = SWITCH_EVENT_SUBCLASS_ANY; + /* TODO: free strdup? */ + event_binding->subclass_name = strdup(subclass_name); } event_binding->next = NULL; - bind_event_profile(event_binding, kazoo_globals.events->events); - - /* bind to the event with a unique ID and capture the event_node pointer */ switch_uuid_str(event_binding->id, sizeof(event_binding->id)); - if (switch_event_bind_removable(event_binding->id, event_type, event_binding->subclass_name, event_handler, event_binding, &event_binding->node) != SWITCH_STATUS_SUCCESS) { + if (switch_event_bind_removable(event_binding->id, event_type, subclass_name, event_handler, event_stream, &event_binding->node) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to bind to event %s %s!\n" ,switch_event_name(event_binding->type), event_binding->subclass_name ? event_binding->subclass_name : ""); return SWITCH_STATUS_GENERR; 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 0e4e842f2c..006ffe32f0 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_fetch_agent.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_fetch_agent.c @@ -32,9 +32,38 @@ */ #include "mod_kazoo.h" +struct xml_fetch_reply_s { + char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; + char *xml_str; + struct xml_fetch_reply_s *next; +}; +typedef struct xml_fetch_reply_s xml_fetch_reply_t; +struct fetch_handler_s { + erlang_pid pid; + struct fetch_handler_s *next; +}; +typedef struct fetch_handler_s fetch_handler_t; +struct ei_xml_client_s { + ei_node_t *ei_node; + fetch_handler_t *fetch_handlers; + struct ei_xml_client_s *next; +}; +typedef struct ei_xml_client_s ei_xml_client_t; +struct ei_xml_agent_s { + switch_memory_pool_t *pool; + switch_xml_section_t section; + switch_thread_rwlock_t *lock; + ei_xml_client_t *clients; + switch_mutex_t *current_client_mutex; + ei_xml_client_t *current_client; + switch_mutex_t *replies_mutex; + switch_thread_cond_t *new_reply; + xml_fetch_reply_t *replies; +}; +typedef struct ei_xml_agent_s ei_xml_agent_t; static char *xml_section_to_string(switch_xml_section_t section) { switch(section) { @@ -48,8 +77,6 @@ static char *xml_section_to_string(switch_xml_section_t section) { return "chatplan"; case SWITCH_XML_SECTION_CHANNELS: return "channels"; - case SWITCH_XML_SECTION_LANGUAGES: - return "languages"; default: return "unknown"; } @@ -106,11 +133,6 @@ static switch_xml_t fetch_handler(const char *section, const char *tag_name, con ei_xml_client_t *client; fetch_handler_t *fetch_handler; xml_fetch_reply_t reply, *pending, *prev = NULL; - switch_event_t *event = params; - kazoo_fetch_profile_ptr profile = agent->profile; - const char *fetch_call_id; - ei_send_msg_t *send_msg = NULL; - int sent = 0; now = switch_micro_time_now(); @@ -142,60 +164,12 @@ static switch_xml_t fetch_handler(const char *section, const char *tag_name, con return xml; } - if(event == NULL) { - if (switch_event_create(&event, SWITCH_EVENT_GENERAL) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error creating event for fetch handler\n"); - return xml; - } - } - /* prepare the reply collector */ switch_uuid_get(&uuid); switch_uuid_format(reply.uuid_str, &uuid); reply.next = NULL; reply.xml_str = NULL; - if((fetch_call_id = switch_event_get_header(event, "Fetch-Call-UUID")) != NULL) { - switch_core_session_t *session = NULL; - if((session = switch_core_session_force_locate(fetch_call_id)) != NULL) { - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_channel_event_set_data(channel, event); - switch_core_session_rwunlock(session); - } - } - - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Fetch-UUID", reply.uuid_str); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Fetch-Section", section); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Fetch-Tag", tag_name); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Fetch-Key-Name", key_name); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Fetch-Key-Value", key_value); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Fetch-Timeout", "%u", profile->fetch_timeout); - switch_event_add_header(event, SWITCH_STACK_BOTTOM, "Fetch-Timestamp-Micro", "%ld", (uint64_t)now); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Kazoo-Version", VERSION); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Kazoo-Bundle", BUNDLE); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Kazoo-Release", RELEASE); - - switch_malloc(send_msg, sizeof(*send_msg)); - - if(client->ei_node->legacy) { - ei_x_new_with_version(&send_msg->buf); - ei_x_encode_tuple_header(&send_msg->buf, 7); - ei_x_encode_atom(&send_msg->buf, "fetch"); - ei_x_encode_atom(&send_msg->buf, section); - _ei_x_encode_string(&send_msg->buf, tag_name ? tag_name : "undefined"); - _ei_x_encode_string(&send_msg->buf, key_name ? key_name : "undefined"); - _ei_x_encode_string(&send_msg->buf, key_value ? key_value : "undefined"); - _ei_x_encode_string(&send_msg->buf, reply.uuid_str); - ei_encode_switch_event_headers(&send_msg->buf, event); - } else { - kazoo_message_ptr msg = kazoo_message_create_fetch(event, profile); - ei_x_new_with_version(&send_msg->buf); - ei_x_encode_tuple_header(&send_msg->buf, 2); - ei_x_encode_atom(&send_msg->buf, "fetch"); - ei_encode_json(&send_msg->buf, msg->JObj); - kazoo_message_destroy(&msg); - } - /* add our reply placeholder to the replies list */ switch_mutex_lock(agent->replies_mutex); if (!agent->replies) { @@ -207,8 +181,28 @@ static switch_xml_t fetch_handler(const char *section, const char *tag_name, con switch_mutex_unlock(agent->replies_mutex); fetch_handler = client->fetch_handlers; - while (fetch_handler != NULL && sent == 0) { + while (fetch_handler != NULL) { + ei_send_msg_t *send_msg; + + switch_malloc(send_msg, sizeof(*send_msg)); memcpy(&send_msg->pid, &fetch_handler->pid, sizeof(erlang_pid)); + + ei_x_new_with_version(&send_msg->buf); + + ei_x_encode_tuple_header(&send_msg->buf, 7); + ei_x_encode_atom(&send_msg->buf, "fetch"); + ei_x_encode_atom(&send_msg->buf, section); + _ei_x_encode_string(&send_msg->buf, tag_name ? tag_name : "undefined"); + _ei_x_encode_string(&send_msg->buf, key_name ? key_name : "undefined"); + _ei_x_encode_string(&send_msg->buf, key_value ? key_value : "undefined"); + _ei_x_encode_string(&send_msg->buf, reply.uuid_str); + + if (params) { + ei_encode_switch_event_headers(&send_msg->buf, params); + } else { + ei_x_encode_empty_list(&send_msg->buf); + } + if (switch_queue_trypush(client->ei_node->send_msgs, send_msg) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to send %s XML request to %s <%d.%d.%d>\n" ,section @@ -216,6 +210,8 @@ static switch_xml_t fetch_handler(const char *section, const char *tag_name, con ,fetch_handler->pid.creation ,fetch_handler->pid.num ,fetch_handler->pid.serial); + ei_x_free(&send_msg->buf); + switch_safe_free(send_msg); } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sending %s XML request (%s) to %s <%d.%d.%d>\n" ,section @@ -224,19 +220,11 @@ static switch_xml_t fetch_handler(const char *section, const char *tag_name, con ,fetch_handler->pid.creation ,fetch_handler->pid.num ,fetch_handler->pid.serial); - sent = 1; } + fetch_handler = fetch_handler->next; } - if(!sent) { - ei_x_free(&send_msg->buf); - switch_safe_free(send_msg); - } - - if(params == NULL) - switch_event_destroy(&event); - /* wait for a reply (if there isnt already one...amazingly improbable but lets not take shortcuts */ switch_mutex_lock(agent->replies_mutex); @@ -304,42 +292,6 @@ static switch_xml_t fetch_handler(const char *section, const char *tag_name, con return xml; } -void bind_fetch_profile(ei_xml_agent_t *agent, kazoo_config_ptr fetch_handlers) -{ - switch_hash_index_t *hi; - kazoo_fetch_profile_ptr val = NULL, ptr = NULL; - - for (hi = switch_core_hash_first(fetch_handlers->hash); hi; hi = switch_core_hash_next(&hi)) { - switch_core_hash_this(hi, NULL, NULL, (void**) &val); - if (val && val->section == agent->section) { - ptr = val; - break; - } - } - agent->profile = ptr; -} - -void rebind_fetch_profiles(kazoo_config_ptr fetch_handlers) -{ - if(kazoo_globals.config_fetch_binding != NULL) - bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.config_fetch_binding), fetch_handlers); - - if(kazoo_globals.directory_fetch_binding != NULL) - bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.directory_fetch_binding), fetch_handlers); - - if(kazoo_globals.dialplan_fetch_binding != NULL) - bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.dialplan_fetch_binding), fetch_handlers); - - if(kazoo_globals.channels_fetch_binding != NULL) - bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.channels_fetch_binding), fetch_handlers); - - if(kazoo_globals.languages_fetch_binding != NULL) - bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.languages_fetch_binding), fetch_handlers); - - if(kazoo_globals.chatplan_fetch_binding != NULL) - bind_fetch_profile((ei_xml_agent_t *) switch_xml_get_binding_user_data(kazoo_globals.chatplan_fetch_binding), fetch_handlers); -} - static switch_status_t bind_fetch_agent(switch_xml_section_t section, switch_xml_binding_t **binding) { switch_memory_pool_t *pool = NULL; ei_xml_agent_t *agent; @@ -374,8 +326,6 @@ static switch_status_t bind_fetch_agent(switch_xml_section_t section, switch_xml switch_thread_cond_create(&agent->new_reply, pool); agent->replies = NULL; - bind_fetch_profile(agent, kazoo_globals.fetch_handlers); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Bound to %s XML requests\n" ,xml_section_to_string(section)); @@ -386,9 +336,6 @@ static switch_status_t unbind_fetch_agent(switch_xml_binding_t **binding) { ei_xml_agent_t *agent; ei_xml_client_t *client; - if(*binding == NULL) - return SWITCH_STATUS_GENERR; - /* get a pointer to our user_data */ agent = (ei_xml_agent_t *)switch_xml_get_binding_user_data(*binding); @@ -452,9 +399,6 @@ static switch_status_t remove_xml_client(ei_node_t *ei_node, switch_xml_binding_ ei_xml_client_t *client, *prev = NULL; int found = 0; - if(binding == NULL) - return SWITCH_STATUS_GENERR; - agent = (ei_xml_agent_t *)switch_xml_get_binding_user_data(binding); /* write-lock the agent */ @@ -631,9 +575,8 @@ switch_status_t bind_fetch_agents() { bind_fetch_agent(SWITCH_XML_SECTION_CONFIG, &kazoo_globals.config_fetch_binding); bind_fetch_agent(SWITCH_XML_SECTION_DIRECTORY, &kazoo_globals.directory_fetch_binding); bind_fetch_agent(SWITCH_XML_SECTION_DIALPLAN, &kazoo_globals.dialplan_fetch_binding); - bind_fetch_agent(SWITCH_XML_SECTION_CHANNELS, &kazoo_globals.channels_fetch_binding); - bind_fetch_agent(SWITCH_XML_SECTION_LANGUAGES, &kazoo_globals.languages_fetch_binding); bind_fetch_agent(SWITCH_XML_SECTION_CHATPLAN, &kazoo_globals.chatplan_fetch_binding); + bind_fetch_agent(SWITCH_XML_SECTION_CHANNELS, &kazoo_globals.channels_fetch_binding); return SWITCH_STATUS_SUCCESS; } @@ -642,9 +585,8 @@ switch_status_t unbind_fetch_agents() { unbind_fetch_agent(&kazoo_globals.config_fetch_binding); unbind_fetch_agent(&kazoo_globals.directory_fetch_binding); unbind_fetch_agent(&kazoo_globals.dialplan_fetch_binding); - unbind_fetch_agent(&kazoo_globals.channels_fetch_binding); - unbind_fetch_agent(&kazoo_globals.languages_fetch_binding); unbind_fetch_agent(&kazoo_globals.chatplan_fetch_binding); + unbind_fetch_agent(&kazoo_globals.channels_fetch_binding); return SWITCH_STATUS_SUCCESS; } @@ -653,9 +595,8 @@ switch_status_t remove_xml_clients(ei_node_t *ei_node) { remove_xml_client(ei_node, kazoo_globals.config_fetch_binding); remove_xml_client(ei_node, kazoo_globals.directory_fetch_binding); remove_xml_client(ei_node, kazoo_globals.dialplan_fetch_binding); - remove_xml_client(ei_node, kazoo_globals.channels_fetch_binding); - remove_xml_client(ei_node, kazoo_globals.languages_fetch_binding); remove_xml_client(ei_node, kazoo_globals.chatplan_fetch_binding); + remove_xml_client(ei_node, kazoo_globals.channels_fetch_binding); return SWITCH_STATUS_SUCCESS; } @@ -665,9 +606,6 @@ switch_status_t add_fetch_handler(ei_node_t *ei_node, erlang_pid *from, switch_x ei_xml_client_t *client; fetch_handler_t *fetch_handler; - if(binding == NULL) - return SWITCH_STATUS_GENERR; - agent = (ei_xml_agent_t *)switch_xml_get_binding_user_data(binding); /* write-lock the agent */ @@ -715,9 +653,8 @@ switch_status_t remove_fetch_handlers(ei_node_t *ei_node, erlang_pid *from) { remove_fetch_handler(ei_node, from, kazoo_globals.config_fetch_binding); remove_fetch_handler(ei_node, from, kazoo_globals.directory_fetch_binding); remove_fetch_handler(ei_node, from, kazoo_globals.dialplan_fetch_binding); - remove_fetch_handler(ei_node, from, kazoo_globals.channels_fetch_binding); - remove_fetch_handler(ei_node, from, kazoo_globals.languages_fetch_binding); remove_fetch_handler(ei_node, from, kazoo_globals.chatplan_fetch_binding); + remove_fetch_handler(ei_node, from, kazoo_globals.channels_fetch_binding); return SWITCH_STATUS_SUCCESS; } @@ -752,9 +689,8 @@ switch_status_t handle_api_command_streams(ei_node_t *ei_node, switch_stream_han handle_api_command_stream(ei_node, stream, kazoo_globals.config_fetch_binding); handle_api_command_stream(ei_node, stream, kazoo_globals.directory_fetch_binding); handle_api_command_stream(ei_node, stream, kazoo_globals.dialplan_fetch_binding); - handle_api_command_stream(ei_node, stream, kazoo_globals.channels_fetch_binding); - handle_api_command_stream(ei_node, stream, kazoo_globals.languages_fetch_binding); handle_api_command_stream(ei_node, stream, kazoo_globals.chatplan_fetch_binding); + handle_api_command_stream(ei_node, stream, kazoo_globals.channels_fetch_binding); return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_fields.h b/src/mod/event_handlers/mod_kazoo/kazoo_fields.h deleted file mode 100644 index 95aab4e917..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_fields.h +++ /dev/null @@ -1,195 +0,0 @@ -/* -* 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. -* -* Based on mod_skel by -* Anthony Minessale II -* -* Contributor(s): -* -* Daniel Bryars -* Tim Brown -* Anthony Minessale II -* William King -* Mike Jerris -* -* kazoo.c -- Sends FreeSWITCH events to an AMQP broker -* -*/ - -#ifndef KAZOO_FIELDS_H -#define KAZOO_FIELDS_H - -#include - -#define MAX_LIST_FIELDS 25 - -typedef struct kazoo_log_levels kazoo_loglevels_t; -typedef kazoo_loglevels_t *kazoo_loglevels_ptr; - -struct kazoo_log_levels -{ - switch_log_level_t success_log_level; - switch_log_level_t failed_log_level; - switch_log_level_t warn_log_level; - switch_log_level_t info_log_level; - switch_log_level_t time_log_level; - switch_log_level_t filtered_event_log_level; - switch_log_level_t filtered_field_log_level; - -}; - -typedef struct kazoo_logging kazoo_logging_t; -typedef kazoo_logging_t *kazoo_logging_ptr; - -struct kazoo_logging -{ - kazoo_loglevels_ptr levels; - const char *profile_name; - const char *event_name; -}; - -typedef struct kazoo_list_s { - char *value[MAX_LIST_FIELDS]; - int size; -} kazoo_list_t; - -typedef enum { - FILTER_COMPARE_REGEX, - FILTER_COMPARE_LIST, - FILTER_COMPARE_VALUE, - FILTER_COMPARE_PREFIX, - FILTER_COMPARE_EXISTS -} kazoo_filter_compare_type; - -typedef enum { - FILTER_EXCLUDE, - FILTER_INCLUDE, - FILTER_ENSURE -} kazoo_filter_type; - -typedef struct kazoo_filter_t { - kazoo_filter_type type; - kazoo_filter_compare_type compare; - char* name; - char* value; - kazoo_list_t list; - struct kazoo_filter_t* next; -} kazoo_filter, *kazoo_filter_ptr; - - -typedef enum { - JSON_NONE, - JSON_STRING, - JSON_NUMBER, - JSON_BOOLEAN, - JSON_OBJECT, - JSON_RAW -} kazoo_json_field_type; - -typedef enum { - FIELD_NONE, - FIELD_COPY, - FIELD_STATIC, - FIELD_FIRST_OF, - FIELD_EXPAND, - FIELD_PREFIX, - FIELD_OBJECT, - FIELD_GROUP, - FIELD_REFERENCE, - -} kazoo_field_type; - -typedef struct kazoo_field_t kazoo_field; -typedef kazoo_field *kazoo_field_ptr; - -typedef struct kazoo_fields_t kazoo_fields; -typedef kazoo_fields *kazoo_fields_ptr; - -typedef struct kazoo_definition_t kazoo_definition; -typedef kazoo_definition *kazoo_definition_ptr; - -struct kazoo_field_t { - char* name; - char* value; - char* as; - kazoo_list_t list; - switch_bool_t exclude_prefix; - kazoo_field_type in_type; - kazoo_json_field_type out_type; - kazoo_filter_ptr filter; - - kazoo_definition_ptr ref; - kazoo_field_ptr next; - kazoo_fields_ptr children; -}; - -struct kazoo_fields_t { - kazoo_field_ptr head; - int verbose; -}; - - -struct kazoo_definition_t { - char* name; - kazoo_field_ptr head; - kazoo_filter_ptr filter; -}; - -struct kazoo_event { - kazoo_event_profile_ptr profile; - char *name; - kazoo_fields_ptr fields; - kazoo_filter_ptr filter; - - kazoo_event_t* next; -}; - -struct kazoo_event_profile { - char *name; - kazoo_config_ptr root; - switch_bool_t running; - switch_memory_pool_t *pool; - kazoo_filter_ptr filter; - kazoo_fields_ptr fields; - kazoo_event_ptr events; - - kazoo_loglevels_ptr logging; -}; - -struct kazoo_fetch_profile { - char *name; - kazoo_config_ptr root; - switch_bool_t running; - switch_memory_pool_t *pool; - kazoo_fields_ptr fields; - int fetch_timeout; - switch_mutex_t *fetch_reply_mutex; - switch_hash_t *fetch_reply_hash; - switch_xml_binding_t *fetch_binding; - switch_xml_section_t section; - - kazoo_loglevels_ptr logging; -}; - -#endif /* KAZOO_FIELDS_H */ - diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_message.c b/src/mod/event_handlers/mod_kazoo/kazoo_message.c deleted file mode 100644 index c95a254062..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_message.c +++ /dev/null @@ -1,458 +0,0 @@ -/* -* 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. -* -* Based on mod_skel by -* Anthony Minessale II -* -* Contributor(s): -* -* Daniel Bryars -* Tim Brown -* Anthony Minessale II -* William King -* Mike Jerris -* -* kazoo.c -- Sends FreeSWITCH events to an AMQP broker -* -*/ - -#include "mod_kazoo.h" - -/* deletes then add */ -void kazoo_cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) -{ - cJSON_DeleteItemFromObject(object, string); - cJSON_AddItemToObject(object, string, item); -} - -static int inline filter_compare(switch_event_t* evt, kazoo_filter_ptr filter) -{ - switch_event_header_t *header; - int hasValue = 0, /*size, */n; - char *value; - - switch(filter->compare) { - - case FILTER_COMPARE_EXISTS: - hasValue = switch_event_get_header(evt, filter->name) != NULL ? 1 : 0; - break; - - case FILTER_COMPARE_VALUE: - value = switch_event_get_header_nil(evt, filter->name); - hasValue = !strcmp(value, filter->value); - break; - - case FILTER_COMPARE_PREFIX: - for (header = evt->headers; header; header = header->next) { - if(!strncmp(header->name, filter->value, strlen(filter->value))) { - hasValue = 1; - break; - } - } - break; - - case FILTER_COMPARE_LIST: - value = switch_event_get_header(evt, filter->name); - if(value) { - for(n = 0; n < filter->list.size; n++) { - if(!strncmp(value, filter->list.value[n], strlen(filter->list.value[n]))) { - hasValue = 1; - break; - } - } - } - break; - - case FILTER_COMPARE_REGEX: - break; - - default: - break; - } - - return hasValue; -} - -static kazoo_filter_ptr inline filter_event(switch_event_t* evt, kazoo_filter_ptr filter) -{ - while(filter) { - int hasValue = filter_compare(evt, filter); - if(filter->type == FILTER_EXCLUDE) { - if(hasValue) - break; - } else if(filter->type == FILTER_INCLUDE) { - if(!hasValue) - break; - } - filter = filter->next; - } - return filter; -} - -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; - - 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)); - } - } -} - -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; - if( (fields2 && fields2->verbose) - || (fields1 && fields1->verbose) - || ( (!fields2) && (!fields1)) ) { - status = switch_event_serialize_json_obj(evt, clone); - } else { - status = SWITCH_STATUS_SUCCESS; - *clone = cJSON_CreateObject(); - if((*clone) == NULL) { - status = SWITCH_STATUS_GENERR; - } - } - return status; -} - -static cJSON * kazoo_event_json_value(kazoo_json_field_type type, const char *value) { - cJSON *item = NULL; - switch(type) { - case JSON_STRING: - item = cJSON_CreateString(value); - break; - - case JSON_NUMBER: - item = cJSON_CreateNumber(strtod(value, NULL)); - break; - - case JSON_BOOLEAN: - item = cJSON_CreateBool(switch_true(value)); - break; - - case JSON_OBJECT: - item = cJSON_CreateObject(); - break; - - case JSON_RAW: - item = cJSON_CreateRaw(value); - break; - - default: - break; - }; - - return item; -} - -static cJSON * kazoo_event_add_json_value(cJSON *dst, kazoo_field_ptr field, const char *as, const char *value) { - cJSON *item = NULL; - if(value || field->out_type == JSON_OBJECT) { - if((item = kazoo_event_json_value(field->out_type, value)) != NULL) { - kazoo_cJSON_AddItemToObject(dst, as, item); - } - } - return item; -} - -#define MAX_FIRST_OF 25 - -char * first_of(switch_event_t *src, char * in) -{ - switch_event_header_t *header; - char *y1, *y2, *y3 = NULL; - char *value[MAX_FIRST_OF]; - int n, size; - - y1 = strdup(in); - if((y2 = (char *) switch_stristr("first-of", y1)) != NULL) { - char tmp[2048] = ""; - y3 = switch_find_end_paren((const char *)y2 + 8, '(', ')'); - *++y3='\0'; - *y2 = '\0'; - size = switch_separate_string(y2 + 9, '|', value, MAX_FIRST_OF); - for(n=0; n < size; n++) { - header = switch_event_get_header_ptr(src, value[n]); - if(header) { - switch_snprintf(tmp, sizeof(tmp), "%s%s%s", y1, header->name, y3); - free(y1); - y2 = strdup(tmp); - y3 = first_of(src, y2); - if(y2 == y3) { - return y2; - } else { - return y3; - } - } - } - } - free(y1); - return in; - -} - -cJSON * kazoo_event_add_field_to_json(cJSON *dst, switch_event_t *src, kazoo_field_ptr field) -{ - switch_event_header_t *header; - char *expanded, *firstOf; - uint i, n; - cJSON *item = NULL; - - switch(field->in_type) { - case FIELD_COPY: - 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 { - item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, header->value); - } - } - break; - - case FIELD_EXPAND: - firstOf = first_of(src, field->value); - expanded = switch_event_expand_headers(src, firstOf); - if(expanded != NULL && !zstr(expanded)) { - item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, expanded); - } - if(expanded != firstOf) { - free(expanded); - } - if(firstOf != field->value) { - free(firstOf); - } - break; - - case FIELD_FIRST_OF: - for(n = 0; n < field->list.size; n++) { - if(*field->list.value[n] == '#') { - item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, ++field->list.value[n]); - break; - } else { - header = switch_event_get_header_ptr(src, field->list.value[n]); - if(header) { - 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 { - item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, header->value); - } - break; - } - } - } - break; - - case FIELD_PREFIX: - for (header = src->headers; header; header = header->next) { - if(!strncmp(header->name, field->name, strlen(field->name))) { - if (header->idx) { - cJSON *array = cJSON_CreateArray(); - for(i = 0; i < header->idx; i++) { - cJSON_AddItemToArray(array, kazoo_event_json_value(field->out_type, header->array[i])); - } - kazoo_cJSON_AddItemToObject(dst, field->exclude_prefix ? header->name+strlen(field->name) : header->name, array); - } else { - kazoo_event_add_json_value(dst, field, field->exclude_prefix ? header->name+strlen(field->name) : header->name, header->value); - } - } - } - break; - - case FIELD_STATIC: - item = kazoo_event_add_json_value(dst, field, field->name, field->value); - break; - - case FIELD_GROUP: - item = dst; - break; - - default: - break; - } - - return item; -} - -static switch_status_t kazoo_event_add_fields_to_json(kazoo_logging_ptr logging, cJSON *dst, switch_event_t *src, kazoo_field_ptr field) { - - kazoo_filter_ptr filter; - cJSON *item = NULL; - while(field) { - if(field->in_type == FIELD_REFERENCE) { - if(field->ref) { - if((filter = filter_event(src, field->ref->filter)) != 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); - } - } else { - 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) { - 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); - if(field->children && item != NULL) { - if(field->children->verbose && field->out_type == JSON_OBJECT) { - kazoo_event_init_json_fields(src, item); - } - kazoo_event_add_fields_to_json(logging, field->out_type == JSON_OBJECT ? item : dst, src, field->children->head); - } - } - } - - field = field->next; - } - - return SWITCH_STATUS_SUCCESS; -} - - -kazoo_message_ptr kazoo_message_create_event(switch_event_t* evt, kazoo_event_ptr event, kazoo_event_profile_ptr profile) -{ - kazoo_message_ptr message; - cJSON *JObj = NULL; - kazoo_filter_ptr filtered; - kazoo_logging_t logging; - - logging.levels = profile->logging; - logging.event_name = switch_event_get_header_nil(evt, "Event-Name"); - logging.profile_name = profile->name; - - switch_event_add_header(evt, SWITCH_STACK_BOTTOM, "Switch-Nodename", "%s@%s", "freeswitch", switch_event_get_header(evt, "FreeSWITCH-Hostname")); - - - 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"); - return NULL; - } - memset(message, 0, sizeof(kazoo_message_t)); - - if(profile->filter) { - // filtering - if((filtered = filter_event(evt, profile->filter)) != 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) { - 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; - } - } - - kazoo_event_init_json(profile->fields, event ? event->fields : NULL, evt, &JObj); - - if(profile->fields) - kazoo_event_add_fields_to_json(&logging, JObj, evt, profile->fields->head); - - if(event && event->fields) - kazoo_event_add_fields_to_json(&logging, JObj, evt, event->fields->head); - - message->JObj = JObj; - - - return message; - - -} - -kazoo_message_ptr kazoo_message_create_fetch(switch_event_t* evt, kazoo_fetch_profile_ptr profile) -{ - kazoo_message_ptr message; - cJSON *JObj = NULL; - kazoo_logging_t logging; - - logging.levels = profile->logging; - logging.event_name = switch_event_get_header_nil(evt, "Event-Name"); - logging.profile_name = profile->name; - - switch_event_add_header(evt, SWITCH_STACK_BOTTOM, "Switch-Nodename", "%s@%s", "freeswitch", switch_event_get_header(evt, "FreeSWITCH-Hostname")); - - 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"); - return NULL; - } - memset(message, 0, sizeof(kazoo_message_t)); - - - kazoo_event_init_json(profile->fields, NULL, evt, &JObj); - - if(profile->fields) - kazoo_event_add_fields_to_json(&logging, JObj, evt, profile->fields->head); - - message->JObj = JObj; - - - return message; - - -} - - -void kazoo_message_destroy(kazoo_message_ptr *msg) -{ - if (!msg || !*msg) return; - if((*msg)->JObj != NULL) - cJSON_Delete((*msg)->JObj); - switch_safe_free(*msg); - -} - - -/* 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_message.h b/src/mod/event_handlers/mod_kazoo/kazoo_message.h deleted file mode 100644 index 0674c71f0b..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_message.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -* 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. -* -* Based on mod_skel by -* Anthony Minessale II -* -* Contributor(s): -* -* Daniel Bryars -* Tim Brown -* Anthony Minessale II -* William King -* Mike Jerris -* -* kazoo.c -- Sends FreeSWITCH events to an AMQP broker -* -*/ - -#ifndef KAZOO_MESSAGE_H -#define KAZOO_MESSAGE_H - -#include - -typedef struct { - uint64_t timestamp; - uint64_t start; - uint64_t filter; - uint64_t serialize; - uint64_t print; - uint64_t rk; -} kazoo_message_times_t, *kazoo_message_times_ptr; - -typedef struct { - cJSON *JObj; -} kazoo_message_t, *kazoo_message_ptr; - - -kazoo_message_ptr kazoo_message_create_event(switch_event_t* evt, kazoo_event_ptr event, kazoo_event_profile_ptr profile); -kazoo_message_ptr kazoo_message_create_fetch(switch_event_t* evt, kazoo_fetch_profile_ptr profile); - -void kazoo_message_destroy(kazoo_message_ptr *msg); - - -#endif /* KAZOO_MESSAGE_H */ - diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_node.c b/src/mod/event_handlers/mod_kazoo/kazoo_node.c index 3ec739e74b..17da6dc582 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_node.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_node.c @@ -53,8 +53,6 @@ static char *REQUEST_ATOMS[] = { "nixevent", "sendevent", "sendmsg", - "commands", - "command", "bind", "getpid", "version", @@ -64,8 +62,7 @@ static char *REQUEST_ATOMS[] = { "fetch_reply", "config", "bgapi4", - "api4", - "no_legacy" + "api4" }; typedef enum { @@ -75,8 +72,6 @@ typedef enum { REQUEST_NIXEVENT, REQUEST_SENDEVENT, REQUEST_SENDMSG, - REQUEST_COMMANDS, - REQUEST_COMMAND, REQUEST_BIND, REQUEST_GETPID, REQUEST_VERSION, @@ -87,13 +82,11 @@ typedef enum { REQUEST_CONFIG, REQUEST_BGAPI4, REQUEST_API4, - REQUEST_NO_LEGACY, REQUEST_MAX } request_atoms_t; static switch_status_t find_request(char *atom, int *request) { - int i; - for (i = 0; i < REQUEST_MAX; i++) { + for (int i = 0; i < REQUEST_MAX; i++) { if(!strncmp(atom, REQUEST_ATOMS[i], MAXATOMLEN)) { *request = i; return SWITCH_STATUS_SUCCESS; @@ -274,7 +267,7 @@ static switch_status_t api_exec_stream(char *cmd, char *arg, switch_stream_handl } } else if (!stream->data || !strlen(stream->data)) { *reply = switch_mprintf("%s: Command returned no output", cmd); - status = SWITCH_STATUS_SUCCESS; + status = SWITCH_STATUS_FALSE; } else { *reply = strdup(stream->data); status = SWITCH_STATUS_SUCCESS; @@ -419,10 +412,11 @@ static void log_sendmsg_request(char *uuid, switch_event_t *event) switch_ssize_t hlen = -1; unsigned long CMD_EXECUTE = switch_hashfunc_default("execute", &hlen); unsigned long CMD_XFEREXT = switch_hashfunc_default("xferext", &hlen); + // unsigned long CMD_HANGUP = switch_hashfunc_default("hangup", &hlen); + // unsigned long CMD_NOMEDIA = switch_hashfunc_default("nomedia", &hlen); + // unsigned long CMD_UNICAST = switch_hashfunc_default("unicast", &hlen); if (zstr(cmd)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "log|%s|invalid \n", uuid); - DUMP_EVENT(event); return; } @@ -459,7 +453,6 @@ static void log_sendmsg_request(char *uuid, switch_event_t *event) static switch_status_t build_event(switch_event_t *event, ei_x_buff * buf) { int propslist_length, arity; - int n=0; if(!event) { return SWITCH_STATUS_FALSE; @@ -469,7 +462,7 @@ static switch_status_t build_event(switch_event_t *event, ei_x_buff * buf) { return SWITCH_STATUS_FALSE; } - while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && n < propslist_length) { + while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity)) { char key[1024]; char *value; @@ -489,21 +482,9 @@ static switch_status_t build_event(switch_event_t *event, ei_x_buff * buf) { switch_safe_free(event->body); event->body = value; } else { - if(!strcasecmp(key, "Call-ID")) { - switch_core_session_t *session = NULL; - if(!zstr(value)) { - if ((session = switch_core_session_force_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); - } - } - } switch_event_add_header_string(event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, key, value); } - n++; } - ei_skip_term(buf->buff, &buf->index); return SWITCH_STATUS_SUCCESS; } @@ -544,16 +525,6 @@ static switch_status_t erlang_response_ok(ei_x_buff *rbuf) { return SWITCH_STATUS_SUCCESS; } -static switch_status_t erlang_response_ok_uuid(ei_x_buff *rbuf, const char * uuid) { - if (rbuf) { - ei_x_encode_tuple_header(rbuf, 2); - ei_x_encode_atom(rbuf, "ok"); - ei_x_encode_binary(rbuf, uuid, strlen(uuid)); - } - - return SWITCH_STATUS_SUCCESS; -} - static switch_status_t handle_request_noevents(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { ei_event_stream_t *event_stream; @@ -583,7 +554,6 @@ static switch_status_t handle_request_nixevent(ei_node_t *ei_node, erlang_pid *p switch_event_types_t event_type; ei_event_stream_t *event_stream; int custom = 0, length = 0; - int i; if (ei_decode_list_header(buf->buff, &buf->index, &length) || length == 0) { @@ -596,7 +566,7 @@ static switch_status_t handle_request_nixevent(ei_node_t *ei_node, erlang_pid *p return erlang_response_ok(rbuf); } - for (i = 1; i <= length; i++) { + for (int i = 1; i <= length; i++) { if (ei_decode_atom_safe(buf->buff, &buf->index, event_name)) { switch_mutex_unlock(ei_node->event_streams_mutex); return erlang_response_badarg(rbuf); @@ -606,22 +576,16 @@ static switch_status_t handle_request_nixevent(ei_node_t *ei_node, erlang_pid *p remove_event_binding(event_stream, SWITCH_EVENT_CUSTOM, event_name); } else if (switch_name_event(event_name, &event_type) == SWITCH_STATUS_SUCCESS) { switch (event_type) { - case SWITCH_EVENT_CUSTOM: custom++; break; - case SWITCH_EVENT_ALL: - { - switch_event_types_t type; - for (type = 0; type < SWITCH_EVENT_ALL; type++) { + for (switch_event_types_t type = 0; type < SWITCH_EVENT_ALL; type++) { if(type != SWITCH_EVENT_CUSTOM) { remove_event_binding(event_stream, type, NULL); } } break; - } - default: remove_event_binding(event_stream, event_type, NULL); } @@ -668,82 +632,6 @@ static switch_status_t handle_request_sendevent(ei_node_t *ei_node, erlang_pid * return erlang_response_badarg(rbuf); } -static switch_status_t handle_request_command(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { - switch_core_session_t *session; - switch_event_t *event = NULL; - char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; - switch_uuid_t cmd_uuid; - char cmd_uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; - - if (ei_decode_string_or_binary_limited(buf->buff, &buf->index, sizeof(uuid_str), uuid_str)) { - return erlang_response_badarg(rbuf); - } - - switch_uuid_get(&cmd_uuid); - switch_uuid_format(cmd_uuid_str, &cmd_uuid); - - switch_event_create(&event, SWITCH_EVENT_COMMAND); - if (build_event(event, buf) != SWITCH_STATUS_SUCCESS) { - return erlang_response_badarg(rbuf); - } - - log_sendmsg_request(uuid_str, event); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event-uuid", cmd_uuid_str); - - if (zstr_buf(uuid_str) || !(session = switch_core_session_locate(uuid_str))) { - return erlang_response_baduuid(rbuf); - } - switch_core_session_queue_private_event(session, &event, SWITCH_FALSE); - switch_core_session_rwunlock(session); - - return erlang_response_ok_uuid(rbuf, cmd_uuid_str); -} - -static switch_status_t handle_request_commands(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { - switch_core_session_t *session; - char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; - int propslist_length, n; - switch_uuid_t cmd_uuid; - char cmd_uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; - - if (ei_decode_string_or_binary_limited(buf->buff, &buf->index, sizeof(uuid_str), uuid_str)) { - return erlang_response_badarg(rbuf); - } - - if (zstr_buf(uuid_str) || !(session = switch_core_session_locate(uuid_str))) { - return erlang_response_baduuid(rbuf); - } - - switch_uuid_get(&cmd_uuid); - switch_uuid_format(cmd_uuid_str, &cmd_uuid); - - if (ei_decode_list_header(buf->buff, &buf->index, &propslist_length)) { - switch_core_session_rwunlock(session); - return SWITCH_STATUS_FALSE; - } - - for(n = 0; n < propslist_length; n++) { - switch_event_t *event = NULL; - switch_event_create(&event, SWITCH_EVENT_COMMAND); - if (build_event(event, buf) != SWITCH_STATUS_SUCCESS) { - switch_core_session_rwunlock(session); - return erlang_response_badarg(rbuf); - } - log_sendmsg_request(uuid_str, event); - if(n == (propslist_length - 1)) { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event-uuid", cmd_uuid_str); - } else { - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event-uuid", "null"); - } - switch_core_session_queue_private_event(session, &event, SWITCH_FALSE); - } - - switch_core_session_rwunlock(session); - - return erlang_response_ok_uuid(rbuf, cmd_uuid_str); - -} - static switch_status_t handle_request_sendmsg(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { switch_core_session_t *session; switch_event_t *event = NULL; @@ -771,8 +659,8 @@ static switch_status_t handle_request_sendmsg(ei_node_t *ei_node, erlang_pid *pi static switch_status_t handle_request_config(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { - fetch_config(); - return erlang_response_ok(rbuf); + fetch_config_filters(); + return erlang_response_ok(rbuf); } static switch_status_t handle_request_bind(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { @@ -787,8 +675,8 @@ static switch_status_t handle_request_bind(ei_node_t *ei_node, erlang_pid *pid, switch(section) { case SWITCH_XML_SECTION_CONFIG: add_fetch_handler(ei_node, pid, kazoo_globals.config_fetch_binding); - if(!kazoo_globals.config_fetched) - fetch_config(); + if(!kazoo_globals.config_filters_fetched) + fetch_config_filters(); break; case SWITCH_XML_SECTION_DIRECTORY: add_fetch_handler(ei_node, pid, kazoo_globals.directory_fetch_binding); @@ -796,15 +684,12 @@ static switch_status_t handle_request_bind(ei_node_t *ei_node, erlang_pid *pid, case SWITCH_XML_SECTION_DIALPLAN: add_fetch_handler(ei_node, pid, kazoo_globals.dialplan_fetch_binding); break; - case SWITCH_XML_SECTION_CHANNELS: - add_fetch_handler(ei_node, pid, kazoo_globals.channels_fetch_binding); - break; - case SWITCH_XML_SECTION_LANGUAGES: - add_fetch_handler(ei_node, pid, kazoo_globals.languages_fetch_binding); - break; case SWITCH_XML_SECTION_CHATPLAN: add_fetch_handler(ei_node, pid, kazoo_globals.chatplan_fetch_binding); break; + case SWITCH_XML_SECTION_CHANNELS: + add_fetch_handler(ei_node, pid, kazoo_globals.channels_fetch_binding); + break; default: return erlang_response_badarg(rbuf); } @@ -971,19 +856,11 @@ static switch_status_t handle_request_api(ei_node_t *ei_node, erlang_pid *pid, e return SWITCH_STATUS_SUCCESS; } -static switch_status_t handle_request_no_legacy(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) -{ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "nolegacy: %s\n", ei_node->peer_nodename); - ei_node->legacy = SWITCH_FALSE; - - return erlang_response_ok(rbuf); -} - static switch_status_t handle_request_event(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { char event_name[MAXATOMLEN + 1]; + switch_event_types_t event_type; ei_event_stream_t *event_stream; - int length = 0; - int i; + int custom = 0, length = 0; if (ei_decode_list_header(buf->buff, &buf->index, &length) || !length) { return erlang_response_badarg(rbuf); @@ -991,18 +868,38 @@ static switch_status_t handle_request_event(ei_node_t *ei_node, erlang_pid *pid, switch_mutex_lock(ei_node->event_streams_mutex); if (!(event_stream = find_event_stream(ei_node->event_streams, pid))) { - event_stream = new_event_stream(ei_node, pid); + event_stream = new_event_stream(&ei_node->event_streams, pid); /* ensure we are notified if the requesting processes dies so we can clean up */ ei_link(ei_node, ei_self(&kazoo_globals.ei_cnode), pid); } - for (i = 1; i <= length; i++) { - + for (int i = 1; i <= length; i++) { if (ei_decode_atom_safe(buf->buff, &buf->index, event_name)) { switch_mutex_unlock(ei_node->event_streams_mutex); return erlang_response_badarg(rbuf); } - add_event_binding(event_stream, event_name); + + if (custom) { + add_event_binding(event_stream, SWITCH_EVENT_CUSTOM, event_name); + } else if (switch_name_event(event_name, &event_type) == SWITCH_STATUS_SUCCESS) { + switch (event_type) { + case SWITCH_EVENT_CUSTOM: + custom++; + break; + case SWITCH_EVENT_ALL: + for (switch_event_types_t type = 0; type < SWITCH_EVENT_ALL; type++) { + if(type != SWITCH_EVENT_CUSTOM) { + add_event_binding(event_stream, type, NULL); + } + } + break; + default: + add_event_binding(event_stream, event_type, NULL); + } + } else { + switch_mutex_unlock(ei_node->event_streams_mutex); + return erlang_response_badarg(rbuf); + } } switch_mutex_unlock(ei_node->event_streams_mutex); @@ -1058,24 +955,21 @@ static switch_status_t handle_request_fetch_reply(ei_node_t *ei_node, erlang_pid case SWITCH_XML_SECTION_DIALPLAN: result = fetch_reply(uuid_str, xml_str, kazoo_globals.dialplan_fetch_binding); break; - case SWITCH_XML_SECTION_CHANNELS: - result = fetch_reply(uuid_str, xml_str, kazoo_globals.channels_fetch_binding); - break; - case SWITCH_XML_SECTION_LANGUAGES: - result = fetch_reply(uuid_str, xml_str, kazoo_globals.languages_fetch_binding); - break; case SWITCH_XML_SECTION_CHATPLAN: result = fetch_reply(uuid_str, xml_str, kazoo_globals.chatplan_fetch_binding); break; + case SWITCH_XML_SECTION_CHANNELS: + result = fetch_reply(uuid_str, xml_str, kazoo_globals.channels_fetch_binding); + break; default: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received fetch reply for an unknown configuration section: %s\n", section_str); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Recieved fetch reply for an unknown configuration section: %s\n", section_str); return erlang_response_badarg(rbuf); } if (result == SWITCH_STATUS_SUCCESS) { return erlang_response_ok(rbuf); } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received fetch reply for an unknown/expired UUID: %s\n", uuid_str); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Recieved fetch reply for an unknown/expired UUID: %s\n", uuid_str); return erlang_response_baduuid(rbuf); } } @@ -1116,10 +1010,6 @@ static switch_status_t handle_kazoo_request(ei_node_t *ei_node, erlang_pid *pid, return handle_request_sendevent(ei_node, pid, buf, rbuf); case REQUEST_SENDMSG: return handle_request_sendmsg(ei_node, pid, buf, rbuf); - case REQUEST_COMMAND: - return handle_request_command(ei_node, pid, buf, rbuf); - case REQUEST_COMMANDS: - return handle_request_commands(ei_node, pid, buf, rbuf); case REQUEST_BIND: return handle_request_bind(ei_node, pid, buf, rbuf); case REQUEST_GETPID: @@ -1134,14 +1024,12 @@ static switch_status_t handle_kazoo_request(ei_node_t *ei_node, erlang_pid *pid, return handle_request_event(ei_node, pid, buf, rbuf); case REQUEST_FETCH_REPLY: return handle_request_fetch_reply(ei_node, pid, buf, rbuf); - case REQUEST_CONFIG: - return handle_request_config(ei_node, pid, buf, rbuf); - case REQUEST_BGAPI4: - return handle_request_bgapi4(ei_node, pid, buf, rbuf); + case REQUEST_CONFIG: + return handle_request_config(ei_node, pid, buf, rbuf); + case REQUEST_BGAPI4: + return handle_request_bgapi4(ei_node, pid, buf, rbuf); case REQUEST_API4: return handle_request_api4(ei_node, pid, buf, rbuf); - case REQUEST_NO_LEGACY: - return handle_request_no_legacy(ei_node, pid, buf, rbuf); default: return erlang_response_notimplemented(rbuf); } @@ -1326,7 +1214,7 @@ static switch_status_t handle_erl_send(ei_node_t *ei_node, erlang_msg *msg, ei_x } else if (!strncmp(msg->toname, "mod_kazoo", MAXATOMLEN)) { return handle_mod_kazoo_request(ei_node, msg, buf); } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received erlang message to unknown process \"%s\" (ensure you are using Kazoo v2.14+).\n", msg->toname); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Recieved erlang message to unknown process \"%s\" (ensure you are using Kazoo v2.14+).\n", msg->toname); return SWITCH_STATUS_GENERR; } } @@ -1374,7 +1262,7 @@ static void *SWITCH_THREAD_FUNC receive_handler(switch_thread_t *thread, void *o while (switch_test_flag(ei_node, LFLAG_RUNNING) && switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) { void *pop; - if (switch_queue_pop_timeout(ei_node->received_msgs, &pop, 100000) == SWITCH_STATUS_SUCCESS) { + if (switch_queue_pop_timeout(ei_node->received_msgs, &pop, 500000) == SWITCH_STATUS_SUCCESS) { ei_received_msg_t *received_msg = (ei_received_msg_t *) pop; handle_erl_msg(ei_node, &received_msg->msg, &received_msg->buf); ei_x_free(&received_msg->buf); @@ -1425,7 +1313,7 @@ static void *SWITCH_THREAD_FUNC handle_node(switch_thread_t *thread, void *obj) } while (++send_msg_count <= kazoo_globals.send_msg_batch - && switch_queue_pop_timeout(ei_node->send_msgs, &pop, 20000) == SWITCH_STATUS_SUCCESS) { + && switch_queue_trypop(ei_node->send_msgs, &pop) == SWITCH_STATUS_SUCCESS) { ei_send_msg_t *send_msg = (ei_send_msg_t *) pop; ei_helper_send(ei_node, &send_msg->pid, &send_msg->buf); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sent erlang message to %s <%d.%d.%d>\n" @@ -1543,7 +1431,6 @@ switch_status_t new_kazoo_node(int nodefd, ErlConnect *conn) { ei_node->nodefd = nodefd; ei_node->peer_nodename = switch_core_strdup(ei_node->pool, conn->nodename); ei_node->created_time = switch_micro_time_now(); - ei_node->legacy = kazoo_globals.enable_legacy; /* store the IP and node name we are talking with */ switch_os_sock_put(&ei_node->socket, (switch_os_socket_t *)&nodefd, pool); diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_tweaks.c b/src/mod/event_handlers/mod_kazoo/kazoo_tweaks.c deleted file mode 100644 index 2aefb5ab98..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_tweaks.c +++ /dev/null @@ -1,502 +0,0 @@ -/* - * 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" - -static const char *bridge_variables[] = { - "Call-Control-Queue", - "Call-Control-PID", - "ecallmgr_Call-Interaction-ID", - "ecallmgr_Ecallmgr-Node", - NULL -}; - -static switch_status_t kz_tweaks_signal_bridge_on_hangup(switch_core_session_t *session) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_event_t *my_event; - - const char *peer_uuid = switch_channel_get_variable(channel, "Bridge-B-Unique-ID"); - - if (switch_event_create(&my_event, SWITCH_EVENT_CHANNEL_UNBRIDGE) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(my_event, SWITCH_STACK_BOTTOM, "Bridge-A-Unique-ID", switch_core_session_get_uuid(session)); - switch_event_add_header_string(my_event, SWITCH_STACK_BOTTOM, "Bridge-B-Unique-ID", peer_uuid); - switch_channel_event_set_data(channel, my_event); - switch_event_fire(&my_event); - } - - return SWITCH_STATUS_SUCCESS; -} - -static const switch_state_handler_table_t kz_tweaks_signal_bridge_state_handlers = { - /*.on_init */ NULL, - /*.on_routing */ NULL, - /*.on_execute */ NULL, - /*.on_hangup */ kz_tweaks_signal_bridge_on_hangup, - /*.on_exchange_media */ NULL, - /*.on_soft_execute */ NULL, - /*.on_consume_media */ NULL, - /*.on_hibernate */ NULL -}; - -static void kz_tweaks_handle_bridge_variables(switch_event_t *event) -{ - switch_core_session_t *a_session = NULL, *b_session = NULL; - const char *a_leg = switch_event_get_header(event, "Bridge-A-Unique-ID"); - const char *b_leg = switch_event_get_header(event, "Bridge-B-Unique-ID"); - int i; - - if (a_leg && (a_session = switch_core_session_force_locate(a_leg)) != NULL) { - switch_channel_t *a_channel = switch_core_session_get_channel(a_session); - 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) { - 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_TRUE, -1); - switch_channel_set_variable(a_channel, bridge_variables[i], val); - switch_safe_strdup(val); - } - switch_core_session_rwunlock(b_session); - } - } else { - if(b_leg && (b_session = switch_core_session_force_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++) { - const char *val = switch_channel_get_variable_dup(b_channel, bridge_variables[i], SWITCH_TRUE, -1); - switch_channel_set_variable(b_channel, bridge_variables[i], val); - switch_safe_strdup(val); - } - } - switch_core_session_rwunlock(b_session); - } - } - switch_core_session_rwunlock(a_session); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NOT FOUND : %s\n", a_leg); - } - -} - -static void kz_tweaks_handle_bridge_replaces(switch_event_t *event) -{ - switch_event_t *my_event; - - const char *replaced_call_id = switch_event_get_header(event, "variable_sip_replaces_call_id"); - const char *a_leg_call_id = switch_event_get_header(event, "variable_sip_replaces_a-leg"); - const char *peer_uuid = switch_event_get_header(event, "Unique-ID"); - int processed = 0; - - if(a_leg_call_id && replaced_call_id) { - const char *call_id = switch_event_get_header(event, "Bridge-B-Unique-ID"); - switch_core_session_t *session = NULL; - if ((session = switch_core_session_force_locate(peer_uuid)) != NULL) { - switch_channel_t *channel = switch_core_session_get_channel(session); - processed = switch_true(switch_channel_get_variable_dup(channel, "Bridge-Event-Processed", SWITCH_FALSE, -1)); - switch_channel_set_variable(channel, "Bridge-Event-Processed", "true"); - switch_core_session_rwunlock(session); - } - - if ((processed) && call_id && (session = switch_core_session_force_locate(call_id)) != NULL) { - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_channel_set_variable(channel, "Bridge-Event-Processed", "true"); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "creating channel_bridge event A - %s , B - %s\n", switch_core_session_get_uuid(session), peer_uuid); - 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(session)); - switch_event_add_header_string(my_event, SWITCH_STACK_BOTTOM, "Bridge-B-Unique-ID", peer_uuid); - switch_channel_event_set_data(channel, my_event); - switch_event_fire(&my_event); - } - switch_channel_set_variable(channel, "Bridge-B-Unique-ID", peer_uuid); - switch_channel_add_state_handler(channel, &kz_tweaks_signal_bridge_state_handlers); - switch_core_session_rwunlock(session); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NOT FOUND : %s\n", call_id); - } - - } - -} - -static void kz_tweaks_channel_bridge_event_handler(switch_event_t *event) -{ - kz_tweaks_handle_bridge_replaces(event); - kz_tweaks_handle_bridge_variables(event); -} - -// TRANSFERS - -static void kz_tweaks_channel_replaced_event_handler(switch_event_t *event) -{ - const char *uuid = switch_event_get_header(event, "Unique-ID"); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "REPLACED : %s\n", uuid); -} - -static void kz_tweaks_channel_intercepted_event_handler(switch_event_t *event) -{ - const char *uuid = switch_event_get_header(event, "Unique-ID"); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "INTERCEPTED : %s\n", uuid); -} - -static void kz_tweaks_channel_transferor_event_handler(switch_event_t *event) -{ - switch_core_session_t *uuid_session = NULL; - const char *uuid = switch_event_get_header(event, "Unique-ID"); - const char *call_id = switch_event_get_header(event, "att_xfer_destination_peer_uuid"); - const char *peer_uuid = switch_event_get_header(event, "att_xfer_destination_call_id"); - - const char *file = switch_event_get_header(event, "Event-Calling-File"); - const char *func = switch_event_get_header(event, "Event-Calling-Function"); - const char *line = switch_event_get_header(event, "Event-Calling-Line-Number"); - - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR : %s , %s , %s, %s , %s , %s \n", uuid, call_id, peer_uuid, file, func, line); - if ((uuid_session = switch_core_session_force_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, "ecallmgr_Call-Interaction-ID", SWITCH_TRUE, -1); - // set to uuid & peer_uuid - if(interaction_id != NULL) { - switch_core_session_t *session = NULL; - if(call_id && (session = switch_core_session_force_locate(call_id)) != NULL) { - switch_channel_t *channel = switch_core_session_get_channel(session); - const char* prv_interaction_id = switch_channel_get_variable_dup(channel, "ecallmgr_Call-Interaction-ID", SWITCH_TRUE, -1); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "LOCATING UUID PRV : %s : %s\n", prv_interaction_id, interaction_id); - switch_channel_set_variable(channel, "ecallmgr_Call-Interaction-ID", interaction_id); - switch_core_session_rwunlock(session); - switch_safe_strdup(prv_interaction_id); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR NO UUID SESSION: %s , %s , %s \n", uuid, call_id, peer_uuid); - } - if(peer_uuid && (session = switch_core_session_force_locate(peer_uuid)) != NULL) { - switch_channel_t *channel = switch_core_session_get_channel(session); - const char* prv_interaction_id = switch_channel_get_variable_dup(channel, "ecallmgr_Call-Interaction-ID", SWITCH_TRUE, -1); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "LOCATING PEER UUID PRV : %s : %s\n", prv_interaction_id, interaction_id); - switch_channel_set_variable(channel, "ecallmgr_Call-Interaction-ID", interaction_id); - switch_core_session_rwunlock(session); - switch_safe_strdup(prv_interaction_id); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR NO PEER SESSION: %s , %s , %s \n", uuid, call_id, peer_uuid); - } - switch_safe_strdup(interaction_id); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR ID = NULL : %s , %s , %s \n", uuid, call_id, peer_uuid); - } - switch_core_session_rwunlock(uuid_session); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SESSION NOT FOUND : %s\n", call_id); - } -} - -static void kz_tweaks_channel_transferee_event_handler(switch_event_t *event) -{ - const char *uuid = switch_event_get_header(event, "Unique-ID"); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEREE : %s\n", uuid); -} - -// END TRANSFERS - - -static switch_status_t kz_tweaks_handle_loopback(switch_core_session_t *session) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - const char * loopback_leg = NULL; - const char * loopback_aleg = NULL; - switch_event_t *event = NULL; - switch_event_header_t *header = NULL; - switch_event_t *to_add = NULL; - switch_event_t *to_remove = NULL; - switch_caller_profile_t *caller; - int n = 0; - - caller = switch_channel_get_caller_profile(channel); - if(strncmp(caller->source, "mod_loopback", 12)) - return SWITCH_STATUS_SUCCESS; - - if((loopback_leg = switch_channel_get_variable(channel, "loopback_leg")) == NULL) - return SWITCH_STATUS_SUCCESS; - - if(strncmp(loopback_leg, "B", 1)) - return SWITCH_STATUS_SUCCESS; - - switch_channel_get_variables(channel, &event); - switch_event_create_plain(&to_add, SWITCH_EVENT_CHANNEL_DATA); - switch_event_create_plain(&to_remove, SWITCH_EVENT_CHANNEL_DATA); - - for(header = event->headers; header; header = header->next) { - if(!strncmp(header->name, "Export-Loopback-", 16)) { - switch_event_add_variable_name_printf(to_add, SWITCH_STACK_BOTTOM, header->value, "%s", header->name+16); - switch_channel_set_variable(channel, header->name, NULL); - n++; - } else if(!strncmp(header->name, "ecallmgr_", 9)) { - switch_event_add_header_string(to_remove, SWITCH_STACK_BOTTOM, header->name, header->value); - } - } - if(n) { - for(header = to_remove->headers; header; header = header->next) { - switch_channel_set_variable(channel, header->name, NULL); - } - for(header = to_add->headers; header; header = header->next) { - switch_channel_set_variable(channel, header->name, header->value); - } - - // cleanup leg A - loopback_aleg = switch_channel_get_variable(channel, "other_loopback_leg_uuid"); - if(loopback_aleg != NULL) { - switch_core_session_t *a_session = NULL; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "found loopback a-leg uuid - %s\n", loopback_aleg); - if ((a_session = switch_core_session_locate(loopback_aleg))) { - switch_channel_t *a_channel = switch_core_session_get_channel(a_session); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "found loopback session a - %s\n", loopback_aleg); - switch_channel_del_variable_prefix(a_channel, "Export-Loopback-"); - switch_core_session_rwunlock(a_session); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Couldn't locate loopback session a - %s\n", loopback_aleg); - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Couldn't find loopback a-leg uuid!\n"); - } - } - - switch_event_destroy(&event); - switch_event_destroy(&to_add); - switch_event_destroy(&to_remove); - - return SWITCH_STATUS_SUCCESS; - -} - -static void kz_tweaks_handle_caller_id(switch_core_session_t *session) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - const char *acl_token = switch_channel_get_variable(channel, "acl_token"); - if(acl_token) { - switch_ivr_set_user(session, acl_token); - } -} - -static switch_status_t kz_tweaks_handle_auth_token(switch_core_session_t *session) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_event_t *event; - const char *token = switch_channel_get_variable(channel, "sip_h_X-FS-Auth-Token"); - if(token) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Authenticating user for nightmare xfer %s\n", token); - if (switch_ivr_set_user(session, token) == SWITCH_STATUS_SUCCESS) { - if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(channel, event); - switch_event_fire(&event); - } - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Authenticated user from nightmare xfer %s\n", token); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Error Authenticating user for nightmare xfer %s\n", token); - } - } - - return SWITCH_STATUS_SUCCESS; - -} - -static switch_status_t kz_tweaks_handle_nightmare_xfer(switch_core_session_t *session) -{ - switch_core_session_t *replace_session = NULL; - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_event_t *event; - const char *replaced_call_id = switch_channel_get_variable(channel, "sip_replaces_call_id"); - const char *core_uuid = switch_channel_get_variable(channel, "sip_h_X-FS-From-Core-UUID"); - const char *partner_uuid = switch_channel_get_variable(channel, "sip_h_X-FS-Refer-Partner-UUID"); - const char *interaction_id = switch_channel_get_variable(channel, "sip_h_X-FS-Call-Interaction-ID"); - if(core_uuid && partner_uuid && replaced_call_id && interaction_id) { - switch_channel_set_variable(channel, "ecallmgr_Call-Interaction-ID", interaction_id); - if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(channel, event); - switch_event_fire(&event); - } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "checking nightmare xfer tweak for %s\n", switch_channel_get_uuid(channel)); - if ((replace_session = switch_core_session_locate(replaced_call_id))) { - switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_session); - switch_channel_set_variable(replaced_call_channel, "ecallmgr_Call-Interaction-ID", interaction_id); - if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(replaced_call_channel, event); - switch_event_fire(&event); - } - switch_core_session_rwunlock(replace_session); - } - if ((replace_session = switch_core_session_locate(partner_uuid))) { - switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_session); - switch_channel_set_variable(replaced_call_channel, "ecallmgr_Call-Interaction-ID", interaction_id); - if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(replaced_call_channel, event); - switch_event_fire(&event); - } - switch_core_session_rwunlock(replace_session); - } - } - - return SWITCH_STATUS_SUCCESS; - -} - -static switch_status_t kz_tweaks_handle_replaces_id(switch_core_session_t *session) -{ - switch_core_session_t *replace_call_session = NULL; - switch_event_t *event; - switch_channel_t *channel = switch_core_session_get_channel(session); - const char *replaced_call_id = switch_channel_get_variable(channel, "sip_replaces_call_id"); - const char *core_uuid = switch_channel_get_variable(channel, "sip_h_X-FS-From-Core-UUID"); - if((!core_uuid) && replaced_call_id) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "checking replaces header tweak for %s\n", replaced_call_id); - if ((replace_call_session = switch_core_session_locate(replaced_call_id))) { - switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_call_session); - int i; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "setting bridge variables from %s to %s\n", replaced_call_id, switch_channel_get_uuid(channel)); - for(i = 0; bridge_variables[i] != NULL; i++) { - const char *val = switch_channel_get_variable_dup(replaced_call_channel, bridge_variables[i], SWITCH_TRUE, -1); - switch_channel_set_variable(channel, bridge_variables[i], val); - switch_safe_strdup(val); - } - if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(channel, event); - switch_event_fire(&event); - } - switch_core_session_rwunlock(replace_call_session); - } - } - - return SWITCH_STATUS_SUCCESS; - -} - - -static switch_status_t kz_tweaks_handle_switch_uri(switch_core_session_t *session) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - const char *profile_url = switch_channel_get_variable(channel, "sofia_profile_url"); - if(profile_url) { - int n = strcspn(profile_url, "@"); - switch_channel_set_variable(channel, "Switch-URL", profile_url); - switch_channel_set_variable_printf(channel, "Switch-URI", "sip:%s", n > 0 ? profile_url + n + 1 : profile_url); - } - - return SWITCH_STATUS_SUCCESS; - -} - - -static switch_status_t kz_tweaks_on_init(switch_core_session_t *session) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "checking tweaks for %s\n", switch_channel_get_uuid(channel)); - kz_tweaks_handle_switch_uri(session); - kz_tweaks_handle_caller_id(session); - kz_tweaks_handle_auth_token(session); - kz_tweaks_handle_nightmare_xfer(session); - kz_tweaks_handle_replaces_id(session); - kz_tweaks_handle_loopback(session); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_state_handler_table_t kz_tweaks_state_handlers = { - /*.on_init */ kz_tweaks_on_init, - /*.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 */ NULL -}; - - -static void kz_tweaks_register_state_handlers() -{ - switch_core_add_state_handler(&kz_tweaks_state_handlers); -} - -static void kz_tweaks_unregister_state_handlers() -{ - switch_core_remove_state_handler(&kz_tweaks_state_handlers); -} - -static void kz_tweaks_bind_events() -{ - if (switch_event_bind("kz_tweaks", SWITCH_EVENT_CHANNEL_BRIDGE, SWITCH_EVENT_SUBCLASS_ANY, kz_tweaks_channel_bridge_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind to channel_bridge event!\n"); - } - if (switch_event_bind("kz_tweaks", SWITCH_EVENT_CUSTOM, "sofia::replaced", kz_tweaks_channel_replaced_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind to channel_bridge event!\n"); - } - if (switch_event_bind("kz_tweaks", SWITCH_EVENT_CUSTOM, "sofia::intercepted", kz_tweaks_channel_intercepted_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind to channel_bridge event!\n"); - } - if (switch_event_bind("kz_tweaks", SWITCH_EVENT_CUSTOM, "sofia::transferor", kz_tweaks_channel_transferor_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind to channel_bridge event!\n"); - } - if (switch_event_bind("kz_tweaks", SWITCH_EVENT_CUSTOM, "sofia::transferee", kz_tweaks_channel_transferee_event_handler, NULL) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind to channel_bridge event!\n"); - } -} - -static void kz_tweaks_unbind_events() -{ - switch_event_unbind_callback(kz_tweaks_channel_bridge_event_handler); - switch_event_unbind_callback(kz_tweaks_channel_replaced_event_handler); - switch_event_unbind_callback(kz_tweaks_channel_intercepted_event_handler); - switch_event_unbind_callback(kz_tweaks_channel_transferor_event_handler); - switch_event_unbind_callback(kz_tweaks_channel_transferee_event_handler); -} - -void kz_tweaks_start() -{ - kz_tweaks_register_state_handlers(); - kz_tweaks_bind_events(); -} - -void kz_tweaks_stop() -{ - kz_tweaks_unbind_events(); - kz_tweaks_unregister_state_handlers(); -} - -/* 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_utils.c b/src/mod/event_handlers/mod_kazoo/kazoo_utils.c index c793b3d566..024e98b858 100644 --- a/src/mod/event_handlers/mod_kazoo/kazoo_utils.c +++ b/src/mod/event_handlers/mod_kazoo/kazoo_utils.c @@ -34,99 +34,664 @@ */ #include "mod_kazoo.h" -char *kazoo_expand_header(switch_memory_pool_t *pool, switch_event_t *event, char *val) -{ - char *expanded; - char *dup = NULL; +/* Stolen from code added to ei in R12B-5. + * Since not everyone has this version yet; + * provide our own version. + * */ - expanded = switch_event_expand_headers(event, val); - dup = switch_core_strdup(pool, expanded); +#define put8(s,n) do { \ + (s)[0] = (char)((n) & 0xff); \ + (s) += 1; \ + } while (0) - if (expanded != val) { - free(expanded); - } +#define put32be(s,n) do { \ + (s)[0] = ((n) >> 24) & 0xff; \ + (s)[1] = ((n) >> 16) & 0xff; \ + (s)[2] = ((n) >> 8) & 0xff; \ + (s)[3] = (n) & 0xff; \ + (s) += 4; \ + } while (0) - return dup; +#ifdef EI_DEBUG +static void ei_x_print_reg_msg(ei_x_buff *buf, char *dest, int send) { + char *mbuf = NULL; + int i = 1; + + 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); + } + + free(mbuf); } -char* switch_event_get_first_of(switch_event_t *event, const char *list[]) -{ - switch_event_header_t *header = NULL; - int i = 0; - while(list[i] != NULL) { - if((header = switch_event_get_header_ptr(event, list[i])) != NULL) - break; - i++; - } - if(header != NULL) { - return header->value; - } else { - return "nodomain"; +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; + + ei_x_new(&pidbuf); + ei_x_encode_pid(&pidbuf, pid); + + ei_s_print_term(&pbuf, pidbuf.buff, &i); + + 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) { + 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; + + for (i = 0, hp = event->headers; hp; hp = hp->next, i++); + + if (event->body) + i++; + + ei_x_encode_list_header(ebuf, i + 1); + + 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"); + } + + 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)); + } + + ei_x_encode_empty_list(ebuf); +} + +void close_socket(switch_socket_t ** sock) { + if (*sock) { + switch_socket_shutdown(*sock, SWITCH_SHUTDOWN_READWRITE); + switch_socket_close(*sock); + *sock = NULL; } } -SWITCH_DECLARE(switch_status_t) switch_event_add_variable_name_printf(switch_event_t *event, switch_stack_t stack, const char *val, const char *fmt, ...) -{ - int ret = 0; - char *varname; - va_list ap; - switch_status_t status = SWITCH_STATUS_SUCCESS; +void close_socketfd(int *sockfd) { + if (*sockfd) { + shutdown(*sockfd, SHUT_RDWR); + close(*sockfd); + } +} - switch_assert(event != NULL); +switch_socket_t *create_socket_with_port(switch_memory_pool_t *pool, switch_port_t port) { + switch_sockaddr_t *sa; + switch_socket_t *socket; - - va_start(ap, fmt); - ret = switch_vasprintf(&varname, fmt, ap); - va_end(ap); - - if (ret == -1) { - return SWITCH_STATUS_MEMERR; + if(switch_sockaddr_info_get(&sa, kazoo_globals.ip, SWITCH_UNSPEC, port, 0, pool)) { + return NULL; } - status = switch_event_add_header_string(event, stack, varname, val); + if (switch_socket_create(&socket, switch_sockaddr_get_family(sa), SOCK_STREAM, SWITCH_PROTO_TCP, pool)) { + return NULL; + } - free(varname); + if (switch_socket_opt_set(socket, SWITCH_SO_REUSEADDR, 1)) { + return NULL; + } - return status; + if (switch_socket_bind(socket, sa)) { + return NULL; + } + + if (switch_socket_listen(socket, 5)){ + return NULL; + } + + switch_getnameinfo(&kazoo_globals.hostname, sa, 0); + + // if (kazoo_globals.nat_map && switch_nat_get_type()) { + // switch_nat_add_mapping(port, SWITCH_NAT_TCP, NULL, SWITCH_FALSE); + // } + + return socket; } -SWITCH_DECLARE(switch_xml_t) kz_xml_child(switch_xml_t xml, const char *name) -{ - xml = (xml) ? xml->child : NULL; - while (xml && strcasecmp(name, xml->name)) - xml = xml->sibling; - return xml; +switch_socket_t *create_socket(switch_memory_pool_t *pool) { + return create_socket_with_port(pool, 0); + } -void kz_xml_process(switch_xml_t cfg) -{ - switch_xml_t xml_process; - for (xml_process = kz_xml_child(cfg, "X-PRE-PROCESS"); xml_process; xml_process = xml_process->next) { - const char *cmd = switch_xml_attr(xml_process, "cmd"); - const char *data = switch_xml_attr(xml_process, "data"); - if(cmd != NULL && !strcasecmp(cmd, "set") && data) { - char *name = (char *) data; - char *val = strchr(name, '='); +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]; + //EI_MAX_COOKIE_SIZE+1 + char *atsign; - if (val) { - char *ve = val++; - while (*val && *val == ' ') { - val++; - } - *ve-- = '\0'; - while (*ve && *ve == ' ') { - *ve-- = '\0'; - } - } + /* copy the erlang interface nodename into something we can modify */ + strncpy(cnodename, name, EI_MAXALIVELEN); - if (name && val) { - switch_core_set_variable(name, val); - } + if ((atsign = strchr(cnodename, '@'))) { + /* we got a qualified node name, don't guess the host/domain */ + snprintf(nodename, MAXNODELEN + 1, "%s", kazoo_globals.ei_nodename); + /* truncate the alivename at the @ */ + *atsign = '\0'; + } else { + if (zstr(kazoo_globals.hostname) || !strncasecmp(kazoo_globals.ip, "0.0.0.0", 7) || !strncasecmp(kazoo_globals.ip, "::", 2)) { + memcpy(hostname, switch_core_get_hostname(), EI_MAXHOSTNAMELEN); + } else { + memcpy(hostname, kazoo_globals.hostname, EI_MAXHOSTNAMELEN); + } + + snprintf(nodename, MAXNODELEN + 1, "%s@%s", kazoo_globals.ei_nodename, hostname); + } + + if (kazoo_globals.ei_shortname) { + char *off; + if ((off = strchr(nodename, '.'))) { + *off = '\0'; } } + /* 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; } +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; + + 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 */ + + 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); +} + +int ei_helper_send(ei_node_t *ei_node, erlang_pid *to, ei_x_buff *buf) { + int ret = 0; + + 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); + } + + return ret; +} + +int ei_decode_atom_safe(char *buf, int *index, char *dst) { + int 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; + } 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; + } 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; + + ei_get_type(buf, index, &type, &size); + + if (type != ERL_STRING_EXT && type != ERL_BINARY_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); + + if (type == ERL_NIL_EXT) { + 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); + } + + return res; +} + +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); + + if (type != ERL_STRING_EXT && type != ERL_BINARY_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); + return -1; + } + + if (type == ERL_NIL_EXT) { + 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); + } + + return res; +} + +switch_hash_t *create_default_filter() { + switch_hash_t *filter; + + switch_core_hash_init(&filter); + + switch_core_hash_insert(filter, "Acquired-UUID", "1"); + switch_core_hash_insert(filter, "action", "1"); + switch_core_hash_insert(filter, "Action", "1"); + switch_core_hash_insert(filter, "alt_event_type", "1"); + switch_core_hash_insert(filter, "Answer-State", "1"); + switch_core_hash_insert(filter, "Application", "1"); + switch_core_hash_insert(filter, "Application-Data", "1"); + switch_core_hash_insert(filter, "Application-Name", "1"); + switch_core_hash_insert(filter, "Application-Response", "1"); + switch_core_hash_insert(filter, "att_xfer_replaced_by", "1"); + switch_core_hash_insert(filter, "Auth-Method", "1"); + switch_core_hash_insert(filter, "Auth-Realm", "1"); + switch_core_hash_insert(filter, "Auth-User", "1"); + switch_core_hash_insert(filter, "Bridge-A-Unique-ID", "1"); + switch_core_hash_insert(filter, "Bridge-B-Unique-ID", "1"); + switch_core_hash_insert(filter, "Call-Direction", "1"); + switch_core_hash_insert(filter, "Caller-Callee-ID-Name", "1"); + switch_core_hash_insert(filter, "Caller-Callee-ID-Number", "1"); + switch_core_hash_insert(filter, "Caller-Caller-ID-Name", "1"); + switch_core_hash_insert(filter, "Caller-Caller-ID-Number", "1"); + switch_core_hash_insert(filter, "Caller-Screen-Bit", "1"); + switch_core_hash_insert(filter, "Caller-Privacy-Hide-Name", "1"); + switch_core_hash_insert(filter, "Caller-Privacy-Hide-Number", "1"); + switch_core_hash_insert(filter, "Caller-Context", "1"); + switch_core_hash_insert(filter, "Caller-Controls", "1"); + switch_core_hash_insert(filter, "Caller-Destination-Number", "1"); + switch_core_hash_insert(filter, "Caller-Dialplan", "1"); + switch_core_hash_insert(filter, "Caller-Network-Addr", "1"); + switch_core_hash_insert(filter, "Caller-Unique-ID", "1"); + switch_core_hash_insert(filter, "Call-ID", "1"); + switch_core_hash_insert(filter, "Channel-Call-State", "1"); + switch_core_hash_insert(filter, "Channel-Call-UUID", "1"); + switch_core_hash_insert(filter, "Channel-Presence-ID", "1"); + switch_core_hash_insert(filter, "Channel-State", "1"); + switch_core_hash_insert(filter, "Chat-Permissions", "1"); + switch_core_hash_insert(filter, "Conference-Name", "1"); + switch_core_hash_insert(filter, "Conference-Profile-Name", "1"); + switch_core_hash_insert(filter, "Conference-Unique-ID", "1"); + switch_core_hash_insert(filter, "contact", "1"); + switch_core_hash_insert(filter, "Detected-Tone", "1"); + switch_core_hash_insert(filter, "dialog_state", "1"); + switch_core_hash_insert(filter, "direction", "1"); + switch_core_hash_insert(filter, "Distributed-From", "1"); + switch_core_hash_insert(filter, "DTMF-Digit", "1"); + switch_core_hash_insert(filter, "DTMF-Duration", "1"); + switch_core_hash_insert(filter, "Event-Date-Timestamp", "1"); + switch_core_hash_insert(filter, "Event-Name", "1"); + switch_core_hash_insert(filter, "Event-Subclass", "1"); + switch_core_hash_insert(filter, "expires", "1"); + switch_core_hash_insert(filter, "Expires", "1"); + switch_core_hash_insert(filter, "Ext-SIP-IP", "1"); + switch_core_hash_insert(filter, "File", "1"); + switch_core_hash_insert(filter, "FreeSWITCH-Hostname", "1"); + switch_core_hash_insert(filter, "from", "1"); + switch_core_hash_insert(filter, "Hunt-Destination-Number", "1"); + switch_core_hash_insert(filter, "ip", "1"); + switch_core_hash_insert(filter, "Message-Account", "1"); + switch_core_hash_insert(filter, "metadata", "1"); + switch_core_hash_insert(filter, "old_node_channel_uuid", "1"); + switch_core_hash_insert(filter, "Other-Leg-Callee-ID-Name", "1"); + switch_core_hash_insert(filter, "Other-Leg-Callee-ID-Number", "1"); + switch_core_hash_insert(filter, "Other-Leg-Caller-ID-Name", "1"); + switch_core_hash_insert(filter, "Other-Leg-Caller-ID-Number", "1"); + switch_core_hash_insert(filter, "Other-Leg-Destination-Number", "1"); + switch_core_hash_insert(filter, "Other-Leg-Direction", "1"); + switch_core_hash_insert(filter, "Other-Leg-Unique-ID", "1"); + switch_core_hash_insert(filter, "Other-Leg-Channel-Name", "1"); + switch_core_hash_insert(filter, "Participant-Type", "1"); + switch_core_hash_insert(filter, "Path", "1"); + switch_core_hash_insert(filter, "profile_name", "1"); + switch_core_hash_insert(filter, "Profiles", "1"); + switch_core_hash_insert(filter, "proto-specific-event-name", "1"); + switch_core_hash_insert(filter, "Raw-Application-Data", "1"); + switch_core_hash_insert(filter, "realm", "1"); + switch_core_hash_insert(filter, "Resigning-UUID", "1"); + switch_core_hash_insert(filter, "set", "1"); + switch_core_hash_insert(filter, "sip_auto_answer", "1"); + switch_core_hash_insert(filter, "sip_auth_method", "1"); + switch_core_hash_insert(filter, "sip_from_host", "1"); + switch_core_hash_insert(filter, "sip_from_user", "1"); + switch_core_hash_insert(filter, "sip_to_host", "1"); + switch_core_hash_insert(filter, "sip_to_user", "1"); + switch_core_hash_insert(filter, "sub-call-id", "1"); + switch_core_hash_insert(filter, "technology", "1"); + switch_core_hash_insert(filter, "to", "1"); + switch_core_hash_insert(filter, "Unique-ID", "1"); + switch_core_hash_insert(filter, "URL", "1"); + switch_core_hash_insert(filter, "username", "1"); + switch_core_hash_insert(filter, "variable_channel_is_moving", "1"); + switch_core_hash_insert(filter, "variable_collected_digits", "1"); + switch_core_hash_insert(filter, "variable_current_application", "1"); + switch_core_hash_insert(filter, "variable_current_application_data", "1"); + switch_core_hash_insert(filter, "variable_domain_name", "1"); + switch_core_hash_insert(filter, "variable_effective_caller_id_name", "1"); + switch_core_hash_insert(filter, "variable_effective_caller_id_number", "1"); + switch_core_hash_insert(filter, "variable_holding_uuid", "1"); + switch_core_hash_insert(filter, "variable_hold_music", "1"); + switch_core_hash_insert(filter, "variable_media_group_id", "1"); + switch_core_hash_insert(filter, "variable_originate_disposition", "1"); + switch_core_hash_insert(filter, "variable_origination_uuid", "1"); + switch_core_hash_insert(filter, "variable_playback_terminator_used", "1"); + switch_core_hash_insert(filter, "variable_presence_id", "1"); + switch_core_hash_insert(filter, "variable_record_ms", "1"); + switch_core_hash_insert(filter, "variable_recovered", "1"); + switch_core_hash_insert(filter, "variable_silence_hits_exhausted", "1"); + switch_core_hash_insert(filter, "variable_sip_auth_realm", "1"); + switch_core_hash_insert(filter, "variable_sip_from_host", "1"); + switch_core_hash_insert(filter, "variable_sip_from_user", "1"); + switch_core_hash_insert(filter, "variable_sip_from_tag", "1"); + switch_core_hash_insert(filter, "variable_sip_h_X-AUTH-IP", "1"); + switch_core_hash_insert(filter, "variable_sip_received_ip", "1"); + switch_core_hash_insert(filter, "variable_sip_to_host", "1"); + switch_core_hash_insert(filter, "variable_sip_to_user", "1"); + switch_core_hash_insert(filter, "variable_sip_to_tag", "1"); + switch_core_hash_insert(filter, "variable_sofia_profile_name", "1"); + switch_core_hash_insert(filter, "variable_transfer_history", "1"); + switch_core_hash_insert(filter, "variable_user_name", "1"); + switch_core_hash_insert(filter, "variable_endpoint_disposition", "1"); + switch_core_hash_insert(filter, "variable_originate_disposition", "1"); + switch_core_hash_insert(filter, "variable_bridge_hangup_cause", "1"); + switch_core_hash_insert(filter, "variable_hangup_cause", "1"); + switch_core_hash_insert(filter, "variable_last_bridge_proto_specific_hangup_cause", "1"); + switch_core_hash_insert(filter, "variable_proto_specific_hangup_cause", "1"); + switch_core_hash_insert(filter, "VM-Call-ID", "1"); + switch_core_hash_insert(filter, "VM-sub-call-id", "1"); + switch_core_hash_insert(filter, "whistle_application_name", "1"); + switch_core_hash_insert(filter, "whistle_application_response", "1"); + switch_core_hash_insert(filter, "whistle_event_name", "1"); + switch_core_hash_insert(filter, "kazoo_application_name", "1"); + switch_core_hash_insert(filter, "kazoo_application_response", "1"); + switch_core_hash_insert(filter, "kazoo_event_name", "1"); + switch_core_hash_insert(filter, "sip_auto_answer_notify", "1"); + switch_core_hash_insert(filter, "eavesdrop_group", "1"); + switch_core_hash_insert(filter, "origination_caller_id_name", "1"); + switch_core_hash_insert(filter, "origination_caller_id_number", "1"); + switch_core_hash_insert(filter, "origination_callee_id_name", "1"); + switch_core_hash_insert(filter, "origination_callee_id_number", "1"); + switch_core_hash_insert(filter, "sip_auth_username", "1"); + switch_core_hash_insert(filter, "sip_auth_password", "1"); + switch_core_hash_insert(filter, "effective_caller_id_name", "1"); + switch_core_hash_insert(filter, "effective_caller_id_number", "1"); + switch_core_hash_insert(filter, "effective_callee_id_name", "1"); + switch_core_hash_insert(filter, "effective_callee_id_number", "1"); + switch_core_hash_insert(filter, "variable_destination_number", "1"); + switch_core_hash_insert(filter, "variable_effective_callee_id_name", "1"); + switch_core_hash_insert(filter, "variable_effective_callee_id_number", "1"); + switch_core_hash_insert(filter, "variable_record_silence_hits", "1"); + switch_core_hash_insert(filter, "variable_refer_uuid", "1"); + switch_core_hash_insert(filter, "variable_sip_call_id", "1"); + switch_core_hash_insert(filter, "variable_sip_h_Referred-By", "1"); + switch_core_hash_insert(filter, "variable_sip_h_X-AUTH-PORT", "1"); + switch_core_hash_insert(filter, "variable_sip_loopback_req_uri", "1"); + switch_core_hash_insert(filter, "variable_sip_received_port", "1"); + switch_core_hash_insert(filter, "variable_sip_refer_to", "1"); + switch_core_hash_insert(filter, "variable_sip_req_host", "1"); + switch_core_hash_insert(filter, "variable_sip_req_uri", "1"); + switch_core_hash_insert(filter, "variable_transfer_source", "1"); + switch_core_hash_insert(filter, "variable_uuid", "1"); + + /* Registration headers */ + switch_core_hash_insert(filter, "call-id", "1"); + switch_core_hash_insert(filter, "profile-name", "1"); + switch_core_hash_insert(filter, "from-user", "1"); + switch_core_hash_insert(filter, "from-host", "1"); + switch_core_hash_insert(filter, "presence-hosts", "1"); + switch_core_hash_insert(filter, "contact", "1"); + switch_core_hash_insert(filter, "rpid", "1"); + switch_core_hash_insert(filter, "status", "1"); + switch_core_hash_insert(filter, "expires", "1"); + switch_core_hash_insert(filter, "to-user", "1"); + switch_core_hash_insert(filter, "to-host", "1"); + switch_core_hash_insert(filter, "network-ip", "1"); + switch_core_hash_insert(filter, "network-port", "1"); + switch_core_hash_insert(filter, "username", "1"); + switch_core_hash_insert(filter, "realm", "1"); + switch_core_hash_insert(filter, "user-agent", "1"); + + switch_core_hash_insert(filter, "Hangup-Cause", "1"); + switch_core_hash_insert(filter, "Unique-ID", "1"); + switch_core_hash_insert(filter, "variable_switch_r_sdp", "1"); + switch_core_hash_insert(filter, "variable_rtp_local_sdp_str", "1"); + switch_core_hash_insert(filter, "variable_sip_to_uri", "1"); + switch_core_hash_insert(filter, "variable_sip_from_uri", "1"); + switch_core_hash_insert(filter, "variable_sip_user_agent", "1"); + switch_core_hash_insert(filter, "variable_duration", "1"); + switch_core_hash_insert(filter, "variable_billsec", "1"); + switch_core_hash_insert(filter, "variable_billmsec", "1"); + switch_core_hash_insert(filter, "variable_progresssec", "1"); + switch_core_hash_insert(filter, "variable_progress_uepoch", "1"); + switch_core_hash_insert(filter, "variable_progress_media_uepoch", "1"); + switch_core_hash_insert(filter, "variable_start_uepoch", "1"); + switch_core_hash_insert(filter, "variable_digits_dialed", "1"); + switch_core_hash_insert(filter, "Member-ID", "1"); + switch_core_hash_insert(filter, "Floor", "1"); + switch_core_hash_insert(filter, "Video", "1"); + switch_core_hash_insert(filter, "Hear", "1"); + switch_core_hash_insert(filter, "Speak", "1"); + switch_core_hash_insert(filter, "Talking", "1"); + switch_core_hash_insert(filter, "Current-Energy", "1"); + switch_core_hash_insert(filter, "Energy-Level", "1"); + switch_core_hash_insert(filter, "Mute-Detect", "1"); + + /* RTMP headers */ + switch_core_hash_insert(filter, "RTMP-Session-ID", "1"); + switch_core_hash_insert(filter, "RTMP-Profile", "1"); + switch_core_hash_insert(filter, "RTMP-Flash-Version", "1"); + switch_core_hash_insert(filter, "RTMP-SWF-URL", "1"); + switch_core_hash_insert(filter, "RTMP-TC-URL", "1"); + switch_core_hash_insert(filter, "RTMP-Page-URL", "1"); + switch_core_hash_insert(filter, "User", "1"); + switch_core_hash_insert(filter, "Domain", "1"); + + /* Fax headers */ + switch_core_hash_insert(filter, "variable_fax_bad_rows", "1"); + switch_core_hash_insert(filter, "variable_fax_document_total_pages", "1"); + switch_core_hash_insert(filter, "variable_fax_document_transferred_pages", "1"); + switch_core_hash_insert(filter, "variable_fax_ecm_used", "1"); + switch_core_hash_insert(filter, "variable_fax_result_code", "1"); + switch_core_hash_insert(filter, "variable_fax_result_text", "1"); + switch_core_hash_insert(filter, "variable_fax_success", "1"); + switch_core_hash_insert(filter, "variable_fax_transfer_rate", "1"); + switch_core_hash_insert(filter, "variable_fax_local_station_id", "1"); + switch_core_hash_insert(filter, "variable_fax_remote_station_id", "1"); + switch_core_hash_insert(filter, "variable_fax_remote_country", "1"); + switch_core_hash_insert(filter, "variable_fax_remote_vendor", "1"); + switch_core_hash_insert(filter, "variable_fax_remote_model", "1"); + switch_core_hash_insert(filter, "variable_fax_image_resolution", "1"); + switch_core_hash_insert(filter, "variable_fax_file_image_resolution", "1"); + switch_core_hash_insert(filter, "variable_fax_image_size", "1"); + switch_core_hash_insert(filter, "variable_fax_image_pixel_size", "1"); + switch_core_hash_insert(filter, "variable_fax_file_image_pixel_size", "1"); + switch_core_hash_insert(filter, "variable_fax_longest_bad_row_run", "1"); + switch_core_hash_insert(filter, "variable_fax_encoding", "1"); + switch_core_hash_insert(filter, "variable_fax_encoding_name", "1"); + switch_core_hash_insert(filter, "variable_fax_header", "1"); + switch_core_hash_insert(filter, "variable_fax_ident", "1"); + switch_core_hash_insert(filter, "variable_fax_timezone", "1"); + switch_core_hash_insert(filter, "variable_fax_doc_id", "1"); + switch_core_hash_insert(filter, "variable_fax_doc_database", "1"); + switch_core_hash_insert(filter, "variable_has_t38", "1"); + + /* Secure headers */ + switch_core_hash_insert(filter, "variable_sdp_secure_savp_only", "1"); + switch_core_hash_insert(filter, "variable_rtp_has_crypto", "1"); + switch_core_hash_insert(filter, "variable_rtp_secure_media", "1"); + switch_core_hash_insert(filter, "variable_rtp_secure_media_confirmed", "1"); + switch_core_hash_insert(filter, "variable_rtp_secure_media_confirmed_audio", "1"); + switch_core_hash_insert(filter, "variable_rtp_secure_media_confirmed_video", "1"); + switch_core_hash_insert(filter, "variable_zrtp_secure_media", "1"); + switch_core_hash_insert(filter, "variable_zrtp_secure_media_confirmed", "1"); + switch_core_hash_insert(filter, "variable_zrtp_secure_media_confirmed_audio", "1"); + switch_core_hash_insert(filter, "variable_zrtp_secure_media_confirmed_video", "1"); + switch_core_hash_insert(filter, "sdp_secure_savp_only", "1"); + switch_core_hash_insert(filter, "rtp_has_crypto", "1"); + switch_core_hash_insert(filter, "rtp_secure_media", "1"); + switch_core_hash_insert(filter, "rtp_secure_media_confirmed", "1"); + switch_core_hash_insert(filter, "rtp_secure_media_confirmed_audio", "1"); + switch_core_hash_insert(filter, "rtp_secure_media_confirmed_video", "1"); + switch_core_hash_insert(filter, "zrtp_secure_media", "1"); + switch_core_hash_insert(filter, "zrtp_secure_media_confirmed", "1"); + switch_core_hash_insert(filter, "zrtp_secure_media_confirmed_audio", "1"); + switch_core_hash_insert(filter, "zrtp_secure_media_confirmed_video", "1"); + + /* Device Redirect headers */ + switch_core_hash_insert(filter, "variable_last_bridge_hangup_cause", "1"); + switch_core_hash_insert(filter, "variable_sip_redirected_by", "1"); + switch_core_hash_insert(filter, "intercepted_by", "1"); + switch_core_hash_insert(filter, "variable_bridge_uuid", "1"); + switch_core_hash_insert(filter, "Record-File-Path", "1"); + + /* Loopback headers */ + switch_core_hash_insert(filter, "variable_loopback_bowout_on_execute", "1"); + switch_core_hash_insert(filter, "variable_loopback_bowout", "1"); + switch_core_hash_insert(filter, "variable_other_loopback_leg_uuid", "1"); + switch_core_hash_insert(filter, "variable_loopback_leg", "1"); + switch_core_hash_insert(filter, "variable_is_loopback", "1"); + + // SMS + switch_core_hash_insert(filter, "Message-ID", "1"); + switch_core_hash_insert(filter, "Delivery-Failure", "1"); + switch_core_hash_insert(filter, "Delivery-Result-Code", "1"); + + return filter; +} + +static void *SWITCH_THREAD_FUNC fetch_config_filters_exec(switch_thread_t *thread, void *obj) +{ + char *cf = "kazoo.conf"; + switch_xml_t cfg, xml, child, param; + switch_event_t *params; + switch_memory_pool_t *pool = (switch_memory_pool_t *)obj; + + switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS); + switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Action", "request-filter"); + + if (!(xml = switch_xml_open_cfg(cf, &cfg, params))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open configuration file %s\n", cf); + } else if ((child = switch_xml_child(cfg, "event-filter"))) { + switch_hash_t *filter; + switch_hash_t *old_filter; + + switch_core_hash_init(&filter); + for (param = switch_xml_child(child, "header"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + switch_core_hash_insert(filter, var, "1"); + } + + old_filter = kazoo_globals.event_filter; + kazoo_globals.config_filters_fetched = 1; + kazoo_globals.event_filter = filter; + if (old_filter) { + switch_core_hash_destroy(&old_filter); + } + + switch_xml_free(xml); + } + + if (params) switch_event_destroy(¶ms); + switch_core_destroy_memory_pool(&pool); + + return NULL; +} + +void fetch_config_filters() { + 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 filters\n"); + + switch_core_new_memory_pool(&pool); + + switch_threadattr_create(&thd_attr, pool); + switch_threadattr_detach_set(thd_attr, 1); + switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); + + switch_uuid_get(&uuid); + switch_thread_create(&thread, thd_attr, fetch_config_filters_exec, pool, pool); + +} + + + /* For Emacs: * Local Variables: * mode:c diff --git a/src/mod/event_handlers/mod_kazoo/mod_kazoo.c b/src/mod/event_handlers/mod_kazoo/mod_kazoo.c index 5b255738ff..b666920d3f 100644 --- a/src/mod/event_handlers/mod_kazoo/mod_kazoo.c +++ b/src/mod/event_handlers/mod_kazoo/mod_kazoo.c @@ -32,12 +32,608 @@ */ #include "mod_kazoo.h" -globals_t kazoo_globals = {0}; - +#define KAZOO_DESC "kazoo information" +#define KAZOO_SYNTAX " []" +globals_t kazoo_globals; +SWITCH_MODULE_LOAD_FUNCTION(mod_kazoo_load); +SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_kazoo_shutdown); +SWITCH_MODULE_RUNTIME_FUNCTION(mod_kazoo_runtime); SWITCH_MODULE_DEFINITION(mod_kazoo, mod_kazoo_load, mod_kazoo_shutdown, mod_kazoo_runtime); +SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_ip, kazoo_globals.ip); +SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_ei_cookie, kazoo_globals.ei_cookie); +SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_ei_nodename, kazoo_globals.ei_nodename); +SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_kazoo_var_prefix, kazoo_globals.kazoo_var_prefix); + +static switch_status_t api_erlang_status(switch_stream_handle_t *stream) { + switch_sockaddr_t *sa; + uint16_t port; + char ipbuf[48]; + const char *ip_addr; + ei_node_t *ei_node; + + 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); + + stream->write_function(stream, "Running %s\n", VERSION); + stream->write_function(stream, "Listening for new Erlang connections on %s:%u with cookie %s\n", ip_addr, port, kazoo_globals.ei_cookie); + stream->write_function(stream, "Registered as Erlang node %s, visible as %s\n", kazoo_globals.ei_cnode.thisnodename, kazoo_globals.ei_cnode.thisalivename); + + if (kazoo_globals.ei_compat_rel) { + stream->write_function(stream, "Using Erlang compatibility mode: %d\n", kazoo_globals.ei_compat_rel); + } + + switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock); + ei_node = kazoo_globals.ei_nodes; + if (!ei_node) { + stream->write_function(stream, "No erlang nodes connected\n"); + } else { + stream->write_function(stream, "Connected to:\n"); + while(ei_node != NULL) { + unsigned int year, day, hour, min, sec, delta; + + delta = (switch_micro_time_now() - ei_node->created_time) / 1000000; + sec = delta % 60; + min = delta / 60 % 60; + hour = delta / 3600 % 24; + day = delta / 86400 % 7; + year = delta / 31556926 % 12; + stream->write_function(stream, " %s (%s:%d) up %d years, %d days, %d hours, %d minutes, %d seconds\n" + ,ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port, year, day, hour, min, sec); + ei_node = ei_node->next; + } + } + switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t api_erlang_event_filter(switch_stream_handle_t *stream) { + switch_hash_index_t *hi = NULL; + int column = 0; + + for (hi = (switch_hash_index_t *)switch_core_hash_first_iter(kazoo_globals.event_filter, hi); hi; hi = switch_core_hash_next(&hi)) { + const void *key; + void *val; + switch_core_hash_this(hi, &key, NULL, &val); + stream->write_function(stream, "%-50s", (char *)key); + if (++column > 2) { + stream->write_function(stream, "\n"); + column = 0; + } + } + + if (++column > 2) { + stream->write_function(stream, "\n"); + column = 0; + } + + stream->write_function(stream, "%-50s", kazoo_globals.kazoo_var_prefix); + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t api_erlang_nodes_list(switch_stream_handle_t *stream) { + ei_node_t *ei_node; + + switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock); + ei_node = kazoo_globals.ei_nodes; + while(ei_node != NULL) { + stream->write_function(stream, "%s (%s)\n", ei_node->peer_nodename, ei_node->remote_ip); + ei_node = ei_node->next; + } + switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t api_erlang_nodes_count(switch_stream_handle_t *stream) { + ei_node_t *ei_node; + int count = 0; + + switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock); + ei_node = kazoo_globals.ei_nodes; + while(ei_node != NULL) { + count++; + ei_node = ei_node->next; + } + switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); + + stream->write_function(stream, "%d\n", count); + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t api_complete_erlang_node(const char *line, const char *cursor, switch_console_callback_match_t **matches) { + switch_console_callback_match_t *my_matches = NULL; + switch_status_t status = SWITCH_STATUS_FALSE; + ei_node_t *ei_node; + + switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock); + ei_node = kazoo_globals.ei_nodes; + while(ei_node != NULL) { + switch_console_push_match(&my_matches, ei_node->peer_nodename); + ei_node = ei_node->next; + } + switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); + + if (my_matches) { + *matches = my_matches; + status = SWITCH_STATUS_SUCCESS; + } + + return status; +} + +static switch_status_t handle_node_api_event_stream(ei_event_stream_t *event_stream, switch_stream_handle_t *stream) { + ei_event_binding_t *binding; + int column = 0; + + switch_mutex_lock(event_stream->socket_mutex); + if (event_stream->connected == SWITCH_FALSE) { + switch_sockaddr_t *sa; + uint16_t port; + char ipbuf[48] = {0}; + const char *ip_addr; + + switch_socket_addr_get(&sa, SWITCH_TRUE, event_stream->acceptor); + port = switch_sockaddr_get_port(sa); + ip_addr = switch_get_addr(ipbuf, sizeof (ipbuf), sa); + + if (zstr(ip_addr)) { + ip_addr = kazoo_globals.ip; + } + + stream->write_function(stream, "%s:%d -> disconnected\n" + ,ip_addr, port); + } else { + stream->write_function(stream, "%s:%d -> %s:%d\n" + ,event_stream->local_ip, event_stream->local_port + ,event_stream->remote_ip, event_stream->remote_port); + } + + binding = event_stream->bindings; + while(binding != NULL) { + if (binding->type == SWITCH_EVENT_CUSTOM) { + stream->write_function(stream, "CUSTOM %-43s", binding->subclass_name); + } else { + stream->write_function(stream, "%-50s", switch_event_name(binding->type)); + } + + if (++column > 2) { + stream->write_function(stream, "\n"); + column = 0; + } + + binding = binding->next; + } + switch_mutex_unlock(event_stream->socket_mutex); + + if (!column) { + stream->write_function(stream, "\n"); + } else { + stream->write_function(stream, "\n\n"); + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t handle_node_api_event_streams(ei_node_t *ei_node, switch_stream_handle_t *stream) { + ei_event_stream_t *event_stream; + + switch_mutex_lock(ei_node->event_streams_mutex); + event_stream = ei_node->event_streams; + while(event_stream != NULL) { + handle_node_api_event_stream(event_stream, stream); + event_stream = event_stream->next; + } + switch_mutex_unlock(ei_node->event_streams_mutex); + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t handle_node_api_command(ei_node_t *ei_node, switch_stream_handle_t *stream, uint32_t command) { + unsigned int year, day, hour, min, sec, delta; + + switch (command) { + case API_COMMAND_DISCONNECT: + stream->write_function(stream, "Disconnecting erlang node %s at managers request\n", ei_node->peer_nodename); + switch_clear_flag(ei_node, LFLAG_RUNNING); + break; + case API_COMMAND_REMOTE_IP: + delta = (switch_micro_time_now() - ei_node->created_time) / 1000000; + sec = delta % 60; + min = delta / 60 % 60; + hour = delta / 3600 % 24; + day = delta / 86400 % 7; + year = delta / 31556926 % 12; + + stream->write_function(stream, "Uptime %d years, %d days, %d hours, %d minutes, %d seconds\n", year, day, hour, min, sec); + stream->write_function(stream, "Local Address %s:%d\n", ei_node->local_ip, ei_node->local_port); + stream->write_function(stream, "Remote Address %s:%d\n", ei_node->remote_ip, ei_node->remote_port); + break; + case API_COMMAND_STREAMS: + handle_node_api_event_streams(ei_node, stream); + break; + case API_COMMAND_BINDINGS: + handle_api_command_streams(ei_node, stream); + break; + default: + break; + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t api_erlang_node_command(switch_stream_handle_t *stream, const char *nodename, uint32_t command) { + ei_node_t *ei_node; + + switch_thread_rwlock_rdlock(kazoo_globals.ei_nodes_lock); + ei_node = kazoo_globals.ei_nodes; + while(ei_node != NULL) { + int length = strlen(ei_node->peer_nodename); + + if (!strncmp(ei_node->peer_nodename, nodename, length)) { + handle_node_api_command(ei_node, stream, command); + switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); + return SWITCH_STATUS_SUCCESS; + } + + ei_node = ei_node->next; + } + switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); + + return SWITCH_STATUS_NOTFOUND; +} + +static int read_cookie_from_file(char *filename) { + int fd; + char cookie[MAXATOMLEN + 1]; + char *end; + struct stat buf; + ssize_t res; + + if (!stat(filename, &buf)) { + if ((buf.st_mode & S_IRWXG) || (buf.st_mode & S_IRWXO)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s must only be accessible by owner only.\n", filename); + return 2; + } + if (buf.st_size > MAXATOMLEN) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%s contains a cookie larger than the maximum atom size of %d.\n", filename, MAXATOMLEN); + return 2; + } + fd = open(filename, O_RDONLY); + if (fd < 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to open cookie file %s : %d.\n", filename, errno); + return 2; + } + + if ((res = read(fd, cookie, MAXATOMLEN)) < 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to read cookie file %s : %d.\n", filename, errno); + } + + cookie[MAXATOMLEN] = '\0'; + + /* replace any end of line characters with a null */ + if ((end = strchr(cookie, '\n'))) { + *end = '\0'; + } + + if ((end = strchr(cookie, '\r'))) { + *end = '\0'; + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set cookie from file %s: %s\n", filename, cookie); + + set_pref_ei_cookie(cookie); + return 0; + } else { + /* don't error here, because we might be blindly trying to read $HOME/.erlang.cookie, and that can fail silently */ + return 1; + } +} + +static switch_status_t config(void) { + char *cf = "kazoo.conf"; + switch_xml_t cfg, xml, child, param; + kazoo_globals.send_all_headers = 0; + kazoo_globals.send_all_private_headers = 1; + kazoo_globals.connection_timeout = 500; + kazoo_globals.receive_timeout = 200; + kazoo_globals.receive_msg_preallocate = 2000; + kazoo_globals.event_stream_preallocate = 4000; + kazoo_globals.send_msg_batch = 10; + kazoo_globals.event_stream_framing = 2; + kazoo_globals.port = 0; + kazoo_globals.io_fault_tolerance = 10; + + if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open configuration file %s\n", cf); + return SWITCH_STATUS_FALSE; + } else { + if ((child = switch_xml_child(cfg, "settings"))) { + for (param = switch_xml_child(child, "param"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + char *val = (char *) switch_xml_attr_soft(param, "value"); + + if (!strcmp(var, "listen-ip")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set bind ip address: %s\n", val); + set_pref_ip(val); + } else if (!strcmp(var, "listen-port")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set bind port: %s\n", val); + kazoo_globals.port = atoi(val); + } else if (!strcmp(var, "cookie")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set cookie: %s\n", val); + set_pref_ei_cookie(val); + } else if (!strcmp(var, "cookie-file")) { + if (read_cookie_from_file(val) == 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to read cookie from %s\n", val); + } + } else if (!strcmp(var, "nodename")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set node name: %s\n", val); + set_pref_ei_nodename(val); + } else if (!strcmp(var, "shortname")) { + kazoo_globals.ei_shortname = switch_true(val); + } else if (!strcmp(var, "kazoo-var-prefix")) { + set_pref_kazoo_var_prefix(val); + } else if (!strcmp(var, "compat-rel")) { + if (atoi(val) >= 7) + kazoo_globals.ei_compat_rel = atoi(val); + else + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid compatibility release '%s' specified\n", val); + } else if (!strcmp(var, "nat-map")) { + kazoo_globals.nat_map = switch_true(val); + } else if (!strcmp(var, "send-all-headers")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-all-headers: %s\n", val); + kazoo_globals.send_all_headers = switch_true(val); + } else if (!strcmp(var, "send-all-private-headers")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-all-private-headers: %s\n", val); + kazoo_globals.send_all_private_headers = switch_true(val); + } else if (!strcmp(var, "connection-timeout")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set connection-timeout: %s\n", val); + kazoo_globals.connection_timeout = atoi(val); + } else if (!strcmp(var, "receive-timeout")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set receive-timeout: %s\n", val); + kazoo_globals.receive_timeout = atoi(val); + } else if (!strcmp(var, "receive-msg-preallocate")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set receive-msg-preallocate: %s\n", val); + kazoo_globals.receive_msg_preallocate = atoi(val); + } else if (!strcmp(var, "event-stream-preallocate")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set event-stream-preallocate: %s\n", val); + kazoo_globals.event_stream_preallocate = atoi(val); + } else if (!strcmp(var, "send-msg-batch-size")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set send-msg-batch-size: %s\n", val); + kazoo_globals.send_msg_batch = atoi(val); + } else if (!strcmp(var, "event-stream-framing")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set event-stream-framing: %s\n", val); + kazoo_globals.event_stream_framing = atoi(val); + } else if (!strcmp(var, "io-fault-tolerance")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set io-fault-tolerance: %s\n", val); + kazoo_globals.io_fault_tolerance = atoi(val); + } + } + } + + if ((child = switch_xml_child(cfg, "event-filter"))) { + switch_hash_t *filter; + + switch_core_hash_init(&filter); + for (param = switch_xml_child(child, "header"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + switch_core_hash_insert(filter, var, "1"); + } + + kazoo_globals.event_filter = filter; + } + + switch_xml_free(xml); + } + + if (kazoo_globals.receive_msg_preallocate < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid receive message preallocate value, disabled\n"); + kazoo_globals.receive_msg_preallocate = 0; + } + + if (kazoo_globals.event_stream_preallocate < 0) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid event stream preallocate value, disabled\n"); + kazoo_globals.event_stream_preallocate = 0; + } + + if (kazoo_globals.send_msg_batch < 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid send message batch size, reverting to default\n"); + kazoo_globals.send_msg_batch = 10; + } + + if (kazoo_globals.io_fault_tolerance < 1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid I/O fault tolerance, reverting to default\n"); + kazoo_globals.io_fault_tolerance = 10; + } + + if (!kazoo_globals.event_filter) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Event filter not found in configuration, using default\n"); + kazoo_globals.event_filter = create_default_filter(); + } + + if (kazoo_globals.event_stream_framing < 1 || kazoo_globals.event_stream_framing > 4) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid event stream framing value, using default\n"); + kazoo_globals.event_stream_framing = 2; + } + + if (zstr(kazoo_globals.kazoo_var_prefix)) { + set_pref_kazoo_var_prefix("variable_ecallmgr*"); + kazoo_globals.var_prefix_length = 17; //ignore the * + } else { + /* we could use the global pool but then we would have to conditionally + * free the pointer if it was not drawn from the XML */ + char *buf; + int size = switch_snprintf(NULL, 0, "variable_%s*", kazoo_globals.kazoo_var_prefix) + 1; + + switch_malloc(buf, size); + switch_snprintf(buf, size, "variable_%s*", kazoo_globals.kazoo_var_prefix); + switch_safe_free(kazoo_globals.kazoo_var_prefix); + kazoo_globals.kazoo_var_prefix = buf; + kazoo_globals.var_prefix_length = size - 2; //ignore the * + } + + if (!kazoo_globals.num_worker_threads) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Number of worker threads not found in configuration, using default\n"); + kazoo_globals.num_worker_threads = 10; + } + + if (zstr(kazoo_globals.ip)) { + set_pref_ip("0.0.0.0"); + } + + if (zstr(kazoo_globals.ei_cookie)) { + int res; + char *home_dir = getenv("HOME"); + char path_buf[1024]; + + if (!zstr(home_dir)) { + /* $HOME/.erlang.cookie */ + switch_snprintf(path_buf, sizeof (path_buf), "%s%s%s", home_dir, SWITCH_PATH_SEPARATOR, ".erlang.cookie"); + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Checking for cookie at path: %s\n", path_buf); + + res = read_cookie_from_file(path_buf); + if (res) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "No cookie or valid cookie file specified, using default cookie\n"); + set_pref_ei_cookie("ClueCon"); + } + } + } + + if (!kazoo_globals.ei_nodename) { + set_pref_ei_nodename("freeswitch"); + } + + if (!kazoo_globals.nat_map) { + kazoo_globals.nat_map = 0; + } + + return SWITCH_STATUS_SUCCESS; +} + +static switch_status_t create_acceptor() { + switch_sockaddr_t *sa; + uint16_t port; + 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) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Compatability with OTP R%d requested\n", kazoo_globals.ei_compat_rel); + ei_set_compat_rel(kazoo_globals.ei_compat_rel); + } + + if (!(kazoo_globals.acceptor = create_socket_with_port(kazoo_globals.pool, kazoo_globals.port))) { + return SWITCH_STATUS_SOCKERR; + } + + 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); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Erlang connection acceptor listening on %s:%u\n", ip_addr, port); + + /* try to initialize the erlang interface */ + if (create_ei_cnode(ip_addr, kazoo_globals.ei_nodename, &kazoo_globals.ei_cnode) != SWITCH_STATUS_SUCCESS) { + return SWITCH_STATUS_SOCKERR; + } + + /* tell the erlang port manager where we can be reached. this returns a file descriptor pointing to epmd or -1 */ + if ((kazoo_globals.epmdfd = ei_publish(&kazoo_globals.ei_cnode, port)) == -1) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, + "Failed to publish port to epmd. Try starting it yourself or run an erl shell with the -sname or -name option.\n"); + return SWITCH_STATUS_SOCKERR; + } + + 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_STANDARD_API(exec_api_cmd) +{ + char *argv[1024] = { 0 }; + int unknown_command = 1, argc = 0; + char *mycmd = NULL; + + const char *usage_string = "USAGE:\n" + "--------------------------------------------------------------------------------------------------------------------\n" + "erlang status - provides an overview of the current status\n" + "erlang event_filter - lists the event headers that will be sent to Erlang nodes\n" + "erlang nodes list - lists connected Erlang nodes (usefull for monitoring tools)\n" + "erlang nodes count - provides a count of connected Erlang nodes (usefull for monitoring tools)\n" + "erlang node disconnect - disconnects an Erlang node\n" + "erlang node connection - Shows the connection info\n" + "erlang node event_streams - lists the event streams for an Erlang node\n" + "erlang node fetch_bindings - lists the XML fetch bindings for an Erlang node\n" + "---------------------------------------------------------------------------------------------------------------------\n"; + + if (zstr(cmd)) { + stream->write_function(stream, "%s", usage_string); + return SWITCH_STATUS_SUCCESS; + } + + if (!(mycmd = strdup(cmd))) { + return SWITCH_STATUS_MEMERR; + } + + if (!(argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))))) { + stream->write_function(stream, "%s", usage_string); + switch_safe_free(mycmd); + return SWITCH_STATUS_SUCCESS; + } + + if (zstr(argv[0])) { + stream->write_function(stream, "%s", usage_string); + switch_safe_free(mycmd); + return SWITCH_STATUS_SUCCESS; + } + + if (!strncmp(argv[0], "status", 6)) { + unknown_command = 0; + api_erlang_status(stream); + } else if (!strncmp(argv[0], "event_filter", 6)) { + unknown_command = 0; + api_erlang_event_filter(stream); + } else if (!strncmp(argv[0], "nodes", 6) && !zstr(argv[1])) { + if (!strncmp(argv[1], "list", 6)) { + unknown_command = 0; + api_erlang_nodes_list(stream); + } else if (!strncmp(argv[1], "count", 6)) { + unknown_command = 0; + api_erlang_nodes_count(stream); + } + } else if (!strncmp(argv[0], "node", 6) && !zstr(argv[1]) && !zstr(argv[2])) { + if (!strncmp(argv[2], "disconnect", 6)) { + unknown_command = 0; + api_erlang_node_command(stream, argv[1], API_COMMAND_DISCONNECT); + } else if (!strncmp(argv[2], "connection", 2)) { + unknown_command = 0; + api_erlang_node_command(stream, argv[1], API_COMMAND_REMOTE_IP); + } else if (!strncmp(argv[2], "event_streams", 6)) { + unknown_command = 0; + api_erlang_node_command(stream, argv[1], API_COMMAND_STREAMS); + } else if (!strncmp(argv[2], "fetch_bindings", 6)) { + unknown_command = 0; + api_erlang_node_command(stream, argv[1], API_COMMAND_BINDINGS); + } + } + + if (unknown_command) { + stream->write_function(stream, "%s", usage_string); + } + + switch_safe_free(mycmd); + return SWITCH_STATUS_SUCCESS; +} + SWITCH_MODULE_LOAD_FUNCTION(mod_kazoo_load) { switch_api_interface_t *api_interface = NULL; switch_application_interface_t *app_interface = NULL; @@ -47,17 +643,34 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_kazoo_load) { kazoo_globals.pool = pool; kazoo_globals.ei_nodes = NULL; - // ensure epmd is running - - if(kazoo_load_config() != SWITCH_STATUS_SUCCESS) { + if(config() != SWITCH_STATUS_SUCCESS) { // TODO: what would we need to clean up here? switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Improper configuration!\n"); return SWITCH_STATUS_TERM; } + 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); + return SWITCH_STATUS_TERM; + } + /* connect my internal structure to the blank pointer passed to me */ *module_interface = switch_loadable_module_create_module_interface(pool, modname); + /* create an api for cli debug commands */ + SWITCH_ADD_API(api_interface, "erlang", KAZOO_DESC, exec_api_cmd, KAZOO_SYNTAX); + switch_console_set_complete("add erlang status"); + switch_console_set_complete("add erlang event_filter"); + switch_console_set_complete("add erlang nodes list"); + switch_console_set_complete("add erlang nodes count"); + switch_console_set_complete("add erlang node ::erlang::node disconnect"); + switch_console_set_complete("add erlang node ::erlang::node connection"); + switch_console_set_complete("add erlang node ::erlang::node event_streams"); + switch_console_set_complete("add erlang node ::erlang::node fetch_bindings"); + switch_console_add_complete_func("::erlang::node", api_complete_erlang_node); + switch_thread_rwlock_create(&kazoo_globals.ei_nodes_lock, pool); switch_set_flag(&kazoo_globals, LFLAG_RUNNING); @@ -65,18 +678,12 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_kazoo_load) { /* create all XML fetch agents */ bind_fetch_agents(); - /* create an api for cli debug commands */ - add_cli_api(module_interface, api_interface); - /* add our modified commands */ add_kz_commands(module_interface, api_interface); /* add our modified dptools */ add_kz_dptools(module_interface, app_interface); - /* add tweaks */ - kz_tweaks_start(); - /* indicate that the module should continue to be loaded */ return SWITCH_STATUS_SUCCESS; } @@ -84,10 +691,8 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_kazoo_load) { SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_kazoo_shutdown) { int sanity = 0; - - remove_cli_api(); - - kz_tweaks_stop(); + switch_console_set_complete("del erlang"); + switch_console_del_complete_func("::erlang::node"); /* stop taking new requests and start shuting down the threads */ switch_clear_flag(&kazoo_globals, LFLAG_RUNNING); @@ -105,8 +710,6 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_kazoo_shutdown) { switch_core_hash_destroy(&kazoo_globals.event_filter); } - kazoo_destroy_config(); - switch_thread_rwlock_wrlock(kazoo_globals.ei_nodes_lock); switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); switch_thread_rwlock_destroy(kazoo_globals.ei_nodes_lock); @@ -119,9 +722,9 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_kazoo_shutdown) { unbind_fetch_agents(); /* Close the port we reserved for uPnP/Switch behind firewall, if necessary */ - if (kazoo_globals.nat_map && switch_nat_get_type()) { - switch_nat_del_mapping(kazoo_globals.port, SWITCH_NAT_TCP); - } + // if (kazoo_globals.nat_map && switch_nat_get_type()) { + // switch_nat_del_mapping(kazoo_globals.port, SWITCH_NAT_TCP); + // } /* clean up our allocated preferences */ switch_safe_free(kazoo_globals.ip); @@ -132,6 +735,50 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_kazoo_shutdown) { return SWITCH_STATUS_SUCCESS; } +SWITCH_MODULE_RUNTIME_FUNCTION(mod_kazoo_runtime) { + switch_os_socket_t os_socket; + + switch_atomic_inc(&kazoo_globals.threads); + + switch_os_sock_get(&os_socket, kazoo_globals.acceptor); + + while (switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) { + int nodefd; + ErlConnect conn; + + /* zero out errno because ei_accept doesn't differentiate between a */ + /* failed authentication or a socket failure, or a client version */ + /* mismatch or a godzilla attack (and a godzilla attack is highly likely) */ + errno = 0; + + /* wait here for an erlang node to connect, timming out to check if our module is still running every now-and-again */ + if ((nodefd = ei_accept_tmo(&kazoo_globals.ei_cnode, (int) os_socket, &conn, kazoo_globals.connection_timeout)) == ERL_ERROR) { + if (erl_errno == ETIMEDOUT) { + continue; + } else if (errno) { + 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); + } + continue; + } + + if (!switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) { + break; + } + + /* NEW ERLANG NODE CONNECTION! Hello friend! */ + new_kazoo_node(nodefd, &conn); + } + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Erlang connection acceptor shut down\n"); + + switch_atomic_dec(&kazoo_globals.threads); + + return SWITCH_STATUS_TERM; +} + /* For Emacs: * Local Variables: diff --git a/src/mod/event_handlers/mod_kazoo/mod_kazoo.h b/src/mod/event_handlers/mod_kazoo/mod_kazoo.h index 165e9ff1ce..9de7db6ea0 100644 --- a/src/mod/event_handlers/mod_kazoo/mod_kazoo.h +++ b/src/mod/event_handlers/mod_kazoo/mod_kazoo.h @@ -1,32 +1,167 @@ #include #include -#include #include #include #include #include #include -#include #define MAX_ACL 100 #define CMD_BUFLEN 1024 * 1000 #define MAX_QUEUE_LEN 25000 #define MAX_MISSED 500 #define MAX_PID_CHARS 255 +#define VERSION "mod_kazoo v1.4.0-1" - -#include "kazoo_ei.h" -#include "kazoo_message.h" +#define API_COMMAND_DISCONNECT 0 +#define API_COMMAND_REMOTE_IP 1 +#define API_COMMAND_STREAMS 2 +#define API_COMMAND_BINDINGS 3 typedef enum { LFLAG_RUNNING = (1 << 0) } event_flag_t; +struct ei_send_msg_s { + ei_x_buff buf; + erlang_pid pid; +}; +typedef struct ei_send_msg_s ei_send_msg_t; +struct ei_received_msg_s { + ei_x_buff buf; + erlang_msg msg; +}; +typedef struct ei_received_msg_s ei_received_msg_t; +struct ei_event_binding_s { + char id[SWITCH_UUID_FORMATTED_LENGTH + 1]; + switch_event_node_t *node; + switch_event_types_t type; + const char *subclass_name; + struct ei_event_binding_s *next; +}; +typedef struct ei_event_binding_s ei_event_binding_t; +struct ei_event_stream_s { + switch_memory_pool_t *pool; + ei_event_binding_t *bindings; + switch_queue_t *queue; + switch_socket_t *acceptor; + switch_pollset_t *pollset; + switch_pollfd_t *pollfd; + switch_socket_t *socket; + switch_mutex_t *socket_mutex; + switch_bool_t connected; + char remote_ip[48]; + uint16_t remote_port; + char local_ip[48]; + uint16_t local_port; + erlang_pid pid; + uint32_t flags; + struct ei_event_stream_s *next; +}; +typedef struct ei_event_stream_s ei_event_stream_t; +struct ei_node_s { + int nodefd; + switch_atomic_t pending_bgapi; + switch_atomic_t receive_handlers; + switch_memory_pool_t *pool; + ei_event_stream_t *event_streams; + switch_mutex_t *event_streams_mutex; + switch_queue_t *send_msgs; + switch_queue_t *received_msgs; + char *peer_nodename; + switch_time_t created_time; + switch_socket_t *socket; + char remote_ip[48]; + uint16_t remote_port; + char local_ip[48]; + uint16_t local_port; + uint32_t flags; + struct ei_node_s *next; +}; +typedef struct ei_node_s ei_node_t; +struct globals_s { + switch_memory_pool_t *pool; + switch_atomic_t threads; + switch_socket_t *acceptor; + struct ei_cnode_s ei_cnode; + switch_thread_rwlock_t *ei_nodes_lock; + ei_node_t *ei_nodes; + switch_xml_binding_t *config_fetch_binding; + switch_xml_binding_t *directory_fetch_binding; + switch_xml_binding_t *dialplan_fetch_binding; + switch_xml_binding_t *chatplan_fetch_binding; + switch_xml_binding_t *channels_fetch_binding; + switch_hash_t *event_filter; + int epmdfd; + int num_worker_threads; + switch_bool_t nat_map; + switch_bool_t ei_shortname; + int ei_compat_rel; + char *ip; + char *hostname; + char *ei_cookie; + char *ei_nodename; + char *kazoo_var_prefix; + int var_prefix_length; + uint32_t flags; + int send_all_headers; + int send_all_private_headers; + int connection_timeout; + int receive_timeout; + int receive_msg_preallocate; + int event_stream_preallocate; + int send_msg_batch; + short event_stream_framing; + switch_port_t port; + int config_filters_fetched; + int io_fault_tolerance; +}; +typedef struct globals_s globals_t; +extern globals_t kazoo_globals; + +/* kazoo_node.c */ +switch_status_t new_kazoo_node(int nodefd, ErlConnect *conn); + +/* kazoo_event_stream.c */ +ei_event_stream_t *find_event_stream(ei_event_stream_t *event_streams, const erlang_pid *from); +ei_event_stream_t *new_event_stream(ei_event_stream_t **event_streams, const erlang_pid *from); +switch_status_t remove_event_stream(ei_event_stream_t **event_streams, const erlang_pid *from); +switch_status_t remove_event_streams(ei_event_stream_t **event_streams); +unsigned long get_stream_port(const ei_event_stream_t *event_stream); +switch_status_t add_event_binding(ei_event_stream_t *event_stream, const switch_event_types_t event_type, const char *subclass_name); +switch_status_t remove_event_binding(ei_event_stream_t *event_stream, const switch_event_types_t event_type, const char *subclass_name); +switch_status_t remove_event_bindings(ei_event_stream_t *event_stream); + +/* kazoo_fetch_agent.c */ +switch_status_t bind_fetch_agents(); +switch_status_t unbind_fetch_agents(); +switch_status_t remove_xml_clients(ei_node_t *ei_node); +switch_status_t add_fetch_handler(ei_node_t *ei_node, erlang_pid *from, switch_xml_binding_t *binding); +switch_status_t remove_fetch_handlers(ei_node_t *ei_node, erlang_pid *from); +switch_status_t fetch_reply(char *uuid_str, char *xml_str, switch_xml_binding_t *binding); +switch_status_t handle_api_command_streams(ei_node_t *ei_node, switch_stream_handle_t *stream); + +/* kazoo_utils.c */ +void close_socket(switch_socket_t **sock); +void close_socketfd(int *sockfd); +switch_socket_t *create_socket_with_port(switch_memory_pool_t *pool, switch_port_t port); +switch_socket_t *create_socket(switch_memory_pool_t *pool); +switch_status_t create_ei_cnode(const char *ip_addr, const char *name, struct ei_cnode_s *ei_cnode); +switch_status_t ei_compare_pids(const erlang_pid *pid1, const erlang_pid *pid2); +void ei_encode_switch_event_headers(ei_x_buff *ebuf, switch_event_t *event); +void ei_encode_switch_event_headers_2(ei_x_buff *ebuf, switch_event_t *event, int decode); +void ei_link(ei_node_t *ei_node, erlang_pid * from, erlang_pid * to); +void ei_encode_switch_event(ei_x_buff * ebuf, switch_event_t *event); +int ei_helper_send(ei_node_t *ei_node, erlang_pid* to, ei_x_buff *buf); +int ei_decode_atom_safe(char *buf, int *index, char *dst); +int ei_decode_string_or_binary_limited(char *buf, int *index, int maxsize, char *dst); +int ei_decode_string_or_binary(char *buf, int *index, char **dst); +switch_hash_t *create_default_filter(); /* kazoo_commands.c */ void add_kz_commands(switch_loadable_module_interface_t **module_interface, switch_api_interface_t *api_interface); @@ -34,23 +169,9 @@ void add_kz_commands(switch_loadable_module_interface_t **module_interface, swit /* kazoo_dptools.c */ void add_kz_dptools(switch_loadable_module_interface_t **module_interface, switch_application_interface_t *app_interface); -/* kazoo_api.c */ -void add_cli_api(switch_loadable_module_interface_t **module_interface, switch_api_interface_t *api_interface); -void remove_cli_api(); - -/* kazoo_utils.c */ -char *kazoo_expand_header(switch_memory_pool_t *pool, switch_event_t *event, char *val); -char* switch_event_get_first_of(switch_event_t *event, const char *list[]); -SWITCH_DECLARE(switch_status_t) switch_event_add_variable_name_printf(switch_event_t *event, switch_stack_t stack, const char *val, const char *fmt, ...); -void kz_xml_process(switch_xml_t cfg); - -/* kazoo_tweaks.c */ -void kz_tweaks_start(); -void kz_tweaks_stop(); - -SWITCH_MODULE_LOAD_FUNCTION(mod_kazoo_load); -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_kazoo_shutdown); +#define _ei_x_encode_string(buf, string) { ei_x_encode_binary(buf, string, strlen(string)); } +void fetch_config_filters(); /* For Emacs: * Local Variables: