diff --git a/build/modules.conf.in b/build/modules.conf.in index 7bf59e2acc..8453e290b7 100644 --- a/build/modules.conf.in +++ b/build/modules.conf.in @@ -110,7 +110,6 @@ event_handlers/mod_event_socket #event_handlers/mod_json_cdr #event_handlers/mod_radius_cdr #event_handlers/mod_odbc_cdr -#event_handlers/mod_kazoo #event_handlers/mod_rayo #event_handlers/mod_smpp #event_handlers/mod_snmp diff --git a/build/modules.conf.most b/build/modules.conf.most index fbf8100a90..62595a4891 100644 --- a/build/modules.conf.most +++ b/build/modules.conf.most @@ -104,7 +104,6 @@ event_handlers/mod_event_multicast event_handlers/mod_event_socket event_handlers/mod_format_cdr event_handlers/mod_json_cdr -event_handlers/mod_kazoo #event_handlers/mod_radius_cdr event_handlers/mod_odbc_cdr event_handlers/mod_rayo diff --git a/conf/vanilla/autoload_configs/kazoo.conf.xml b/conf/vanilla/autoload_configs/kazoo.conf.xml deleted file mode 100644 index b730523d4c..0000000000 --- a/conf/vanilla/autoload_configs/kazoo.conf.xml +++ /dev/null @@ -1,215 +0,0 @@ - - - - - - - - - - - - - - - - - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - -
-
-
-
-
-
-
-
-
-
- - - diff --git a/configure.ac b/configure.ac index e4ab33ae5c..348103f8db 100644 --- a/configure.ac +++ b/configure.ac @@ -2208,7 +2208,6 @@ AC_CONFIG_FILES([Makefile src/mod/event_handlers/mod_fail2ban/Makefile src/mod/event_handlers/mod_format_cdr/Makefile src/mod/event_handlers/mod_json_cdr/Makefile - src/mod/event_handlers/mod_kazoo/Makefile src/mod/event_handlers/mod_radius_cdr/Makefile src/mod/event_handlers/mod_odbc_cdr/Makefile src/mod/event_handlers/mod_rayo/Makefile diff --git a/debian/bootstrap.sh b/debian/bootstrap.sh index 75a8957509..aba9e38bf7 100755 --- a/debian/bootstrap.sh +++ b/debian/bootstrap.sh @@ -673,7 +673,6 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}), freeswitch-mod-event-multicast (= \${binary:Version}), freeswitch-mod-event-socket (= \${binary:Version}), freeswitch-mod-json-cdr (= \${binary:Version}), - freeswitch-mod-kazoo (= \${binary:Version}), freeswitch-mod-snmp (= \${binary:Version}), freeswitch-mod-local-stream (= \${binary:Version}), freeswitch-mod-native-file (= \${binary:Version}), @@ -910,7 +909,6 @@ Depends: \${misc:Depends}, freeswitch (= \${binary:Version}), freeswitch-mod-event-multicast-dbg (= \${binary:Version}), freeswitch-mod-event-socket-dbg (= \${binary:Version}), freeswitch-mod-json-cdr-dbg (= \${binary:Version}), - freeswitch-mod-kazoo-dbg (= \${binary:Version}), freeswitch-mod-snmp-dbg (= \${binary:Version}), freeswitch-mod-local-stream-dbg (= \${binary:Version}), freeswitch-mod-native-file-dbg (= \${binary:Version}), diff --git a/debian/control-modules b/debian/control-modules index 3179f8eeef..0f0784d3f5 100644 --- a/debian/control-modules +++ b/debian/control-modules @@ -542,12 +542,6 @@ Module: event_handlers/mod_json_cdr Description: mod_json_cdr Adds mod_json_cdr. -Module: event_handlers/mod_kazoo -Description: mod_kazoo - Adds mod_kazoo. -Build-Depends: erlang-dev -Depends: erlang - Module: event_handlers/mod_odbc_cdr Description: mod_odbc_cdr Adds mod_odbc_cdr. diff --git a/freeswitch.spec b/freeswitch.spec index 9e3d505e80..98ce36cb90 100644 --- a/freeswitch.spec +++ b/freeswitch.spec @@ -952,16 +952,6 @@ Requires: %{name} = %{version}-%{release} %description event-format-cdr JSON and XML Logger for the FreeSWITCH open source telephony platform -%package kazoo -Summary: Kazoo Module for the FreeSWITCH open source telephony platform -Group: System/Libraries -Requires: %{name} = %{version}-%{release} -Requires: erlang -BuildRequires: erlang - -%description kazoo -Kazoo Module for FreeSWITCH. - %package event-multicast Summary: Multicast Event System for the FreeSWITCH open source telephony platform Group: System/Libraries @@ -1480,7 +1470,7 @@ ENDPOINTS_MODULES=" \ ###################################################################################################################### EVENT_HANDLERS_MODULES="event_handlers/mod_cdr_csv event_handlers/mod_cdr_pg_csv event_handlers/mod_cdr_sqlite \ event_handlers/mod_cdr_mongodb event_handlers/mod_format_cdr event_handlers/mod_erlang_event event_handlers/mod_event_multicast \ - event_handlers/mod_event_socket event_handlers/mod_json_cdr event_handlers/mod_kazoo event_handlers/mod_radius_cdr \ + event_handlers/mod_event_socket event_handlers/mod_json_cdr event_handlers/mod_radius_cdr \ event_handlers/mod_snmp" %if %{build_mod_rayo} EVENT_HANDLERS_MODULES+=" event_handlers/mod_rayo" @@ -1916,7 +1906,6 @@ fi %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/http_cache.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/ivr.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/java.conf.xml -%config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/kazoo.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/lcr.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/local_stream.conf.xml %config(noreplace) %attr(0640, freeswitch, daemon) %{sysconfdir}/autoload_configs/logfile.conf.xml @@ -2286,9 +2275,6 @@ fi %files event-json-cdr %{MODINSTDIR}/mod_json_cdr.so* -%files kazoo -%{MODINSTDIR}/mod_kazoo.so* - %files event-radius-cdr %{MODINSTDIR}/mod_radius_cdr.so* diff --git a/src/mod/event_handlers/mod_kazoo/Makefile.am b/src/mod/event_handlers/mod_kazoo/Makefile.am deleted file mode 100644 index 36e7a9ea4a..0000000000 --- a/src/mod/event_handlers/mod_kazoo/Makefile.am +++ /dev/null @@ -1,37 +0,0 @@ -include $(top_srcdir)/build/modmake.rulesam -MODNAME=mod_kazoo - -if HAVE_ERLANG - -KAZOO_DEFS=kazoo_definitions.o - -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 += kazoo_endpoints.c -mod_kazoo_la_SOURCES += kazoo_cdr.c -mod_kazoo_la_SOURCES += kz_node.c - -mod_kazoo_la_CFLAGS = $(AM_CFLAGS) @ERLANG_CFLAGS@ -D_REENTRANT -DERLANG_VERSION=@ERLANG_VERSION@ -DERLANG_MAJOR=@ERLANG_MAJOR@ -DERLANG_MINOR=@ERLANG_MINOR@ -mod_kazoo_la_LIBADD = $(KAZOO_DEFS) $(switch_builddir)/libfreeswitch.la -mod_kazoo_la_LDFLAGS = -avoid-version -module -no-undefined -shared @ERLANG_LDFLAGS@ - -BUILT_SOURCES = $(KAZOO_DEFS) - -$(KAZOO_DEFS): kazoo.conf.xml - -.S.o: $< - @$(CC) $(CFLAGS) -o $@ -c $< - -install-exec-am: - @install `which epmd` $(DESTDIR)$(bindir)/fs_epmd - -else -install: error -all: error -error: - $(error You must install erlang to build this module) -endif 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 4422af121b..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo.conf.xml +++ /dev/null @@ -1,1275 +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 96f9ff7bb4..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_api.c +++ /dev/null @@ -1,573 +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 -#define API_COMMAND_OPTION 4 - -#define API_NODE_OPTION_FRAMING 0 -#define API_NODE_OPTION_KEEPALIVE 1 -#define API_NODE_OPTION_LEGACY 2 -#define API_NODE_OPTION_MAX 99 - -static const char *node_runtime_options[] = { - "event-stream-framing", - "event-stream-keepalive", - "enable-legacy", - NULL -}; - -static int api_find_node_option(char *option) { - int i; - for(i = 0; node_runtime_options[i] != NULL; i++) { - if(!strcasecmp(option, node_runtime_options[i])) { - return i; - } - } - return API_NODE_OPTION_MAX; -} - -static switch_status_t api_get_node_option(ei_node_t *ei_node, switch_stream_handle_t *stream, char *arg) { - int option = api_find_node_option(arg); - switch_status_t ret = SWITCH_STATUS_SUCCESS; - switch (option) { - case API_NODE_OPTION_FRAMING: - stream->write_function(stream, "+OK %i", ei_node->event_stream_framing); - break; - - case API_NODE_OPTION_KEEPALIVE: - stream->write_function(stream, "+OK %i", ei_node->event_stream_keepalive); - break; - - case API_NODE_OPTION_LEGACY: - stream->write_function(stream, "+OK %s", ei_node->legacy ? "true" : "false"); - break; - - default: - stream->write_function(stream, "-ERR invalid option %s", arg); - ret = SWITCH_STATUS_NOTFOUND; - break; - } - - return ret; -} - -static switch_status_t api_set_node_option(ei_node_t *ei_node, switch_stream_handle_t *stream, char *name, char *value) { - int option = api_find_node_option(name); - short val; - switch_status_t ret = SWITCH_STATUS_SUCCESS; - switch (option) { - case API_NODE_OPTION_FRAMING: - val = atoi(value); - if (val != 1 && val != 2 && val != 4) { - stream->write_function(stream, "-ERR Invalid event stream framing value (%i)", val); - ret = SWITCH_STATUS_GENERR; - } else { - stream->write_function(stream, "+OK %i", val); - ei_node->event_stream_framing = val; - } - break; - - case API_NODE_OPTION_KEEPALIVE: - val = switch_true(value); - stream->write_function(stream, "+OK %i", val); - ei_node->event_stream_keepalive = val; - break; - - case API_NODE_OPTION_LEGACY: - ei_node->legacy = switch_true(value); - stream->write_function(stream, "+OK %s", ei_node->legacy ? "true" : "false"); - break; - - default: - stream->write_function(stream, "-ERR invalid option %s", name); - ret = SWITCH_STATUS_NOTFOUND; - break; - } - - return ret; -} - -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; - int idx = 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"); - } - - while(kazoo_globals.kazoo_var_prefixes[idx] != NULL) { - char var[100]; - char *prefix = kazoo_globals.kazoo_var_prefixes[idx]; - sprintf(var, "%s*", prefix); - stream->write_function(stream, "%-50s", var); - idx++; - } - - - 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 { - unsigned int year, day, hour, min, sec, delta; - - delta = (switch_micro_time_now() - event_stream->connected_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:%d -> %s:%d for %d years, %d days, %d hours, %d minutes, %d seconds\n" - ,event_stream->local_ip, event_stream->local_port - ,event_stream->remote_ip, event_stream->remote_port - ,year, day, hour, min, sec); - } - - 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 switch_status_t handle_node_api_command_arg(ei_node_t *ei_node, switch_stream_handle_t *stream, uint32_t command, char *arg) { - - switch (command) { - case API_COMMAND_OPTION: - return api_get_node_option(ei_node, stream, arg); - break; - default: - break; - } - - return SWITCH_STATUS_NOTFOUND; -} - -static switch_status_t handle_node_api_command_args(ei_node_t *ei_node, switch_stream_handle_t *stream, uint32_t command, int argc, char *argv[]) { - - switch (command) { - case API_COMMAND_OPTION: - return api_set_node_option(ei_node, stream, argv[0], argv[1]); - break; - default: - break; - } - - return SWITCH_STATUS_NOTFOUND; -} - -static switch_status_t api_erlang_node_command_arg(switch_stream_handle_t *stream, const char *nodename, uint32_t command, char *arg) { - ei_node_t *ei_node; - switch_status_t ret = SWITCH_STATUS_NOTFOUND; - - 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)) { - ret = handle_node_api_command_arg(ei_node, stream, command, arg); - switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); - return ret ; - } - - ei_node = ei_node->next; - } - switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); - - return ret; -} - -static switch_status_t api_erlang_node_command_args(switch_stream_handle_t *stream, const char *nodename, uint32_t command, int argc, char *argv[]) { - ei_node_t *ei_node; - switch_status_t ret = SWITCH_STATUS_NOTFOUND; - - 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)) { - ret = handle_node_api_command_args(ei_node, stream, command, argc, argv); - switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); - return ret; - } - - ei_node = ei_node->next; - } - switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); - - return ret; -} - -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", 7)) { - unknown_command = 0; - api_erlang_status(stream); - } else if (!strncmp(argv[0], "event_filter", 13)) { - 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", 11)) { - unknown_command = 0; - api_erlang_node_command(stream, argv[1], API_COMMAND_DISCONNECT); - } else if (!strncmp(argv[2], "connection", 11)) { - unknown_command = 0; - api_erlang_node_command(stream, argv[1], API_COMMAND_REMOTE_IP); - } else if (!strncmp(argv[2], "event_streams", 14)) { - unknown_command = 0; - api_erlang_node_command(stream, argv[1], API_COMMAND_STREAMS); - } else if (!strncmp(argv[2], "fetch_bindings", 15)) { - unknown_command = 0; - api_erlang_node_command(stream, argv[1], API_COMMAND_BINDINGS); - } else if (!strncmp(argv[2], "option", 7) && !zstr(argv[3])) { - unknown_command = 0; - if(argc > 4 && !zstr(argv[4])) - api_erlang_node_command_args(stream, argv[1], API_COMMAND_OPTION, argc - 3, &argv[3]); - else - api_erlang_node_command_arg(stream, argv[1], API_COMMAND_OPTION, argv[3]); - } - } - - 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 = NULL; - 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_cdr.c b/src/mod/event_handlers/mod_kazoo/kazoo_cdr.c deleted file mode 100644 index fef66f8be3..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_cdr.c +++ /dev/null @@ -1,630 +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" - -#define MY_EVENT_JSON_CDR "KZ_CDR" - -#define maybe_add_json_string(_json, _name, _string) \ - if (!zstr(_string)) cJSON_AddItemToObject(_json, _name, cJSON_CreateString((char *)_string)) - -static void kz_switch_ivr_set_json_profile_data(cJSON *json, switch_caller_profile_t *caller_profile) -{ - cJSON *soft = NULL; - profile_node_t *pn = NULL; - - maybe_add_json_string(json, "Username", caller_profile->username); - maybe_add_json_string(json, "Dialplan", caller_profile->dialplan); - maybe_add_json_string(json, "ANI", caller_profile->ani); - maybe_add_json_string(json, "ANIII", caller_profile->aniii); - maybe_add_json_string(json, "Caller-ID-Name", caller_profile->caller_id_name); - maybe_add_json_string(json, "Caller-ID-Number", caller_profile->caller_id_number); - maybe_add_json_string(json, "Caller-ID-Original-Name", caller_profile->orig_caller_id_name); - maybe_add_json_string(json, "Caller-ID-Original-Number", caller_profile->orig_caller_id_number); - maybe_add_json_string(json, "Network-Address", caller_profile->network_addr); - maybe_add_json_string(json, "RDNIS", caller_profile->rdnis); - maybe_add_json_string(json, "Destination-Number", caller_profile->destination_number); - maybe_add_json_string(json, "Callee-ID-Name", caller_profile->callee_id_name); - maybe_add_json_string(json, "Callee-ID-Number", caller_profile->callee_id_number); - maybe_add_json_string(json, "UUID", caller_profile->uuid); - maybe_add_json_string(json, "Source", caller_profile->source); - maybe_add_json_string(json, "Context", caller_profile->context); - maybe_add_json_string(json, "Channel-Name", caller_profile->chan_name); - maybe_add_json_string(json, "Profile-UUID", caller_profile->uuid_str); - maybe_add_json_string(json, "Profile-Clone-Of", caller_profile->clone_of); - maybe_add_json_string(json, "Transfer-Source", caller_profile->transfer_source); - cJSON_AddItemToObject(json, "Direction", cJSON_CreateString(caller_profile->direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound")); - cJSON_AddItemToObject(json, "Logical-Direction", cJSON_CreateString(caller_profile->logical_direction == SWITCH_CALL_DIRECTION_OUTBOUND ? "outbound" : "inbound")); - - soft = cJSON_CreateObject(); - for (pn = caller_profile->soft; pn; pn = pn->next) { - maybe_add_json_string(soft, pn->var, pn->val); - } - - cJSON_AddItemToObject(json, "Directory", soft); -} - -SWITCH_DECLARE(void) kz_switch_ivr_set_json_call_flaws(cJSON *json, switch_core_session_t *session, switch_media_type_t type) -{ - const char *name = (type == SWITCH_MEDIA_TYPE_VIDEO) ? "Video" : "Audio"; - cJSON *j_stat; - switch_rtp_stats_t *stats = switch_core_media_get_stats(session, type, NULL); - - if (!stats) return; - - if (!stats->inbound.error_log && !stats->outbound.error_log) return; - - j_stat = cJSON_CreateObject(); - cJSON_AddItemToObject(json, name, j_stat); - - if (stats->inbound.error_log) { - cJSON *j_err_log, *j_err, *j_in; - switch_error_period_t *ep; - - j_in = cJSON_CreateObject(); - cJSON_AddItemToObject(j_stat, "Inbound", j_in); - - j_err_log = cJSON_CreateArray(); - cJSON_AddItemToObject(j_in, "Error-Log", j_err_log); - - for(ep = stats->inbound.error_log; ep; ep = ep->next) { - - if (!(ep->start && ep->stop)) continue; - - j_err = cJSON_CreateObject(); - - cJSON_AddItemToObject(j_err, "Start", cJSON_CreateNumber(ep->start)); - cJSON_AddItemToObject(j_err, "Stop", cJSON_CreateNumber(ep->stop)); - cJSON_AddItemToObject(j_err, "Flaws", cJSON_CreateNumber(ep->flaws)); - cJSON_AddItemToObject(j_err, "Consecutive-Flaws", cJSON_CreateNumber(ep->consecutive_flaws)); - cJSON_AddItemToObject(j_err, "Duration-MS", cJSON_CreateNumber((ep->stop - ep->start) / 1000)); - cJSON_AddItemToArray(j_err_log, j_err); - } - } - - if (stats->outbound.error_log) { - cJSON *j_err_log, *j_err, *j_out; - switch_error_period_t *ep; - - j_out = cJSON_CreateObject(); - cJSON_AddItemToObject(j_stat, "Outbound", j_out); - - j_err_log = cJSON_CreateArray(); - cJSON_AddItemToObject(j_out, "Error-Log", j_err_log); - - for(ep = stats->outbound.error_log; ep; ep = ep->next) { - - if (!(ep->start && ep->stop)) continue; - - j_err = cJSON_CreateObject(); - - cJSON_AddItemToObject(j_err, "Start", cJSON_CreateNumber(ep->start)); - cJSON_AddItemToObject(j_err, "Stop", cJSON_CreateNumber(ep->stop)); - cJSON_AddItemToObject(j_err, "Flaws", cJSON_CreateNumber(ep->flaws)); - cJSON_AddItemToObject(j_err, "Consecutive-Flaws", cJSON_CreateNumber(ep->consecutive_flaws)); - cJSON_AddItemToObject(j_err, "Duration-MS", cJSON_CreateNumber((ep->stop - ep->start) / 1000)); - cJSON_AddItemToArray(j_err_log, j_err); - } - } -} - -#define add_jstat(_j, _i, _s) \ - switch_snprintf(var_val, sizeof(var_val), "%" SWITCH_SIZE_T_FMT, _i); \ - cJSON_AddItemToObject(_j, _s, cJSON_CreateNumber(_i)) - -SWITCH_DECLARE(void) kz_switch_ivr_set_json_call_stats(cJSON *json, switch_core_session_t *session, switch_media_type_t type) -{ - const char *name = (type == SWITCH_MEDIA_TYPE_VIDEO) ? "Video" : "Audio"; - cJSON *j_stat, *j_in, *j_out; - switch_rtp_stats_t *stats = switch_core_media_get_stats(session, type, NULL); - char var_val[35] = ""; - - if (!stats) return; - - j_stat = cJSON_CreateObject(); - j_in = cJSON_CreateObject(); - j_out = cJSON_CreateObject(); - - cJSON_AddItemToObject(json, name, j_stat); - cJSON_AddItemToObject(j_stat, "Inbound", j_in); - cJSON_AddItemToObject(j_stat, "Outbound", j_out); - - stats->inbound.std_deviation = sqrt(stats->inbound.variance); - - add_jstat(j_in, stats->inbound.raw_bytes, "Raw-Bytes"); - add_jstat(j_in, stats->inbound.media_bytes, "Media-Bytes"); - add_jstat(j_in, stats->inbound.packet_count, "Packet-Count"); - add_jstat(j_in, stats->inbound.media_packet_count, "Media-Packet-Count"); - add_jstat(j_in, stats->inbound.skip_packet_count, "Skip-Packet-Count"); - add_jstat(j_in, stats->inbound.jb_packet_count, "Jitter-Packet-Count"); - add_jstat(j_in, stats->inbound.dtmf_packet_count, "DTMF-Packet-Count"); - add_jstat(j_in, stats->inbound.cng_packet_count, "CNG-Packet-Count"); - add_jstat(j_in, stats->inbound.flush_packet_count, "Flush-Packet-Count"); - add_jstat(j_in, stats->inbound.largest_jb_size, "Largest-JB-Size"); - add_jstat(j_in, stats->inbound.min_variance, "Jitter-Min-Variance"); - add_jstat(j_in, stats->inbound.max_variance, "Jitter-Max-Variance"); - add_jstat(j_in, stats->inbound.lossrate, "Jitter-Loss-Rate"); - add_jstat(j_in, stats->inbound.burstrate, "Jitter-Burst-Rate"); - add_jstat(j_in, stats->inbound.mean_interval, "Mean-Interval"); - add_jstat(j_in, stats->inbound.flaws, "Flaw-Total"); - add_jstat(j_in, stats->inbound.R, "Quality-Percentage"); - add_jstat(j_in, stats->inbound.mos, "MOS"); - - - add_jstat(j_out, stats->outbound.raw_bytes, "Raw-Bytes"); - add_jstat(j_out, stats->outbound.media_bytes, "Media-Bytes"); - add_jstat(j_out, stats->outbound.packet_count, "Packet-Count"); - add_jstat(j_out, stats->outbound.media_packet_count, "Media-Packet-Count"); - add_jstat(j_out, stats->outbound.skip_packet_count, "Skip-Packet-Count"); - add_jstat(j_out, stats->outbound.dtmf_packet_count, "DTMF-Packet-Count"); - add_jstat(j_out, stats->outbound.cng_packet_count, "CNG-Packet-Count"); - add_jstat(j_out, stats->rtcp.packet_count, "RTCP-Packet-Count"); - add_jstat(j_out, stats->rtcp.octet_count, "RTCP-Octet-Count"); -} - -static switch_status_t kz_report_channel_flaws(switch_core_session_t *session, switch_event_t *cdr_event) -{ - cJSON *callStats = cJSON_CreateObject(); - - kz_switch_ivr_set_json_call_flaws(callStats, session, SWITCH_MEDIA_TYPE_AUDIO); - kz_switch_ivr_set_json_call_flaws(callStats, session, SWITCH_MEDIA_TYPE_VIDEO); - - switch_event_add_header_string_nodup(cdr_event, SWITCH_STACK_BOTTOM, "_json_channel_media_errors", cJSON_PrintUnformatted(callStats)); - - cJSON_Delete(callStats); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t kz_report_channel_stats(switch_core_session_t *session, switch_event_t *cdr_event) -{ - cJSON *callStats = cJSON_CreateObject(); - - kz_switch_ivr_set_json_call_stats(callStats, session, SWITCH_MEDIA_TYPE_AUDIO); - kz_switch_ivr_set_json_call_stats(callStats, session, SWITCH_MEDIA_TYPE_VIDEO); - - switch_event_add_header_string_nodup(cdr_event, SWITCH_STACK_BOTTOM, "_json_channel_stats", cJSON_PrintUnformatted(callStats)); - - cJSON_Delete(callStats); - - return SWITCH_STATUS_SUCCESS; - -} - -static switch_status_t kz_report_app_log(switch_core_session_t *session, switch_event_t *cdr_event) -{ - switch_app_log_t *ap, *app_log = switch_core_session_get_app_log(session); - cJSON *j_apps = NULL; - - if (!app_log) { - return SWITCH_STATUS_FALSE; - } - - j_apps = cJSON_CreateArray(); - - for (ap = app_log; ap; ap = ap->next) { - cJSON *j_application = cJSON_CreateObject(); - cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->app)); - cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(ap->arg)); - cJSON_AddItemToObject(j_application, "app_stamp", cJSON_CreateNumber(ap->stamp)); - cJSON_AddItemToArray(j_apps, j_application); - } - - switch_event_add_header_string_nodup(cdr_event, SWITCH_STACK_BOTTOM, "_json_application_log", cJSON_PrintUnformatted(j_apps)); - - cJSON_Delete(j_apps); - - return SWITCH_STATUS_SUCCESS; - -} - -static switch_status_t kz_report_callflow_extension(switch_caller_profile_t *caller_profile, cJSON *j_profile) -{ - cJSON *j_caller_extension, *j_caller_extension_apps, *j_application, *j_inner_extension; - if (caller_profile->caller_extension) { - switch_caller_application_t *ap; - - j_caller_extension = cJSON_CreateObject(); - j_caller_extension_apps = cJSON_CreateArray(); - - cJSON_AddItemToObject(j_profile, "extension", j_caller_extension); - - cJSON_AddItemToObject(j_caller_extension, "name", cJSON_CreateString(caller_profile->caller_extension->extension_name)); - cJSON_AddItemToObject(j_caller_extension, "number", cJSON_CreateString(caller_profile->caller_extension->extension_number)); - cJSON_AddItemToObject(j_caller_extension, "applications", j_caller_extension_apps); - - if (caller_profile->caller_extension->current_application) { - cJSON_AddItemToObject(j_caller_extension, "current_app", cJSON_CreateString(caller_profile->caller_extension->current_application->application_name)); - } - - for (ap = caller_profile->caller_extension->applications; ap; ap = ap->next) { - j_application = cJSON_CreateObject(); - - cJSON_AddItemToArray(j_caller_extension_apps, j_application); - - if (ap == caller_profile->caller_extension->current_application) { - cJSON_AddItemToObject(j_application, "last_executed", cJSON_CreateString("true")); - } - cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->application_name)); - cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(switch_str_nil(ap->application_data))); - } - - if (caller_profile->caller_extension->children) { - switch_caller_profile_t *cp = NULL; - j_inner_extension = cJSON_CreateArray(); - cJSON_AddItemToObject(j_caller_extension, "sub_extensions", j_inner_extension); - for (cp = caller_profile->caller_extension->children; cp; cp = cp->next) { - - if (!cp->caller_extension) { - continue; - } - - j_caller_extension = cJSON_CreateObject(); - cJSON_AddItemToArray(j_inner_extension, j_caller_extension); - - cJSON_AddItemToObject(j_caller_extension, "name", cJSON_CreateString(cp->caller_extension->extension_name)); - cJSON_AddItemToObject(j_caller_extension, "number", cJSON_CreateString(cp->caller_extension->extension_number)); - - cJSON_AddItemToObject(j_caller_extension, "dialplan", cJSON_CreateString((char *)cp->dialplan)); - - if (cp->caller_extension->current_application) { - cJSON_AddItemToObject(j_caller_extension, "current_app", cJSON_CreateString(cp->caller_extension->current_application->application_name)); - } - - j_caller_extension_apps = cJSON_CreateArray(); - cJSON_AddItemToObject(j_caller_extension, "applications", j_caller_extension_apps); - for (ap = cp->caller_extension->applications; ap; ap = ap->next) { - j_application = cJSON_CreateObject(); - cJSON_AddItemToArray(j_caller_extension_apps, j_application); - - if (ap == cp->caller_extension->current_application) { - cJSON_AddItemToObject(j_application, "last_executed", cJSON_CreateString("true")); - } - cJSON_AddItemToObject(j_application, "app_name", cJSON_CreateString(ap->application_name)); - cJSON_AddItemToObject(j_application, "app_data", cJSON_CreateString(switch_str_nil(ap->application_data))); - } - } - } - } - - return SWITCH_STATUS_SUCCESS; - -} - -static switch_status_t kz_report_callflow(switch_core_session_t *session, switch_event_t *cdr_event) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_caller_profile_t *caller_profile; - cJSON *j_main_cp, *j_times, *j_callflow, *j_profile, *j_o; - - - caller_profile = switch_channel_get_caller_profile(channel); - - j_callflow = cJSON_CreateArray(); - - while (caller_profile) { - - j_profile = cJSON_CreateObject(); - - if (!zstr(caller_profile->dialplan)) { - cJSON_AddItemToObject(j_profile, "dialplan", cJSON_CreateString((char *)caller_profile->dialplan)); - } - - if (!zstr(caller_profile->profile_index)) { - cJSON_AddItemToObject(j_profile, "profile_index", cJSON_CreateString((char *)caller_profile->profile_index)); - } - - kz_report_callflow_extension(caller_profile, j_profile); - - j_main_cp = cJSON_CreateObject(); - cJSON_AddItemToObject(j_profile, "Caller-Profile", j_main_cp); - - kz_switch_ivr_set_json_profile_data(j_main_cp, caller_profile); - - if (caller_profile->originator_caller_profile) { - j_o = cJSON_CreateObject(); - cJSON_AddItemToObject(j_main_cp, "originator", j_o); - kz_switch_ivr_set_json_profile_data(j_o, caller_profile->originator_caller_profile); - kz_report_callflow_extension(caller_profile->originator_caller_profile, j_o); - } - - if (caller_profile->originatee_caller_profile) { - j_o = cJSON_CreateObject(); - cJSON_AddItemToObject(j_main_cp, "originatee", j_o); - kz_switch_ivr_set_json_profile_data(j_o, caller_profile->originatee_caller_profile); - kz_report_callflow_extension(caller_profile->originatee_caller_profile, j_o); - } - - if (caller_profile->times) { - j_times = cJSON_CreateObject(); - cJSON_AddItemToObject(j_profile, "Time", j_times); - cJSON_AddItemToObject(j_times, "Created", cJSON_CreateNumber(caller_profile->times->created)); - cJSON_AddItemToObject(j_times, "Profile-Created", cJSON_CreateNumber(caller_profile->times->profile_created)); - cJSON_AddItemToObject(j_times, "Progress", cJSON_CreateNumber(caller_profile->times->progress)); - cJSON_AddItemToObject(j_times, "Progress-Media", cJSON_CreateNumber(caller_profile->times->progress_media)); - cJSON_AddItemToObject(j_times, "Answered", cJSON_CreateNumber(caller_profile->times->answered)); - cJSON_AddItemToObject(j_times, "Bridged", cJSON_CreateNumber(caller_profile->times->bridged)); - cJSON_AddItemToObject(j_times, "Last-Hold", cJSON_CreateNumber(caller_profile->times->last_hold)); - cJSON_AddItemToObject(j_times, "Hold-Accumulated", cJSON_CreateNumber(caller_profile->times->hold_accum)); - cJSON_AddItemToObject(j_times, "Hangup", cJSON_CreateNumber(caller_profile->times->hungup)); - cJSON_AddItemToObject(j_times, "Resurrect", cJSON_CreateNumber(caller_profile->times->resurrected)); - cJSON_AddItemToObject(j_times, "Transfer", cJSON_CreateNumber(caller_profile->times->transferred)); - } - cJSON_AddItemToArray(j_callflow, j_profile); - caller_profile = caller_profile->next; - } - - switch_event_add_header_string_nodup(cdr_event, SWITCH_STACK_BOTTOM, "_json_callflow", cJSON_PrintUnformatted(j_callflow)); - - cJSON_Delete(j_callflow); - - - return SWITCH_STATUS_SUCCESS; - -} - - -#define ORIGINATED_LEGS_VARIABLE "originated_legs" -#define ORIGINATED_LEGS_ITEM_DELIM ';' - -#define ORIGINATE_CAUSES_VARIABLE "originate_causes" -#define ORIGINATE_CAUSES_ITEM_DELIM ';' - -static switch_status_t kz_report_originated_legs(switch_core_session_t *session, switch_event_t *cdr_event) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - cJSON *j_originated = cJSON_CreateArray(); - const char *originated_legs_var = NULL, *originate_causes_var = NULL; - int idx = 0; - - while(1) { - char *argv_leg[10] = { 0 }, *argv_cause[10] = { 0 }; - char *originated_legs, *originate_causes; - cJSON *j_originated_leg; - originated_legs_var = switch_channel_get_variable_dup(channel, ORIGINATED_LEGS_VARIABLE, SWITCH_FALSE, idx); - originate_causes_var = switch_channel_get_variable_dup(channel, ORIGINATE_CAUSES_VARIABLE, SWITCH_FALSE, idx); - - if (zstr(originated_legs_var) || zstr(originate_causes_var)) { - break; - } - - originated_legs = strdup(originated_legs_var); - originate_causes = strdup(originate_causes_var); - - switch_separate_string(originated_legs, ORIGINATED_LEGS_ITEM_DELIM, argv_leg, (sizeof(argv_leg) / sizeof(argv_leg[0]))); - switch_separate_string(originate_causes, ORIGINATE_CAUSES_ITEM_DELIM, argv_cause, (sizeof(argv_cause) / sizeof(argv_cause[0]))); - - j_originated_leg = cJSON_CreateObject(); - cJSON_AddItemToObject(j_originated_leg, "Call-ID", cJSON_CreateString(argv_leg[0])); - cJSON_AddItemToObject(j_originated_leg, "Caller-ID-Name", cJSON_CreateString(argv_leg[1])); - cJSON_AddItemToObject(j_originated_leg, "Caller-ID-Number", cJSON_CreateString(argv_leg[2])); - cJSON_AddItemToObject(j_originated_leg, "Result", cJSON_CreateString(argv_cause[1])); - - cJSON_AddItemToArray(j_originated, j_originated_leg); - - switch_safe_free(originated_legs); - switch_safe_free(originate_causes); - - idx++; - } - - switch_event_add_header_string_nodup(cdr_event, SWITCH_STACK_BOTTOM, "_json_originated_legs", cJSON_PrintUnformatted(j_originated)); - - cJSON_Delete(j_originated); - - return SWITCH_STATUS_SUCCESS; -} - -#define MAX_HISTORY 50 -#define HST_ARRAY_DELIM "|:" -#define HST_ITEM_DELIM ':' - -static void kz_report_transfer_history_item(char* value, cJSON *json) -{ - char *argv[4] = { 0 }; - char *item = strdup(value); - int argc = switch_separate_string(item, HST_ITEM_DELIM, argv, (sizeof(argv) / sizeof(argv[0]))); - cJSON *jitem = cJSON_CreateObject(); - char *epoch = NULL, *callid = NULL, *type = NULL; - int add = 0; - if(argc == 4) { - add = 1; - epoch = argv[0]; - callid = argv[1]; - type = argv[2]; - - if(!strncmp(type, "bl_xfer", 7)) { - //char *split = strchr(argv[3], '/'); - //if(split) *(split++) = '\0'; - cJSON_AddItemToObject(jitem, "Caller-Profile-ID", cJSON_CreateString(callid)); - cJSON_AddItemToObject(jitem, "Type", cJSON_CreateString("blind")); - cJSON_AddItemToObject(jitem, "Extension", cJSON_CreateString(argv[3])); - cJSON_AddItemToObject(jitem, "Timestamp", cJSON_CreateNumber(strtod(epoch, NULL))); - } else if(!strncmp(type, "att_xfer", 8)) { - char *split = strchr(argv[3], '/'); - if(split) { - *(split++) = '\0'; - cJSON_AddItemToObject(jitem, "Caller-Profile-ID", cJSON_CreateString(callid)); - cJSON_AddItemToObject(jitem, "Type", cJSON_CreateString("attended")); - cJSON_AddItemToObject(jitem, "Transferee", cJSON_CreateString(argv[3])); - cJSON_AddItemToObject(jitem, "Transferer", cJSON_CreateString(split)); - cJSON_AddItemToObject(jitem, "Timestamp", cJSON_CreateNumber(strtod(epoch, NULL))); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER TYPE '%s' NOT HANDLED => %s\n", type, item); - add = 0; - } - } else if(!strncmp(type, "uuid_br", 7)) { - cJSON_AddItemToObject(jitem, "Caller-Profile-ID", cJSON_CreateString(callid)); - cJSON_AddItemToObject(jitem, "Type", cJSON_CreateString("bridge")); - cJSON_AddItemToObject(jitem, "Other-Leg", cJSON_CreateString(argv[3])); - cJSON_AddItemToObject(jitem, "Timestamp", cJSON_CreateNumber(strtod(epoch, NULL))); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER TYPE '%s' NOT HANDLED => %s\n", type, item); - add = 0; - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TRANSFER TYPE SPLIT ERROR %i => %s\n", argc, item); - } - if(add) { - cJSON_AddItemToArray(json, jitem); - } else { - cJSON_Delete(jitem); - } - switch_safe_free(item); -} - -static switch_status_t kz_report_transfer_history(switch_core_session_t *session, switch_event_t *cdr_event, const char* var_name) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - cJSON *j_transfer = NULL; - char *tmp_history = NULL, *history = NULL, *argv[MAX_HISTORY] = { 0 }; - char event_header[50]; - int n, argc = 0; - const char *transfer_var = switch_channel_get_variable_dup(channel, var_name, SWITCH_FALSE, -1); - if (zstr(transfer_var)) { - return SWITCH_STATUS_SUCCESS; - } - - if (!(tmp_history = strdup(transfer_var))) { - return SWITCH_STATUS_SUCCESS; - } - - sprintf(event_header, "_json_%s", var_name); - history = tmp_history; - j_transfer = cJSON_CreateArray(); - - if (!strncmp(history, "ARRAY::", 7)) { - history += 7; - argc = switch_separate_string_string(history, HST_ARRAY_DELIM, argv, (sizeof(argv) / sizeof(argv[0]))); - for(n=0; n < argc; n++) { - kz_report_transfer_history_item(argv[n], j_transfer); - } - switch_event_add_header_string_nodup(cdr_event, SWITCH_STACK_BOTTOM, event_header, cJSON_PrintUnformatted(j_transfer)); - } else if (strchr(history, HST_ITEM_DELIM)) { - kz_report_transfer_history_item(history, j_transfer); - switch_event_add_header_string_nodup(cdr_event, SWITCH_STACK_BOTTOM, event_header, cJSON_PrintUnformatted(j_transfer)); - } - cJSON_Delete(j_transfer); - switch_safe_free(tmp_history); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t kz_report(switch_core_session_t *session, switch_event_t *cdr_event) -{ - kz_report_app_log(session, cdr_event); - kz_report_callflow(session, cdr_event); - kz_report_channel_stats(session, cdr_event); - kz_report_channel_flaws(session, cdr_event); - kz_report_originated_legs(session, cdr_event); - kz_report_transfer_history(session, cdr_event, SWITCH_TRANSFER_HISTORY_VARIABLE); - kz_report_transfer_history(session, cdr_event, SWITCH_TRANSFER_SOURCE_VARIABLE); - return SWITCH_STATUS_SUCCESS; -} - - -static switch_status_t kz_cdr_on_reporting(switch_core_session_t *session) -{ - switch_event_t *cdr_event = NULL; - switch_channel_t *channel = switch_core_session_get_channel(session); - - if (switch_event_create_subclass(&cdr_event, SWITCH_EVENT_CUSTOM, MY_EVENT_JSON_CDR) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "error creating event for report data!\n"); - return SWITCH_STATUS_FALSE; - } - - kz_report(session, cdr_event); - switch_channel_event_set_data(channel, cdr_event); - switch_event_fire(&cdr_event); - - return SWITCH_STATUS_SUCCESS; -} - - -static switch_state_handler_table_t kz_cdr_state_handlers = { - /*.on_init */ NULL, - /*.on_routing */ NULL, - /*.on_execute */ NULL, - /*.on_hangup */ NULL, - /*.on_exchange_media */ NULL, - /*.on_soft_execute */ NULL, - /*.on_consume_media */ NULL, - /*.on_hibernate */ NULL, - /*.on_reset */ NULL, - /*.on_park */ NULL, - /*.on_reporting */ kz_cdr_on_reporting -}; - - -static void kz_cdr_register_state_handlers() -{ - switch_core_add_state_handler(&kz_cdr_state_handlers); -} - -static void kz_cdr_unregister_state_handlers() -{ - switch_core_remove_state_handler(&kz_cdr_state_handlers); -} - -static void kz_cdr_register_events() -{ - if (switch_event_reserve_subclass(MY_EVENT_JSON_CDR) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass %s!\n", MY_EVENT_JSON_CDR); - } -} - -static void kz_cdr_unregister_events() -{ - switch_event_free_subclass(MY_EVENT_JSON_CDR); -} - - -void kz_cdr_start() -{ - kz_cdr_register_events(); - kz_cdr_register_state_handlers(); -} - -void kz_cdr_stop() -{ - kz_cdr_unregister_state_handlers(); - kz_cdr_unregister_events(); -} - -/* For Emacs: - * Local Variables: - * mode:c - * indent-tabs-mode:t - * tab-width:4 - * c-basic-offset:4 - * End: - * For VIM: - * vim:set softtabstop=4 shiftwidth=4 tabstop=4: - */ diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_commands.c b/src/mod/event_handlers/mod_kazoo/kazoo_commands.c deleted file mode 100644 index 16f00ad1a0..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_commands.c +++ /dev/null @@ -1,592 +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 - * - * - * kazoo_commands.c -- clones of mod_commands commands slightly modified for kazoo - * - */ -#include "mod_kazoo.h" -#include -#include - -#define UUID_SET_DESC "Set a variable" -#define UUID_SET_SYNTAX " [value]" - -#define UUID_MULTISET_DESC "Set multiple variables" -#define UUID_MULTISET_SYNTAX " =;=..." - -#define KZ_HTTP_PUT_DESC "upload a local freeswitch file to a url" -#define KZ_HTTP_PUT_SYNTAX "localfile url" - -#define KZ_FIRST_OF_DESC "returns first-of existing event header in params" -#define KZ_FIRST_OF_SYNTAX "list of headers to check" - -#define MAX_FIRST_OF 25 - -SWITCH_STANDARD_API(kz_first_of) -{ - char delim = '|'; - char *mycmd = NULL, *mycmd_dup = NULL, *argv[MAX_FIRST_OF] = { 0 }; - int n, argc = 0; - switch_event_header_t *header = NULL; - switch_channel_t *channel = NULL; - - if (zstr(cmd)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "invalid arg\n"); - return SWITCH_STATUS_GENERR; - } - - if ( session ) { - channel = switch_core_session_get_channel(session); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "GOT CHANNEL\n"); - } - - mycmd_dup = mycmd = strdup(cmd); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "FIRST-OF %s\n", mycmd); - if (!zstr(mycmd) && *mycmd == '^' && *(mycmd+1) == '^') { - mycmd += 2; - delim = *mycmd++; - } - argc = switch_separate_string(mycmd, delim, argv, (sizeof(argv) / sizeof(argv[0]))); - for(n=0; n < argc; n++) { - char* item = argv[n]; - if(*item == '#' || *item == '!' || *item == '?') { - if(*(++item) != '\0') { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "RETURNING default %s\n", item); - stream->write_function(stream, item); - break; - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "CHECKING %s\n", item); - if (channel) { - const char *var = switch_channel_get_variable_dup(channel, item, SWITCH_FALSE, -1); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "CHECKING CHANNEL %s\n", item); - if (var) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "GOT FROM CHANNEL %s => %s\n", item, var); - stream->write_function(stream, var); - break; - } - if (!strncmp(item, "variable_", 9)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "CHECKING CHANNEL %s\n", item+9); - var = switch_channel_get_variable_dup(channel, item+9, SWITCH_FALSE, -1); - if (var) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "GOT FROM CHANNEL %s => %s\n", item+9, var); - stream->write_function(stream, var); - break; - } - } - } - header = switch_event_get_header_ptr(stream->param_event, item); - if(header) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "RETURNING %s : %s\n", item, header->value); - stream->write_function(stream, header->value); - break; - } - } - } - - switch_safe_free(mycmd_dup); - return SWITCH_STATUS_SUCCESS; -} - -switch_status_t kz_uuid_setvar(int urldecode, const char *cmd, switch_core_session_t *session, switch_stream_handle_t *stream) -{ - switch_core_session_t *psession = NULL; - char *mycmd = NULL, *argv[3] = { 0 }; - int argc = 0; - - if (!zstr(cmd) && (mycmd = strdup(cmd))) { - argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); - if ((argc == 2 || argc == 3) && !zstr(argv[0])) { - char *uuid = argv[0]; - char *var_name = argv[1]; - char *var_value = NULL; - - if (argc == 3) { - var_value = argv[2]; - } - - if ((psession = switch_core_session_locate(uuid))) { - switch_channel_t *channel; - switch_event_t *event; - channel = switch_core_session_get_channel(psession); - - if (zstr(var_name)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n"); - stream->write_function(stream, "-ERR No variable specified\n"); - } else { - if(urldecode) { - switch_url_decode(var_value); - } - switch_channel_set_variable(channel, var_name, var_value); - kz_check_set_profile_var(channel, var_name, var_value); - stream->write_function(stream, "+OK\n"); - } - - 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(psession); - - } else { - stream->write_function(stream, "-ERR No such channel!\n"); - } - goto done; - } - } - - stream->write_function(stream, "-USAGE: %s\n", UUID_SET_SYNTAX); - - done: - switch_safe_free(mycmd); - return SWITCH_STATUS_SUCCESS; -} - -SWITCH_STANDARD_API(uuid_setvar_function) -{ - return kz_uuid_setvar(0, cmd, session, stream); -} - -SWITCH_STANDARD_API(uuid_setvar_encoded_function) -{ - return kz_uuid_setvar(1, cmd, session, stream); -} - -switch_status_t kz_uuid_setvar_multi(int urldecode, const char *cmd, switch_core_session_t *session, switch_stream_handle_t *stream) -{ - switch_core_session_t *psession = NULL; - char delim = ';'; - char *mycmd = NULL, *vars, *argv[64] = { 0 }; - int argc = 0; - char *var_name, *var_value = NULL; - - if (!zstr(cmd) && (mycmd = strdup(cmd))) { - char *uuid = mycmd; - if (!(vars = strchr(uuid, ' '))) { - goto done; - } - *vars++ = '\0'; - if (*vars == '^' && *(vars+1) == '^') { - vars += 2; - delim = *vars++; - } - if ((psession = switch_core_session_locate(uuid))) { - switch_channel_t *channel = switch_core_session_get_channel(psession); - switch_event_t *event; - int x, y = 0; - argc = switch_separate_string(vars, delim, argv, (sizeof(argv) / sizeof(argv[0]))); - - for (x = 0; x < argc; x++) { - var_name = argv[x]; - if (var_name && (var_value = strchr(var_name, '='))) { - *var_value++ = '\0'; - } - if (zstr(var_name)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n"); - stream->write_function(stream, "-ERR No variable specified\n"); - } else { - if(urldecode) { - switch_url_decode(var_value); - } - switch_channel_set_variable(channel, var_name, var_value); - kz_check_set_profile_var(channel, var_name, var_value); - - y++; - } - } - - /* keep kazoo nodes in sync */ - 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(psession); - if (y) { - stream->write_function(stream, "+OK\n"); - goto done; - } - } else { - stream->write_function(stream, "-ERR No such channel!\n"); - } - } - - stream->write_function(stream, "-USAGE: %s\n", UUID_MULTISET_SYNTAX); - - done: - switch_safe_free(mycmd); - return SWITCH_STATUS_SUCCESS; -} - -SWITCH_STANDARD_API(uuid_setvar_multi_function) -{ - return kz_uuid_setvar_multi(0, cmd, session, stream); -} - -SWITCH_STANDARD_API(uuid_setvar_multi_encoded_function) -{ - return kz_uuid_setvar_multi(1, cmd, session, stream); -} - -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; - int len = strlen(buffer); - char buf[1024]; - if(len > 2 && len < 1024) { - snprintf(buf, sizeof(buf), "%s", buffer); - switch_event_add_header_string(event, SWITCH_STACK_PUSH | SWITCH_STACK_BOTTOM, "Reply-Headers", buf); - } - return nitems * size; -} - -SWITCH_STANDARD_API(kz_http_put) -{ - switch_status_t status = SWITCH_STATUS_SUCCESS; - switch_memory_pool_t *lpool = NULL; - switch_memory_pool_t *pool = NULL; - char *args = NULL; - char *argv[10] = { 0 }; - int argc = 0; - switch_event_t *params = NULL; - char *url = NULL; - char *filename = NULL; - int delete_file = 0; - - switch_curl_slist_t *headers = NULL; /* optional linked-list of HTTP headers */ - char *ext; /* file extension, used for MIME type identification */ - const char *mime_type = "application/octet-stream"; - char *buf = NULL; - char *error = NULL; - - CURL *curl_handle = NULL; - long httpRes = 0; - struct stat file_info = {0}; - FILE *file_to_put = NULL; - - if (session) { - pool = switch_core_session_get_pool(session); - } else { - switch_core_new_memory_pool(&lpool); - pool = lpool; - } - - if (zstr(cmd)) { - stream->write_function(stream, "USAGE: %s\n", KZ_HTTP_PUT_SYNTAX); - status = SWITCH_STATUS_SUCCESS; - goto done; - } - - args = strdup(cmd); - argc = switch_separate_string(args, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); - if (argc != 2) { - stream->write_function(stream, "USAGE: %s\n", KZ_HTTP_PUT_SYNTAX); - status = SWITCH_STATUS_SUCCESS; - goto done; - } - - /* parse params and get profile */ - url = switch_core_strdup(pool, argv[0]); - if (*url == '{') { - if (switch_event_create_brackets(url, '{', '}', ',', ¶ms, &url, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { - status = SWITCH_STATUS_FALSE; - stream->write_function(stream, "-ERR error parsing parameters\n"); - goto done; - } - } - - filename = switch_core_strdup(pool, argv[1]); - - /* guess what type of mime content this is going to be */ - if ((ext = strrchr(filename, '.'))) { - ext++; - if (!(mime_type = switch_core_mime_ext2type(ext))) { - mime_type = "application/octet-stream"; - } - } - - buf = switch_mprintf("Content-Type: %s", mime_type); - headers = switch_curl_slist_append(headers, buf); - - /* open file and get the file size */ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "opening %s for upload to %s\n", filename, url); - - /* libcurl requires FILE* */ - file_to_put = fopen(filename, "rb"); - if (!file_to_put) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "fopen() error: %s\n", strerror(errno)); - stream->write_function(stream, "-ERR error opening file\n"); - status = SWITCH_STATUS_FALSE; - goto done; - } - - if (fstat(fileno(file_to_put), &file_info) == -1) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "fstat() error: %s\n", strerror(errno)); - stream->write_function(stream, "-ERR fstat error\n"); - goto done; - } - - curl_handle = switch_curl_easy_init(); - if (!curl_handle) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "switch_curl_easy_init() failure\n"); - status = SWITCH_STATUS_FALSE; - stream->write_function(stream, "-ERR switch_curl_easy init failure\n"); - goto done; - } - switch_curl_easy_setopt(curl_handle, CURLOPT_UPLOAD, 1); -#if !defined(LIBCURL_VERSION_NUM) || (LIBCURL_VERSION_NUM < 0x070c01) - switch_curl_easy_setopt(curl_handle, CURLOPT_PUT, 1); -#endif - switch_curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, 1); - switch_curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers); - switch_curl_easy_setopt(curl_handle, CURLOPT_URL, url); - switch_curl_easy_setopt(curl_handle, CURLOPT_READDATA, file_to_put); - switch_curl_easy_setopt(curl_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size); - switch_curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1); - switch_curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10); - switch_curl_easy_setopt(curl_handle, CURLOPT_FAILONERROR, 1); - switch_curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "freeswitch-kazoo/1.0"); - switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERDATA, stream->param_event); - switch_curl_easy_setopt(curl_handle, CURLOPT_HEADERFUNCTION, header_callback); - switch_curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, body_callback); - - 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); - switch_curl_easy_cleanup(curl_handle); - - 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_file = 1; - } 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); - status = SWITCH_STATUS_GENERR; - } - -done: - if (file_to_put) { - fclose(file_to_put); - if(delete_file) { - remove(filename); - } - } - - if (headers) { - switch_curl_slist_free_all(headers); - } - - switch_safe_free(buf); - switch_safe_free(error); - - switch_safe_free(args); - - if (lpool) { - switch_core_destroy_memory_pool(&lpool); - } - - if (params) { - switch_event_destroy(¶ms); - } - - return status; -} - -SWITCH_STANDARD_API(kz_expand_api) -{ - char *p = NULL, *input = NULL; - char *uuid = NULL, *mycmd; - - if (zstr(cmd)) { - stream->write_function(stream, "-ERR invalid input"); - return SWITCH_STATUS_GENERR; - } - - if (!(mycmd = strdup(cmd))) { - stream->write_function(stream, "-ERR no memory"); - return SWITCH_STATUS_GENERR; - } - - if (!strncasecmp(mycmd, "uuid:", 5)) { - uuid = mycmd + 5; - if ((input = strchr(uuid, ' ')) != NULL) { - *input++ = '\0'; - } else { - stream->write_function(stream, "-ERR invalid argument"); - switch_safe_free(mycmd); - return SWITCH_STATUS_GENERR; - } - } else { - input = mycmd; - } - - p = kz_expand(input, uuid); - stream->write_function(stream, "+OK %s", p); - if (p != input) { - switch_safe_free(p); - } - switch_safe_free(mycmd); - return SWITCH_STATUS_SUCCESS; -} - -SWITCH_STANDARD_API(kz_eval_api) -{ - char *p = NULL, *input = NULL; - char *uuid = NULL, *mycmd; - switch_core_session_t *nsession = NULL; - switch_channel_t *channel = NULL; - - - if (zstr(cmd)) { - stream->write_function(stream, "-ERR invalid input"); - return SWITCH_STATUS_GENERR; - } - - if (!(mycmd = strdup(cmd))) { - stream->write_function(stream, "-ERR no memory"); - return SWITCH_STATUS_GENERR; - } - - if (!strncasecmp(mycmd, "uuid:", 5)) { - uuid = mycmd + 5; - if ((input = strchr(uuid, ' ')) != NULL) { - *input++ = '\0'; - if ((nsession = switch_core_session_locate(uuid)) != NULL) { - channel = switch_core_session_get_channel(nsession); - } else { - stream->write_function(stream, "-ERR invalid session"); - switch_safe_free(mycmd); - return SWITCH_STATUS_GENERR; - } - } else { - stream->write_function(stream, "-ERR invalid argument"); - switch_safe_free(mycmd); - return SWITCH_STATUS_GENERR; - } - } else if (session == NULL) { - stream->write_function(stream, "-ERR invalid argument"); - switch_safe_free(mycmd); - return SWITCH_STATUS_GENERR; - } else { - channel = switch_core_session_get_channel(session); - input = mycmd; - } - - p = switch_channel_expand_variables_check(channel, input, NULL, NULL, 0); - stream->write_function(stream, "+OK %s", p); - if (p != input) { - switch_safe_free(p); - } - switch_safe_free(mycmd); - if (nsession) { - switch_core_session_rwunlock(nsession); - } - return SWITCH_STATUS_SUCCESS; -} - -#define KZ_CONTACT_DESC "returns kazoo contact" -#define KZ_CONTACT_SYNTAX "endpoint@account" - -SWITCH_STANDARD_API(kz_contact_fun) -{ - switch_event_t *params = NULL; - const char *var = NULL; - switch_xml_t xml_node = NULL; - switch_xml_t xml_root = NULL; - - const char *reply = "error/subscriber_absent"; - - if (!cmd) { - stream->write_function(stream, "%s", reply); - return SWITCH_STATUS_SUCCESS; - } - - switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS); - switch_assert(params); - switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "action", "call"); - switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Fetch-Exclude-Cache", "true"); - - /* - if (stream->param_event) { - switch_event_merge(params, stream->param_event); - } - */ - - /* - if (session) { - switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Fetch-Call-UUID", switch_core_session_get_uuid(session)); - } else if (stream->param_event && (var = switch_event_get_header(stream->param_event, "ent_originate_aleg_uuid")) != NULL) { - switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Fetch-Call-UUID", var); - } - */ - - if (switch_xml_locate("directory", "location", "id", cmd, &xml_root, &xml_node, params, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS) { - stream->write_function(stream, "%s", reply); - return SWITCH_STATUS_SUCCESS; - } - - var = switch_xml_attr(xml_node, "value"); - if (!zstr(var)) { - reply = var; - } - - stream->write_function(stream, "%s", reply); - - switch_xml_free(xml_root); - return SWITCH_STATUS_SUCCESS; -} - -void add_kz_commands(switch_loadable_module_interface_t **module_interface) { - switch_api_interface_t *api_interface = NULL; - SWITCH_ADD_API(api_interface, "kz_uuid_setvar_multi", UUID_SET_DESC, uuid_setvar_multi_function, UUID_MULTISET_SYNTAX); - SWITCH_ADD_API(api_interface, "kz_uuid_setvar_multi_encoded", UUID_SET_DESC, uuid_setvar_multi_encoded_function, UUID_MULTISET_SYNTAX); - switch_console_set_complete("add kz_uuid_setvar_multi ::console::list_uuid"); - switch_console_set_complete("add kz_uuid_setvar_multi_encoded ::console::list_uuid"); - SWITCH_ADD_API(api_interface, "kz_uuid_setvar", UUID_MULTISET_DESC, uuid_setvar_function, UUID_SET_SYNTAX); - SWITCH_ADD_API(api_interface, "kz_uuid_setvar_encoded", UUID_MULTISET_DESC, uuid_setvar_encoded_function, UUID_SET_SYNTAX); - switch_console_set_complete("add kz_uuid_setvar ::console::list_uuid"); - switch_console_set_complete("add kz_uuid_setvar_encoded ::console::list_uuid"); - SWITCH_ADD_API(api_interface, "kz_http_put", KZ_HTTP_PUT_DESC, kz_http_put, KZ_HTTP_PUT_SYNTAX); - SWITCH_ADD_API(api_interface, "first-of", KZ_FIRST_OF_DESC, kz_first_of, KZ_FIRST_OF_SYNTAX); - SWITCH_ADD_API(api_interface, "kz_expand", KZ_FIRST_OF_DESC, kz_expand_api, KZ_FIRST_OF_SYNTAX); - SWITCH_ADD_API(api_interface, "kz_eval", KZ_FIRST_OF_DESC, kz_eval_api, KZ_FIRST_OF_SYNTAX); - SWITCH_ADD_API(api_interface, "kz_contact", KZ_CONTACT_DESC, kz_contact_fun, KZ_CONTACT_SYNTAX); -} - 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 a64677074b..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_config.c +++ /dev/null @@ -1,553 +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; - loglevels->trace_log_level = SWITCH_LOG_DEBUG1; - loglevels->debug_log_level = SWITCH_LOG_DEBUG; - loglevels->error_log_level = SWITCH_LOG_ERROR; - loglevels->hashing_log_level = SWITCH_LOG_DEBUG1; - - if ((xml_logging = switch_xml_child(cfg, "logging")) != NULL) { - for (xml_level = switch_xml_child(xml_logging, "log"); xml_level; xml_level = xml_level->next) { - 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); - } else if (!strncmp(var, "trace", 5)) { - loglevels->trace_log_level = log_str2level(val); - } else if (!strncmp(var, "debug", 5)) { - loglevels->debug_log_level = log_str2level(val); - } else if (!strncmp(var, "error", 5)) { - loglevels->error_log_level = log_str2level(val); - } else if (!strncmp(var, "hashing", 7)) { - loglevels->hashing_log_level = log_str2level(val); - } - } /* xml_level for loop */ - } - - *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; - } else if (!strncmp(compare, "field", 5)) { - cur->compare = FILTER_COMPARE_FIELD; - } - } - - 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"); - const char *as_array = switch_xml_attr(cfg, "as-array"); - kazoo_field_ptr cur = (kazoo_field_ptr) switch_core_alloc(pool, sizeof(kazoo_field)); - cur->in_type = FIELD_NONE; - cur->out_type = JSON_NONE; - - 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(as_array) { - cur->out_type_as_array = switch_true(as_array); - } - - 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; - 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, using default\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, using default\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_WARNING, "unable to locate definitions section for kazoo, using default\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 d0117fda5f..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_config.h +++ /dev/null @@ -1,63 +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); -switch_status_t kazoo_config_field(kazoo_config_ptr definitions, switch_memory_pool_t *pool, switch_xml_t cfg, kazoo_field_ptr *ptr); -void destroy_config(kazoo_config_ptr *ptr); - -#endif /* KAZOO_CONFIG_H */ - diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_definitions.S b/src/mod/event_handlers/mod_kazoo/kazoo_definitions.S deleted file mode 100644 index 0bbe0137cb..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_definitions.S +++ /dev/null @@ -1,8 +0,0 @@ - .global kz_default_config - .global kz_default_config_size - .section .rodata -kz_default_config: - .incbin "kazoo.conf.xml" -1: -kz_default_config_size: - .int 1b - kz_default_config diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_defs.h b/src/mod/event_handlers/mod_kazoo/kazoo_defs.h deleted file mode 100644 index 7fe86dd354..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_defs.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef KAZOO_DEFS_H_ -#define KAZOO_DEFS_H_ - -#define INTERACTION_VARIABLE "Call-Interaction-ID" - -#define UNIX_EPOCH_IN_GREGORIAN 62167219200 -#define UNIX_EPOCH_IN_GREGORIAN_STR "62167219200" - -#endif /* KAZOO_DEFS_H_ */ diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_dptools.c b/src/mod/event_handlers/mod_kazoo/kazoo_dptools.c deleted file mode 100644 index 5a01650969..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_dptools.c +++ /dev/null @@ -1,980 +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 - * - * - * kazoo_dptools.c -- clones of mod_dptools commands slightly modified for kazoo - * - */ -#include "mod_kazoo.h" - -#define SET_SHORT_DESC "Set a channel variable" -#define SET_LONG_DESC "Set a channel variable for the channel calling the application." -#define SET_SYNTAX "=" - -#define MULTISET_SHORT_DESC "Set many channel variables" -#define MULTISET_LONG_DESC "Set many channel variables for the channel calling the application" -#define MULTISET_SYNTAX "[^^]= =" - -#define UNSET_SHORT_DESC "Unset a channel variable" -#define UNSET_LONG_DESC "Unset a channel variable for the channel calling the application." -#define UNSET_SYNTAX "" - -#define MULTIUNSET_SHORT_DESC "Unset many channel variables" -#define MULTIUNSET_LONG_DESC "Unset many channel variables for the channel calling the application." -#define MULTIUNSET_SYNTAX "[^^] " - -#define EXPORT_SHORT_DESC "Export many channel variables" -#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 " [^^]= =" - -#define KZ_ENDLESS_PLAYBACK_SHORT_DESC "Playback File Endlessly until break" -#define KZ_ENDLESS_PLAYBACK_LONG_DESC "Endlessly Playback a file to the channel until a break occurs" -#define KZ_ENDLESS_PLAYBACK_SYNTAX "" - -#define NOOP_SHORT_DESC "no operation" -#define NOOP_LONG_DESC "no operation. serves as a control point" -#define NOOP_SYNTAX "[]" - -static void base_set (switch_core_session_t *session, const char *data, int urldecode, switch_stack_t stack) -{ - char *var, *val = NULL; - - if (zstr(data)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n"); - } else { - switch_channel_t *channel = switch_core_session_get_channel(session); - char *expanded = NULL; - - var = switch_core_session_strdup(session, data); - - if (!(val = strchr(var, '='))) { - val = strchr(var, ','); - } - - if (val) { - *val++ = '\0'; - if (zstr(val)) { - val = NULL; - } - } - - if (val) { - if(urldecode) { - switch_url_decode(val); - } - expanded = switch_channel_expand_variables(channel, val); - } - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%s SET [%s]=[%s] => [%s]\n", switch_channel_get_name(channel), var, val, - expanded ? expanded : "UNDEF"); - switch_channel_add_variable_var_check(channel, var, expanded, SWITCH_FALSE, stack); - kz_check_set_profile_var(channel, var, expanded); - if (expanded && expanded != val) { - switch_safe_free(expanded); - } - } -} - -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, int urldecode, switch_stack_t stack) -{ - char *var, *val = NULL; - - if (zstr(data)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n"); - } else { - switch_channel_t *channel = switch_core_session_get_channel(session); - char *expanded = NULL; - - var = switch_core_session_strdup(session, data); - - if (!(val = strchr(var, '='))) { - val = strchr(var, ','); - } - - if (val) { - *val++ = '\0'; - if (zstr(val)) { - val = NULL; - } - } - - if (val) { - if(urldecode) { - switch_url_decode(val); - } - expanded = switch_channel_expand_variables(channel, val); - - if(!kz_is_exported(session, var)) { - 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); - } else { - if(strcmp(switch_str_nil(switch_channel_get_variable_dup(channel, var, SWITCH_FALSE, -1)), expanded)) { - switch_channel_set_variable(channel, var, expanded); - } - } - 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); -} - -void kz_multiset(switch_core_session_t *session, const char* data, int urldecode) -{ - char delim = ' '; - char *arg = (char *) data; - switch_event_t *event; - - if (!zstr(arg) && *arg == '^' && *(arg+1) == '^') { - arg += 2; - delim = *arg++; - } - - if(delim != '\0') { - switch_channel_t *channel = switch_core_session_get_channel(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(session, array[i], urldecode, 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(multiset_function) -{ - kz_multiset(session, data, 0); -} - -SWITCH_STANDARD_APP(multiset_encoded_function) -{ - kz_multiset(session, data, 1); -} - -void kz_uuid_multiset(switch_core_session_t *session, const char* data, int urldecode) -{ - 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_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], urldecode, 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, urldecode, SWITCH_STACK_BOTTOM); - } - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "multiset with empty args\n"); - } -} - -SWITCH_STANDARD_APP(uuid_multiset_function) -{ - kz_uuid_multiset(session, data, 0); -} - -SWITCH_STANDARD_APP(uuid_multiset_encoded_function) -{ - kz_uuid_multiset(session, data, 1); -} - -void kz_set(switch_core_session_t *session, const char* data, int urldecode) { - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_event_t *event; - - base_set(session, data, urldecode, 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); - } -} - -SWITCH_STANDARD_APP(set_function) -{ - kz_set(session, data, 0); -} - -SWITCH_STANDARD_APP(set_encoded_function) -{ - kz_set(session, data, 1); -} - -SWITCH_STANDARD_APP(unset_function) { - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_event_t *event; - - if (zstr(data)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No variable name specified.\n"); - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "UNSET [%s]\n", (char *) data); - switch_channel_set_variable(switch_core_session_get_channel(session), data, NULL); - } - - if (switch_event_create(&event, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(channel, event); - switch_event_fire(&event); - } -} - -SWITCH_STANDARD_APP(multiunset_function) { - char delim = ' '; - char *arg = (char *) data; - - if (!zstr(arg) && *arg == '^' && *(arg+1) == '^') { - arg += 2; - delim = *arg++; - } - - if(delim != '\0') { - 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++) { - 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); - } - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "multiunset with empty args\n"); - } -} - - -void kz_export(switch_core_session_t *session, const char* data, int urldecode) -{ - char delim = ' '; - char *arg = (char *) data; - - if (!zstr(arg) && *arg == '^' && *(arg+1) == '^') { - arg += 2; - delim = *arg++; - } - - if(delim != '\0') { - 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_export(session, array[i], urldecode, SWITCH_STACK_BOTTOM); - } - } else { - base_export(session, data, urldecode, SWITCH_STACK_BOTTOM); - } - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "export with empty args\n"); - } -} - -SWITCH_STANDARD_APP(export_function) -{ - kz_export(session, data, 0); -} - -SWITCH_STANDARD_APP(export_encoded_function) -{ - kz_export(session, data, 1); -} - -// copied from mod_dptools with allow SWITCH_STATUS_BREAK -SWITCH_STANDARD_APP(kz_endless_playback_function) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_status_t status = SWITCH_STATUS_SUCCESS; - const char *file = data; - - while (switch_channel_ready(channel)) { - status = switch_ivr_play_file(session, NULL, file, NULL); - - if (status != SWITCH_STATUS_SUCCESS) { - break; - } - } - - switch (status) { - case SWITCH_STATUS_SUCCESS: - switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "FILE PLAYED"); - break; - case SWITCH_STATUS_BREAK: - switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "PLAYBACK_INTERRUPTED"); - break; - case SWITCH_STATUS_NOTFOUND: - switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "FILE NOT FOUND"); - break; - default: - switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "PLAYBACK ERROR"); - break; - } - -} - -SWITCH_STANDARD_APP(kz_moh_function) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_status_t status = SWITCH_STATUS_SUCCESS; - switch_file_handle_t fh = { 0 }; - const char *var_samples = switch_channel_get_variable_dup(channel, "moh_playback_samples", SWITCH_FALSE, -1); - unsigned int samples = 0; - char * my_data = NULL; - - if (var_samples) { - fh.samples = samples = atoi(var_samples); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "SETTING SAMPLES %d\n", samples); - } - - switch_channel_set_variable(channel, SWITCH_PLAYBACK_TERMINATOR_USED, ""); - - /* - * hack for proper position - */ - if (!strncmp(data, "http_cache://", 13) && session) { - switch_channel_t *channel = switch_core_session_get_channel(session); - char * resolve = switch_mprintf("${http_get({prefetch=true}%s)}", data+13); - my_data = switch_channel_expand_variables_check(channel, resolve, NULL, NULL, 0); - } else { - my_data = strdup(data); - } - - status = switch_ivr_play_file(session, &fh, my_data, NULL); -// status = switch_ivr_play_file(session, &fh, data, NULL); - - switch_assert(!(fh.flags & SWITCH_FILE_OPEN)); - - switch (status) { - case SWITCH_STATUS_SUCCESS: - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "MOH PLAYED SUCCESS\n"); - switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "MOH FILE PLAYED"); - switch_channel_set_variable(channel, "moh_playback_samples", "0"); - break; - case SWITCH_STATUS_BREAK: - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "MOH PLAYED BREAK\n"); - switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "MOH FILE PLAYED"); - if ((var_samples = switch_channel_get_variable_dup(channel, "playback_samples", SWITCH_FALSE, -1)) != NULL) { - samples += atoi(var_samples); - if (samples >= fh.samples) { - samples = 0; - } - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "SETTING MOH SAMPLES %d\n", samples); - switch_channel_set_variable_printf(channel, "moh_playback_samples", "%d", samples); - } - break; - case SWITCH_STATUS_NOTFOUND: - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "MOH PLAYED NOT FOUND\n"); - switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "MOH FILE NOT FOUND"); - break; - default: - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "MOH PLAYED DEFAULT\n"); - switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, "MOH PLAYBACK ERROR"); - break; - } - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "MOH duration %" SWITCH_INT64_T_FMT "\n", fh.duration); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "MOH offset_pos %d\n", fh.offset_pos); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "MOH pos %" SWITCH_INT64_T_FMT "\n", fh.pos); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "MOH sample_count %" SWITCH_SIZE_T_FMT "\n", fh.sample_count); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "MOH samples %d\n", fh.samples); - - switch_safe_free(my_data); -} - -SWITCH_STANDARD_APP(noop_function) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; - const char *response = uuid_str; - - if (zstr(data)) { - switch_uuid_str(uuid_str, sizeof(uuid_str)); - } else { - response = data; - } - - switch_channel_set_variable(channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, response); -} - -SWITCH_STANDARD_APP(kz_restore_caller_id_function) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_caller_profile_t *cp = switch_channel_get_caller_profile(channel); - cp->caller_id_name = cp->orig_caller_id_name; - cp->caller_id_number = cp->orig_caller_id_number; -} - -SWITCH_STANDARD_APP(kz_audio_bridge_function) -{ - switch_channel_t *caller_channel = switch_core_session_get_channel(session); - switch_core_session_t *peer_session = NULL; - switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING; - switch_status_t status = SWITCH_STATUS_FALSE; - - if (zstr(data)) { - return; - } - - status = switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL); - - if (status != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Originate Failed. Cause: %s\n", switch_channel_cause2str(cause)); - - switch_channel_set_variable(caller_channel, "originate_failed_cause", switch_channel_cause2str(cause)); - switch_channel_set_variable(caller_channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, switch_channel_cause2str(cause)); - switch_channel_handle_cause(caller_channel, cause); - - return; - } else { - const char* uuid = switch_core_session_get_uuid(session); - const char* peer_uuid = switch_core_session_get_uuid(peer_session); - - - switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session); - if (switch_true(switch_channel_get_variable(caller_channel, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE)) || - switch_true(switch_channel_get_variable(peer_channel, SWITCH_BYPASS_MEDIA_AFTER_BRIDGE_VARIABLE))) { - switch_channel_set_flag(caller_channel, CF_BYPASS_MEDIA_AFTER_BRIDGE); - } - - while(1) { - const char *xfer_uuid; - switch_channel_state_t a_state , a_running_state; - switch_channel_state_t b_state , b_running_state; - status = switch_ivr_multi_threaded_bridge(session, peer_session, NULL, NULL, NULL); - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "BRIDGE RESULT %i\n", status); - if(status != 0) { - break; - } - - a_state = switch_channel_get_state(caller_channel); - a_running_state = switch_channel_get_running_state(caller_channel); - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "A STATE %s %s => %s , %s\n", switch_channel_state_name(a_running_state), switch_channel_state_name(a_state), uuid, peer_uuid); - - if(a_state >= CS_HANGUP) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "A HANGUP = %s , %s\n", uuid, peer_uuid); - break; - } - - b_state = switch_channel_get_state(peer_channel); - b_running_state = switch_channel_get_running_state(peer_channel); - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "B STATE %s %s => %s , %s\n", switch_channel_state_name(b_running_state), switch_channel_state_name(b_state), uuid, peer_uuid); - - if(b_state >= CS_HANGUP) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "B HANGUP = %s , %s\n", uuid, peer_uuid); - switch_channel_set_variable(caller_channel, SWITCH_CURRENT_APPLICATION_RESPONSE_VARIABLE, switch_channel_cause2str(switch_channel_get_cause(peer_channel))); - break; - } - - if(!(xfer_uuid=switch_channel_get_variable(caller_channel, "att_xfer_peer_uuid"))) { - if(!(xfer_uuid=switch_channel_get_variable(peer_channel, "att_xfer_peer_uuid"))) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "XFER UUID NULL\n"); - break; - } - } - - switch_channel_set_variable(caller_channel, "att_xfer_peer_uuid", NULL); - switch_channel_set_variable(peer_channel, "att_xfer_peer_uuid", NULL); - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "WAIT 1\n"); - - switch_channel_clear_flag(peer_channel, CF_UUID_BRIDGE_ORIGINATOR); - switch_channel_set_state(peer_channel, CS_RESET); - switch_channel_wait_for_state(peer_channel, NULL, CS_RESET); - switch_channel_clear_state_handler(peer_channel, NULL); - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "WAIT 3\n"); - - switch_channel_set_flag(caller_channel, CF_UUID_BRIDGE_ORIGINATOR); - switch_channel_clear_flag(caller_channel, CF_TRANSFER); - switch_channel_clear_flag(caller_channel, CF_REDIRECT); - switch_channel_set_flag(peer_channel, CF_UUID_BRIDGE_ORIGINATOR); - switch_channel_clear_flag(peer_channel, CF_TRANSFER); - switch_channel_clear_flag(peer_channel, CF_REDIRECT); - - if(!switch_channel_media_up(caller_channel)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "A MEDIA DOWN HANGUP = %s, %s , %s\n", xfer_uuid, uuid, peer_uuid); - } - if(!switch_channel_media_up(peer_channel)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "B MEDIA DOWN HANGUP = %s, %s , %s\n", xfer_uuid, uuid, peer_uuid); - } - switch_channel_set_state(caller_channel, CS_EXECUTE); - switch_channel_set_state(peer_channel, CS_EXECUTE); - - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "XFER LOOP %s %s , %s\n", xfer_uuid, uuid, peer_uuid); - - } - - if (peer_session) { - switch_core_session_rwunlock(peer_session); - } - } -} - -SWITCH_STANDARD_APP(kz_audio_bridge_uuid_function) -{ - switch_core_session_t *peer_session = NULL; - const char * peer_uuid = NULL; - - if (zstr(data)) { - return; - } - - peer_uuid = switch_core_session_strdup(session, data); - if (peer_uuid && (peer_session = switch_core_session_locate(peer_uuid))) { - switch_ivr_multi_threaded_bridge(session, peer_session, NULL, NULL, NULL); - } - - if (peer_session) { - switch_core_session_rwunlock(peer_session); - } -} - - -struct kz_att_keys { - const char *attxfer_cancel_key; - const char *attxfer_hangup_key; - const char *attxfer_conf_key; -}; - -static switch_status_t kz_att_xfer_on_dtmf(switch_core_session_t *session, void *input, switch_input_type_t itype, void *buf, unsigned int buflen) -{ - switch_core_session_t *peer_session = (switch_core_session_t *) buf; - if (!buf || !peer_session) { - return SWITCH_STATUS_SUCCESS; - } - - switch (itype) { - case SWITCH_INPUT_TYPE_DTMF: - { - switch_dtmf_t *dtmf = (switch_dtmf_t *) input; - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session); - struct kz_att_keys *keys = switch_channel_get_private(channel, "__kz_keys"); - - if (dtmf->digit == *keys->attxfer_hangup_key) { - switch_channel_hangup(channel, SWITCH_CAUSE_ATTENDED_TRANSFER); - return SWITCH_STATUS_FALSE; - } - - if (dtmf->digit == *keys->attxfer_cancel_key) { - switch_channel_hangup(peer_channel, SWITCH_CAUSE_NORMAL_CLEARING); - return SWITCH_STATUS_FALSE; - } - - if (dtmf->digit == *keys->attxfer_conf_key) { - switch_caller_extension_t *extension = NULL; - const char *app = "three_way"; - const char *app_arg = switch_core_session_get_uuid(session); - const char *holding = switch_channel_get_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE); - switch_core_session_t *b_session; - - if (holding && (b_session = switch_core_session_locate(holding))) { - switch_channel_t *b_channel = switch_core_session_get_channel(b_session); - if (!switch_channel_ready(b_channel)) { - app = "intercept"; - } - switch_core_session_rwunlock(b_session); - } - - if ((extension = switch_caller_extension_new(peer_session, app, app_arg)) == 0) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Memory Error!\n"); - abort(); - } - - switch_caller_extension_add_application(peer_session, extension, app, app_arg); - switch_channel_set_caller_extension(peer_channel, extension); - switch_channel_set_state(peer_channel, CS_RESET); - switch_channel_wait_for_state(peer_channel, channel, CS_RESET); - switch_channel_set_state(peer_channel, CS_EXECUTE); - switch_channel_set_variable(channel, SWITCH_HANGUP_AFTER_BRIDGE_VARIABLE, NULL); - return SWITCH_STATUS_FALSE; - } - - } - break; - default: - break; - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t kz_att_xfer_tmp_hanguphook(switch_core_session_t *session) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_channel_state_t state = switch_channel_get_state(channel); - - if (state == CS_HANGUP || state == CS_ROUTING) { - const char *bond = switch_channel_get_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE); - - if (!zstr(bond)) { - switch_core_session_t *b_session; - - if ((b_session = switch_core_session_locate(bond))) { - switch_channel_t *b_channel = switch_core_session_get_channel(b_session); - if (switch_channel_up(b_channel)) { - switch_channel_set_flag(b_channel, CF_REDIRECT); - } - switch_core_session_rwunlock(b_session); - } - } - - switch_core_event_hook_remove_state_change(session, kz_att_xfer_tmp_hanguphook); - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t kz_att_xfer_hanguphook(switch_core_session_t *session) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_channel_state_t state = switch_channel_get_state(channel); - const char *id = NULL; - const char *peer_uuid = NULL; - - if (state == CS_HANGUP || state == CS_ROUTING) { - if ((id = switch_channel_get_variable(channel, "xfer_uuids"))) { - switch_stream_handle_t stream = { 0 }; - SWITCH_STANDARD_STREAM(stream); - if ((peer_uuid = switch_channel_get_variable(channel, "xfer_peer_uuid"))) { - switch_core_session_t *peer_session = NULL; - if ((peer_session = switch_core_session_locate(peer_uuid)) != NULL ) { - switch_ivr_transfer_recordings(session, peer_session); - switch_core_session_rwunlock(peer_session); - } - } - switch_api_execute("uuid_bridge", id, NULL, &stream); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "\nHangup Command uuid_bridge(%s):\n%s\n", id, - switch_str_nil((char *) stream.data)); - switch_safe_free(stream.data); - } - - switch_core_event_hook_remove_state_change(session, kz_att_xfer_hanguphook); - } - return SWITCH_STATUS_SUCCESS; -} - - -static void kz_att_xfer_set_result(switch_channel_t *channel, switch_status_t status) -{ - switch_channel_set_variable(channel, SWITCH_ATT_XFER_RESULT_VARIABLE, status == SWITCH_STATUS_SUCCESS ? "success" : "failure"); -} - -struct kz_att_obj { - switch_core_session_t *session; - const char *data; - int running; -}; - -void *SWITCH_THREAD_FUNC kz_att_thread_run(switch_thread_t *thread, void *obj) -{ - struct kz_att_obj *att = (struct kz_att_obj *) obj; - struct kz_att_keys *keys = NULL; - switch_core_session_t *session = att->session; - switch_core_session_t *peer_session = NULL; - const char *data = att->data; - switch_call_cause_t cause = SWITCH_CAUSE_NORMAL_CLEARING; - switch_channel_t *channel = switch_core_session_get_channel(session), *peer_channel = NULL; - const char *bond = NULL; - switch_bool_t follow_recording = switch_true(switch_channel_get_variable(channel, "recording_follow_attxfer")); - const char *attxfer_cancel_key = NULL, *attxfer_hangup_key = NULL, *attxfer_conf_key = NULL; - int br = 0; - switch_event_t *event = NULL; - switch_core_session_t *b_session = NULL; - switch_channel_t *b_channel = NULL; - - att->running = 1; - - if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) { - return NULL; - } - - bond = switch_channel_get_partner_uuid(channel); - if ((b_session = switch_core_session_locate(bond)) == NULL) { - switch_core_session_rwunlock(session); - return NULL; - } - switch_channel_set_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE, bond); - switch_core_event_hook_add_state_change(session, kz_att_xfer_tmp_hanguphook); - - if (switch_ivr_originate(session, &peer_session, &cause, data, 0, NULL, NULL, NULL, NULL, NULL, SOF_NONE, NULL, NULL) - != SWITCH_STATUS_SUCCESS || !peer_session) { - switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond); - goto end; - } - - peer_channel = switch_core_session_get_channel(peer_session); - switch_channel_set_flag(peer_channel, CF_INNER_BRIDGE); - switch_channel_set_flag(channel, CF_INNER_BRIDGE); - - if (!(attxfer_cancel_key = switch_channel_get_variable(channel, "attxfer_cancel_key"))) { - if (!(attxfer_cancel_key = switch_channel_get_variable(peer_channel, "attxfer_cancel_key"))) { - attxfer_cancel_key = "#"; - } - } - - if (!(attxfer_hangup_key = switch_channel_get_variable(channel, "attxfer_hangup_key"))) { - if (!(attxfer_hangup_key = switch_channel_get_variable(peer_channel, "attxfer_hangup_key"))) { - attxfer_hangup_key = "*"; - } - } - - if (!(attxfer_conf_key = switch_channel_get_variable(channel, "attxfer_conf_key"))) { - if (!(attxfer_conf_key = switch_channel_get_variable(peer_channel, "attxfer_conf_key"))) { - attxfer_conf_key = "0"; - } - } - - keys = switch_core_session_alloc(session, sizeof(*keys)); - keys->attxfer_cancel_key = switch_core_session_strdup(session, attxfer_cancel_key); - keys->attxfer_hangup_key = switch_core_session_strdup(session, attxfer_hangup_key); - keys->attxfer_conf_key = switch_core_session_strdup(session, attxfer_conf_key); - switch_channel_set_private(channel, "__kz_keys", keys); - - switch_channel_set_variable(channel, "att_xfer_peer_uuid", switch_core_session_get_uuid(peer_session)); - - switch_ivr_multi_threaded_bridge(session, peer_session, kz_att_xfer_on_dtmf, peer_session, NULL); - - switch_channel_clear_flag(peer_channel, CF_INNER_BRIDGE); - switch_channel_clear_flag(channel, CF_INNER_BRIDGE); - - if (switch_channel_down(peer_channel)) { - switch_core_session_rwunlock(peer_session); - switch_channel_set_variable(channel, SWITCH_SIGNAL_BOND_VARIABLE, bond); - goto end; - } - - /* - * we're emiting the transferee event so that callctl can update - */ - b_channel = switch_core_session_get_channel(b_session); - if (switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, "sofia::transferee") == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(b_channel, event); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "att_xfer_replaced_call_id", switch_core_session_get_uuid(peer_session)); - switch_event_fire(&event); - } - - if (!switch_channel_ready(channel)) { - switch_status_t status; - - if (follow_recording) { - switch_ivr_transfer_recordings(session, peer_session); - } - status = switch_ivr_uuid_bridge(switch_core_session_get_uuid(peer_session), bond); - kz_att_xfer_set_result(peer_channel, status); - br++; - } else { - // switch_channel_set_variable_printf(b_channel, "xfer_uuids", "%s %s", switch_core_session_get_uuid(peer_session), switch_core_session_get_uuid(session)); - switch_channel_set_variable_printf(channel, "xfer_uuids", "%s %s", switch_core_session_get_uuid(peer_session), bond); - switch_channel_set_variable(channel, "xfer_peer_uuid", switch_core_session_get_uuid(peer_session)); - - switch_core_event_hook_add_state_change(session, kz_att_xfer_hanguphook); - // switch_core_event_hook_add_state_change(b_session, kz_att_xfer_hanguphook); - } - -/* - * this was commented so that the existing bridge - * doesn't end - * - if (!br) { - switch_status_t status = switch_ivr_uuid_bridge(switch_core_session_get_uuid(session), bond); - att_xfer_set_result(channel, status); - } -*/ - - switch_core_session_rwunlock(peer_session); - - end: - - switch_core_event_hook_remove_state_change(session, kz_att_xfer_tmp_hanguphook); - - switch_channel_set_variable(channel, SWITCH_SOFT_HOLDING_UUID_VARIABLE, NULL); - switch_channel_clear_flag(channel, CF_XFER_ZOMBIE); - - switch_core_session_rwunlock(b_session); - switch_core_session_rwunlock(session); - att->running = 0; - - return NULL; -} - -SWITCH_STANDARD_APP(kz_att_xfer_function) -{ - switch_thread_t *thread; - switch_threadattr_t *thd_attr = NULL; - switch_memory_pool_t *pool = switch_core_session_get_pool(session); - struct kz_att_obj *att; - switch_channel_t *channel = switch_core_session_get_channel(session); - - switch_threadattr_create(&thd_attr, pool); - switch_threadattr_detach_set(thd_attr, 1); - switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_threadattr_detach_set(thd_attr, 1); - - att = switch_core_session_alloc(session, sizeof(*att)); - att->running = -1; - att->session = session; - att->data = switch_core_session_strdup(session, data); - switch_thread_create(&thread, thd_attr, kz_att_thread_run, att, pool); - - while(att->running && switch_channel_up(channel)) { - switch_yield(100000); - } -} - -void add_kz_dptools(switch_loadable_module_interface_t **module_interface) { - switch_application_interface_t *app_interface = NULL; - SWITCH_ADD_APP(app_interface, "kz_set", SET_SHORT_DESC, SET_LONG_DESC, set_function, SET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); - SWITCH_ADD_APP(app_interface, "kz_set_encoded", SET_SHORT_DESC, SET_LONG_DESC, set_encoded_function, SET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); - SWITCH_ADD_APP(app_interface, "kz_multiset", MULTISET_SHORT_DESC, MULTISET_LONG_DESC, multiset_function, MULTISET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); - SWITCH_ADD_APP(app_interface, "kz_multiset_encoded", MULTISET_SHORT_DESC, MULTISET_LONG_DESC, multiset_encoded_function, MULTISET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); - SWITCH_ADD_APP(app_interface, "kz_unset", UNSET_SHORT_DESC, UNSET_LONG_DESC, unset_function, UNSET_SYNTAX, 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_export_encoded", EXPORT_SHORT_DESC, EXPORT_LONG_DESC, export_encoded_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_uuid_multiset_encoded", UUID_MULTISET_SHORT_DESC, UUID_MULTISET_LONG_DESC, uuid_multiset_encoded_function, UUID_MULTISET_SYNTAX, SAF_SUPPORT_NOMEDIA | SAF_ROUTING_EXEC | SAF_ZOMBIE_EXEC); - SWITCH_ADD_APP(app_interface, "kz_endless_playback", KZ_ENDLESS_PLAYBACK_SHORT_DESC, KZ_ENDLESS_PLAYBACK_LONG_DESC, kz_endless_playback_function, KZ_ENDLESS_PLAYBACK_SYNTAX, SAF_NONE); - SWITCH_ADD_APP(app_interface, "kz_restore_caller_id", NOOP_SHORT_DESC, NOOP_LONG_DESC, kz_restore_caller_id_function, NOOP_SYNTAX, SAF_NONE); - SWITCH_ADD_APP(app_interface, "noop", NOOP_SHORT_DESC, NOOP_LONG_DESC, noop_function, NOOP_SYNTAX, SAF_NONE); - SWITCH_ADD_APP(app_interface, "kz_bridge", "Bridge Audio", "Bridge the audio between two sessions", kz_audio_bridge_function, "", SAF_SUPPORT_NOMEDIA|SAF_SUPPORT_TEXT_ONLY); - SWITCH_ADD_APP(app_interface, "kz_bridge_uuid", "Bridge Audio", "Bridge the audio between two sessions", kz_audio_bridge_uuid_function, "", SAF_SUPPORT_NOMEDIA|SAF_SUPPORT_TEXT_ONLY); - SWITCH_ADD_APP(app_interface, "kz_att_xfer", "Attended Transfer", "Attended Transfer", kz_att_xfer_function, "", SAF_NONE); - SWITCH_ADD_APP(app_interface, "kz_moh", "Kazoo MOH Playback", "Kazoo MOH Playback", kz_moh_function, "", SAF_NONE); -} 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 5f617b5f1d..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_ei.h +++ /dev/null @@ -1,295 +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" - -#define KZ_MAX_SEPARATE_STRINGS 10 -#define HOSTNAME_MAX 1024 -#define NODENAME_MAX 1024 - -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; - switch_time_t connected_time; - 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; - short event_stream_framing; - short event_stream_keepalive; - switch_interval_time_t queue_timeout; - 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; - short event_stream_framing; - short event_stream_keepalive; - switch_interval_time_t event_stream_queue_timeout; - switch_interval_time_t receiver_queue_timeout; - switch_interval_time_t sender_queue_timeout; - 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 kz_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 node_worker_threads; - switch_bool_t nat_map; - switch_bool_t ei_shortname; - int ei_compat_rel; - char *ip; - char *hostname; - struct hostent* hostname_ent; - char *ei_cookie; - char *ei_nodename; - uint32_t flags; - int send_all_headers; - int send_all_private_headers; - int connection_timeout; - int ei_receive_timeout; - switch_interval_time_t node_sender_queue_timeout; - switch_interval_time_t node_receiver_queue_timeout; - int receive_msg_preallocate; - int event_stream_preallocate; - int send_msg_batch; - short event_stream_framing; - short event_stream_keepalive; - switch_interval_time_t event_stream_queue_timeout; - switch_port_t port; - int config_fetched; - int io_fault_tolerance; - switch_interval_time_t io_fault_tolerance_sleep; - kazoo_event_profile_ptr events; - kazoo_config_ptr definitions; - kazoo_config_ptr event_handlers; - kazoo_config_ptr fetch_handlers; - kazoo_json_term json_encoding; - - char **profile_vars_prefixes; - char **kazoo_var_prefixes; - - int legacy_events; - uint8_t tweaks[KZ_TWEAK_MAX]; - switch_bool_t expand_headers_on_fetch; - - switch_interval_time_t delay_before_initial_fetch; - - -}; -typedef struct kz_globals_s kz_globals_t; -extern kz_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 kz_erl_init(); -void kz_erl_shutdown(); -SWITCH_DECLARE(switch_status_t) ei_queue_pop(switch_queue_t *queue, void **data, switch_interval_time_t timeout); - -void fetch_config(); - -switch_status_t kazoo_load_config(); -void kazoo_destroy_config(); -void kz_set_hostname(); - -#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); - - - -#define kz_test_tweak(flag) (kazoo_globals.tweaks[flag] ? 1 : 0) -#define kz_set_tweak(flag) kazoo_globals.tweaks[flag] = 1 -#define kz_clear_tweak(flag) kazoo_globals.tweaks[flag] = 0 - -#endif /* KAZOO_EI_H */ - -/* For Emacs: - * 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 3c626c15da..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_ei_config.c +++ /dev/null @@ -1,708 +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" - -#define KZ_DEFAULT_STREAM_PRE_ALLOCATE 8192 - -#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; - - 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 (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; - } -} - -void kz_set_hostname() -{ - if (kazoo_globals.hostname == NULL) { - char hostname[NODENAME_MAX]; - memcpy(hostname, switch_core_get_hostname(), NODENAME_MAX); - kazoo_globals.hostname_ent = gethostbyname(hostname); - if(kazoo_globals.hostname_ent != NULL) { - kazoo_globals.hostname = switch_core_strdup(kazoo_globals.pool, kazoo_globals.hostname_ent->h_name); - } else { - kazoo_globals.hostname = switch_core_strdup(kazoo_globals.pool, hostname); - } - } -} - -switch_status_t kazoo_ei_config(switch_xml_t cfg) { - switch_xml_t child, param; - char* kazoo_var_prefix = NULL; - char* profile_vars_prefix = NULL; - char* sep_array[KZ_MAX_SEPARATE_STRINGS]; - int array_len, i; - kazoo_globals.send_all_headers = 0; - kazoo_globals.send_all_private_headers = 1; - kazoo_globals.connection_timeout = 500; - kazoo_globals.ei_receive_timeout = 200; - kazoo_globals.receive_msg_preallocate = 2000; - kazoo_globals.event_stream_preallocate = KZ_DEFAULT_STREAM_PRE_ALLOCATE; - kazoo_globals.send_msg_batch = 10; - kazoo_globals.event_stream_framing = 2; - kazoo_globals.event_stream_keepalive = 1; - kazoo_globals.event_stream_queue_timeout = 200000; - kazoo_globals.node_receiver_queue_timeout = 100000; - kazoo_globals.node_sender_queue_timeout = 0; - kazoo_globals.port = 0; - kazoo_globals.io_fault_tolerance = 3; - kazoo_globals.io_fault_tolerance_sleep = 100000; // 100 ms - kazoo_globals.json_encoding = ERLANG_TUPLE; - kazoo_globals.delay_before_initial_fetch = 10000000; - - kazoo_globals.legacy_events = SWITCH_FALSE; - kazoo_globals.expand_headers_on_fetch = SWITCH_TRUE; - - kz_set_tweak(KZ_TWEAK_INTERACTION_ID); - kz_set_tweak(KZ_TWEAK_EXPORT_VARS); - kz_set_tweak(KZ_TWEAK_SWITCH_URI); - kz_set_tweak(KZ_TWEAK_REPLACES_CALL_ID); - kz_set_tweak(KZ_TWEAK_LOOPBACK_VARS); - kz_set_tweak(KZ_TWEAK_CALLER_ID); - kz_set_tweak(KZ_TWEAK_TRANSFERS); - kz_set_tweak(KZ_TWEAK_BRIDGE); - kz_set_tweak(KZ_TWEAK_BRIDGE_REPLACES_ALEG); - kz_set_tweak(KZ_TWEAK_BRIDGE_REPLACES_CALL_ID); - kz_set_tweak(KZ_TWEAK_BRIDGE_VARIABLES); - kz_set_tweak(KZ_TWEAK_RESTORE_CALLER_ID_ON_BLIND_XFER); - - - - if ((child = switch_xml_child(cfg, "settings"))) { - 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")) { - kazoo_var_prefix = switch_core_strdup(kazoo_globals.pool, val); - } else if (!strcmp(var, "set-profile-vars-prefix")) { - profile_vars_prefix = switch_core_strdup(kazoo_globals.pool, 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.ei_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, "event-stream-keep-alive")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set event-stream-keep-alive: %s\n", val); - kazoo_globals.event_stream_keepalive = switch_true(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, "io-fault-tolerance-sleep-micro")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val); - kazoo_globals.io_fault_tolerance_sleep = atoi(val); - } else if (!strcmp(var, "io-fault-tolerance-sleep-ms")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val); - kazoo_globals.io_fault_tolerance_sleep = atoi(val) * 1000; - } else if (!strcmp(var, "io-fault-tolerance-sleep-sec")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val); - kazoo_globals.io_fault_tolerance_sleep = atoi(val) * 1000000; - - - } else if (!strcmp(var, "node-worker-threads")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set node-worker-threads: %s\n", val); - kazoo_globals.node_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, "legacy-events")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set legacy-events: %s\n", val); - kazoo_globals.legacy_events = switch_true(val); - } else if (!strcmp(var, "expand-headers-on-fetch")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set expand-headers-on-fetch: %s\n", val); - kazoo_globals.expand_headers_on_fetch = switch_true(val); - } else if (!strcmp(var, "node-receiver-queue-timeout")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val); - kazoo_globals.node_receiver_queue_timeout = atoi(val); - } else if (!strcmp(var, "node-sender-queue-timeout")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val); - kazoo_globals.node_sender_queue_timeout = atoi(val); - } else if (!strcmp(var, "event-stream-queue-timeout")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val); - kazoo_globals.event_stream_queue_timeout = atoi(val); - } else if (!strcmp(var, "delay-before-initial-fetch-micro")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val); - kazoo_globals.delay_before_initial_fetch = atoi(val); - } else if (!strcmp(var, "delay-before-initial-fetch-ms")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val); - kazoo_globals.delay_before_initial_fetch = atoi(val) * 1000; - } else if (!strcmp(var, "delay-before-initial-fetch-sec")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set %s : %s\n", var, val); - kazoo_globals.delay_before_initial_fetch = atoi(val) * 1000000; - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "unknown config option %s : %s\n", var, val); - } - } - } - - if ((child = switch_xml_child(cfg, "tweaks"))) { - char *default_tweaks = (char *) switch_xml_attr_soft(child, "default"); - if (default_tweaks && !zstr(default_tweaks)) { - int i, v = switch_true(default_tweaks) ? 1 : 0; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set tweak default : %s\n", default_tweaks); - for (i = 0; i < KZ_TWEAK_MAX; i++) kazoo_globals.tweaks[i] = v; - } - for (param = switch_xml_child(child, "tweak"); param; param = param->next) { - kz_tweak_t tweak = KZ_TWEAK_MAX; - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - if(var && val && kz_name_tweak(var, &tweak) == SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set tweak %s : %s\n", var, val); - if(switch_true(val)) { - kz_set_tweak(tweak); - } else { - kz_clear_tweak(tweak); - } - } - } - } - - if ((child = switch_xml_child(cfg, "variables"))) { - for (param = switch_xml_child(child, "variable"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - if(var && val) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Set core variable %s : %s\n", var, val); - switch_core_set_variable(var, 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_var_prefix)) { - kazoo_var_prefix = switch_core_strdup(kazoo_globals.pool, "ecallmgr_;cav_"); - } - - if (zstr(profile_vars_prefix)) { - profile_vars_prefix = switch_core_strdup(kazoo_globals.pool, "effective_;origination_"); - } - - kazoo_globals.kazoo_var_prefixes = switch_core_alloc(kazoo_globals.pool, sizeof(char*) * KZ_MAX_SEPARATE_STRINGS); - array_len = switch_separate_string(kazoo_var_prefix, ';', sep_array, KZ_MAX_SEPARATE_STRINGS - 1); - for(i=0; i < array_len; i++) { - char var[100]; - sprintf(var, "variable_%s", sep_array[i]); - kazoo_globals.kazoo_var_prefixes[i] = switch_core_strdup(kazoo_globals.pool, var); - } - - kazoo_globals.profile_vars_prefixes = switch_core_alloc(kazoo_globals.pool, sizeof(char*) * KZ_MAX_SEPARATE_STRINGS); - array_len = switch_separate_string(profile_vars_prefix, ';', sep_array, KZ_MAX_SEPARATE_STRINGS - 1); - for(i=0; i < array_len; i++) { - kazoo_globals.profile_vars_prefixes[i] = switch_core_strdup(kazoo_globals.pool, sep_array[i]); - } - - if (!kazoo_globals.node_worker_threads) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Number of node worker threads not found in configuration, using default\n"); - kazoo_globals.node_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 = NULL; - switch_xml_t child, param; - char* xml = NULL; - kazoo_config_ptr definitions = NULL, fetch_handlers = NULL, event_handlers = NULL; - kazoo_event_profile_ptr events = NULL; - - xml = strndup(kz_default_config, kz_default_config_size); - def = switch_xml_parse_str_dup(xml); - - kz_xml_process(def); - kz_xml_process(cfg); - - if ((child = switch_xml_child(cfg, "variables"))) { - for (param = switch_xml_child(child, "variable"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - if(var && val) { - switch_core_set_variable(var, val); - } - } - } else if ((child = switch_xml_child(def, "variables"))) { - for (param = switch_xml_child(child, "variable"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - if(var && val) { - switch_core_set_variable(var, val); - } - } - } - - definitions = kazoo_config_definitions(cfg); - if(definitions == NULL) { - if(kazoo_globals.definitions == NULL) { - definitions = kazoo_config_definitions(def); - } else { - definitions = kazoo_globals.definitions; - } - } - - fetch_handlers = kazoo_config_fetch_handlers(definitions, cfg); - if(fetch_handlers == NULL) { - if(kazoo_globals.fetch_handlers == NULL) { - fetch_handlers = kazoo_config_fetch_handlers(definitions, def); - } else { - fetch_handlers = kazoo_globals.fetch_handlers; - } - } - - event_handlers = kazoo_config_event_handlers(definitions, cfg); - if(event_handlers == NULL) { - if(kazoo_globals.event_handlers == NULL) { - event_handlers = kazoo_config_event_handlers(definitions, def); - } else { - event_handlers = kazoo_globals.event_handlers; - } - } - - 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); - event_handlers = kazoo_config_event_handlers(definitions, def); - events = (kazoo_event_profile_ptr) switch_core_hash_find(event_handlers->hash, "default"); - } - - if(kazoo_globals.events != events) { - bind_event_profiles(events->events); - kazoo_globals.events = events; - } - - if(kazoo_globals.event_handlers != event_handlers) { - kazoo_config_ptr tmp = kazoo_globals.event_handlers; - kazoo_globals.event_handlers = event_handlers; - destroy_config(&tmp); - } - - if(kazoo_globals.fetch_handlers != fetch_handlers) { - kazoo_config_ptr tmp = kazoo_globals.fetch_handlers; - kazoo_globals.fetch_handlers = fetch_handlers; - rebind_fetch_profiles(fetch_handlers); - destroy_config(&tmp); - } - - if(kazoo_globals.definitions != definitions) { - kazoo_config_ptr tmp = kazoo_globals.definitions; - kazoo_globals.definitions = definitions; - destroy_config(&tmp); - } - - - 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); - if (switch_xml_child(event, "logging") != NULL) { - kazoo_config_loglevels(pool, event, &cur->logging); - } - } - } - - 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) { - char *tmp = switch_xml_toxml(cfg, SWITCH_FALSE); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Fetch Profile[%s] invalid fetch-section: %s\n", name, tmp); - free(tmp); - 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 ef45af0ea3..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_ei_utils.c +++ /dev/null @@ -1,1089 +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: - if ((fabs(((double) item->valueint) - item->valuedouble) <= DBL_EPSILON) && (item->valuedouble <= INT_MAX) && (item->valuedouble >= INT_MIN)) { - ei_x_encode_longlong(ebuf, item->valueint); - } else { - if (fmod(item->valuedouble, 1) == 0) { - ei_x_encode_ulonglong(ebuf, item->valuedouble); - } else { - ei_x_encode_double(ebuf, item->valuedouble); - } - } - break; - - case cJSON_True: - ei_x_encode_boolean(ebuf, 1); - break; - - case cJSON_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 { - if (fmod(item->valuedouble, 1) == 0) { - ei_x_encode_ulonglong(ebuf, item->valuedouble); - } else { - ei_x_encode_double(ebuf, item->valuedouble); - } - } - break; - - case cJSON_True: - ei_x_encode_boolean(ebuf, 1); - break; - - case cJSON_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; - } - - 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]; - 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", name); - /* truncate the alivename at the @ */ - *atsign++ = '\0'; - strncpy(hostname, atsign, EI_MAXHOSTNAMELEN); - } else { - strncpy(hostname, kazoo_globals.hostname, EI_MAXHOSTNAMELEN); - snprintf(nodename, MAXNODELEN + 1, "%s@%s", name, hostname); - } - - if (kazoo_globals.ei_shortname) { - char *off; - if ((off = strchr(nodename, '.'))) { - *off = '\0'; - } - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "creating nodename: %s\n", nodename); - - /* init the ec stuff */ - if (ei_connect_xinit(ei_cnode, hostname, cnodename, nodename, (Erl_IpAddr) ip_addr, kazoo_globals.ei_cookie, 0) < 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to initialize the erlang interface connection structure\n"); - return SWITCH_STATUS_FALSE; - } - - 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_LIST_EXT && type != ERL_NIL_EXT) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unexpected erlang term type %d (size %d), needed binary or string\n", type, size); - return -1; - } - - *dst = malloc(size + 1); - - 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_LIST_EXT && type != ERL_NIL_EXT) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unexpected erlang term type %d (size %d), needed binary or string\n", type, size); - return -1; - } - - if (size > maxsize) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Requested decoding of %s with size %d into a buffer of size %d\n", - type == ERL_BINARY_EXT ? "binary" : "string", size, maxsize); - 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("fs_epmd -daemon")) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, - "Failed to start epmd manually! Is epmd in $PATH? If not, start it yourself or run an erl shell with -sname or -name\n"); - 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, "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"); - - /* 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); - } - switch_event_destroy(¶ms); - -} - -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); - } - switch_event_destroy(¶ms); - -} - -static void *SWITCH_THREAD_FUNC fetch_config_exec(switch_thread_t *thread, void *obj) -{ - switch_memory_pool_t *pool = (switch_memory_pool_t *) obj; - ei_node_t *node; - int fetch_filters = 0, fetch_handlers = 0; - - // give some time for node initialization - switch_sleep(kazoo_globals.delay_before_initial_fetch); - - for (node = kazoo_globals.ei_nodes; node != NULL; node = node->next) { - if (node->legacy ) { - fetch_filters++; - } else { - fetch_handlers++; - } - } - - if (fetch_filters) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "fetching filters for kazoo\n"); - fetch_config_filters(pool); - } - - if (fetch_handlers) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "fetching kazoo handlers\n"); - 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_NOTICE, "scheduling fetch for 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); - -} - -#ifdef WITH_KAZOO_ERL_SHUTDOWN -#if (ERLANG_MAJOR == 10 && ERLANG_MINOR >= 3) || ERLANG_MAJOR >= 11 -typedef struct ei_mutex_s { -#ifdef __WIN32__ - HANDLE lock; -#elif VXWORKS - SEM_ID lock; -#else /* unix */ -#if defined(HAVE_MIT_PTHREAD_H) || defined(HAVE_PTHREAD_H) - pthread_mutex_t *lock; -#else /* ! (HAVE_MIT_PTHREAD_H || HAVE_PTHREAD_H) */ - void *dummy; /* Actually never used */ -#endif /* ! (HAVE_MIT_PTHREAD_H || HAVE_PTHREAD_H) */ -#endif /* unix */ -}ei_mutex_t; - -typedef struct ei_socket_info_s { - int socket; - ei_socket_callbacks *cbs; - void *ctx; - int dist_version; - ei_cnode cnode; /* A copy, not a pointer. We don't know when freed */ - char cookie[EI_MAX_COOKIE_SIZE+1]; -}ei_socket_info; - -extern ei_socket_info *ei_sockets; -extern ei_mutex_t* ei_sockets_lock; -extern int ei_n_sockets; -extern int ei_sz_sockets; - -int ei_mutex_free(ei_mutex_t *l, int nblock); - -#endif -#endif - -void kz_erl_init() -{ -#if (ERLANG_MAJOR == 10 && ERLANG_MINOR >= 3) || ERLANG_MAJOR >= 11 - ei_init(); -#endif -} - -void kz_erl_shutdown() -{ -#ifdef WITH_KAZOO_ERL_SHUTDOWN -#if (ERLANG_MAJOR == 10 && ERLANG_MINOR >= 3) || ERLANG_MAJOR >= 11 - ei_mutex_free(ei_sockets_lock, 1); - ei_sockets_lock = NULL; - free(ei_sockets); - ei_sockets = NULL; - ei_n_sockets = ei_sz_sockets = 0; -#endif -#endif -} - -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; -} - -SWITCH_DECLARE(switch_status_t) ei_queue_pop(switch_queue_t *queue, void **data, switch_interval_time_t timeout) -{ - if (timeout == 0) { - return switch_queue_trypop(queue, data); - } else { - return switch_queue_pop_timeout(queue, data, timeout); - } -} -/* 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_endpoints.c b/src/mod/event_handlers/mod_kazoo/kazoo_endpoints.c deleted file mode 100644 index 4ddfeddae4..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_endpoints.c +++ /dev/null @@ -1,500 +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 - * - * - * kazoo_dptools.c -- clones of mod_dptools commands slightly modified for kazoo - * - */ -#include "mod_kazoo.h" - -#define INTERACTION_VARIABLE "Call-Interaction-ID" - -static const char *x_bridge_variables[] = { - "Call-Control-Queue", - "Call-Control-PID", - "Call-Control-Node", - INTERACTION_VARIABLE, - "ecallmgr_Ecallmgr-Node", - "sip_h_k-cid", - "Switch-URI", - "Switch-URL", - NULL -}; - -static void kz_tweaks_variables_to_event(switch_core_session_t *session, switch_event_t *event) -{ - int i; - switch_channel_t *channel = switch_core_session_get_channel(session); - for(i = 0; x_bridge_variables[i] != NULL; i++) { - const char *val = switch_channel_get_variable_dup(channel, x_bridge_variables[i], SWITCH_FALSE, -1); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, x_bridge_variables[i], val); - } -} - -static switch_call_cause_t kz_endpoint_outgoing_channel(switch_core_session_t *session, - switch_event_t *var_event, - switch_caller_profile_t *outbound_profile_in, - switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags, - switch_call_cause_t *cancel_cause) -{ - switch_xml_t x_user = NULL, x_param, x_params, x_callfwd; - char *user = NULL, *domain = NULL, *dup_domain = NULL, *dialed_user = NULL; - char *dest = NULL; - switch_call_cause_t cause = SWITCH_CAUSE_NONE; - unsigned int timelimit = SWITCH_DEFAULT_TIMEOUT; - switch_channel_t *new_channel = NULL; - switch_event_t *params = NULL, *var_event_orig = var_event; - char stupid[128] = ""; - const char *skip = NULL, *var = NULL; - switch_core_session_t *a_session = NULL, *e_session = NULL; - cJSON * ctx = NULL; - const char *endpoint_dial = NULL; - const char *callforward_dial = NULL; - const char *failover_dial = NULL; - char *b_failover_dial = NULL; - const char *endpoint_separator = NULL; - const char *varval = NULL; - char *d_dest = NULL; - switch_channel_t *channel = NULL; - switch_originate_flag_t myflags = SOF_NONE; - char *cid_name_override = NULL; - char *cid_num_override = NULL; - switch_event_t *event = NULL; - switch_status_t status = SWITCH_STATUS_SUCCESS; - switch_caller_profile_t *outbound_profile = NULL; - - - if (zstr(outbound_profile_in->destination_number)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "NO DESTINATION NUMBER\n"); - goto done; - } - - user = strdup(outbound_profile_in->destination_number); - - if (!user) - goto done; - - if ((domain = strchr(user, '@'))) { - *domain++ = '\0'; - } else { - domain = switch_core_get_domain(SWITCH_TRUE); - dup_domain = domain; - } - - if (!domain) { - goto done; - } - - - switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS); - switch_assert(params); - switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "as_channel", "true"); - switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "action", "user_call"); - if (session) { - switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "Unique-ID", switch_core_session_get_uuid(session)); - } - - if (var_event) { - switch_event_merge(params, var_event); - } - - if (var_event && (skip = switch_event_get_header(var_event, "user_recurse_variables")) && switch_false(skip)) { - if ((var = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) || (var = switch_event_get_header(var_event, "leg_timeout"))) { - timelimit = atoi(var); - } - var_event = NULL; - } - - if (switch_xml_locate_user_merged("id", user, domain, NULL, &x_user, params) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Can't find user [%s@%s]\n", user, domain); - cause = SWITCH_CAUSE_SUBSCRIBER_ABSENT; - goto done; - } - - if (var_event) { - const char * str_ctx = switch_event_get_header(var_event, "kz-endpoint-runtime-context"); - if ( str_ctx ) { - ctx = cJSON_Parse(str_ctx); - if (ctx) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call context parsed => %s\n", str_ctx); - } - } - } - - if ((x_params = switch_xml_child(x_user, "variables"))) { - for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) { - const char *pvar = switch_xml_attr_soft(x_param, "name"); - const char *val = switch_xml_attr(x_param, "value"); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "adding variable to var_event => %s = %s\n", pvar, val); - if (!var_event) { - switch_event_create(&var_event, SWITCH_EVENT_GENERAL); - } else { - switch_event_del_header(var_event, pvar); - } - switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, pvar, val); - } - } - - if ((x_params = switch_xml_child(x_user, "params"))) { - for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) { - const char *pvar = switch_xml_attr_soft(x_param, "name"); - const char *val = switch_xml_attr(x_param, "value"); - - if (!strcasecmp(pvar, "endpoint-dial-string")) { - endpoint_dial = val; - } else if (!strcasecmp(pvar, "callforward-dial-string")) { - callforward_dial = val; - } else if (!strcasecmp(pvar, "endpoint-separator")) { - endpoint_separator = val; - } else if (!strncasecmp(pvar, "dial-var-", 9)) { - if (!var_event) { - switch_event_create(&var_event, SWITCH_EVENT_GENERAL); - } else { - switch_event_del_header(var_event, pvar + 9); - } - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "adding dialog var to var_event => %s = %s\n", pvar + 9, val); - switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, pvar + 9, val); - } - } - } - - x_callfwd = switch_xml_child(x_user, "call-forward"); - if (x_callfwd) { - switch_bool_t call_fwd_is_substitute = SWITCH_FALSE, - call_fwd_is_failover = SWITCH_FALSE, - call_fwd_direct_calls_only = SWITCH_FALSE, - call_fwd_is_valid = SWITCH_TRUE; - for (x_param = switch_xml_child(x_callfwd, "variable"); x_param; x_param = x_param->next) { - const char *var = switch_xml_attr_soft(x_param, "name"); - const char *val = switch_xml_attr(x_param, "value"); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "cfw %s => %s\n", var, val); - if (!strcasecmp(var, "Is-Substitute")) { - call_fwd_is_substitute = switch_true(val); - } else if (!strcasecmp(var, "Is-Failover")) { - call_fwd_is_failover = switch_true(val); - } else if (!strcasecmp(var, "Direct-Calls-Only")) { - call_fwd_direct_calls_only = switch_true(val); - } - } - - if (call_fwd_direct_calls_only) { - call_fwd_is_valid = SWITCH_FALSE; - if (ctx ) { - cJSON *json_flags = cJSON_GetObjectItem(ctx, "Flags"); - if (json_flags && json_flags->type == cJSON_Array) { - cJSON *item; - cJSON_ArrayForEach(item, json_flags) { - if (!strcmp(item->valuestring, "direct_call")) { - call_fwd_is_valid = SWITCH_TRUE; - break; - } - } - if (!call_fwd_is_valid) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "call fwd requires direct_call and it was not found\n"); - } - } - } - } - - if (!call_fwd_is_valid) { - dest = endpoint_dial ? strdup(endpoint_dial) : strdup(""); - } else if (call_fwd_is_failover) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "setting failover => %s\n", callforward_dial); - dest = endpoint_dial ? strdup(endpoint_dial) : strdup(""); - failover_dial = callforward_dial; - } else if (call_fwd_is_substitute) { - dest = callforward_dial ? strdup(callforward_dial) : strdup(""); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "setting call fwd substitute => %s\n", dest); - } else { - dest = switch_mprintf("%s%s%s", endpoint_dial ? endpoint_dial : "", (endpoint_dial ? endpoint_separator ? endpoint_separator : "," : ""), callforward_dial); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "setting call fwd append => %s => %s\n", callforward_dial, dest); - } - } else { - dest = endpoint_dial ? strdup(endpoint_dial) : strdup(""); - } - - dialed_user = (char *)switch_xml_attr(x_user, "id"); - - if (var_event) { - switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_user", dialed_user); - switch_event_add_header_string(var_event, SWITCH_STACK_BOTTOM, "dialed_domain", domain); - } - - if (!dest) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "No dial-string available, please check your user directory.\n"); - cause = SWITCH_CAUSE_MANDATORY_IE_MISSING; - goto done; - } - - if (var_event) { - cid_name_override = switch_event_get_header(var_event, "origination_caller_id_name"); - cid_num_override = switch_event_get_header(var_event, "origination_caller_id_number"); - } - - if(session) { - a_session = session; - } else if(var_event) { - const char* uuid_e_session = switch_event_get_header(var_event, "ent_originate_aleg_uuid"); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "CHECKING ORIGINATE-UUID : %s\n", uuid_e_session); - if (uuid_e_session && (e_session = switch_core_session_locate(uuid_e_session)) != NULL) { - a_session = e_session; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "FOUND ORIGINATE-UUID : %s\n", uuid_e_session); - } - } - - if (a_session) { - switch_event_create(&event, SWITCH_EVENT_GENERAL); - channel = switch_core_session_get_channel(a_session); - if ((varval = switch_channel_get_variable(channel, SWITCH_CALL_TIMEOUT_VARIABLE)) - || (var_event && (varval = switch_event_get_header(var_event, "leg_timeout")))) { - timelimit = atoi(varval); - } - switch_channel_event_set_data(channel, event); - - switch_channel_set_variable(channel, "dialed_user", dialed_user); - switch_channel_set_variable(channel, "dialed_domain", domain); - - } else { - if (var_event) { - switch_event_dup(&event, var_event); - switch_event_del_header(event, "dialed_user"); - switch_event_del_header(event, "dialed_domain"); - if ((varval = switch_event_get_header(var_event, SWITCH_CALL_TIMEOUT_VARIABLE)) || - (varval = switch_event_get_header(var_event, "leg_timeout"))) { - timelimit = atoi(varval); - } - } else { - switch_event_create(&event, SWITCH_EVENT_REQUEST_PARAMS); - switch_assert(event); - } - - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialed_user", dialed_user); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialed_domain", domain); - } - - if ((x_params = switch_xml_child(x_user, "profile-variables"))) { - for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) { - const char *pvar = switch_xml_attr_soft(x_param, "name"); - const char *val = switch_xml_attr(x_param, "value"); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "adding profile variable to event => %s = %s\n", pvar, val); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, pvar, val); - } - } - - if ((x_params = switch_xml_child(x_user, "variables"))) { - for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) { - const char *pvar = switch_xml_attr_soft(x_param, "name"); - const char *val = switch_xml_attr(x_param, "value"); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "adding variable to event => %s = %s\n", pvar, val); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, pvar, val); - } - } - - if ((x_params = switch_xml_child(x_user, "params"))) { - for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) { - const char *pvar = switch_xml_attr_soft(x_param, "name"); - const char *val = switch_xml_attr(x_param, "value"); - - if (!strncasecmp(pvar, "dial-var-", 9)) { - switch_event_del_header(event, pvar + 9); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "adding dialog var to event => %s = %s\n", pvar + 9, val); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, pvar + 9, val); - } - } - } - - // add runtime vars to event for expand - if (ctx) { - kz_expand_json_to_event(ctx, event, "kz_ctx"); - } - - d_dest = kz_event_expand_headers(event, dest); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "dialing %s => %s\n", dest, d_dest); - - if(failover_dial) { - b_failover_dial = kz_event_expand_headers(event, failover_dial); - } - - if (var_event) { - kz_expand_headers(event, var_event); - } - - switch_event_destroy(&event); - - - if ((flags & SOF_NO_LIMITS)) { - myflags |= SOF_NO_LIMITS; - } - - if ((flags & SOF_FORKED_DIAL)) { - myflags |= SOF_NOBLOCK; - } - - if ( a_session ) { - if(var_event) { - kz_tweaks_variables_to_event(a_session, var_event); - } - } - - if(e_session) { - switch_core_session_rwunlock(e_session); - } - - switch_snprintf(stupid, sizeof(stupid), "kz/%s", dialed_user); - if (switch_stristr(stupid, d_dest)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Waddya Daft? You almost called '%s' in an infinate loop!\n", stupid); - cause = SWITCH_CAUSE_INVALID_IE_CONTENTS; - goto done; - } - - // - outbound_profile = outbound_profile_in; - /* - outbound_profile = switch_caller_profile_dup(outbound_profile_in->pool, outbound_profile_in); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG1, "CHECKING CALLER-ID\n"); - if ((x_params = switch_xml_child(x_user, "profile-variables"))) { - const char* val = NULL; - outbound_profile->soft = NULL; - for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) { - const char *pvar = switch_xml_attr(x_param, "name"); - const char *val = switch_xml_attr(x_param, "value"); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG1, "setting profile var %s = %s\n", pvar, val); - switch_caller_profile_set_var(outbound_profile, pvar, val); - } - // * TODO * verify onnet/offnet - if((val=switch_caller_get_field_by_name(outbound_profile, "Endpoint-Caller-ID-Name"))) { - outbound_profile->callee_id_name = val; - outbound_profile->orig_caller_id_name = val; - } - if((val=switch_caller_get_field_by_name(outbound_profile, "Endpoint-Caller-ID-Number"))) { - outbound_profile->callee_id_number = val; - outbound_profile->orig_caller_id_number = val; - } - } - */ - - status = switch_ivr_originate(session, new_session, &cause, d_dest, timelimit, NULL, - cid_name_override, cid_num_override, outbound_profile, var_event, myflags, - cancel_cause, NULL); - - if (status != SWITCH_STATUS_SUCCESS && b_failover_dial) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "trying failover => %s\n", failover_dial); - status = switch_ivr_originate(session, new_session, &cause, b_failover_dial, timelimit, NULL, - cid_name_override, cid_num_override, outbound_profile, var_event, myflags, - cancel_cause, NULL); - } - - if (status == SWITCH_STATUS_SUCCESS) { - const char *context; - switch_caller_profile_t *cp; - - if (var_event) { - switch_event_del_header(var_event, "origination_uuid"); - } - - new_channel = switch_core_session_get_channel(*new_session); - - if ((context = switch_channel_get_variable(new_channel, "user_context"))) { - if ((cp = switch_channel_get_caller_profile(new_channel))) { - cp->context = switch_core_strdup(cp->pool, context); - } - } - - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG1, "CHECKING CALLER-ID\n"); - if ((x_params = switch_xml_child(x_user, "profile-variables"))) { - switch_caller_profile_t *cp = switch_channel_get_caller_profile(new_channel); - const char* val = NULL; - cp->soft = NULL; - for (x_param = switch_xml_child(x_params, "variable"); x_param; x_param = x_param->next) { - const char *pvar = switch_xml_attr(x_param, "name"); - const char *val = switch_xml_attr(x_param, "value"); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_DEBUG1, "setting profile var %s = %s\n", pvar, val); - switch_channel_set_profile_var(new_channel, pvar, val); - //switch_caller_profile_set_var(cp, pvar, val); - } - // * TODO * verify onnet/offnet - if((val=switch_caller_get_field_by_name(cp, "Endpoint-Caller-ID-Name"))) { - cp->callee_id_name = val; - cp->orig_caller_id_name = val; - } - if((val=switch_caller_get_field_by_name(cp, "Endpoint-Caller-ID-Number"))) { - cp->callee_id_number = val; - cp->orig_caller_id_number = val; - } - } - switch_core_session_rwunlock(*new_session); - } - - done: - - if (d_dest && d_dest != dest) { - switch_safe_free(d_dest); - } - - if(b_failover_dial && b_failover_dial != failover_dial) { - switch_safe_free(b_failover_dial); - } - - switch_safe_free(dest); - - if (ctx) { - cJSON_Delete(ctx); - } - - if (x_user) { - switch_xml_free(x_user); - } - - if (params) { - switch_event_destroy(¶ms); - } - - if (var_event && var_event_orig != var_event) { - switch_event_destroy(&var_event); - } - - switch_safe_free(user); - switch_safe_free(dup_domain); - return cause; -} - - -/* kazoo endpoint */ - - -switch_io_routines_t kz_endpoint_io_routines = { - /*.outgoing_channel */ kz_endpoint_outgoing_channel -}; - -void add_kz_endpoints(switch_loadable_module_interface_t **module_interface) { - switch_endpoint_interface_t *kz_endpoint_interface; - kz_endpoint_interface = (switch_endpoint_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE); - kz_endpoint_interface->interface_name = "kz"; - kz_endpoint_interface->io_routines = &kz_endpoint_io_routines; -} diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_event_stream.c b/src/mod/event_handlers/mod_kazoo/kazoo_event_stream.c deleted file mode 100644 index 3d1f18326b..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_event_stream.c +++ /dev/null @@ -1,750 +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 - * - * - * kazoo_event_streams.c -- Event Publisher - * - */ -#include "mod_kazoo.h" - -#define MAX_FRAMING 4 - -/* Blatantly repurposed from switch_eventc */ -static char *my_dup(const char *s) { - size_t len = strlen(s) + 1; - void *new = malloc(len); - switch_assert(new); - - return (char *) memcpy(new, s, len); -} - -#ifndef DUP -#define DUP(str) my_dup(str) -#endif - -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++) { - if(!strncmp(name, private_headers[i], strlen(private_headers[i]))) { - return 1; - } - } - return 0; -} - -static int is_kazoo_var(char* header) -{ - int idx = 0; - while(kazoo_globals.kazoo_var_prefixes[idx] != NULL) { - char *prefix = kazoo_globals.kazoo_var_prefixes[idx]; - if(!strncasecmp(header, prefix, strlen(prefix))) { - return 1; - } - idx++; - } - - return 0; -} - -static switch_status_t kazoo_event_dup(switch_event_t **clone, switch_event_t *event, switch_hash_t *filter) { - switch_event_header_t *header; - - if (switch_event_create_subclass(clone, SWITCH_EVENT_CLONE, event->subclass_name) != SWITCH_STATUS_SUCCESS) { - return SWITCH_STATUS_GENERR; - } - - (*clone)->event_id = event->event_id; - (*clone)->event_user_data = event->event_user_data; - (*clone)->bind_user_data = event->bind_user_data; - (*clone)->flags = event->flags; - - for (header = event->headers; header; header = header->next) { - if (event->subclass_name && !strcmp(header->name, "Event-Subclass")) { - continue; - } - - if (!is_kazoo_var(header->name) - && filter - && !switch_core_hash_find(filter, header->name) - && (!kazoo_globals.send_all_headers) - && (!(kazoo_globals.send_all_private_headers && is_private_header(header->name))) - ) - { - continue; - } - - if (header->idx) { - int i; - for (i = 0; i < header->idx; i++) { - switch_event_add_header_string(*clone, SWITCH_STACK_PUSH, header->name, header->array[i]); - } - } else { - switch_event_add_header_string(*clone, SWITCH_STACK_BOTTOM, header->name, header->value); - } - } - - if (event->body) { - (*clone)->body = DUP(event->body); - } - - (*clone)->key = event->key; - - 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, 3); - ei_x_encode_atom(ebuf, "event"); - if(kazoo_globals.json_encoding == ERLANG_TUPLE) { - ei_x_encode_atom(ebuf, "json"); - } else { - ei_x_encode_atom(ebuf, "map"); - } - 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; - - /* 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; - } - - kz_event_decode(event); - - 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); - return; - } - } else { - ei_x_new(ebuf); - } - - ebuf->index = MAX_FRAMING; - - ei_x_encode_version(ebuf); - - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Target-Node", event_binding->stream->node->peer_nodename); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Switch-Nodename", kazoo_globals.ei_cnode.thisnodename); - - if(event_stream->node->legacy) { - res = encode_event_old(event, ebuf); - } else { - res = encode_event_new(event, ebuf); - } - - switch_event_del_header(event, "Switch-Nodename"); - switch_event_del_header(event, "Target-Node"); - - if(!res) { - ei_x_free(ebuf); - switch_safe_free(ebuf); - 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) { - /* 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); - } - -} - -static void *SWITCH_THREAD_FUNC event_stream_loop(switch_thread_t *thread, void *obj) { - ei_event_stream_t *event_stream = (ei_event_stream_t *) obj; - ei_event_binding_t *event_binding; - switch_sockaddr_t *sa; - uint16_t port; - char ipbuf[48]; - const char *ip_addr; - void *pop; - short event_stream_framing; - short event_stream_keepalive; - short ok = 1; - - switch_atomic_inc(&kazoo_globals.threads); - - switch_assert(event_stream != NULL); - - event_stream_framing = event_stream->event_stream_framing; - event_stream_keepalive = event_stream->event_stream_keepalive; - - /* figure out what socket we just opened */ - switch_socket_addr_get(&sa, SWITCH_FALSE, event_stream->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, "Starting erlang event stream %p on %s:%u for %s <%d.%d.%d>\n" - ,(void *)event_stream, ip_addr, port, event_stream->pid.node, event_stream->pid.creation - ,event_stream->pid.num, event_stream->pid.serial); - - while (switch_test_flag(event_stream, LFLAG_RUNNING) && switch_test_flag(&kazoo_globals, LFLAG_RUNNING) && ok) { - const switch_pollfd_t *fds; - int32_t numfds; - - /* 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++) { - switch_socket_t *newsocket; - - /* accept the new client connection */ - if (switch_socket_accept(&newsocket, event_stream->acceptor, event_stream->pool) == SWITCH_STATUS_SUCCESS) { - switch_sockaddr_t *sa; - - if (switch_socket_opt_set(newsocket, SWITCH_SO_NONBLOCK, TRUE)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't set socket as non-blocking\n"); - } - - if (event_stream_keepalive) { - if (switch_socket_opt_set(newsocket, SWITCH_SO_KEEPALIVE, TRUE)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't set socket keep-alive\n"); - } - } - - if (switch_socket_opt_set(newsocket, SWITCH_SO_TCP_NODELAY, 1)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Couldn't disable Nagle.\n"); - } - - /* close the current client, if there is one */ - close_socket(&event_stream->socket); - - switch_mutex_lock(event_stream->socket_mutex); - /* start sending to the new client */ - event_stream->socket = newsocket; - - switch_socket_addr_get(&sa, SWITCH_TRUE, newsocket); - event_stream->remote_port = switch_sockaddr_get_port(sa); - switch_get_addr(event_stream->remote_ip, sizeof (event_stream->remote_ip), sa); - - switch_socket_addr_get(&sa, SWITCH_FALSE, newsocket); - event_stream->local_port = switch_sockaddr_get_port(sa); - switch_get_addr(event_stream->local_ip, sizeof (event_stream->local_ip), sa); - - event_stream->connected = SWITCH_TRUE; - event_stream->connected_time = switch_micro_time_now(); - - switch_mutex_unlock(event_stream->socket_mutex); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Erlang event stream %p client %s:%u\n", (void *)event_stream, event_stream->remote_ip, event_stream->remote_port); - } - } - } - - /* if there was an event waiting in our queue send it to the client */ - if (ei_queue_pop(event_stream->queue, &pop, event_stream->queue_timeout) == SWITCH_STATUS_SUCCESS) { - ei_x_buff *ebuf = (ei_x_buff *) pop; - - if (event_stream->socket) { - switch_size_t size = 1, expected = 0; - switch_status_t status = SWITCH_STATUS_SUCCESS; - - if(ebuf->index >= pow(2, 8 * event_stream_framing)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sending frame size %d with insufficient frame capacity, change event_stream_framing here and tcp_packet_type in ecallmgr\n", ebuf->index); - } else { - if(event_stream_framing) { - int index = ebuf->index - MAX_FRAMING; - char byte; - short i = event_stream_framing; - while (i) { - byte = index >> (8 * --i); - ebuf->buff[MAX_FRAMING - i - 1] = byte; - } - } - expected = size = (switch_size_t)ebuf->index - MAX_FRAMING + event_stream_framing; - if((status = switch_socket_send(event_stream->socket, ebuf->buff + (MAX_FRAMING - event_stream_framing), &size)) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error %d sending event stream\n", status); - ok = 0; - } else if(expected != size) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error sending event stream, sent bytes is different of expected\n"); - ok = 0; - } - } - } - - ei_x_free(ebuf); - switch_safe_free(ebuf); - } - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Shutting down erlang event stream %p\n", (void *)event_stream); - - /* unbind from the system events */ - event_binding = event_stream->bindings; - while(event_binding != NULL) { - switch_event_unbind(&event_binding->node); - event_binding = event_binding->next; - } - event_stream->bindings = NULL; - - /* clear and destroy any remaining queued events */ - while (switch_queue_trypop(event_stream->queue, &pop) == SWITCH_STATUS_SUCCESS) { - ei_x_buff *ebuf = (ei_x_buff *) pop; - ei_x_free(ebuf); - switch_safe_free(ebuf); - } - - /* remove the acceptor pollset */ - switch_pollset_remove(event_stream->pollset, event_stream->pollfd); - - /* close any open sockets */ - close_socket(&event_stream->acceptor); - - switch_mutex_lock(event_stream->socket_mutex); - event_stream->connected = SWITCH_FALSE; - close_socket(&event_stream->socket); - switch_mutex_unlock(event_stream->socket_mutex); - - switch_mutex_destroy(event_stream->socket_mutex); - - /* clean up the memory */ - switch_core_destroy_memory_pool(&event_stream->pool); - - switch_atomic_dec(&kazoo_globals.threads); - - return NULL; -} - -ei_event_stream_t *new_event_stream(ei_node_t *ei_node, 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) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Out of memory: How many Alzheimer's patients does it take to screw in a light bulb? To get to the other side.\n"); - return NULL; - } - - /* from the memory pool, allocate the event stream structure */ - if (!(event_stream = switch_core_alloc(pool, sizeof (*event_stream)))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Out of memory: I may have Alzheimers but at least I dont have Alzheimers.\n"); - goto cleanup; - } - - /* prepare the event stream */ - memset(event_stream, 0, sizeof(*event_stream)); - event_stream->bindings = NULL; - event_stream->pool = pool; - event_stream->connected = SWITCH_FALSE; - event_stream->node = ei_node; - event_stream->event_stream_framing = ei_node->event_stream_framing; - event_stream->event_stream_keepalive = ei_node->event_stream_keepalive; - event_stream->queue_timeout = ei_node->event_stream_queue_timeout; - memcpy(&event_stream->pid, from, sizeof(erlang_pid)); - switch_queue_create(&event_stream->queue, MAX_QUEUE_LEN, pool); - - /* create a socket for accepting the event stream client */ - if (!(event_stream->acceptor = create_socket(pool))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Like car accidents, most hardware problems are due to driver error.\n"); - goto cleanup; - } - - if (switch_socket_opt_set(event_stream->acceptor, SWITCH_SO_NONBLOCK, TRUE)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Hey, it compiles!\n"); - goto cleanup; - } - - /* create a pollset so we can efficiently check for new client connections */ - if (switch_pollset_create(&event_stream->pollset, 1000, pool, 0) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "My software never has bugs. It just develops random features.\n"); - goto cleanup; - } - - switch_socket_create_pollfd(&event_stream->pollfd, event_stream->acceptor, SWITCH_POLLIN | SWITCH_POLLERR, NULL, pool); - if (switch_pollset_add(event_stream->pollset, event_stream->pollfd) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "If you saw a heat wave, would you wave back?\n"); - goto cleanup; - } - - switch_mutex_init(&event_stream->socket_mutex, SWITCH_MUTEX_DEFAULT, pool); - - /* add the new event stream to the link list - * since the event streams link list is only - * accessed from the same thread no locks - * are required */ - if (!*event_streams) { - *event_streams = event_stream; - } else { - event_stream->next = *event_streams; - *event_streams = event_stream; - } - - /* when we start we are running */ - switch_set_flag(event_stream, LFLAG_RUNNING); - - switch_threadattr_create(&thd_attr, event_stream->pool); - switch_threadattr_detach_set(thd_attr, 1); - switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_thread_create(&thread, thd_attr, event_stream_loop, event_stream, event_stream->pool); - - return event_stream; - -cleanup: - - if (event_stream) { - /* remove the acceptor pollset */ - if (event_stream->pollset) { - switch_pollset_remove(event_stream->pollset, event_stream->pollfd); - } - - /* close any open sockets */ - if (event_stream->acceptor) { - close_socket(&event_stream->acceptor); - } - } - - /* clean up the memory */ - switch_core_destroy_memory_pool(&pool); - - return NULL; - -} - -unsigned long get_stream_port(const ei_event_stream_t *event_stream) { - switch_sockaddr_t *sa; - switch_socket_addr_get(&sa, SWITCH_FALSE, event_stream->acceptor); - return (unsigned long) switch_sockaddr_get_port(sa); -} - -ei_event_stream_t *find_event_stream(ei_event_stream_t *event_stream, const erlang_pid *from) { - while (event_stream != NULL) { - if (ei_compare_pids(&event_stream->pid, from) == SWITCH_STATUS_SUCCESS) { - return event_stream; - } - event_stream = event_stream->next; - } - - return NULL; -} - -switch_status_t remove_event_stream(ei_event_stream_t **event_streams, const erlang_pid *from) { - ei_event_stream_t *event_stream, *prev = NULL; - int found = 0; - - /* if there are no event bindings there is nothing to do */ - if (!*event_streams) { - return SWITCH_STATUS_SUCCESS; - } - - /* try to find the event stream for the client process */ - event_stream = *event_streams; - while(event_stream != NULL) { - if (ei_compare_pids(&event_stream->pid, from) == SWITCH_STATUS_SUCCESS) { - found = 1; - break; - } - - prev = event_stream; - event_stream = event_stream->next; - } - - if (found) { - /* if we found an event stream remove it from - * from the link list */ - if (!prev) { - *event_streams = event_stream->next; - } else { - prev->next = event_stream->next; - } - - /* stop the event stream thread */ - switch_clear_flag(event_stream, LFLAG_RUNNING); - } - - return SWITCH_STATUS_SUCCESS; -} - -switch_status_t remove_event_streams(ei_event_stream_t **event_streams) { - ei_event_stream_t *event_stream = *event_streams; - - while(event_stream != NULL) { - /* stop the event bindings publisher thread */ - switch_clear_flag(event_stream, LFLAG_RUNNING); - - event_stream = event_stream->next; - } - - *event_streams = NULL; - - 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 && (!event_binding->stream->node->legacy)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "event binding to an event without profile in non legacy mode => %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) { - 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; - } - } else if (event_binding->type == event_type) { - return SWITCH_STATUS_SUCCESS; - } - event_binding = event_binding->next; - } - - /* from the event stream memory pool, allocate the event binding structure */ - if (!(event_binding = switch_core_alloc(event_stream->pool, sizeof (*event_binding)))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Out of random-access memory, attempting write-only memory\n"); - return SWITCH_STATUS_FALSE; - } - - /* 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); - } else { - event_binding->subclass_name = SWITCH_EVENT_SUBCLASS_ANY; - } - 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) { - 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; - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding event binding %s to stream %p for %s <%d.%d.%d>: %s %s\n" - ,event_binding->id, (void *)event_stream, event_stream->pid.node, event_stream->pid.creation - ,event_stream->pid.num, event_stream->pid.serial, switch_event_name(event_binding->type) - ,event_binding->subclass_name ? event_binding->subclass_name : ""); - - /* add the new binding to the list */ - if (!event_stream->bindings) { - event_stream->bindings = event_binding; - } else { - event_binding->next = event_stream->bindings; - event_stream->bindings = event_binding; - } - - return SWITCH_STATUS_SUCCESS; -} - -switch_status_t remove_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, *prev = NULL; - int found = 0; - - /* if there are no bindings then there is nothing to do */ - if (!event_binding) { - return SWITCH_STATUS_SUCCESS; - } - - /* try to find the event binding specified */ - while(event_binding != NULL) { - if (event_binding->type == SWITCH_EVENT_CUSTOM - && subclass_name - && event_binding->subclass_name - && !strcmp(subclass_name, event_binding->subclass_name)) { - found = 1; - break; - } else if (event_binding->type == event_type) { - found = 1; - break; - } - - prev = event_binding; - event_binding = event_binding->next; - } - - if (found) { - /* if the event binding exists, unbind from the system */ - switch_event_unbind(&event_binding->node); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removing event binding %s from %p for %s <%d.%d.%d>: %s %s\n" - ,event_binding->id, (void *)event_stream, event_stream->pid.node, event_stream->pid.creation - ,event_stream->pid.num, event_stream->pid.serial, switch_event_name(event_binding->type) - ,event_binding->subclass_name ? event_binding->subclass_name : ""); - - /* remove the event binding from the list */ - if (!prev) { - event_stream->bindings = event_binding->next; - } else { - prev->next = event_binding->next; - } - } - - return SWITCH_STATUS_SUCCESS; -} - -switch_status_t remove_event_bindings(ei_event_stream_t *event_stream) { - ei_event_binding_t *event_binding = event_stream->bindings; - - /* if there are no bindings then there is nothing to do */ - if (!event_binding) { - return SWITCH_STATUS_SUCCESS; - } - - /* try to find the event binding specified */ - while(event_binding != NULL) { - /* if the event binding exists, unbind from the system */ - switch_event_unbind(&event_binding->node); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removing event binding %s from %p for %s <%d.%d.%d>: %s %s\n" - ,event_binding->id, (void *)event_stream, event_stream->pid.node, event_stream->pid.creation - ,event_stream->pid.num, event_stream->pid.serial, switch_event_name(event_binding->type) - ,event_binding->subclass_name ? event_binding->subclass_name : ""); - - event_binding = event_binding->next; - } - - event_stream->bindings = NULL; - - return SWITCH_STATUS_SUCCESS; -} - -/* 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_fetch_agent.c b/src/mod/event_handlers/mod_kazoo/kazoo_fetch_agent.c deleted file mode 100644 index 5023e39344..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_fetch_agent.c +++ /dev/null @@ -1,803 +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 - * - * - * kazoo_fetch.c -- XML fetch request handler - * - */ -#include "mod_kazoo.h" - -static const char *fetch_uuid_sources[] = { - "Fetch-Call-UUID", - "refer-from-channel-id", - "sip_call_id", - NULL -}; - -static char *xml_section_to_string(switch_xml_section_t section) { - switch(section) { - case SWITCH_XML_SECTION_CONFIG: - return "configuration"; - case SWITCH_XML_SECTION_DIRECTORY: - return "directory"; - case SWITCH_XML_SECTION_DIALPLAN: - return "dialplan"; - case SWITCH_XML_SECTION_CHATPLAN: - return "chatplan"; - case SWITCH_XML_SECTION_CHANNELS: - return "channels"; - case SWITCH_XML_SECTION_LANGUAGES: - return "languages"; - default: - return "unknown"; - } -} - -static char *expand_vars(char *xml_str) { - char *var, *val; - char *rp = xml_str; /* read pointer */ - char *ep, *wp, *buff; /* end pointer, write pointer, write buffer */ - - if (!(strstr(xml_str, "$${"))) { - return xml_str; - } - - switch_zmalloc(buff, strlen(xml_str) * 2); - wp = buff; - ep = buff + (strlen(xml_str) * 2) - 1; - - while (*rp && wp < ep) { - if (*rp == '$' && *(rp + 1) == '$' && *(rp + 2) == '{') { - char *e = switch_find_end_paren(rp + 2, '{', '}'); - - if (e) { - rp += 3; - var = rp; - *e++ = '\0'; - rp = e; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "trying to expand %s \n", var); - if ((val = switch_core_get_variable_dup(var))) { - char *p; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "expanded %s to %s\n", var, val); - for (p = val; p && *p && wp <= ep; p++) { - *wp++ = *p; - } - switch_safe_free(val); - } - continue; - } - } - - *wp++ = *rp++; - } - - *wp++ = '\0'; - - switch_safe_free(xml_str); - return buff; -} - -static switch_xml_t fetch_handler(const char *section, const char *tag_name, const char *key_name, const char *key_value, switch_event_t *params, void *user_data) { - switch_xml_t xml = NULL; - switch_uuid_t uuid; - switch_time_t now = 0; - ei_xml_agent_t *agent = (ei_xml_agent_t *) user_data; - 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(); - - if (!switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) { - return xml; - } - - /* read-lock the agent */ - switch_thread_rwlock_rdlock(agent->lock); - - /* serialize access to current, used to round-robin requests */ - /* TODO: check kazoo_globals for round-robin boolean or loop all clients */ - switch_mutex_lock(agent->current_client_mutex); - if (!agent->current_client) { - client = agent->clients; - } else { - client = agent->current_client; - } - if (client) { - agent->current_client = client->next; - } - switch_mutex_unlock(agent->current_client_mutex); - - /* no client, no work required */ - if (!client || !client->fetch_handlers) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "No %s XML erlang handler currently available\n" - ,section); - switch_thread_rwlock_unlock(agent->lock); - return xml; - } - - /* no profile, no work required */ - if (!profile) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "weird case where client is available but there's no profile for %s. try reloading mod_kazoo.\n" - ,section); - switch_thread_rwlock_unlock(agent->lock); - 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; - } - } - - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Switch-Nodename", kazoo_globals.ei_cnode.thisnodename); - - /* prepare the reply collector */ - switch_uuid_get(&uuid); - switch_uuid_format(reply.uuid_str, &uuid); - reply.next = NULL; - reply.xml_str = NULL; - - if(switch_event_get_header(event, "Unique-ID") == NULL) { - int i; - for(i = 0; fetch_uuid_sources[i] != NULL; i++) { - if((fetch_call_id = switch_event_get_header(event, fetch_uuid_sources[i])) != NULL) { - switch_core_session_t *session = NULL; - if((session = switch_core_session_locate(fetch_call_id)) != NULL) { - switch_channel_t *channel = switch_core_session_get_channel(session); - uint32_t verbose = switch_channel_test_flag(channel, CF_VERBOSE_EVENTS); - switch_channel_set_flag(channel, CF_VERBOSE_EVENTS); - switch_channel_event_set_data(channel, event); - switch_channel_set_flag_value(channel, CF_VERBOSE_EVENTS, verbose); - switch_core_session_rwunlock(session); - break; - } - } - } - } - - 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", "%" SWITCH_UINT64_T_FMT, (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); - - kz_event_decode(event); - - 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) { - agent->replies = &reply; - } else { - reply.next = agent->replies; - agent->replies = &reply; - } - switch_mutex_unlock(agent->replies_mutex); - - fetch_handler = client->fetch_handlers; - while (fetch_handler != NULL && sent == 0) { - memcpy(&send_msg->pid, &fetch_handler->pid, sizeof(erlang_pid)); - 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 - ,fetch_handler->pid.node - ,fetch_handler->pid.creation - ,fetch_handler->pid.num - ,fetch_handler->pid.serial); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sending %s XML request (%s) to %s <%d.%d.%d>\n" - ,section - ,reply.uuid_str - ,fetch_handler->pid.node - ,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); - - switch_thread_rwlock_unlock(agent->lock); - - if (!reply.xml_str) { - switch_time_t timeout; - - timeout = switch_micro_time_now() + 3000000; - while (switch_micro_time_now() < timeout) { - /* unlock the replies list and go to sleep, calculate a three second timeout before we started the loop - * plus 100ms to add a little hysteresis between the timeout and the while loop */ - switch_thread_cond_timedwait(agent->new_reply, agent->replies_mutex, (timeout - switch_micro_time_now() + 100000)); - - /* if we woke up (and therefore have locked replies again) check if we got our reply - * otherwise we either timed-out (the while condition will fail) or one of - * our sibling processes got a reply and we should go back to sleep */ - if (reply.xml_str) { - break; - } - } - } - - /* find our reply placeholder in the linked list and remove it */ - pending = agent->replies; - while (pending != NULL) { - if (pending->uuid_str == reply.uuid_str) { - break; - } - - prev = pending; - pending = pending->next; - } - - if (pending) { - if (!prev) { - agent->replies = reply.next; - } else { - prev->next = reply.next; - } - } - - /* we are done with the replies link-list */ - switch_mutex_unlock(agent->replies_mutex); - - /* after all that did we get what we were after?! */ - if (reply.xml_str) { - /* HELL YA WE DID */ - if (kazoo_globals.expand_headers_on_fetch) { - reply.xml_str = expand_vars(reply.xml_str); - } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Received %s XML (%s) after %dms: %s\n" - ,section - ,reply.uuid_str - ,(unsigned int) (switch_micro_time_now() - now) / 1000 - ,reply.xml_str); - if ((xml = switch_xml_parse_str_dynamic(reply.xml_str, SWITCH_FALSE)) == NULL) { - switch_safe_free(reply.xml_str); - } - } else { - /* facepalm */ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Request for %s XML (%s) timed-out after %dms\n" - ,section - ,reply.uuid_str - ,(unsigned int) (switch_micro_time_now() - now) / 1000); - } - - 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; - - if (!fetch_handlers) return; - - 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; - switch_safe_free(hi); -} - -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; - - /* create memory pool for this xml search binging (lives for duration of mod_kazoo runtime) */ - if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Out of memory: They're not people; they're hippies!\n"); - return SWITCH_STATUS_MEMERR; - } - - /* allocate some memory to store the fetch bindings for this section */ - if (!(agent = switch_core_alloc(pool, sizeof (*agent)))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Out of memory: Oh, Jesus tap-dancing Christ!\n"); - return SWITCH_STATUS_MEMERR; - } - - /* try to bind to the switch */ - if (switch_xml_bind_search_function_ret(fetch_handler, section, agent, binding) != SWITCH_STATUS_SUCCESS) { - switch_core_destroy_memory_pool(&pool); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not bind to FreeSWITCH %s XML requests\n" - ,xml_section_to_string(section)); - return SWITCH_STATUS_GENERR; - } - - agent->pool = pool; - agent->section = section; - switch_thread_rwlock_create(&agent->lock, pool); - agent->clients = NULL; - switch_mutex_init(&agent->current_client_mutex, SWITCH_MUTEX_DEFAULT, pool); - agent->current_client = NULL; - switch_mutex_init(&agent->replies_mutex, SWITCH_MUTEX_DEFAULT, pool); - 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)); - - return SWITCH_STATUS_SUCCESS; -} - -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); - - /* unbind from the switch */ - switch_xml_unbind_search_function(binding); - - /* LOCK ALL THE THINGS */ - switch_thread_rwlock_wrlock(agent->lock); - switch_mutex_lock(agent->current_client_mutex); - switch_mutex_lock(agent->replies_mutex); - - /* cleanly destroy each client */ - client = agent->clients; - while(client != NULL) { - ei_xml_client_t *tmp_client = client; - fetch_handler_t *fetch_handler; - - fetch_handler = client->fetch_handlers; - while(fetch_handler != NULL) { - fetch_handler_t *tmp_fetch_handler = fetch_handler; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed %s XML handler %s <%d.%d.%d>\n" - ,xml_section_to_string(agent->section) - ,fetch_handler->pid.node - ,fetch_handler->pid.creation - ,fetch_handler->pid.num - ,fetch_handler->pid.serial); - - fetch_handler = fetch_handler->next; - switch_safe_free(tmp_fetch_handler); - } - - client = client->next; - switch_safe_free(tmp_client); - } - - /* keep the pointers clean, even if its just for a moment */ - agent->clients = NULL; - agent->current_client = NULL; - - /* release the locks! */ - switch_thread_rwlock_unlock(agent->lock); - switch_mutex_unlock(agent->current_client_mutex); - switch_mutex_unlock(agent->replies_mutex); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unbound from %s XML requests\n" - ,xml_section_to_string(agent->section)); - - /* cleanly destroy the bindings */ - switch_thread_rwlock_destroy(agent->lock); - switch_mutex_destroy(agent->current_client_mutex); - switch_mutex_destroy(agent->replies_mutex); - switch_thread_cond_destroy(agent->new_reply); - switch_core_destroy_memory_pool(&agent->pool); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t remove_xml_client(ei_node_t *ei_node, switch_xml_binding_t *binding) { - ei_xml_agent_t *agent; - 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 */ - switch_thread_rwlock_wrlock(agent->lock); - - client = agent->clients; - while (client != NULL) { - if (client->ei_node == ei_node) { - found = 1; - break; - } - - prev = client; - client = client->next; - } - - if (found) { - fetch_handler_t *fetch_handler; - - if (!prev) { - agent->clients = client->next; - } else { - prev->next = client->next; - } - - /* the mutex lock is not required since we have the write lock - * but hey its fun and safe so do it anyway */ - switch_mutex_lock(agent->current_client_mutex); - if (agent->current_client == client) { - agent->current_client = agent->clients; - } - switch_mutex_unlock(agent->current_client_mutex); - - fetch_handler = client->fetch_handlers; - while(fetch_handler != NULL) { - fetch_handler_t *tmp_fetch_handler = fetch_handler; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed %s XML handler %s <%d.%d.%d>\n" - ,xml_section_to_string(agent->section) - ,fetch_handler->pid.node - ,fetch_handler->pid.creation - ,fetch_handler->pid.num - ,fetch_handler->pid.serial); - - fetch_handler = fetch_handler->next; - switch_safe_free(tmp_fetch_handler); - } - - switch_safe_free(client); - } - - switch_thread_rwlock_unlock(agent->lock); - - return SWITCH_STATUS_SUCCESS; -} - -static ei_xml_client_t *add_xml_client(ei_node_t *ei_node, ei_xml_agent_t *agent) { - ei_xml_client_t *client; - - switch_malloc(client, sizeof(*client)); - - client->ei_node = ei_node; - client->fetch_handlers = NULL; - client->next = NULL; - - if (agent->clients) { - client->next = agent->clients; - } - - agent->clients = client; - - return client; -} - -static ei_xml_client_t *find_xml_client(ei_node_t *ei_node, ei_xml_agent_t *agent) { - ei_xml_client_t *client; - - client = agent->clients; - while (client != NULL) { - if (client->ei_node == ei_node) { - return client; - } - - client = client->next; - } - - return NULL; -} - -static switch_status_t remove_fetch_handler(ei_node_t *ei_node, erlang_pid *from, switch_xml_binding_t *binding) { - ei_xml_agent_t *agent; - ei_xml_client_t *client; - fetch_handler_t *fetch_handler, *prev = NULL; - int found = 0; - - agent = (ei_xml_agent_t *)switch_xml_get_binding_user_data(binding); - - /* write-lock the agent */ - switch_thread_rwlock_wrlock(agent->lock); - - if (!(client = find_xml_client(ei_node, agent))) { - switch_thread_rwlock_unlock(agent->lock); - return SWITCH_STATUS_SUCCESS; - } - - fetch_handler = client->fetch_handlers; - while (fetch_handler != NULL) { - if (ei_compare_pids(&fetch_handler->pid, from) == SWITCH_STATUS_SUCCESS) { - found = 1; - break; - } - - prev = fetch_handler; - fetch_handler = fetch_handler->next; - } - - if (found) { - if (!prev) { - client->fetch_handlers = fetch_handler->next; - } else { - prev->next = fetch_handler->next; - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Removed %s XML handler %s <%d.%d.%d>\n" - ,xml_section_to_string(agent->section) - ,fetch_handler->pid.node - ,fetch_handler->pid.creation - ,fetch_handler->pid.num - ,fetch_handler->pid.serial); - - switch_safe_free(fetch_handler); - } - - switch_thread_rwlock_unlock(agent->lock); - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t handle_api_command_stream(ei_node_t *ei_node, switch_stream_handle_t *stream, switch_xml_binding_t *binding) { - ei_xml_agent_t *agent; - ei_xml_client_t *client; - - if (!binding) { - return SWITCH_STATUS_GENERR; - } - - agent = (ei_xml_agent_t *)switch_xml_get_binding_user_data(binding); - - /* read-lock the agent */ - switch_thread_rwlock_rdlock(agent->lock); - client = agent->clients; - while (client != NULL) { - if (client->ei_node == ei_node) { - fetch_handler_t *fetch_handler; - fetch_handler = client->fetch_handlers; - while (fetch_handler != NULL) { - stream->write_function(stream, "XML %s handler <%d.%d.%d>\n" - ,xml_section_to_string(agent->section) - ,fetch_handler->pid.creation - ,fetch_handler->pid.num - ,fetch_handler->pid.serial); - fetch_handler = fetch_handler->next; - } - break; - } - - client = client->next; - } - switch_thread_rwlock_unlock(agent->lock); - - return SWITCH_STATUS_SUCCESS; -} - -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); - - return SWITCH_STATUS_SUCCESS; -} - -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); - - return SWITCH_STATUS_SUCCESS; -} - -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); - - return SWITCH_STATUS_SUCCESS; -} - -switch_status_t add_fetch_handler(ei_node_t *ei_node, erlang_pid *from, switch_xml_binding_t *binding) { - ei_xml_agent_t *agent; - 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 */ - switch_thread_rwlock_wrlock(agent->lock); - - if (!(client = find_xml_client(ei_node, agent))) { - client = add_xml_client(ei_node, agent); - } - - fetch_handler = client->fetch_handlers; - while (fetch_handler != NULL) { - if (ei_compare_pids(&fetch_handler->pid, from) == SWITCH_STATUS_SUCCESS) { - switch_thread_rwlock_unlock(agent->lock); - return SWITCH_STATUS_SUCCESS; - } - fetch_handler = fetch_handler->next; - } - - switch_malloc(fetch_handler, sizeof(*fetch_handler)); - - memcpy(&fetch_handler->pid, from, sizeof(erlang_pid));; - - fetch_handler->next = NULL; - if (client->fetch_handlers) { - fetch_handler->next = client->fetch_handlers; - } - - client->fetch_handlers = fetch_handler; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Added %s XML handler %s <%d.%d.%d>\n" - ,xml_section_to_string(agent->section) - ,fetch_handler->pid.node - ,fetch_handler->pid.creation - ,fetch_handler->pid.num - ,fetch_handler->pid.serial); - - switch_thread_rwlock_unlock(agent->lock); - - ei_link(ei_node, ei_self(&kazoo_globals.ei_cnode), from); - - return SWITCH_STATUS_SUCCESS; -} - -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); - - return SWITCH_STATUS_SUCCESS; -} - -switch_status_t fetch_reply(char *uuid_str, char *xml_str, switch_xml_binding_t *binding) { - ei_xml_agent_t *agent; - xml_fetch_reply_t *reply; - switch_status_t status = SWITCH_STATUS_NOTFOUND; - - agent = (ei_xml_agent_t *)switch_xml_get_binding_user_data(binding); - - switch_mutex_lock(agent->replies_mutex); - reply = agent->replies; - while (reply != NULL) { - if (!strncmp(reply->uuid_str, uuid_str, SWITCH_UUID_FORMATTED_LENGTH)) { - if (!reply->xml_str) { - reply->xml_str = xml_str; - switch_thread_cond_broadcast(agent->new_reply); - status = SWITCH_STATUS_SUCCESS; - } - break; - } - - reply = reply->next; - } - switch_mutex_unlock(agent->replies_mutex); - - return status; -} - -switch_status_t handle_api_command_streams(ei_node_t *ei_node, switch_stream_handle_t *stream) { - 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); - - return SWITCH_STATUS_SUCCESS; -} - -/* 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_fields.h b/src/mod/event_handlers/mod_kazoo/kazoo_fields.h deleted file mode 100644 index 8d17378768..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_fields.h +++ /dev/null @@ -1,203 +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; - switch_log_level_t trace_log_level; - switch_log_level_t debug_log_level; - switch_log_level_t error_log_level; - switch_log_level_t hashing_log_level; - -}; - -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, - FILTER_COMPARE_FIELD - -} 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; - int out_type_as_array; - 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_loglevels_ptr logging; - - 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 43716a8e02..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_message.c +++ /dev/null @@ -1,488 +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, kazoo_logging_ptr logging) -{ - switch_event_header_t *header; - int hasValue = 0, n; - char *value = NULL, *expr = NULL; - - switch(filter->compare) { - - case FILTER_COMPARE_EXISTS: - hasValue = switch_event_get_header(evt, filter->name) != NULL ? 1 : 0; - switch_log_printf(SWITCH_CHANNEL_LOG, logging->levels->trace_log_level, "profile[%s] event %s checking if %s exists => %s\n", logging->profile_name, logging->event_name, filter->name, hasValue ? "true" : "false"); - break; - - case FILTER_COMPARE_VALUE: - if (*filter->name == '$') { - value = expr = kz_event_expand_headers(evt, filter->name); - } else { - value = switch_event_get_header(evt, filter->name); - } - hasValue = value ? !strcmp(value, filter->value) : 0; - switch_log_printf(SWITCH_CHANNEL_LOG, logging->levels->trace_log_level, "profile[%s] event %s compare value %s to %s => %s == %s => %s\n", logging->profile_name, logging->event_name, filter->name, filter->value, value, filter->value, hasValue ? "true" : "false"); - break; - - case FILTER_COMPARE_FIELD: - if (*filter->name == '$') { - value = expr = kz_event_expand_headers(evt, filter->name); - } else { - value = switch_event_get_header(evt, filter->name); - } - hasValue = value ? !strcmp(value, switch_event_get_header_nil(evt, filter->value)) : 0; - switch_log_printf(SWITCH_CHANNEL_LOG, logging->levels->trace_log_level, "profile[%s] event %s compare field %s to %s => %s == %s => %s\n", logging->profile_name, logging->event_name, filter->name, filter->value, value, switch_event_get_header_nil(evt, filter->value), hasValue ? "true" : "false"); - break; - - case FILTER_COMPARE_PREFIX: - 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: - if (*filter->name == '$') { - value = expr = kz_event_expand_headers(evt, filter->name); - } else { - 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; - } - - switch_safe_free(expr); - - return hasValue; -} - -static kazoo_filter_ptr inline filter_event(switch_event_t* evt, kazoo_filter_ptr filter, kazoo_logging_ptr logging) -{ - while(filter) { - int hasValue = filter_compare(evt, filter, logging); - 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 (strncmp(hp->name, "_json_", 6)) { - if (hp->idx) { - cJSON *a = cJSON_CreateArray(); - int i; - - for(i = 0; i < hp->idx; i++) { - cJSON_AddItemToArray(a, cJSON_CreateString(hp->array[i])); - } - - cJSON_AddItemToObject(json, hp->name, a); - - } else { - cJSON_AddItemToObject(json, hp->name, cJSON_CreateString(hp->value)); - } - } - } -} - -static switch_status_t kazoo_event_init_json(kazoo_fields_ptr fields1, kazoo_fields_ptr fields2, switch_event_t* evt, cJSON** clone) -{ - switch_status_t status = SWITCH_STATUS_SUCCESS; - if( (fields2 && fields2->verbose) - || (fields1 && fields1->verbose) - || ( (!fields2) && (!fields1)) ) { - *clone = cJSON_CreateObject(); - if((*clone) == NULL) { - status = SWITCH_STATUS_GENERR; - } else { - kazoo_event_init_json_fields(evt, *clone); - } - } else { - *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_Parse(value); - if (!item) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "parse from raw error!\n"); - 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; -} - - -cJSON * kazoo_event_add_field_to_json(cJSON *dst, switch_event_t *src, kazoo_field_ptr field) -{ - switch_event_header_t *header; - char *expanded; - int i, n; - cJSON *item = NULL; - - switch(field->in_type) { - case FIELD_COPY: - if (!strcmp(field->name, "_body")) { - item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, src->body); - } else if((header = switch_event_get_header_ptr(src, field->name)) != NULL) { - if (header->idx) { - item = cJSON_CreateArray(); - - for(i = 0; i < header->idx; i++) { - cJSON_AddItemToArray(item, kazoo_event_json_value(field->out_type, header->array[i])); - } - - kazoo_cJSON_AddItemToObject(dst, field->as ? field->as : field->name, item); - } else if (field->out_type_as_array) { - item = cJSON_CreateArray(); - cJSON_AddItemToArray(item, kazoo_event_json_value(field->out_type, header->value)); - kazoo_cJSON_AddItemToObject(dst, field->as ? field->as : field->name, item); - } else { - item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, header->value); - } - } - break; - - case FIELD_EXPAND: - expanded = kz_event_expand_headers(src, field->value); - if(expanded != NULL && !zstr(expanded)) { - item = kazoo_event_add_json_value(dst, field, field->as ? field->as : field->name, expanded); - } - - if (expanded != field->value) { - switch_safe_free(expanded); - } - - 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, logging)) != NULL) { - switch_log_printf(SWITCH_CHANNEL_LOG, logging->levels->filtered_field_log_level, "profile[%s] event %s, referenced field %s filtered by settings %s : %s\n", logging->profile_name, logging->event_name, field->ref->name, filter->name, filter->value); - } else { - kazoo_event_add_fields_to_json(logging, dst, src, field->ref->head); - } - } 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, logging)) != NULL) { - switch_log_printf(SWITCH_CHANNEL_LOG, logging->levels->filtered_field_log_level, "profile[%s] event %s, field %s filtered by settings %s : %s\n", logging->profile_name, logging->event_name, field->name, filter->name, filter->value); - } else { - item = kazoo_event_add_field_to_json(dst, src, field); - 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; -} - -#define EVENT_TIMESTAMP_FIELD "Event-Date-Timestamp" -#define JSON_TIMESTAMP_FIELD "Event-Timestamp" - -static switch_status_t kazoo_event_add_timestamp(switch_event_t* evt, cJSON* JObj) -{ - switch_event_header_t *header; - cJSON *item = NULL; - if((header = switch_event_get_header_ptr(evt, EVENT_TIMESTAMP_FIELD)) != NULL) { - if ((item = kazoo_event_json_value(JSON_NUMBER, header->value)) != NULL) { - kazoo_cJSON_AddItemToObject(JObj, JSON_TIMESTAMP_FIELD, item); - return SWITCH_STATUS_SUCCESS; - } - } - return SWITCH_STATUS_NOTFOUND; -} - -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 = evt->subclass_name ? evt->subclass_name : switch_event_get_header_nil(evt, "Event-Name"); - logging.profile_name = profile->name; - - 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, &logging)) != NULL) { - switch_log_printf(SWITCH_CHANNEL_LOG, logging.levels->filtered_event_log_level, "profile[%s] event %s filtered by profile settings %s : %s\n", logging.profile_name, logging.event_name, filtered->name, filtered->value); - kazoo_message_destroy(&message); - return NULL; - } - } - - if (event->logging) { - logging.levels = event->logging; - } - - if (event && event->filter) { - if((filtered = filter_event(evt, event->filter, &logging)) != NULL) { - switch_log_printf(SWITCH_CHANNEL_LOG, logging.levels->filtered_event_log_level, "profile[%s] event %s filtered by event settings %s : %s\n", logging.profile_name, logging.event_name, filtered->name, filtered->value); - kazoo_message_destroy(&message); - return NULL; - } - } - - kazoo_event_init_json(profile->fields, event ? event->fields : NULL, evt, &JObj); - - kazoo_event_add_timestamp(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; - - 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); - - kazoo_event_add_timestamp(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 eade6c4e7b..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_message.h +++ /dev/null @@ -1,66 +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; - -void kazoo_cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); -cJSON * kazoo_event_add_field_to_json(cJSON *dst, switch_event_t *src, kazoo_field_ptr field); -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 deleted file mode 100644 index f75c327023..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_node.c +++ /dev/null @@ -1,1694 +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 - * Darren Schreiber - * Mike Jerris - * Tamas Cseke - * - * - * handle_msg.c -- handle messages received from erlang nodes - * - */ -#include "mod_kazoo.h" - -struct api_command_struct_s { - char *cmd; - char *arg; - ei_node_t *ei_node; - char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; - erlang_pid pid; - switch_memory_pool_t *pool; -}; -typedef struct api_command_struct_s api_command_struct_t; - -static char *REQUEST_ATOMS[] = { - "noevents", - "exit", - "link", - "nixevent", - "sendevent", - "sendmsg", - "commands", - "command", - "bind", - "getpid", - "version", - "bgapi", - "api", - "event", - "fetch_reply", - "config", - "bgapi4", - "api4", - "json_api" -}; - -typedef enum { - REQUEST_NOEVENTS, - REQUEST_EXIT, - REQUEST_LINK, - REQUEST_NIXEVENT, - REQUEST_SENDEVENT, - REQUEST_SENDMSG, - REQUEST_COMMANDS, - REQUEST_COMMAND, - REQUEST_BIND, - REQUEST_GETPID, - REQUEST_VERSION, - REQUEST_BGAPI, - REQUEST_API, - REQUEST_EVENT, - REQUEST_FETCH_REPLY, - REQUEST_CONFIG, - REQUEST_BGAPI4, - REQUEST_API4, - REQUEST_JSON_API, - REQUEST_MAX -} request_atoms_t; - -static switch_status_t find_request(char *atom, int *request) { - int i; - for (i = 0; i < REQUEST_MAX; i++) { - if(!strncmp(atom, REQUEST_ATOMS[i], MAXATOMLEN)) { - *request = i; - return SWITCH_STATUS_SUCCESS; - } - } - - return SWITCH_STATUS_FALSE; -} - -static void destroy_node_handler(ei_node_t *ei_node) { - int pending = 0; - void *pop; - switch_memory_pool_t *pool = ei_node->pool; - - switch_clear_flag(ei_node, LFLAG_RUNNING); - - /* wait for pending bgapi requests to complete */ - while ((pending = switch_atomic_read(&ei_node->pending_bgapi))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for %d pending bgapi requests to complete\n", pending); - switch_yield(500000); - } - - /* wait for receive handlers to complete */ - while ((pending = switch_atomic_read(&ei_node->receive_handlers))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Waiting for %d receive handlers to complete\n", pending); - switch_yield(500000); - } - - switch_mutex_lock(ei_node->event_streams_mutex); - remove_event_streams(&ei_node->event_streams); - switch_mutex_unlock(ei_node->event_streams_mutex); - - remove_xml_clients(ei_node); - - while (switch_queue_trypop(ei_node->received_msgs, &pop) == SWITCH_STATUS_SUCCESS) { - ei_received_msg_t *received_msg = (ei_received_msg_t *) pop; - - ei_x_free(&received_msg->buf); - switch_safe_free(received_msg); - } - - while (switch_queue_trypop(ei_node->send_msgs, &pop) == SWITCH_STATUS_SUCCESS) { - ei_send_msg_t *send_msg = (ei_send_msg_t *) pop; - - ei_x_free(&send_msg->buf); - switch_safe_free(send_msg); - } - - close_socketfd(&ei_node->nodefd); - - switch_mutex_destroy(ei_node->event_streams_mutex); - - switch_core_destroy_memory_pool(&pool); -} - -static switch_status_t add_to_ei_nodes(ei_node_t *this_ei_node) { - switch_thread_rwlock_wrlock(kazoo_globals.ei_nodes_lock); - - if (!kazoo_globals.ei_nodes) { - kazoo_globals.ei_nodes = this_ei_node; - } else { - this_ei_node->next = kazoo_globals.ei_nodes; - kazoo_globals.ei_nodes = this_ei_node; - } - - switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t remove_from_ei_nodes(ei_node_t *this_ei_node) { - ei_node_t *ei_node, *prev = NULL; - int found = 0; - - switch_thread_rwlock_wrlock(kazoo_globals.ei_nodes_lock); - - /* try to find the event bindings list for the requestor */ - ei_node = kazoo_globals.ei_nodes; - while(ei_node != NULL) { - if (ei_node == this_ei_node) { - found = 1; - break; - } - - prev = ei_node; - ei_node = ei_node->next; - } - - if (found) { - if (!prev) { - kazoo_globals.ei_nodes = this_ei_node->next; - } else { - prev->next = ei_node->next; - } - } - - switch_thread_rwlock_unlock(kazoo_globals.ei_nodes_lock); - - return SWITCH_STATUS_SUCCESS; -} - -void kazoo_event_add_unique_header_string(switch_event_t *event, switch_stack_t stack, const char *header_name, const char *data) { - if(!switch_event_get_header_ptr(event, header_name)) - switch_event_add_header_string(event, stack, header_name, data); -} - - -SWITCH_DECLARE(switch_status_t) kazoo_api_execute(const char *cmd, const char *arg, switch_core_session_t *session, switch_stream_handle_t *stream, char** reply) -{ - switch_api_interface_t *api; - switch_status_t status; - char *arg_used; - char *cmd_used; - int fire_event = 0; - char *arg_expanded = NULL; - switch_event_t* evt; - - switch_assert(stream != NULL); - switch_assert(stream->data != NULL); - switch_assert(stream->write_function != NULL); - - switch_event_create(&evt, SWITCH_EVENT_GENERAL); - arg_expanded = switch_event_expand_headers(evt, arg); - switch_event_destroy(&evt); - - cmd_used = (char *) cmd; - arg_used = arg_expanded; - - if (!stream->param_event) { - switch_event_create(&stream->param_event, SWITCH_EVENT_API); - fire_event = 1; - } - - if (stream->param_event) { - if (cmd_used && *cmd_used) { - switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command", cmd_used); - } - if (arg_used && *arg_used) { - switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command-Argument", arg_used); - } - if (arg_expanded && *arg_expanded) { - switch_event_add_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Command-Argument-Expanded", arg_expanded); - } - } - - - if (cmd_used && (api = switch_loadable_module_get_api_interface(cmd_used)) != 0) { - if ((status = api->function(arg_used, session, stream)) != SWITCH_STATUS_SUCCESS) { - kazoo_event_add_unique_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Result", "error"); - kazoo_event_add_unique_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Error", stream->data); - } else { - kazoo_event_add_unique_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Result", "success"); - kazoo_event_add_unique_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Output", stream->data); - } - UNPROTECT_INTERFACE(api); - } else { - status = SWITCH_STATUS_FALSE; - kazoo_event_add_unique_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Result", "error"); - kazoo_event_add_unique_header_string(stream->param_event, SWITCH_STACK_BOTTOM, "API-Error", "invalid command"); - } - - if (stream->param_event && fire_event) { - switch_event_fire(&stream->param_event); - } - - if (cmd_used != cmd) { - switch_safe_free(cmd_used); - } - - if (arg_used != arg_expanded) { - switch_safe_free(arg_used); - } - - if (arg_expanded != arg) { - switch_safe_free(arg_expanded); - } - - return status; -} - -static switch_status_t api_exec_stream(char *cmd, char *arg, switch_stream_handle_t *stream, char **reply) { - switch_status_t status = SWITCH_STATUS_FALSE; - - if (kazoo_api_execute(cmd, arg, NULL, stream, reply) != SWITCH_STATUS_SUCCESS) { - if(stream->data && strlen(stream->data)) { - *reply = strdup(stream->data); - status = SWITCH_STATUS_FALSE; - } else { - *reply = switch_mprintf("%s: Command not found", cmd); - status = SWITCH_STATUS_NOTFOUND; - } - } else if (!stream->data || !strlen(stream->data)) { - *reply = switch_mprintf("%s: Command returned no output", cmd); - status = SWITCH_STATUS_SUCCESS; - } else { - *reply = strdup(stream->data); - status = SWITCH_STATUS_SUCCESS; - } - - return status; -} - -static switch_status_t api_exec(char *cmd, char *arg, char **reply) { - switch_stream_handle_t stream = { 0 }; - switch_status_t status = SWITCH_STATUS_FALSE; - - SWITCH_STANDARD_STREAM(stream); - - status = api_exec_stream(cmd, arg, &stream, reply); - - switch_safe_free(stream.data); - - return status; -} - -static void *SWITCH_THREAD_FUNC bgapi3_exec(switch_thread_t *thread, void *obj) { - api_command_struct_t *acs = (api_command_struct_t *) obj; - switch_memory_pool_t *pool = acs->pool; - char *reply = NULL; - char *cmd = acs->cmd; - char *arg = acs->arg; - ei_node_t *ei_node = acs->ei_node; - ei_send_msg_t *send_msg; - - if(!switch_test_flag(ei_node, LFLAG_RUNNING) || !switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Ignoring command while shuting down\n"); - switch_atomic_dec(&ei_node->pending_bgapi); - return NULL; - } - - switch_malloc(send_msg, sizeof(*send_msg)); - memcpy(&send_msg->pid, &acs->pid, sizeof(erlang_pid)); - - ei_x_new_with_version(&send_msg->buf); - - ei_x_encode_tuple_header(&send_msg->buf, 3); - - if (api_exec(cmd, arg, &reply) == SWITCH_STATUS_SUCCESS) { - ei_x_encode_atom(&send_msg->buf, "bgok"); - } else { - ei_x_encode_atom(&send_msg->buf, "bgerror"); - } - - _ei_x_encode_string(&send_msg->buf, acs->uuid_str); - _ei_x_encode_string(&send_msg->buf, reply); - - if (switch_queue_trypush(ei_node->send_msgs, send_msg) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to send bgapi response %s to %s <%d.%d.%d>\n" - ,acs->uuid_str - ,acs->pid.node - ,acs->pid.creation - ,acs->pid.num - ,acs->pid.serial); - ei_x_free(&send_msg->buf); - switch_safe_free(send_msg); - } - - switch_atomic_dec(&ei_node->pending_bgapi); - - switch_safe_free(reply); - switch_safe_free(acs->arg); - switch_core_destroy_memory_pool(&pool); - - return NULL; -} - - -static void *SWITCH_THREAD_FUNC bgapi4_exec(switch_thread_t *thread, void *obj) { - api_command_struct_t *acs = (api_command_struct_t *) obj; - switch_memory_pool_t *pool = acs->pool; - char *reply = NULL; - char *cmd = acs->cmd; - char *arg = acs->arg; - ei_node_t *ei_node = acs->ei_node; - ei_send_msg_t *send_msg; - switch_stream_handle_t stream = { 0 }; - - if(!switch_test_flag(ei_node, LFLAG_RUNNING) || !switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Ignoring command while shuting down\n"); - switch_atomic_dec(&ei_node->pending_bgapi); - return NULL; - } - - SWITCH_STANDARD_STREAM(stream); - switch_event_create(&stream.param_event, SWITCH_EVENT_API); - - switch_malloc(send_msg, sizeof(*send_msg)); - memcpy(&send_msg->pid, &acs->pid, sizeof(erlang_pid)); - - ei_x_new_with_version(&send_msg->buf); - ei_x_encode_tuple_header(&send_msg->buf, (stream.param_event ? 4 : 3)); - - if (api_exec_stream(cmd, arg, &stream, &reply) == SWITCH_STATUS_SUCCESS) { - ei_x_encode_atom(&send_msg->buf, "bgok"); - } else { - ei_x_encode_atom(&send_msg->buf, "bgerror"); - } - - _ei_x_encode_string(&send_msg->buf, acs->uuid_str); - _ei_x_encode_string(&send_msg->buf, reply); - - if (stream.param_event) { - ei_encode_switch_event_headers_2(&send_msg->buf, stream.param_event, 0); - } - - if (switch_queue_trypush(ei_node->send_msgs, send_msg) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to send bgapi response %s to %s <%d.%d.%d>\n" - ,acs->uuid_str - ,acs->pid.node - ,acs->pid.creation - ,acs->pid.num - ,acs->pid.serial); - ei_x_free(&send_msg->buf); - switch_safe_free(send_msg); - } - - switch_atomic_dec(&ei_node->pending_bgapi); - - if (stream.param_event) { - switch_event_fire(&stream.param_event); - } - - switch_safe_free(reply); - switch_safe_free(acs->arg); - switch_core_destroy_memory_pool(&pool); - switch_safe_free(stream.data); - - return NULL; -} - -static void log_sendmsg_request(char *uuid, switch_event_t *event) -{ - char *cmd = switch_event_get_header(event, "call-command"); - unsigned long cmd_hash; - switch_ssize_t hlen = -1; - unsigned long CMD_EXECUTE = switch_hashfunc_default("execute", &hlen); - unsigned long CMD_XFEREXT = switch_hashfunc_default("xferext", &hlen); - - if (zstr(cmd)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "log|%s|invalid \n", uuid); - DUMP_EVENT(event); - return; - } - - cmd_hash = switch_hashfunc_default(cmd, &hlen); - - if (cmd_hash == CMD_EXECUTE) { - char *app_name = switch_event_get_header(event, "execute-app-name"); - char *app_arg = switch_event_get_header(event, "execute-app-arg"); - - if(app_name) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "log|%s|executing %s %s \n", uuid, app_name, switch_str_nil(app_arg)); - } - } else if (cmd_hash == CMD_XFEREXT) { - switch_event_header_t *hp; - - for (hp = event->headers; hp; hp = hp->next) { - char *app_name; - char *app_arg; - - if (!strcasecmp(hp->name, "application")) { - app_name = strdup(hp->value); - app_arg = strchr(app_name, ' '); - - if (app_arg) { - *app_arg++ = '\0'; - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "log|%s|building xferext extension: %s %s\n", uuid, app_name, app_arg); - switch_safe_free(app_name); - } - } - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "log|%s|transfered call to xferext extension\n", uuid); - } -} - -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; - } - - if (ei_decode_list_header(buf->buff, &buf->index, &propslist_length)) { - return SWITCH_STATUS_FALSE; - } - - while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && n < propslist_length) { - char key[1024]; - char *value; - - if (arity != 2) { - return SWITCH_STATUS_FALSE; - } - - if (ei_decode_string_or_binary_limited(buf->buff, &buf->index, sizeof(key), key)) { - return SWITCH_STATUS_FALSE; - } - - if (ei_decode_string_or_binary(buf->buff, &buf->index, &value)) { - return SWITCH_STATUS_FALSE; - } - - if (!strcmp(key, "body")) { - 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_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_nodup(event, SWITCH_STACK_BOTTOM, key, value); - } - n++; - } - ei_skip_term(buf->buff, &buf->index); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t erlang_response_badarg(ei_x_buff * rbuf) { - if (rbuf) { - ei_x_encode_tuple_header(rbuf, 2); - ei_x_encode_atom(rbuf, "error"); - ei_x_encode_atom(rbuf, "badarg"); - } - - return SWITCH_STATUS_GENERR; -} - -static switch_status_t erlang_response_baduuid(ei_x_buff * rbuf) { - if (rbuf) { - ei_x_format_wo_ver(rbuf, "{~a,~a}", "error", "baduuid"); - } - - return SWITCH_STATUS_NOTFOUND; -} - -static switch_status_t erlang_response_notimplemented(ei_x_buff * rbuf) { - if (rbuf) { - ei_x_encode_tuple_header(rbuf, 2); - ei_x_encode_atom(rbuf, "error"); - ei_x_encode_atom(rbuf, "not_implemented"); - } - - return SWITCH_STATUS_NOTFOUND; -} - -static switch_status_t erlang_response_ok(ei_x_buff *rbuf) { - if (rbuf) { - ei_x_encode_atom(rbuf, "ok"); - } - - 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; - - switch_mutex_lock(ei_node->event_streams_mutex); - if ((event_stream = find_event_stream(ei_node->event_streams, pid))) { - remove_event_bindings(event_stream); - } - switch_mutex_unlock(ei_node->event_streams_mutex); - - return erlang_response_ok(rbuf); -} - -static switch_status_t handle_request_exit(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { - switch_clear_flag(ei_node, LFLAG_RUNNING); - - return erlang_response_ok(rbuf); -} - -static switch_status_t handle_request_link(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { - ei_link(ei_node, ei_self(&kazoo_globals.ei_cnode), pid); - - return erlang_response_ok(rbuf); -} - -static switch_status_t handle_request_nixevent(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 custom = 0, length = 0; - int i; - - if (ei_decode_list_header(buf->buff, &buf->index, &length) - || length == 0) { - return erlang_response_badarg(rbuf); - } - - switch_mutex_lock(ei_node->event_streams_mutex); - if (!(event_stream = find_event_stream(ei_node->event_streams, pid))) { - switch_mutex_unlock(ei_node->event_streams_mutex); - return erlang_response_ok(rbuf); - } - - for (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); - } - - if (custom) { - 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++) { - if(type != SWITCH_EVENT_CUSTOM) { - remove_event_binding(event_stream, type, NULL); - } - } - break; - } - - default: - remove_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); - - return erlang_response_ok(rbuf); -} - -static switch_status_t handle_request_sendevent(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { - char event_name[MAXATOMLEN + 1]; - char subclass_name[MAXATOMLEN + 1]; - switch_event_types_t event_type; - switch_event_t *event = NULL; - - if (ei_decode_atom_safe(buf->buff, &buf->index, event_name) - || switch_name_event(event_name, &event_type) != SWITCH_STATUS_SUCCESS) - { - return erlang_response_badarg(rbuf); - } - - if (!strncasecmp(event_name, "CUSTOM", MAXATOMLEN)) { - if(ei_decode_atom(buf->buff, &buf->index, subclass_name)) { - return erlang_response_badarg(rbuf); - } - switch_event_create_subclass(&event, event_type, subclass_name); - } else { - switch_event_create(&event, event_type); - } - - if (build_event(event, buf) == SWITCH_STATUS_SUCCESS) { - switch_event_fire(&event); - return erlang_response_ok(rbuf); - } - - if(event) { - switch_event_destroy(&event); - } - - 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); - } - - 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); - - 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); - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "event-uuid", cmd_uuid_str); - - 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_event_del_header_val(event, "event-uuid-name", 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; - char 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_event_create(&event, SWITCH_EVENT_SEND_MESSAGE); - if (build_event(event, buf) != SWITCH_STATUS_SUCCESS) { - switch_core_session_rwunlock(session); - return erlang_response_badarg(rbuf); - } - - log_sendmsg_request(uuid_str, event); - - switch_core_session_queue_private_event(session, &event, SWITCH_FALSE); - switch_core_session_rwunlock(session); - - return erlang_response_ok(rbuf); -} - -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); -} - -static switch_status_t handle_request_bind(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { - char section_str[MAXATOMLEN + 1]; - switch_xml_section_t section; - - if (ei_decode_atom_safe(buf->buff, &buf->index, section_str) - || !(section = switch_xml_parse_section_string(section_str))) { - return erlang_response_badarg(rbuf); - } - - switch(section) { - case SWITCH_XML_SECTION_CONFIG: - add_fetch_handler(ei_node, pid, kazoo_globals.config_fetch_binding); - if(!kazoo_globals.config_fetched) { - kazoo_globals.config_fetched = 1; - fetch_config(); - } - break; - case SWITCH_XML_SECTION_DIRECTORY: - add_fetch_handler(ei_node, pid, kazoo_globals.directory_fetch_binding); - break; - 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; - default: - return erlang_response_badarg(rbuf); - } - - return erlang_response_ok(rbuf); -} - -static switch_status_t handle_request_getpid(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { - if (rbuf) { - ei_x_encode_tuple_header(rbuf, 2); - ei_x_encode_atom(rbuf, "ok"); - ei_x_encode_pid(rbuf, ei_self(&kazoo_globals.ei_cnode)); - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t handle_request_version(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { - if (rbuf) { - ei_x_encode_tuple_header(rbuf, 2); - ei_x_encode_atom(rbuf, "ok"); - _ei_x_encode_string(rbuf, VERSION); - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t handle_request_bgapi(switch_thread_start_t func, ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { - api_command_struct_t *acs = NULL; - switch_memory_pool_t *pool; - switch_thread_t *thread; - switch_threadattr_t *thd_attr = NULL; - switch_uuid_t uuid; - char cmd[MAXATOMLEN + 1]; - - if (ei_decode_atom_safe(buf->buff, &buf->index, cmd)) { - return erlang_response_badarg(rbuf); - } - - switch_core_new_memory_pool(&pool); - acs = switch_core_alloc(pool, sizeof(*acs)); - - if (ei_decode_string_or_binary(buf->buff, &buf->index, &acs->arg)) { - switch_core_destroy_memory_pool(&pool); - return erlang_response_badarg(rbuf); - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "bgexec: %s(%s)\n", cmd, acs->arg); - - acs->pool = pool; - acs->ei_node = ei_node; - acs->cmd = switch_core_strdup(pool, cmd); - memcpy(&acs->pid, pid, sizeof(erlang_pid)); - - switch_threadattr_create(&thd_attr, acs->pool); - switch_threadattr_detach_set(thd_attr, 1); - switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - - switch_uuid_get(&uuid); - switch_uuid_format(acs->uuid_str, &uuid); - switch_thread_create(&thread, thd_attr, func, acs, acs->pool); - - switch_atomic_inc(&ei_node->pending_bgapi); - - if (rbuf) { - ei_x_encode_tuple_header(rbuf, 2); - ei_x_encode_atom(rbuf, "ok"); - _ei_x_encode_string(rbuf, acs->uuid_str); - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t handle_request_bgapi3(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { - return handle_request_bgapi(bgapi3_exec, ei_node, pid, buf, rbuf); -} - -static switch_status_t handle_request_bgapi4(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { - return handle_request_bgapi(bgapi4_exec, ei_node, pid, buf, rbuf); -} - -static switch_status_t handle_request_api4(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { - char cmd[MAXATOMLEN + 1]; - char *arg; - switch_stream_handle_t stream = { 0 }; - - SWITCH_STANDARD_STREAM(stream); - switch_event_create(&stream.param_event, SWITCH_EVENT_API); - - if (ei_decode_atom_safe(buf->buff, &buf->index, cmd)) { - return erlang_response_badarg(rbuf); - } - - if (ei_decode_string_or_binary(buf->buff, &buf->index, &arg)) { - return erlang_response_badarg(rbuf); - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "exec: %s(%s)\n", cmd, arg); - - if (rbuf) { - char *reply; - switch_status_t status; - - status = api_exec_stream(cmd, arg, &stream, &reply); - - if (status == SWITCH_STATUS_SUCCESS) { - ei_x_encode_tuple_header(rbuf, 2); - ei_x_encode_atom(rbuf, "ok"); - } else { - ei_x_encode_tuple_header(rbuf, (stream.param_event ? 3 : 2)); - ei_x_encode_atom(rbuf, "error"); - } - - _ei_x_encode_string(rbuf, reply); - - if (stream.param_event && status != SWITCH_STATUS_SUCCESS) { - ei_encode_switch_event_headers(rbuf, stream.param_event); - } - - switch_safe_free(reply); - } - - if (stream.param_event) { - switch_event_fire(&stream.param_event); - } - - switch_safe_free(arg); - switch_safe_free(stream.data); - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t handle_request_json_api(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) -{ - char *arg; - cJSON *jcmd = NULL; - switch_core_session_t *session = NULL; - const char *uuid = NULL; - char *response = NULL; - const char *parse_end = NULL; - switch_status_t status = SWITCH_STATUS_SUCCESS; - - if (ei_decode_string_or_binary(buf->buff, &buf->index, &arg)) { - return erlang_response_badarg(rbuf); - } - - jcmd = cJSON_ParseWithOpts(arg, &parse_end, 0); - - if (!jcmd) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "json api error: %s\n", parse_end); - ei_x_encode_tuple_header(rbuf, 2); - ei_x_encode_atom(rbuf, "error"); - ei_x_encode_tuple_header(rbuf, 2); - ei_x_encode_atom(rbuf, "parse_error"); - _ei_x_encode_string(rbuf, parse_end); - switch_safe_free(arg); - return status; - } - - if ((uuid = cJSON_GetObjectCstr(jcmd, "uuid"))) { - if (!(session = switch_core_session_locate(uuid))) { - cJSON_Delete(jcmd); - switch_safe_free(arg); - return erlang_response_baduuid(rbuf); - } - } - - status = switch_json_api_execute(jcmd, session, NULL); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "json api (%i): %s\n", status , arg); - - response = cJSON_PrintUnformatted(jcmd); - ei_x_encode_tuple_header(rbuf, 2); - if (status == SWITCH_STATUS_SUCCESS) { - ei_x_encode_atom(rbuf, "ok"); - } else { - ei_x_encode_atom(rbuf, "error"); - } - _ei_x_encode_string(rbuf, response); - switch_safe_free(response); - - cJSON_Delete(jcmd); - switch_safe_free(arg); - - if (session) { - switch_core_session_rwunlock(session); - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t handle_request_api(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { - char cmd[MAXATOMLEN + 1]; - char *arg; - - if (ei_decode_atom_safe(buf->buff, &buf->index, cmd)) { - return erlang_response_badarg(rbuf); - } - - if (ei_decode_string_or_binary(buf->buff, &buf->index, &arg)) { - return erlang_response_badarg(rbuf); - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "exec: %s(%s)\n", cmd, arg); - - if (rbuf) { - char *reply; - - ei_x_encode_tuple_header(rbuf, 2); - - if (api_exec(cmd, arg, &reply) == SWITCH_STATUS_SUCCESS) { - ei_x_encode_atom(rbuf, "ok"); - } else { - ei_x_encode_atom(rbuf, "error"); - } - - _ei_x_encode_string(rbuf, reply); - switch_safe_free(reply); - } - - switch_safe_free(arg); - - return SWITCH_STATUS_SUCCESS; -} - -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]; - ei_event_stream_t *event_stream; - int length = 0; - int i; - - if (ei_decode_list_header(buf->buff, &buf->index, &length) || !length) { - return erlang_response_badarg(rbuf); - } - - 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); - /* 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++) { - 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); - } - switch_mutex_unlock(ei_node->event_streams_mutex); - - if (rbuf) { - ei_x_encode_tuple_header(rbuf, 2); - ei_x_encode_atom(rbuf, "ok"); - - ei_x_encode_tuple_header(rbuf, 2); - ei_x_encode_string(rbuf, ei_node->local_ip); - ei_x_encode_ulong(rbuf, get_stream_port(event_stream)); - } - - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t handle_request_fetch_reply(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { - char section_str[MAXATOMLEN + 1]; - char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; - char *xml_str; - switch_xml_section_t section; - switch_status_t result; - - if (ei_decode_atom_safe(buf->buff, &buf->index, section_str) - || !(section = switch_xml_parse_section_string(section_str))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Ignoring a fetch reply without a configuration section\n"); - - return erlang_response_badarg(rbuf); - } - - if (ei_decode_string_or_binary_limited(buf->buff, &buf->index, sizeof(uuid_str), uuid_str) - || zstr_buf(uuid_str)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Ignoring a fetch reply without request UUID\n"); - - return erlang_response_badarg(rbuf); - } - - if (ei_decode_string_or_binary(buf->buff, &buf->index, &xml_str)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Ignoring a fetch reply without XML : %s \n", uuid_str); - - return erlang_response_badarg(rbuf); - } - - if (zstr(xml_str)) { - switch_safe_free(xml_str); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Ignoring an empty fetch reply : %s\n", uuid_str); - - return erlang_response_badarg(rbuf); - } - - switch(section) { - case SWITCH_XML_SECTION_CONFIG: - result = fetch_reply(uuid_str, xml_str, kazoo_globals.config_fetch_binding); - break; - case SWITCH_XML_SECTION_DIRECTORY: - result = fetch_reply(uuid_str, xml_str, kazoo_globals.directory_fetch_binding); - break; - 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; - default: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received fetch reply %s for an unknown configuration section: %s : %s\n", uuid_str, section_str, xml_str); - switch_safe_free(xml_str); - - return erlang_response_badarg(rbuf); - } - - if (result == SWITCH_STATUS_SUCCESS) { - switch_safe_free(xml_str); - - return erlang_response_ok(rbuf); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received fetch reply %s is unknown or has expired : %s\n", uuid_str, xml_str); - switch_safe_free(xml_str); - - return erlang_response_baduuid(rbuf); - } -} - -static switch_status_t handle_kazoo_request(ei_node_t *ei_node, erlang_pid *pid, ei_x_buff *buf, ei_x_buff *rbuf) { - char atom[MAXATOMLEN + 1]; - int type, size, arity = 0, request; - - /* ...{_, _}} | ...atom()} = Buf */ - ei_get_type(buf->buff, &buf->index, &type, &size); - - /* is_tuple(Type) */ - if (type == ERL_SMALL_TUPLE_EXT) { - /* ..._, _} = Buf */ - ei_decode_tuple_header(buf->buff, &buf->index, &arity); - } - - if (ei_decode_atom_safe(buf->buff, &buf->index, atom)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received mod_kazoo message that did not contain a command (ensure you are using Kazoo v2.14+).\n"); - return erlang_response_badarg(rbuf); - } - - if (find_request(atom, &request) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received mod_kazoo message for unimplemented feature (ensure you are using Kazoo v2.14+): %s\n", atom); - return erlang_response_badarg(rbuf); - } - - switch(request) { - case REQUEST_NOEVENTS: - return handle_request_noevents(ei_node, pid, buf, rbuf); - case REQUEST_EXIT: - return handle_request_exit(ei_node, pid, buf, rbuf); - case REQUEST_LINK: - return handle_request_link(ei_node, pid, buf, rbuf); - case REQUEST_NIXEVENT: - return handle_request_nixevent(ei_node, pid, buf, rbuf); - case REQUEST_SENDEVENT: - 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: - return handle_request_getpid(ei_node, pid, buf, rbuf); - case REQUEST_VERSION: - return handle_request_version(ei_node, pid, buf, rbuf); - case REQUEST_BGAPI: - return handle_request_bgapi3(ei_node, pid, buf, rbuf); - case REQUEST_API: - return handle_request_api(ei_node, pid, buf, rbuf); - case REQUEST_EVENT: - 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_API4: - return handle_request_api4(ei_node, pid, buf, rbuf); - case REQUEST_JSON_API: - return handle_request_json_api(ei_node, pid, buf, rbuf); - default: - return erlang_response_notimplemented(rbuf); - } -} - -static switch_status_t handle_mod_kazoo_request(ei_node_t *ei_node, erlang_msg *msg, ei_x_buff *buf) { - char atom[MAXATOMLEN + 1]; - int version, type, size, arity; - - buf->index = 0; - ei_decode_version(buf->buff, &buf->index, &version); - ei_get_type(buf->buff, &buf->index, &type, &size); - - /* is_tuple(Type) */ - if (type != ERL_SMALL_TUPLE_EXT) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received erlang message of an unexpected type (ensure you are using Kazoo v2.14+).\n"); - return SWITCH_STATUS_GENERR; - } - - ei_decode_tuple_header(buf->buff, &buf->index, &arity); - - if (ei_decode_atom_safe(buf->buff, &buf->index, atom)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received erlang message tuple that did not start with an atom (ensure you are using Kazoo v2.14+).\n"); - return SWITCH_STATUS_GENERR; - } - - /* {'$gen_cast', {_, _}} = Buf */ - if (arity == 2 && !strncmp(atom, "$gen_cast", 9)) { - return handle_kazoo_request(ei_node, &msg->from, buf, NULL); - /* {'$gen_call', {_, _}, {_, _}} = Buf */ - } else if (arity == 3 && !strncmp(atom, "$gen_call", 9)) { - switch_status_t status; - ei_send_msg_t *send_msg = NULL; - erlang_ref ref; - - switch_malloc(send_msg, sizeof(*send_msg)); - ei_x_new_with_version(&send_msg->buf); - - /* ...{_, _}, {_, _}} = Buf */ - ei_get_type(buf->buff, &buf->index, &type, &size); - - /* is_tuple(Type) */ - if (type != ERL_SMALL_TUPLE_EXT) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received erlang call message of an unexpected type (ensure you are using Kazoo v2.14+).\n"); - ei_x_free(&send_msg->buf); - switch_safe_free(send_msg); - return SWITCH_STATUS_GENERR; - } - - /* ..._, _}, {_, _}} = Buf */ - ei_decode_tuple_header(buf->buff, &buf->index, &arity); - - /* ...pid(), _}, {_, _}} = Buf */ - if (ei_decode_pid(buf->buff, &buf->index, &send_msg->pid)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received erlang call without a reply pid (ensure you are using Kazoo v2.14+).\n"); - ei_x_free(&send_msg->buf); - switch_safe_free(send_msg); - return SWITCH_STATUS_GENERR; - } - - /* ...ref()}, {_, _}} = Buf */ - if (ei_decode_ref(buf->buff, &buf->index, &ref)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received erlang call without a reply tag (ensure you are using Kazoo v2.14+).\n"); - ei_x_free(&send_msg->buf); - switch_safe_free(send_msg); - return SWITCH_STATUS_GENERR; - } - - /* send_msg->buf = {ref(), ... */ - ei_x_encode_tuple_header(&send_msg->buf, 2); - ei_x_encode_ref(&send_msg->buf, &ref); - - status = handle_kazoo_request(ei_node, &msg->from, buf, &send_msg->buf); - - if (switch_queue_trypush(ei_node->send_msgs, send_msg) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "error queuing reply\n"); - ei_x_free(&send_msg->buf); - switch_safe_free(send_msg); - } - - return status; - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Received inappropriate erlang message (ensure you are using Kazoo v2.14+)\n"); - return SWITCH_STATUS_GENERR; - } -} - -/* fake enough of the net_kernel module to be able to respond to net_adm:ping */ -static switch_status_t handle_net_kernel_request(ei_node_t *ei_node, erlang_msg *msg, ei_x_buff *buf) { - int version, size, type, arity; - char atom[MAXATOMLEN + 1]; - ei_send_msg_t *send_msg = NULL; - erlang_ref ref; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Received net_kernel message, attempting to reply\n"); - - switch_malloc(send_msg, sizeof(*send_msg)); - ei_x_new_with_version(&send_msg->buf); - - buf->index = 0; - ei_decode_version(buf->buff, &buf->index, &version); - ei_get_type(buf->buff, &buf->index, &type, &size); - - /* is_tuple(Buff) */ - if (type != ERL_SMALL_TUPLE_EXT) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Received net_kernel message of an unexpected type\n"); - goto error; - } - - ei_decode_tuple_header(buf->buff, &buf->index, &arity); - - /* {_, _, _} = Buf */ - if (arity != 3) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Received net_kernel tuple has an unexpected arity\n"); - goto error; - } - - /* {'$gen_call', _, _} = Buf */ - if (ei_decode_atom_safe(buf->buff, &buf->index, atom) || strncmp(atom, "$gen_call", 9)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Received net_kernel message tuple does not begin with the atom '$gen_call'\n"); - goto error; - } - - ei_get_type(buf->buff, &buf->index, &type, &size); - - /* {_, Sender, _}=Buff, is_tuple(Sender) */ - if (type != ERL_SMALL_TUPLE_EXT) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Second element of the net_kernel tuple is an unexpected type\n"); - goto error; - } - - ei_decode_tuple_header(buf->buff, &buf->index, &arity); - - /* {_, _}=Sender */ - if (arity != 2) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Second element of the net_kernel message has an unexpected arity\n"); - goto error; - } - - /* {Pid, Ref}=Sender */ - if (ei_decode_pid(buf->buff, &buf->index, &send_msg->pid) || ei_decode_ref(buf->buff, &buf->index, &ref)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Unable to decode erlang pid or ref of the net_kernel tuple second element\n"); - goto error; - } - - ei_get_type(buf->buff, &buf->index, &type, &size); - - /* {_, _, Request}=Buff, is_tuple(Request) */ - if (type != ERL_SMALL_TUPLE_EXT) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Third element of the net_kernel message is an unexpected type\n"); - goto error; - } - - ei_decode_tuple_header(buf->buff, &buf->index, &arity); - - /* {_, _}=Request */ - if (arity != 2) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Third element of the net_kernel message has an unexpected arity\n"); - goto error; - } - - /* {is_auth, _}=Request */ - if (ei_decode_atom_safe(buf->buff, &buf->index, atom) || strncmp(atom, "is_auth", MAXATOMLEN)) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "The net_kernel message third element does not begin with the atom 'is_auth'\n"); - goto error; - } - - /* To ! {Tag, Reply} */ - ei_x_encode_tuple_header(&send_msg->buf, 2); - ei_x_encode_ref(&send_msg->buf, &ref); - ei_x_encode_atom(&send_msg->buf, "yes"); - - if (switch_queue_trypush(ei_node->send_msgs, send_msg) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "unable to queue net kernel message\n"); - goto error; - } - - return SWITCH_STATUS_SUCCESS; - -error: - ei_x_free(&send_msg->buf); - switch_safe_free(send_msg); - return SWITCH_STATUS_GENERR; -} - -static switch_status_t handle_erl_send(ei_node_t *ei_node, erlang_msg *msg, ei_x_buff *buf) { - if (!strncmp(msg->toname, "net_kernel", MAXATOMLEN)) { - return handle_net_kernel_request(ei_node, msg, buf); - } 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); - return SWITCH_STATUS_GENERR; - } -} - -static switch_status_t handle_erl_msg(ei_node_t *ei_node, erlang_msg *msg, ei_x_buff *buf) { - switch (msg->msgtype) { - case ERL_SEND: - case ERL_REG_SEND: - return handle_erl_send(ei_node, msg, buf); - case ERL_LINK: - /* we received an erlang link request? Should we be linking or are they linking to us and this just informs us? */ - return SWITCH_STATUS_SUCCESS; - case ERL_UNLINK: - /* we received an erlang unlink request? Same question as the ERL_LINK, are we expected to do something? */ - return SWITCH_STATUS_SUCCESS; - case ERL_EXIT: - /* we received a notice that a process we were linked to has exited, clean up any bindings */ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Received erlang exit notice for %s <%d.%d.%d>\n", msg->from.node, msg->from.creation, msg->from.num, msg->from.serial); - - switch_mutex_lock(ei_node->event_streams_mutex); - remove_event_stream(&ei_node->event_streams, &msg->from); - switch_mutex_unlock(ei_node->event_streams_mutex); - - remove_fetch_handlers(ei_node, &msg->from); - return SWITCH_STATUS_SUCCESS; - case ERL_EXIT2: - /* erlang nodes appear to send both the old and new style exit notices so just ignore these */ - return SWITCH_STATUS_FALSE; - default: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Received unexpected erlang message type %d\n", (int) (msg->msgtype)); - return SWITCH_STATUS_FALSE; - } -} - -static void *SWITCH_THREAD_FUNC receive_handler(switch_thread_t *thread, void *obj) { - ei_node_t *ei_node = (ei_node_t *) obj; - - switch_atomic_inc(&kazoo_globals.threads); - switch_atomic_inc(&ei_node->receive_handlers); - - switch_assert(ei_node != NULL); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Starting erlang receive handler %p: %s (%s:%d)\n", (void *)ei_node, ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port); - - while (switch_test_flag(ei_node, LFLAG_RUNNING) && switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) { - void *pop = NULL; - - if (ei_queue_pop(ei_node->received_msgs, &pop, ei_node->receiver_queue_timeout) == 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); - switch_safe_free(received_msg); - } - } - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Shutdown erlang receive handler %p: %s (%s:%d)\n", (void *)ei_node, ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port); - - switch_atomic_dec(&ei_node->receive_handlers); - switch_atomic_dec(&kazoo_globals.threads); - - return NULL; -} - -static void *SWITCH_THREAD_FUNC handle_node(switch_thread_t *thread, void *obj) { - ei_node_t *ei_node = (ei_node_t *) obj; - ei_received_msg_t *received_msg = NULL; - int fault_count = 0; - - switch_atomic_inc(&kazoo_globals.threads); - - switch_assert(ei_node != NULL); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Starting node request handler %p: %s (%s:%d)\n", (void *)ei_node, ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port); - - add_to_ei_nodes(ei_node); - - while (switch_test_flag(ei_node, LFLAG_RUNNING) && switch_test_flag(&kazoo_globals, LFLAG_RUNNING)) { - int status; - int send_msg_count = 0; - void *pop = NULL; - - if (!received_msg) { - switch_malloc(received_msg, sizeof(*received_msg)); - /* create a new buf for the erlang message and a rbuf for the reply */ - if(kazoo_globals.receive_msg_preallocate > 0) { - switch_malloc(received_msg->buf.buff, kazoo_globals.receive_msg_preallocate); - received_msg->buf.buffsz = kazoo_globals.receive_msg_preallocate; - received_msg->buf.index = 0; - if(received_msg->buf.buff == NULL) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not pre-allocate memory for mod_kazoo message\n"); - goto exit; - } - } else { - ei_x_new(&received_msg->buf); - } - } else { - received_msg->buf.index = 0; - } - - while (++send_msg_count <= kazoo_globals.send_msg_batch - && ei_queue_pop(ei_node->send_msgs, &pop, ei_node->sender_queue_timeout) == 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" - ,send_msg->pid.node - ,send_msg->pid.creation - ,send_msg->pid.num - ,send_msg->pid.serial); - ei_x_free(&send_msg->buf); - switch_safe_free(send_msg); - } - - /* wait for a erlang message, or timeout to check if the module is still running */ - status = ei_xreceive_msg_tmo(ei_node->nodefd, &received_msg->msg, &received_msg->buf, kazoo_globals.ei_receive_timeout); - - switch (status) { - case ERL_TICK: - /* erlang nodes send ticks to eachother to validate they are still reachable, we dont have to do anything here */ - fault_count = 0; - break; - case ERL_MSG: - fault_count = 0; - - if (kazoo_globals.receive_msg_preallocate > 0 && received_msg->buf.buffsz > kazoo_globals.receive_msg_preallocate) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "increased received message buffer size to %d\n", received_msg->buf.buffsz); - } - - if (switch_queue_trypush(ei_node->received_msgs, received_msg) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to push erlang received message from %s <%d.%d.%d> into queue\n", received_msg->msg.from.node, received_msg->msg.from.creation, received_msg->msg.from.num, received_msg->msg.from.serial); - ei_x_free(&received_msg->buf); - switch_safe_free(received_msg); - } - - received_msg = NULL; - break; - case ERL_ERROR: - switch (erl_errno) { - case ETIMEDOUT: - case EAGAIN: - /* if ei_xreceive_msg_tmo just timed out, ignore it and let the while loop check if we are still running */ - /* the erlang lib just wants us to try to receive again, so we will! */ - fault_count = 0; - break; - case EMSGSIZE: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Erlang communication fault with node %p %s (%s:%d): my spoon is too big\n", (void *)ei_node, ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port); - switch_clear_flag(ei_node, LFLAG_RUNNING); - break; - case EIO: - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Erlang communication fault with node %p %s (%s:%d): socket closed or I/O error [fault count %d]\n", (void *)ei_node, ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port, ++fault_count); - - if (fault_count >= kazoo_globals.io_fault_tolerance) { - switch_clear_flag(ei_node, LFLAG_RUNNING); - } else { - switch_sleep(kazoo_globals.io_fault_tolerance_sleep); - } - - break; - default: - /* OH NOS! something has gone horribly wrong, shutdown the connection if status set by ei_xreceive_msg_tmo is less than or equal to 0 */ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Erlang communication fault with node %p %s (%s:%d): erl_errno=%d errno=%d\n", (void *)ei_node, ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port, erl_errno, errno); - if (status < 0) { - switch_clear_flag(ei_node, LFLAG_RUNNING); - } - break; - } - break; - default: - /* HUH? didnt plan for this, whatevs shutdown the connection if status set by ei_xreceive_msg_tmo is less than or equal to 0 */ - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unexpected erlang receive status %p %s (%s:%d): %d\n", (void *)ei_node, ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port, status); - if (status < 0) { - switch_clear_flag(ei_node, LFLAG_RUNNING); - } - break; - } - } - - exit: - - if (received_msg) { - ei_x_free(&received_msg->buf); - switch_safe_free(received_msg); - } - - remove_from_ei_nodes(ei_node); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Shutdown erlang node handler %p: %s (%s:%d)\n", (void *)ei_node, ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port); - - destroy_node_handler(ei_node); - - switch_atomic_dec(&kazoo_globals.threads); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Shutdown Complete for erlang node handler %p: %s (%s:%d)\n", (void *)ei_node, ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port); - - return NULL; -} - -/* Create a thread to wait for messages from an erlang node and process them */ -switch_status_t new_kazoo_node(int nodefd, ErlConnect *conn) { - switch_thread_t *thread; - switch_threadattr_t *thd_attr = NULL; - switch_memory_pool_t *pool = NULL; - switch_sockaddr_t *sa; - ei_node_t *ei_node; - int i = 0; - - /* create memory pool for this erlang node */ - if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Out of memory: Too bad drinking scotch isn't a paying job or Kenny's dad would be a millionare!\n"); - return SWITCH_STATUS_MEMERR; - } - - /* from the erlang node's memory pool, allocate some memory for the structure */ - if (!(ei_node = switch_core_alloc(pool, sizeof (*ei_node)))) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Out of memory: Stan, don't you know the first law of physics? Anything that's fun costs at least eight dollars.\n"); - return SWITCH_STATUS_MEMERR; - } - - memset(ei_node, 0, sizeof(*ei_node)); - - /* store the location of our pool */ - ei_node->pool = pool; - - /* save the file descriptor that the erlang interface lib uses to communicate with the new node */ - 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.legacy_events; - ei_node->event_stream_framing = kazoo_globals.event_stream_framing; - ei_node->event_stream_keepalive = kazoo_globals.event_stream_keepalive; - ei_node->event_stream_queue_timeout = kazoo_globals.event_stream_queue_timeout; - ei_node->receiver_queue_timeout = kazoo_globals.node_receiver_queue_timeout; - ei_node->sender_queue_timeout = kazoo_globals.node_sender_queue_timeout; - - /* store the IP and node name we are talking with */ - switch_os_sock_put(&ei_node->socket, (switch_os_socket_t *)&nodefd, pool); - - switch_socket_addr_get(&sa, SWITCH_TRUE, ei_node->socket); - ei_node->remote_port = switch_sockaddr_get_port(sa); - switch_get_addr(ei_node->remote_ip, sizeof (ei_node->remote_ip), sa); - - switch_socket_addr_get(&sa, SWITCH_FALSE, ei_node->socket); - ei_node->local_port = switch_sockaddr_get_port(sa); - switch_get_addr(ei_node->local_ip, sizeof (ei_node->local_ip), sa); - - switch_queue_create(&ei_node->send_msgs, MAX_QUEUE_LEN, pool); - switch_queue_create(&ei_node->received_msgs, MAX_QUEUE_LEN, pool); - - switch_mutex_init(&ei_node->event_streams_mutex, SWITCH_MUTEX_DEFAULT, pool); - - /* when we start we are running */ - switch_set_flag(ei_node, LFLAG_RUNNING); - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "New erlang connection from node %s (%s:%d) -> (%s:%d)\n", ei_node->peer_nodename, ei_node->remote_ip, ei_node->remote_port, ei_node->local_ip, ei_node->local_port); - - for(i = 0; i < kazoo_globals.node_worker_threads; i++) { - switch_threadattr_create(&thd_attr, ei_node->pool); - switch_threadattr_detach_set(thd_attr, 1); - switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_thread_create(&thread, thd_attr, receive_handler, ei_node, ei_node->pool); - } - - switch_threadattr_create(&thd_attr, ei_node->pool); - switch_threadattr_detach_set(thd_attr, 1); - switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); - switch_thread_create(&thread, thd_attr, handle_node, ei_node, ei_node->pool); - - return SWITCH_STATUS_SUCCESS; -} - -/* 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_tweaks.c b/src/mod/event_handlers/mod_kazoo/kazoo_tweaks.c deleted file mode 100644 index e647871855..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_tweaks.c +++ /dev/null @@ -1,666 +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 char *TWEAK_NAMES[] = { - "interaction-id", - "export-vars", - "switch-uri", - "replaces-call-id", - "loopback-vars", - "caller-id", - "transfers", - "bridge", - "bridge-replaces-aleg", - "bridge-replaces-call-id", - "bridge-variables", - "restore-caller-id-on-blind-xfer" -}; - -static const char *bridge_variables[] = { - "Call-Control-Queue", - "Call-Control-PID", - "Call-Control-Node", - INTERACTION_VARIABLE, - "ecallmgr_Ecallmgr-Node", - "sip_h_k-cid", - "Switch-URI", - "Switch-URL", - 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"); - - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "tweak signal bridge on hangup: %s , %s\n", switch_core_session_get_uuid(session), peer_uuid); - - 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, - /*.on_reset */ NULL, - /*.on_park */ NULL, - /*.on_reporting */ NULL, - /*.on_destroy */ 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"); - const char *reentry = switch_event_get_header(event, "Bridge-Event-Processed"); - int i; - - if (!kz_test_tweak(KZ_TWEAK_BRIDGE_VARIABLES)) return; - - if(reentry) return; - - switch_log_printf(SWITCH_CHANNEL_UUID_LOG(a_leg), SWITCH_LOG_DEBUG, "tweak bridge event handler: variables : %s , %s\n", a_leg, b_leg); - - if (a_leg && (a_session = switch_core_session_locate(a_leg)) != NULL) { - switch_channel_t *a_channel = switch_core_session_get_channel(a_session); - switch_channel_timetable_t *a_times = switch_channel_get_timetable(a_channel); - if(b_leg && (b_session = switch_core_session_locate(b_leg)) != NULL) { - switch_channel_t *b_channel = switch_core_session_get_channel(b_session); - switch_channel_timetable_t *b_times = switch_channel_get_timetable(b_channel); - if (a_times->created <= b_times->created) { - for(i = 0; bridge_variables[i] != NULL; i++) { - const char *val = switch_channel_get_variable_dup(a_channel, bridge_variables[i], SWITCH_FALSE, -1); - switch_channel_set_variable(b_channel, bridge_variables[i], val); - } - } else { - for(i = 0; bridge_variables[i] != NULL; i++) { - const char *val = switch_channel_get_variable_dup(b_channel, bridge_variables[i], SWITCH_FALSE, -1); - switch_channel_set_variable(a_channel, bridge_variables[i], val); - } - } - switch_core_session_rwunlock(b_session); - } - switch_core_session_rwunlock(a_session); - } else { - switch_log_printf(SWITCH_CHANNEL_UUID_LOG(a_leg), SWITCH_LOG_DEBUG1, "NOT FOUND : %s\n", a_leg); - } -} - -static void kz_tweaks_handle_bridge_replaces_call_id(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 *peer_uuid = switch_event_get_header(event, "Unique-ID"); - const char *reentry = switch_event_get_header(event, "Bridge-Event-Processed"); - - if (!kz_test_tweak(KZ_TWEAK_BRIDGE_REPLACES_CALL_ID)) return; - - if(reentry) return; - - if(replaced_call_id) { - switch_core_session_t *call_session = NULL; - const char *call_id = switch_event_get_header(event, "Bridge-B-Unique-ID"); - if (call_id && (call_session = switch_core_session_locate(call_id)) != NULL) { - switch_channel_t *call_channel = switch_core_session_get_channel(call_session); - if (switch_event_create(&my_event, SWITCH_EVENT_CHANNEL_BRIDGE) == SWITCH_STATUS_SUCCESS) { - switch_event_add_header_string(my_event, SWITCH_STACK_BOTTOM, "Bridge-A-Unique-ID", switch_core_session_get_uuid(call_session)); - switch_event_add_header_string(my_event, SWITCH_STACK_BOTTOM, "Bridge-B-Unique-ID", peer_uuid); - switch_event_add_header_string(my_event, SWITCH_STACK_BOTTOM, "Bridge-Event-Processed", "true"); - switch_channel_event_set_data(call_channel, my_event); - switch_event_fire(&my_event); - } - switch_channel_set_variable(call_channel, "Bridge-B-Unique-ID", peer_uuid); - switch_channel_add_state_handler(call_channel, &kz_tweaks_signal_bridge_state_handlers); - switch_core_session_rwunlock(call_session); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "NOT FOUND : %s\n", call_id); - } - } -} - -static void kz_tweaks_channel_bridge_event_handler(switch_event_t *event) -{ - if (!kz_test_tweak(KZ_TWEAK_BRIDGE)) return; - - kz_tweaks_handle_bridge_replaces_call_id(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"); - const char *replaced_by = switch_event_get_header(event, "att_xfer_replaced_by"); - - if (!kz_test_tweak(KZ_TWEAK_TRANSFERS)) return; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "REPLACED : %s , %s\n", uuid, replaced_by); -} - -static void kz_tweaks_channel_intercepted_event_handler(switch_event_t *event) -{ - const char *uuid = switch_event_get_header(event, "Unique-ID"); - const char *peer_uuid = switch_event_get_header(event, "intercepted_by"); - - if (!kz_test_tweak(KZ_TWEAK_TRANSFERS)) return; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "INTERCEPTED : %s => %s\n", uuid, peer_uuid); -} - -static void kz_tweaks_channel_transferor_event_handler(switch_event_t *event) -{ - switch_core_session_t *uuid_session = NULL; - switch_event_t *evt = NULL; - const char *uuid = switch_event_get_header(event, "Unique-ID"); - - const char *orig_call_id = switch_event_get_header(event, "att_xfer_original_call_id"); - const char *dest_peer_uuid = switch_event_get_header(event, "att_xfer_destination_peer_uuid"); - const char *dest_call_id = 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"); - - if (!kz_test_tweak(KZ_TWEAK_TRANSFERS)) return; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR : %s , %s , %s, %s, %s , %s , %s \n", uuid, orig_call_id, dest_peer_uuid, dest_call_id, file, func, line); - if ((uuid_session = switch_core_session_locate(uuid)) != NULL) { - switch_channel_t *uuid_channel = switch_core_session_get_channel(uuid_session); - const char* interaction_id = switch_channel_get_variable_dup(uuid_channel, INTERACTION_VARIABLE, SWITCH_TRUE, -1); - // set to uuid & peer_uuid - if(interaction_id != NULL) { - switch_core_session_t *session = NULL; - if(dest_call_id && (session = switch_core_session_locate(dest_call_id)) != NULL) { - switch_channel_t *channel = switch_core_session_get_channel(session); - const char* prv_interaction_id = switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_TRUE, -1); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "LOCATING UUID PRV : %s : %s\n", prv_interaction_id, interaction_id); - switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id); - if (switch_event_create(&evt, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(channel, evt); - switch_event_fire(&evt); - } - switch_core_session_rwunlock(session); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR NO UUID SESSION: %s , %s , %s \n", uuid, dest_call_id, dest_peer_uuid); - } - if(dest_peer_uuid && (session = switch_core_session_locate(dest_peer_uuid)) != NULL) { - switch_channel_t *channel = switch_core_session_get_channel(session); - const char* prv_interaction_id = switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_TRUE, -1); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "LOCATING PEER UUID PRV : %s : %s\n", prv_interaction_id, interaction_id); - switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id); - if (switch_event_create(&evt, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(channel, evt); - switch_event_fire(&evt); - } - switch_core_session_rwunlock(session); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR NO PEER SESSION: %s , %s , %s \n", uuid, dest_call_id, dest_peer_uuid); - } - if(orig_call_id && (session = switch_core_session_locate(orig_call_id)) != NULL) { - switch_channel_t *channel = switch_core_session_get_channel(session); - const char* prv_interaction_id = switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_TRUE, -1); - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "LOCATING PEER UUID PRV : %s : %s\n", prv_interaction_id, interaction_id); - switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id); - if (switch_event_create(&evt, SWITCH_EVENT_CHANNEL_DATA) == SWITCH_STATUS_SUCCESS) { - switch_channel_event_set_data(channel, evt); - switch_event_fire(&evt); - } - switch_core_session_rwunlock(session); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR NO PEER SESSION: %s , %s , %s \n", uuid, dest_call_id, dest_peer_uuid); - } - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEROR ID = NULL : %s , %s , %s \n", uuid, dest_call_id, dest_peer_uuid); - } - switch_core_session_rwunlock(uuid_session); - } else { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "SESSION NOT FOUND : %s\n", uuid); - } -} - -static void kz_tweaks_channel_transferee_event_handler(switch_event_t *event) -{ - const char *uuid = switch_event_get_header(event, "Unique-ID"); - const char *replaced_by_uuid = switch_event_get_header(event, "att_xfer_replaced_call_id"); - - if (!kz_test_tweak(KZ_TWEAK_TRANSFERS)) return; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TRANSFEREE : %s replaced by %s\n", uuid, replaced_by_uuid); -} - -// 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); - switch_channel_t *a_channel = NULL; - const char * loopback_leg = NULL; - const char * loopback_aleg = NULL; - switch_core_session_t *a_session = 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; - - if (!kz_test_tweak(KZ_TWEAK_LOOPBACK_VARS)) { - return SWITCH_STATUS_SUCCESS; - } - - caller = switch_channel_get_caller_profile(channel); - if(strncmp(caller->source, "mod_loopback", 12)) - return SWITCH_STATUS_SUCCESS; - - 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)) { - kz_switch_event_add_variable_name_printf(to_add, SWITCH_STACK_BOTTOM, header->value, "%s", header->name+16); - switch_channel_set_variable(channel, header->name, NULL); - n++; - } else if(!strncmp(header->name, "sip_loopback_", 13)) { - kz_switch_event_add_variable_name_printf(to_add, SWITCH_STACK_BOTTOM, header->value, "sip_%s", header->name+13); - } else if(!strncmp(header->name, "ecallmgr_", 9)) { - switch_event_add_header_string(to_remove, SWITCH_STACK_BOTTOM, header->name, header->value); - } - } - 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_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))) { - 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-"); - } 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"); - } - - /* - * set Interaction-ID - * if we're not crossing account boundaries - */ - if (kz_test_tweak(KZ_TWEAK_INTERACTION_ID)) { - if (a_channel) { - const char *interaction_id = switch_channel_get_variable_dup(a_channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1); - const char *a_account_id = switch_channel_get_variable_dup(a_channel, "ecallmgr_Account-ID", SWITCH_FALSE, -1); - const char *b_account_id = switch_channel_get_variable_dup(channel, "ecallmgr_Account-ID", SWITCH_FALSE, -1); - if ((!a_account_id) || (!b_account_id) || (!strcmp(a_account_id, b_account_id))) { - switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id); - } - } - } - - if (a_session){ - switch_core_session_rwunlock(a_session); - } - 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) -{ - if (kz_test_tweak(KZ_TWEAK_CALLER_ID)) { - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_caller_profile_t* caller = switch_channel_get_caller_profile(channel); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "CHECKING CALLER-ID\n"); - if (caller && switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_INBOUND) { - const char* val = NULL; - if((val=switch_caller_get_field_by_name(caller, "Endpoint-Caller-ID-Name"))) { - caller->caller_id_name = val; - caller->orig_caller_id_name = val; - } - if((val=switch_caller_get_field_by_name(caller, "Endpoint-Caller-ID-Number"))) { - caller->caller_id_number = val; - caller->orig_caller_id_number = val; - } - } - } -} - -static switch_status_t kz_tweaks_handle_nightmare_xfer_interaction_id(switch_core_session_t *session) -{ - if (kz_test_tweak(KZ_TWEAK_INTERACTION_ID)) { - switch_core_session_t *replace_session = NULL; - switch_channel_t *channel = switch_core_session_get_channel(session); - const char *replaced_call_id = switch_channel_get_variable(channel, "sip_replaces_call_id"); - const char *core_uuid = switch_channel_get_variable(channel, "sip_h_X-FS-From-Core-UUID"); - const char *partner_uuid = switch_channel_get_variable(channel, "sip_h_X-FS-Refer-Partner-UUID"); - const char *interaction_id = switch_channel_get_variable(channel, "sip_h_X-FS-Call-Interaction-ID"); - if(core_uuid && partner_uuid && replaced_call_id && interaction_id) { - switch_channel_set_variable(channel, INTERACTION_VARIABLE, interaction_id); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "checking nightmare xfer tweak for %s\n", switch_channel_get_uuid(channel)); - if ((replace_session = switch_core_session_locate(replaced_call_id))) { - switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_session); - switch_channel_set_variable(replaced_call_channel, INTERACTION_VARIABLE, interaction_id); - switch_core_session_rwunlock(replace_session); - } - if ((replace_session = switch_core_session_locate(partner_uuid))) { - switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_session); - switch_channel_set_variable(replaced_call_channel, INTERACTION_VARIABLE, interaction_id); - switch_core_session_rwunlock(replace_session); - } - } - } - - return SWITCH_STATUS_SUCCESS; - -} - -static switch_status_t kz_tweaks_handle_replaces_call_id(switch_core_session_t *session) -{ - if (kz_test_tweak(KZ_TWEAK_REPLACES_CALL_ID)) { - switch_core_session_t *replace_call_session = NULL; - switch_event_t *event; - switch_channel_t *channel = switch_core_session_get_channel(session); - const char *replaced_call_id = switch_channel_get_variable(channel, "sip_replaces_call_id"); - const char *core_uuid = switch_channel_get_variable(channel, "sip_h_X-FS-From-Core-UUID"); - if((!core_uuid) && replaced_call_id) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "checking replaces header tweak for %s\n", replaced_call_id); - if ((replace_call_session = switch_core_session_locate(replaced_call_id))) { - switch_channel_t *replaced_call_channel = switch_core_session_get_channel(replace_call_session); - int i; - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "setting bridge variables from %s to %s\n", replaced_call_id, switch_channel_get_uuid(channel)); - for(i = 0; bridge_variables[i] != NULL; i++) { - const char *val = switch_channel_get_variable_dup(replaced_call_channel, bridge_variables[i], SWITCH_TRUE, -1); - switch_channel_set_variable(channel, bridge_variables[i], val); - } - 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); - if (kz_test_tweak(KZ_TWEAK_SWITCH_URI)) { - const char *profile_url = switch_channel_get_variable(channel, "sofia_profile_url"); - if(profile_url) { - int n = strcspn(profile_url, "@"); - switch_channel_set_variable(channel, "Switch-URL", profile_url); - switch_channel_set_variable_printf(channel, "Switch-URI", "sip:%s", n > 0 ? profile_url + n + 1 : profile_url); - } - } - - return SWITCH_STATUS_SUCCESS; - -} - -static char * kz_tweaks_new_interaction_id() -{ - long int first = (switch_micro_time_now() / 1000000) + UNIX_EPOCH_IN_GREGORIAN; - char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1]; - switch_uuid_t uuid; - switch_uuid_get(&uuid); - switch_uuid_format(uuid_str, &uuid); - uuid_str[8] = '\0'; - return switch_mprintf("%ld-%s", first, uuid_str); -} - -static void kz_tweaks_handle_interaction_id(switch_core_session_t *session) -{ - switch_channel_t *channel = switch_core_session_get_channel(session); - char * val = NULL; - switch_core_session_t *peer_session = NULL; - const char* peer_interaction_id = NULL; - - if (kz_test_tweak(KZ_TWEAK_INTERACTION_ID)) { - val = kz_tweaks_new_interaction_id(); - if (val) { - switch_channel_set_variable(channel, "Original-"INTERACTION_VARIABLE, val); - if(switch_core_session_get_partner(session, &peer_session) == SWITCH_STATUS_SUCCESS) { - switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session); - peer_interaction_id = switch_channel_get_variable_dup(peer_channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "PEER_SESSION => %s\n", peer_interaction_id); - if(peer_interaction_id) { - switch_channel_set_variable(channel, INTERACTION_VARIABLE, peer_interaction_id); - } - switch_core_session_rwunlock(peer_session); - } else if (!switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1)) { - switch_channel_set_variable(channel, INTERACTION_VARIABLE, val); - } - } - - switch_safe_free(val); - } - -} - -static switch_status_t kz_outgoing_channel(switch_core_session_t * session, switch_event_t * event, switch_caller_profile_t * cp, switch_core_session_t * peer_session, switch_originate_flag_t flag) -{ - if (kz_test_tweak(KZ_TWEAK_INTERACTION_ID)) { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "GOT OUTGOING\n"); - if (peer_session) { - switch_channel_t *channel = switch_core_session_get_channel(session); - const char* interaction_id = switch_channel_get_variable_dup(channel, INTERACTION_VARIABLE, SWITCH_FALSE, -1); - switch_channel_t *peer_channel = switch_core_session_get_channel(peer_session); - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "SESSION && PEER_SESSION => %s\n", interaction_id ); - if (interaction_id) { - switch_channel_set_variable(peer_channel, INTERACTION_VARIABLE, interaction_id); - } - } else { - switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "NO SESSION && PEER_SESSION\n"); - } - } - return SWITCH_STATUS_SUCCESS; -} - -static switch_status_t kz_tweaks_register_handle_blind_xfer(switch_core_session_t *session) -{ - if (kz_test_tweak(KZ_TWEAK_RESTORE_CALLER_ID_ON_BLIND_XFER)) { - switch_channel_t *channel = switch_core_session_get_channel(session); - switch_channel_set_variable(channel, "execute_on_blind_transfer", "kz_restore_caller_id"); - } - 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_SESSION_LOG(session), SWITCH_LOG_DEBUG1, "checking tweaks for %s\n", switch_channel_get_uuid(channel)); - switch_channel_set_flag(channel, CF_VERBOSE_EVENTS); - switch_core_event_hook_add_outgoing_channel(session, kz_outgoing_channel); - kz_tweaks_handle_interaction_id(session); - kz_tweaks_handle_switch_uri(session); - kz_tweaks_handle_caller_id(session); - kz_tweaks_handle_nightmare_xfer_interaction_id(session); - kz_tweaks_handle_replaces_call_id(session); - kz_tweaks_handle_loopback(session); - kz_tweaks_register_handle_blind_xfer(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, - /*.on_destroy */ NULL -}; - - -static void kz_tweaks_register_state_handlers() -{ -/* - * we may need two handlers - * one with SSH_FLAG_PRE_EXEC - * and another without it - * mod_loopback tweaks needs post-init (SSH_FLAG_PRE_EXEC off) - * - * kz_tweaks_state_handlers.flags = SSH_FLAG_PRE_EXEC; - * - */ - 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_add_core_variables() -{ - switch_core_set_variable("UNIX_EPOCH_IN_GREGORIAN", UNIX_EPOCH_IN_GREGORIAN_STR); -} - -void kz_tweaks_start() -{ - kz_tweaks_add_core_variables(); - kz_tweaks_register_state_handlers(); - kz_tweaks_bind_events(); -} - -void kz_tweaks_stop() -{ - kz_tweaks_unbind_events(); - kz_tweaks_unregister_state_handlers(); -} - -SWITCH_DECLARE(const char *) kz_tweak_name(kz_tweak_t tweak) -{ - return TWEAK_NAMES[tweak]; -} - -SWITCH_DECLARE(switch_status_t) kz_name_tweak(const char *name, kz_tweak_t *type) -{ - kz_tweak_t x; - for (x = 0; x < KZ_TWEAK_MAX; x++) { - if (!strcasecmp(name, TWEAK_NAMES[x])) { - *type = x; - return SWITCH_STATUS_SUCCESS; - } - } - - return SWITCH_STATUS_FALSE; -} - -/* For Emacs: - * Local Variables: - * mode:c - * 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_tweaks.h b/src/mod/event_handlers/mod_kazoo/kazoo_tweaks.h deleted file mode 100644 index 11cf5f6561..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_tweaks.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include - -typedef enum { - KZ_TWEAK_INTERACTION_ID, - KZ_TWEAK_EXPORT_VARS, - KZ_TWEAK_SWITCH_URI, - KZ_TWEAK_REPLACES_CALL_ID, - KZ_TWEAK_LOOPBACK_VARS, - KZ_TWEAK_CALLER_ID, - KZ_TWEAK_TRANSFERS, - KZ_TWEAK_BRIDGE, - KZ_TWEAK_BRIDGE_REPLACES_ALEG, - KZ_TWEAK_BRIDGE_REPLACES_CALL_ID, - KZ_TWEAK_BRIDGE_VARIABLES, - KZ_TWEAK_RESTORE_CALLER_ID_ON_BLIND_XFER, - - /* No new flags below this line */ - KZ_TWEAK_MAX -} kz_tweak_t; - -void kz_tweaks_start(); -void kz_tweaks_stop(); -SWITCH_DECLARE(const char *) kz_tweak_name(kz_tweak_t tweak); -SWITCH_DECLARE(switch_status_t) kz_name_tweak(const char *name, kz_tweak_t *type); - - -#define kz_test_tweak(flag) (kazoo_globals.tweaks[flag] ? 1 : 0) -#define kz_set_tweak(flag) kazoo_globals.tweaks[flag] = 1 -#define kz_clear_tweak(flag) kazoo_globals.tweaks[flag] = 0 - diff --git a/src/mod/event_handlers/mod_kazoo/kazoo_utils.c b/src/mod/event_handlers/mod_kazoo/kazoo_utils.c deleted file mode 100644 index 951707d179..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_utils.c +++ /dev/null @@ -1,700 +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" - -#define kz_resize(l) {\ -char *dp;\ -olen += (len + l + block);\ -cpos = c - data;\ -if ((dp = realloc(data, olen))) {\ - data = dp;\ - c = data + cpos;\ - memset(c, 0, olen - cpos);\ - }} \ - - -void kz_check_set_profile_var(switch_channel_t *channel, char* var, char *val) -{ - int idx = 0; - while(kazoo_globals.profile_vars_prefixes[idx] != NULL) { - char *prefix = kazoo_globals.profile_vars_prefixes[idx]; - if (!strncasecmp(var, prefix, strlen(prefix))) { - switch_channel_set_profile_var(channel, var + strlen(prefix), val); - - } - idx++; - } -} - -SWITCH_DECLARE(switch_status_t) kz_switch_core_merge_variables(switch_event_t *event) -{ - switch_event_t *global_vars; - switch_status_t status = switch_core_get_variables(&global_vars); - if(status == SWITCH_STATUS_SUCCESS) { - switch_event_merge(event, global_vars); - switch_event_destroy(&global_vars); - } - return status; -} - -SWITCH_DECLARE(switch_status_t) kz_switch_core_base_headers_for_expand(switch_event_t **event) -{ - switch_status_t status = SWITCH_STATUS_GENERR; - *event = NULL; - if(switch_event_create(event, SWITCH_EVENT_GENERAL) == SWITCH_STATUS_SUCCESS) { - status = kz_switch_core_merge_variables(*event); - } - return status; -} - -SWITCH_DECLARE(switch_status_t) kz_expand_api_execute(const char *cmd, const char *arg, switch_core_session_t *session, switch_stream_handle_t *stream) -{ - switch_api_interface_t *api; - switch_status_t status; - char *arg_used; - char *cmd_used; - - switch_assert(stream != NULL); - switch_assert(stream->data != NULL); - switch_assert(stream->write_function != NULL); - - cmd_used = switch_strip_whitespace(cmd); - arg_used = switch_strip_whitespace(arg); - - if (cmd_used && (api = switch_loadable_module_get_api_interface(cmd_used)) != 0) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "executing [%s] => [%s]\n", cmd_used, arg_used); - if ((status = api->function(arg_used, session, stream)) != SWITCH_STATUS_SUCCESS) { - stream->write_function(stream, "COMMAND RETURNED ERROR!\n"); - } - UNPROTECT_INTERFACE(api); - } else { - status = SWITCH_STATUS_FALSE; - stream->write_function(stream, "INVALID COMMAND!\n"); - } - - if (cmd_used != cmd) { - switch_safe_free(cmd_used); - } - - if (arg_used != arg) { - switch_safe_free(arg_used); - } - - return status; -} - - -SWITCH_DECLARE(char *) kz_event_expand_headers_check(switch_event_t *event, const char *in, switch_event_t *var_list, switch_event_t *api_list, uint32_t recur) -{ - char *p, *c = NULL; - char *data, *indup, *endof_indup; - size_t sp = 0, len = 0, olen = 0, vtype = 0, br = 0, cpos, block = 128; - const char *sub_val = NULL; - char *cloned_sub_val = NULL, *expanded_sub_val = NULL; - char *func_val = NULL; - int nv = 0; - char *gvar = NULL, *sb = NULL; - - if (recur > 100) { - return (char *) in; - } - - if (zstr(in)) { - return (char *) in; - } - - nv = switch_string_var_check_const(in) || switch_string_has_escaped_data(in); - - if (!nv) { - return (char *) in; - } - - nv = 0; - olen = strlen(in) + 1; - indup = strdup(in); - switch_assert(indup); - endof_indup = end_of_p(indup) + 1; - - if ((data = malloc(olen))) { - memset(data, 0, olen); - c = data; - for (p = indup; p && p < endof_indup && *p; p++) { - int global = 0; - vtype = 0; - - if (*p == '\\') { - if (*(p + 1) == '$') { - nv = 1; - p++; - if (*(p + 1) == '$') { - p++; - } - } else if (*(p + 1) == '\'') { - p++; - continue; - } else if (*(p + 1) == '\\') { - if (len + 1 >= olen) { - kz_resize(1); - } - - *c++ = *p++; - len++; - continue; - } - } - - if (*p == '$' && !nv) { - if (*(p + 1) == '$') { - p++; - global++; - } - - if (*(p + 1)) { - if (*(p + 1) == '{') { - vtype = global ? 3 : 1; - } else { - nv = 1; - } - } else { - nv = 1; - } - } - - if (nv) { - if (len + 1 >= olen) { - kz_resize(1); - } - - *c++ = *p; - len++; - nv = 0; - continue; - } - - if (vtype) { - char *s = p, *e, *vname, *vval = NULL; - size_t nlen; - - s++; - - if ((vtype == 1 || vtype == 3) && *s == '{') { - br = 1; - s++; - } - - e = s; - vname = s; - while (*e) { - if (br == 1 && *e == '}') { - br = 0; - *e++ = '\0'; - break; - } - - if (br > 0) { - if (e != s && *e == '{') { - br++; - } else if (br > 1 && *e == '}') { - br--; - } - } - - e++; - } - p = e > endof_indup ? endof_indup : e; - - vval = NULL; - for(sb = vname; sb && *sb; sb++) { - if (*sb == ' ') { - vval = sb; - break; - } else if (*sb == '(') { - vval = sb; - br = 1; - break; - } - } - - if (vval) { - e = vval - 1; - *vval++ = '\0'; - - while (*e == ' ') { - *e-- = '\0'; - } - e = vval; - - while (e && *e) { - if (*e == '(') { - br++; - } else if (br > 1 && *e == ')') { - br--; - } else if (br == 1 && *e == ')') { - *e = '\0'; - break; - } - e++; - } - - vtype = 2; - } - - if (vtype == 1 || vtype == 3) { - char *expanded = NULL; - int offset = 0; - int ooffset = 0; - char *ptr; - int idx = -1; - - if ((expanded = kz_event_expand_headers_check(event, (char *) vname, var_list, api_list, recur+1)) == vname) { - expanded = NULL; - } else { - vname = expanded; - } - if ((ptr = strchr(vname, ':'))) { - *ptr++ = '\0'; - offset = atoi(ptr); - if ((ptr = strchr(ptr, ':'))) { - ptr++; - ooffset = atoi(ptr); - } - } - - if ((ptr = strchr(vname, '[')) && strchr(ptr, ']')) { - *ptr++ = '\0'; - idx = atoi(ptr); - } - - if (vtype == 3 || !(sub_val = switch_event_get_header_idx(event, vname, idx))) { - switch_safe_free(gvar); - if ((gvar = switch_core_get_variable_dup(vname))) { - sub_val = gvar; - } - - if (var_list && !switch_event_check_permission_list(var_list, vname)) { - sub_val = ""; - } - - - if ((expanded_sub_val = kz_event_expand_headers_check(event, sub_val, var_list, api_list, recur+1)) == sub_val) { - expanded_sub_val = NULL; - } else { - sub_val = expanded_sub_val; - } - } - - if (sub_val) { - if (offset || ooffset) { - cloned_sub_val = strdup(sub_val); - switch_assert(cloned_sub_val); - sub_val = cloned_sub_val; - } - - if (offset >= 0) { - sub_val += offset; - } else if ((size_t) abs(offset) <= strlen(sub_val)) { - sub_val = cloned_sub_val + (strlen(cloned_sub_val) + offset); - } - - if (ooffset > 0 && (size_t) ooffset < strlen(sub_val)) { - if ((ptr = (char *) sub_val + ooffset)) { - *ptr = '\0'; - } - } - } - - switch_safe_free(expanded); - } else { - char *expanded = NULL; - char *expanded_vname = NULL; - - if ((expanded_vname = kz_event_expand_headers_check(event, (char *) vname, var_list, api_list, recur+1)) == vname) { - expanded_vname = NULL; - } else { - vname = expanded_vname; - } - - if ((expanded = kz_event_expand_headers_check(event, vval, var_list, api_list, recur+1)) == vval) { - expanded = NULL; - } else { - vval = expanded; - } - - if (!switch_core_test_flag(SCF_API_EXPANSION) || (api_list && !switch_event_check_permission_list(api_list, vname))) { - func_val = NULL; - sub_val = ""; - } else { - switch_stream_handle_t stream = { 0 }; - - SWITCH_STANDARD_STREAM(stream); - stream.param_event = event; - if (kz_expand_api_execute(vname, vval, NULL, &stream) == SWITCH_STATUS_SUCCESS) { - func_val = stream.data; - sub_val = func_val; - } else { - free(stream.data); - } - } - - switch_safe_free(expanded); - switch_safe_free(expanded_vname); - } - if ((nlen = sub_val ? strlen(sub_val) : 0)) { - if (len + nlen >= olen) { - kz_resize(nlen); - } - - len += nlen; - strcat(c, sub_val); - c += nlen; - } - - switch_safe_free(func_val); - switch_safe_free(cloned_sub_val); - switch_safe_free(expanded_sub_val); - sub_val = NULL; - vname = NULL; - br = 0; - } - - if (sp) { - if (len + 1 >= olen) { - kz_resize(1); - } - - *c++ = ' '; - sp = 0; - len++; - } - - if (*p == '$') { - p--; - } else { - if (len + 1 >= olen) { - kz_resize(1); - } - - *c++ = *p; - len++; - } - } - } - free(indup); - switch_safe_free(gvar); - - return data; -} - -SWITCH_DECLARE(char *) kz_event_expand_headers(switch_event_t *event, const char *in) -{ - return kz_event_expand_headers_check(event, in, NULL, NULL, 0); -} - -SWITCH_DECLARE(char *) kz_event_expand_headers_pool(switch_memory_pool_t *pool, switch_event_t *event, char *val) -{ - char *expanded; - char *dup = NULL; - - expanded = kz_event_expand_headers(event, val); - dup = switch_core_strdup(pool, expanded); - - if (expanded != val) { - free(expanded); - } - - return dup; -} - -SWITCH_DECLARE(char *) kz_expand(const char *in, const char *uuid) -{ - switch_event_t *event = NULL; - char *ret = NULL; - kz_switch_core_base_headers_for_expand(&event); - if (uuid != NULL) { - switch_core_session_t *nsession = NULL; - if ((nsession = switch_core_session_locate(uuid))) { - switch_channel_event_set_data(switch_core_session_get_channel(nsession), event); - switch_core_session_rwunlock(nsession); - } - } - ret = kz_event_expand_headers_check(event, in, NULL, NULL, 0); - switch_event_destroy(&event); - return ret; -} - -SWITCH_DECLARE(char *) kz_expand_pool(switch_memory_pool_t *pool, const char *in) -{ - char *expanded; - char *dup = NULL; - - if(!(expanded = kz_expand(in, NULL))) { - return NULL; - } - dup = switch_core_strdup(pool, expanded); - - if (expanded != in) { - switch_safe_free(expanded); - } - - return dup; -} - -char* kz_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"; - } -} - -SWITCH_DECLARE(switch_status_t) kz_switch_event_add_variable_name_printf(switch_event_t *event, switch_stack_t stack, const char *val, const char *fmt, ...) -{ - int ret = 0; - char *varname; - va_list ap; - switch_status_t status = SWITCH_STATUS_SUCCESS; - - switch_assert(event != NULL); - - - va_start(ap, fmt); - ret = switch_vasprintf(&varname, fmt, ap); - va_end(ap); - - if (ret == -1) { - return SWITCH_STATUS_MEMERR; - } - - status = switch_event_add_header_string(event, stack, varname, val); - - free(varname); - - return status; -} - -SWITCH_DECLARE(switch_status_t) kz_expand_json_to_event(cJSON *json, switch_event_t *event, char * prefix) -{ - char * fmt = switch_mprintf("%s%s%%s", prefix ? prefix : "", prefix ? "_" : ""); - if (event) { - cJSON *item = NULL; - char *response = NULL; - cJSON_ArrayForEach(item, json) { - if (item->type == cJSON_String) { - response = strdup(item->valuestring); - } else if (item->type == cJSON_Object) { - char * fmt1 = switch_mprintf(fmt, item->string); - kz_expand_json_to_event(item, event, fmt1); - switch_safe_free(fmt1); - continue; - } else { - response = cJSON_PrintUnformatted(item); - } - kz_switch_event_add_variable_name_printf(event, SWITCH_STACK_BOTTOM, response, fmt, item->string); - switch_safe_free(response); - } - } - - switch_safe_free(fmt); - return SWITCH_STATUS_SUCCESS; -} - -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; -} - -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, '='); - - if (val) { - char *ve = val++; - while (*val && *val == ' ') { - val++; - } - *ve-- = '\0'; - while (*ve && *ve == ' ') { - *ve-- = '\0'; - } - } - - if (name && val) { - switch_core_set_variable(name, val); - } - } - } - -} - -void kz_event_decode(switch_event_t *event) -{ - switch_event_header_t *hp; - int i; - for (hp = event->headers; hp; hp = hp->next) { - if (strncmp(hp->name, "_json_", 6)) { - if (hp->idx) { - for(i = 0; i < hp->idx; i++) { - switch_url_decode(hp->array[i]); - } - } else { - switch_url_decode(hp->value); - } - } - } -} - -void kz_expand_headers(switch_event_t *resolver, switch_event_t *event) { - switch_event_t *clone = NULL; - switch_event_header_t *header = NULL; - switch_event_create_plain(&clone, event->event_id); - - for(header = event->headers; header; header = header->next) { - char *expanded = kz_event_expand_headers(resolver, header->value); - if (expanded != header->value) { - switch_event_add_header_string(clone, SWITCH_STACK_BOTTOM, header->name, expanded); - switch_safe_free(expanded); - } - } - - /* we don't want to force unique headers - * so we delete and then merge - */ - for(header = clone->headers; header; header = header->next) { - switch_event_del_header(event, header->name); - } - - switch_event_merge(event, clone); - - switch_event_destroy(&clone); -} - -void kz_expand_headers_self(switch_event_t *event) { - kz_expand_headers(event, event); -} - -char * kz_expand_vars(char *xml_str) { - return kz_expand_vars_pool(xml_str, NULL); -} - -char * kz_expand_vars_pool(char *xml_str, switch_memory_pool_t *pool) { - char *var, *val; - char *rp = xml_str; /* read pointer */ - char *ep, *wp, *buff; /* end pointer, write pointer, write buffer */ - - if (!(strstr(xml_str, "$${"))) { - return xml_str; - } - - switch_zmalloc(buff, strlen(xml_str) * 2); - wp = buff; - ep = buff + (strlen(xml_str) * 2) - 1; - - while (*rp && wp < ep) { - if (*rp == '$' && *(rp + 1) == '$' && *(rp + 2) == '{') { - char *e = switch_find_end_paren(rp + 2, '{', '}'); - - if (e) { - rp += 3; - var = rp; - *e++ = '\0'; - rp = e; - - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "trying to expand %s \n", var); - if ((val = switch_core_get_variable_dup(var))) { - char *p; - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "expanded %s to %s\n", var, val); - for (p = val; p && *p && wp <= ep; p++) { - *wp++ = *p; - } - switch_safe_free(val); - } - continue; - } - } - - *wp++ = *rp++; - } - - *wp++ = '\0'; - - if(pool) { - char * ret = switch_core_strdup(pool, buff); - switch_safe_free(buff); - return ret; - } else { - switch_safe_free(xml_str); - return buff; - } - -} - -switch_status_t kz_json_api(const char * command, cJSON *args, cJSON **res) -{ - switch_status_t status = SWITCH_STATUS_SUCCESS; - cJSON *req = cJSON_CreateObject(); - cJSON_AddItemToObject(req, "command", cJSON_CreateString(command)); - cJSON_AddItemToObject(req, "data", args ? args : cJSON_CreateObject()); - status = switch_json_api_execute(req, NULL, res); - cJSON_Delete(req); - return status; -} - -/* 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.h b/src/mod/event_handlers/mod_kazoo/kazoo_utils.h deleted file mode 100644 index cb5549c760..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kazoo_utils.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include - -#ifdef __cplusplus -#define KZ_BEGIN_EXTERN_C extern "C" { -#define KZ_END_EXTERN_C } -#else -#define KZ_BEGIN_EXTERN_C -#define KZ_END_EXTERN_C -#endif - -KZ_BEGIN_EXTERN_C - -void kz_check_set_profile_var(switch_channel_t *channel, char* var, char *val); - -SWITCH_DECLARE(switch_status_t) kz_switch_core_merge_variables(switch_event_t *event); - -SWITCH_DECLARE(switch_status_t) kz_switch_core_base_headers_for_expand(switch_event_t **event); - -SWITCH_DECLARE(switch_status_t) kz_expand_api_execute(const char *cmd, const char *arg, switch_core_session_t *session, switch_stream_handle_t *stream); - -SWITCH_DECLARE(char *) kz_event_expand_headers_check(switch_event_t *event, const char *in, switch_event_t *var_list, switch_event_t *api_list, uint32_t recur); - -SWITCH_DECLARE(char *) kz_event_expand_headers(switch_event_t *event, const char *in); - -SWITCH_DECLARE(char *) kz_event_expand_headers_pool(switch_memory_pool_t *pool, switch_event_t *event, char *val); - -SWITCH_DECLARE(char *) kz_expand(const char *in, const char *uuid); - -SWITCH_DECLARE(char *) kz_expand_pool(switch_memory_pool_t *pool, const char *in); - -char* kz_switch_event_get_first_of(switch_event_t *event, const char *list[]); - -SWITCH_DECLARE(switch_status_t) kz_switch_event_add_variable_name_printf(switch_event_t *event, switch_stack_t stack, const char *val, const char *fmt, ...); - -SWITCH_DECLARE(switch_xml_t) kz_xml_child(switch_xml_t xml, const char *name); - -void kz_xml_process(switch_xml_t cfg); -void kz_event_decode(switch_event_t *event); - -char * kz_expand_vars(char *xml_str); -void kz_expand_headers(switch_event_t *resolver, switch_event_t *event); -void kz_expand_headers_self(switch_event_t *event); - -char * kz_expand_vars_pool(char *xml_str, switch_memory_pool_t *pool); -switch_status_t kz_json_api(const char * command, cJSON *args, cJSON **res); - -SWITCH_DECLARE(switch_status_t) kz_expand_json_to_event(cJSON *json, switch_event_t *event, char * prefix); - -KZ_END_EXTERN_C diff --git a/src/mod/event_handlers/mod_kazoo/kz_node.c b/src/mod/event_handlers/mod_kazoo/kz_node.c deleted file mode 100644 index 1c50d0586e..0000000000 --- a/src/mod/event_handlers/mod_kazoo/kz_node.c +++ /dev/null @@ -1,91 +0,0 @@ -#include "mod_kazoo.h" - -static int kz_nodes_module_names_array_callback(void *pArg, const char *module_name) -{ - cJSON *json = (cJSON *) pArg; - if(!strstr(module_name, "CORE")) { - cJSON_AddItemToArray(json, cJSON_CreateString(module_name)); - } - return 0; -} - -void kz_nodes_collect_media_role(cJSON *container) -{ - cJSON *retval = NULL; - if(kz_json_api("sofia.status.info", NULL, &retval) == SWITCH_STATUS_SUCCESS) { - if(retval != NULL && (!(retval->type & cJSON_NULL))) { - cJSON_AddItemToObject(container, "Media", cJSON_Duplicate(retval, 1)); - } - } - if(retval) { - cJSON_Delete(retval); - } -} - -void kz_nodes_collect_modules(cJSON *container) -{ - cJSON *modules = cJSON_CreateObject(); - cJSON *loaded = cJSON_CreateArray(); - cJSON *available = cJSON_CreateArray(); - switch_loadable_module_enumerate_available(SWITCH_GLOBAL_dirs.mod_dir, kz_nodes_module_names_array_callback, available); - switch_loadable_module_enumerate_loaded(kz_nodes_module_names_array_callback, loaded); - cJSON_AddItemToObject(modules, "available", available); - cJSON_AddItemToObject(modules, "loaded", loaded); - cJSON_AddItemToObject(container, "Modules", modules); -} - -void kz_nodes_collect_runtime(cJSON *container) -{ - cJSON *retval = NULL; - if(kz_json_api("status", NULL, &retval) == SWITCH_STATUS_SUCCESS) { - if(retval != NULL && (!(retval->type & cJSON_NULL))) { - cJSON *val = cJSON_Duplicate(retval, 1); - cJSON_AddItemToObject(val, "Core-UUID", cJSON_CreateString(switch_core_get_uuid())); - cJSON_AddItemToObject(container, "Runtime-Info", val); - } - } - if(retval) { - cJSON_Delete(retval); - } -} - -void kz_nodes_collect_apps(cJSON *container) -{ - cJSON *apps = cJSON_CreateObject(); - cJSON *app = cJSON_CreateObject(); - cJSON_AddItemToObject(app, "Uptime", cJSON_CreateNumber(switch_core_uptime())); - cJSON_AddItemToObject(apps, "freeswitch", app); - cJSON_AddItemToObject(container, "WhApps", apps); -} - -void kz_nodes_collect_roles(cJSON *container) -{ - cJSON *roles = cJSON_CreateObject(); - cJSON_AddItemToObject(container, "Roles", roles); - kz_nodes_collect_media_role(roles); -} - -cJSON * kz_node_create() -{ - cJSON *node = cJSON_CreateObject(); - - kz_nodes_collect_apps(node); - kz_nodes_collect_runtime(node); - kz_nodes_collect_modules(node); - kz_nodes_collect_roles(node); - - return node; -} - -SWITCH_STANDARD_JSON_API(kz_node_info_json_function) -{ - cJSON * ret = kz_node_create(); - *json_reply = ret; - return SWITCH_STATUS_SUCCESS; -} - -void add_kz_node(switch_loadable_module_interface_t **module_interface) -{ - switch_json_api_interface_t *json_api_interface = NULL; - SWITCH_ADD_JSON_API(json_api_interface, "node.info", "JSON node API", kz_node_info_json_function, ""); -} diff --git a/src/mod/event_handlers/mod_kazoo/mod_kazoo.c b/src/mod/event_handlers/mod_kazoo/mod_kazoo.c deleted file mode 100644 index 15b8fb469c..0000000000 --- a/src/mod/event_handlers/mod_kazoo/mod_kazoo.c +++ /dev/null @@ -1,152 +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" - -kz_globals_t kazoo_globals = {0}; - - - -SWITCH_MODULE_DEFINITION(mod_kazoo, mod_kazoo_load, mod_kazoo_shutdown, mod_kazoo_runtime); - -SWITCH_MODULE_LOAD_FUNCTION(mod_kazoo_load) -{ - kz_erl_init(); - - memset(&kazoo_globals, 0, sizeof(kazoo_globals)); - kazoo_globals.pool = pool; - kz_set_hostname(); - if(kazoo_load_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; - } - - /* connect my internal structure to the blank pointer passed to me */ - *module_interface = switch_loadable_module_create_module_interface(pool, modname); - - switch_thread_rwlock_create(&kazoo_globals.ei_nodes_lock, pool); - - switch_set_flag(&kazoo_globals, LFLAG_RUNNING); - - /* create all XML fetch agents */ - bind_fetch_agents(); - - /* create an api for cli debug commands */ - add_cli_api(module_interface); - - /* add our modified commands */ - add_kz_commands(module_interface); - - /* add our modified dptools */ - add_kz_dptools(module_interface); - - /* add our endpoints */ - add_kz_endpoints(module_interface); - - /* add our kz_node api */ - add_kz_node(module_interface); - - /* add tweaks */ - kz_tweaks_start(); - - /* add our cdr */ - kz_cdr_start(); - - /* indicate that the module should continue to be loaded */ - return SWITCH_STATUS_SUCCESS; -} - -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_kazoo_shutdown) { - int sanity = 0; - - remove_cli_api(); - - kz_cdr_stop(); - - kz_tweaks_stop(); - - /* stop taking new requests and start shuting down the threads */ - switch_clear_flag(&kazoo_globals, LFLAG_RUNNING); - - /* give everyone time to cleanly shutdown */ - while (switch_atomic_read(&kazoo_globals.threads)) { - switch_yield(100000); - if (++sanity >= 200) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unable to kill all threads, continuing. This probably wont end well.....good luck!\n"); - break; - } - } - - /* close the connection to epmd and the acceptor */ - close_socketfd(&kazoo_globals.epmdfd); - close_socket(&kazoo_globals.acceptor); - - /* remove all XML fetch agents */ - unbind_fetch_agents(); - - if (kazoo_globals.event_filter) { - switch_core_hash_destroy(&kazoo_globals.event_filter); - } - - 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); - - /* 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); - } - - kazoo_destroy_config(); - - /* clean up our allocated preferences */ - switch_safe_free(kazoo_globals.ip); - switch_safe_free(kazoo_globals.ei_cookie); - switch_safe_free(kazoo_globals.ei_nodename); - - kz_erl_shutdown(); - - return SWITCH_STATUS_SUCCESS; -} - - -/* 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/mod_kazoo.h b/src/mod/event_handlers/mod_kazoo/mod_kazoo.h deleted file mode 100644 index 37fdd861e7..0000000000 --- a/src/mod/event_handlers/mod_kazoo/mod_kazoo.h +++ /dev/null @@ -1,87 +0,0 @@ -#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 - -extern const char kz_default_config[]; -extern const int kz_default_config_size; - -#include "kazoo_defs.h" -#include "kazoo_tweaks.h" -#include "kazoo_ei.h" -#include "kazoo_message.h" -#include "kazoo_utils.h" - -typedef enum { - LFLAG_RUNNING = (1 << 0) -} event_flag_t; - - -/* kazoo_commands.c */ -void add_kz_commands(switch_loadable_module_interface_t **module_interface); - -/* kazoo_dptools.c */ -void add_kz_dptools(switch_loadable_module_interface_t **module_interface); - -/* kazoo_api.c */ -void add_cli_api(switch_loadable_module_interface_t **module_interface); -void remove_cli_api(); - -/* kazoo_utils.c */ -/* -SWITCH_DECLARE(switch_status_t) kz_switch_core_merge_variables(switch_event_t *event); -SWITCH_DECLARE(switch_status_t) kz_switch_core_base_headers_for_expand(switch_event_t **event); -void kz_check_set_profile_var(switch_channel_t *channel, char* var, char *val); -char* kz_switch_event_get_first_of(switch_event_t *event, const char *list[]); -SWITCH_DECLARE(switch_status_t) kz_switch_event_add_variable_name_printf(switch_event_t *event, switch_stack_t stack, const char *val, const char *fmt, ...); -void kz_xml_process(switch_xml_t cfg); -void kz_event_decode(switch_event_t *event); -char * kz_expand_vars(char *xml_str); -char * kz_expand_vars_pool(char *xml_str, switch_memory_pool_t *pool); -SWITCH_DECLARE(char *) kz_event_expand_headers(switch_event_t *event, const char *in); -SWITCH_DECLARE(char *) kz_expand(const char *in); -SWITCH_DECLARE(char *) kz_expand_pool(switch_memory_pool_t *pool, const char *in); -switch_status_t kz_json_api(const char * command, cJSON *args, cJSON **res); -*/ - -/* kazoo_endpoints.c */ -void add_kz_endpoints(switch_loadable_module_interface_t **module_interface); - -/* kazoo_cdr.c */ -void kz_cdr_start(); -void kz_cdr_stop(); - -/* kazoo_tweaks.c */ -void kz_tweaks_start(); -void kz_tweaks_stop(); -SWITCH_DECLARE(const char *) kz_tweak_name(kz_tweak_t tweak); -SWITCH_DECLARE(switch_status_t) kz_name_tweak(const char *name, kz_tweak_t *type); - -/* kazoo_node.c */ -void add_kz_node(switch_loadable_module_interface_t **module_interface); - -SWITCH_MODULE_LOAD_FUNCTION(mod_kazoo_load); -SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_kazoo_shutdown); - - -/* 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: - */