2006-07-22 21:49:52 +00:00
|
|
|
/*
|
|
|
|
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
|
2012-04-18 16:51:48 +00:00
|
|
|
* Copyright (C) 2005-2012, Anthony Minessale II <anthm@freeswitch.org>
|
2006-07-22 21:49:52 +00:00
|
|
|
*
|
|
|
|
* 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
|
2009-02-04 21:20:54 +00:00
|
|
|
* Anthony Minessale II <anthm@freeswitch.org>
|
2006-07-22 21:49:52 +00:00
|
|
|
* Portions created by the Initial Developer are Copyright (C)
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
*
|
2009-02-04 21:20:54 +00:00
|
|
|
* Anthony Minessale II <anthm@freeswitch.org>
|
2006-07-22 21:49:52 +00:00
|
|
|
*
|
|
|
|
*
|
2008-10-06 23:05:55 +00:00
|
|
|
* mod_event_socket.c -- Socket Controlled Event Handler
|
2006-07-22 21:49:52 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
#include <switch.h>
|
|
|
|
#define CMD_BUFLEN 1024 * 1000
|
2010-12-16 17:34:02 +00:00
|
|
|
#define MAX_QUEUE_LEN 25000
|
2011-01-25 20:13:15 +00:00
|
|
|
#define MAX_MISSED 500
|
2007-06-13 17:06:10 +00:00
|
|
|
SWITCH_MODULE_LOAD_FUNCTION(mod_event_socket_load);
|
|
|
|
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_event_socket_shutdown);
|
|
|
|
SWITCH_MODULE_RUNTIME_FUNCTION(mod_event_socket_runtime);
|
|
|
|
SWITCH_MODULE_DEFINITION(mod_event_socket, mod_event_socket_load, mod_event_socket_shutdown, mod_event_socket_runtime);
|
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
static char *MARKER = "1";
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
LFLAG_AUTHED = (1 << 0),
|
|
|
|
LFLAG_RUNNING = (1 << 1),
|
|
|
|
LFLAG_EVENTS = (1 << 2),
|
2007-01-06 17:06:18 +00:00
|
|
|
LFLAG_LOG = (1 << 3),
|
|
|
|
LFLAG_FULL = (1 << 4),
|
|
|
|
LFLAG_MYEVENTS = (1 << 5),
|
|
|
|
LFLAG_SESSION = (1 << 6),
|
2008-10-23 17:31:22 +00:00
|
|
|
LFLAG_ASYNC = (1 << 7),
|
2008-12-12 15:44:37 +00:00
|
|
|
LFLAG_STATEFUL = (1 << 8),
|
2009-01-16 15:32:10 +00:00
|
|
|
LFLAG_OUTBOUND = (1 << 9),
|
|
|
|
LFLAG_LINGER = (1 << 10),
|
2009-04-30 22:45:46 +00:00
|
|
|
LFLAG_HANDLE_DISCO = (1 << 11),
|
|
|
|
LFLAG_CONNECTED = (1 << 12),
|
|
|
|
LFLAG_RESUME = (1 << 13),
|
2010-01-05 19:47:49 +00:00
|
|
|
LFLAG_AUTH_EVENTS = (1 << 14),
|
|
|
|
LFLAG_ALL_EVENTS_AUTHED = (1 << 15),
|
|
|
|
LFLAG_ALLOW_LOG = (1 << 16)
|
2006-07-22 21:49:52 +00:00
|
|
|
} event_flag_t;
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
EVENT_FORMAT_PLAIN,
|
2010-06-17 16:43:09 +00:00
|
|
|
EVENT_FORMAT_XML,
|
|
|
|
EVENT_FORMAT_JSON
|
2006-07-22 21:49:52 +00:00
|
|
|
} event_format_t;
|
|
|
|
|
|
|
|
struct listener {
|
|
|
|
switch_socket_t *sock;
|
|
|
|
switch_queue_t *event_queue;
|
|
|
|
switch_queue_t *log_queue;
|
|
|
|
switch_memory_pool_t *pool;
|
|
|
|
event_format_t format;
|
|
|
|
switch_mutex_t *flag_mutex;
|
2008-10-30 00:39:55 +00:00
|
|
|
switch_mutex_t *filter_mutex;
|
2006-07-22 21:49:52 +00:00
|
|
|
uint32_t flags;
|
|
|
|
switch_log_level_t level;
|
2006-08-29 23:06:12 +00:00
|
|
|
char *ebuf;
|
2007-03-29 22:31:56 +00:00
|
|
|
uint8_t event_list[SWITCH_EVENT_ALL + 1];
|
2010-01-05 19:47:49 +00:00
|
|
|
uint8_t allowed_event_list[SWITCH_EVENT_ALL + 1];
|
2006-07-22 21:49:52 +00:00
|
|
|
switch_hash_t *event_hash;
|
2010-01-05 19:47:49 +00:00
|
|
|
switch_hash_t *allowed_event_hash;
|
|
|
|
switch_hash_t *allowed_api_hash;
|
2006-09-07 03:58:01 +00:00
|
|
|
switch_thread_rwlock_t *rwlock;
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_core_session_t *session;
|
2008-01-25 23:09:33 +00:00
|
|
|
int lost_events;
|
|
|
|
int lost_logs;
|
2008-10-23 17:31:22 +00:00
|
|
|
time_t last_flush;
|
2009-11-06 20:17:31 +00:00
|
|
|
time_t expire_time;
|
2008-10-23 17:31:22 +00:00
|
|
|
uint32_t timeout;
|
|
|
|
uint32_t id;
|
2008-03-26 22:14:09 +00:00
|
|
|
switch_sockaddr_t *sa;
|
|
|
|
char remote_ip[50];
|
|
|
|
switch_port_t remote_port;
|
2008-10-30 00:39:55 +00:00
|
|
|
switch_event_t *filters;
|
2011-12-08 18:25:52 +00:00
|
|
|
time_t linger_timeout;
|
2006-07-22 21:49:52 +00:00
|
|
|
struct listener *next;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct listener listener_t;
|
|
|
|
|
2008-11-07 14:48:49 +00:00
|
|
|
static struct {
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_mutex_t *listener_mutex;
|
2008-11-07 14:48:49 +00:00
|
|
|
switch_event_node_t *node;
|
2009-05-02 00:58:51 +00:00
|
|
|
int debug;
|
2008-11-07 14:48:49 +00:00
|
|
|
} globals;
|
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
static struct {
|
|
|
|
switch_socket_t *sock;
|
2006-08-29 20:27:43 +00:00
|
|
|
switch_mutex_t *sock_mutex;
|
2006-07-22 21:49:52 +00:00
|
|
|
listener_t *listeners;
|
|
|
|
uint8_t ready;
|
|
|
|
} listen_list;
|
|
|
|
|
2008-03-26 22:14:09 +00:00
|
|
|
#define MAX_ACL 100
|
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
static struct {
|
2007-07-24 21:26:04 +00:00
|
|
|
switch_mutex_t *mutex;
|
2006-07-22 21:49:52 +00:00
|
|
|
char *ip;
|
|
|
|
uint16_t port;
|
|
|
|
char *password;
|
2006-11-09 05:39:04 +00:00
|
|
|
int done;
|
2007-07-24 21:26:04 +00:00
|
|
|
int threads;
|
2008-03-26 22:14:09 +00:00
|
|
|
char *acl[MAX_ACL];
|
|
|
|
uint32_t acl_count;
|
2008-10-23 17:31:22 +00:00
|
|
|
uint32_t id;
|
2009-06-03 14:25:35 +00:00
|
|
|
int nat_map;
|
2006-07-22 21:49:52 +00:00
|
|
|
} prefs;
|
|
|
|
|
2008-10-23 17:31:22 +00:00
|
|
|
|
2010-06-17 16:43:09 +00:00
|
|
|
static const char *format2str(event_format_t format)
|
|
|
|
{
|
|
|
|
switch (format) {
|
|
|
|
case EVENT_FORMAT_PLAIN:
|
|
|
|
return "plain";
|
|
|
|
case EVENT_FORMAT_XML:
|
|
|
|
return "xml";
|
|
|
|
case EVENT_FORMAT_JSON:
|
|
|
|
return "json";
|
|
|
|
}
|
|
|
|
|
|
|
|
return "invalid";
|
|
|
|
}
|
|
|
|
|
2008-10-23 17:31:22 +00:00
|
|
|
static void remove_listener(listener_t *listener);
|
2011-01-25 20:13:15 +00:00
|
|
|
static void kill_listener(listener_t *l, const char *message);
|
2009-02-20 01:10:59 +00:00
|
|
|
static void kill_all_listeners(void);
|
2008-10-23 17:31:22 +00:00
|
|
|
|
|
|
|
static uint32_t next_id(void)
|
|
|
|
{
|
|
|
|
uint32_t id;
|
2008-11-07 14:48:49 +00:00
|
|
|
switch_mutex_lock(globals.listener_mutex);
|
2010-02-06 03:38:24 +00:00
|
|
|
id = ++prefs.id;
|
|
|
|
switch_mutex_unlock(globals.listener_mutex);
|
2008-10-23 17:31:22 +00:00
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2007-10-17 14:59:17 +00:00
|
|
|
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_ip, prefs.ip);
|
|
|
|
SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_pref_pass, prefs.password);
|
2006-07-22 21:49:52 +00:00
|
|
|
|
2008-05-27 04:54:52 +00:00
|
|
|
static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj);
|
|
|
|
static void launch_listener_thread(listener_t *listener);
|
2007-01-06 17:06:18 +00:00
|
|
|
|
2007-10-17 14:59:17 +00:00
|
|
|
static switch_status_t socket_logger(const switch_log_node_t *node, switch_log_level_t level)
|
2006-07-22 21:49:52 +00:00
|
|
|
{
|
|
|
|
listener_t *l;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-11-07 14:48:49 +00:00
|
|
|
switch_mutex_lock(globals.listener_mutex);
|
2006-07-22 21:49:52 +00:00
|
|
|
for (l = listen_list.listeners; l; l = l->next) {
|
|
|
|
if (switch_test_flag(l, LFLAG_LOG) && l->level >= node->level) {
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_log_node_t *dnode = switch_log_node_dup(node);
|
|
|
|
|
2011-01-25 20:13:15 +00:00
|
|
|
if (switch_queue_trypush(l->log_queue, dnode) == SWITCH_STATUS_SUCCESS) {
|
2008-12-20 14:56:08 +00:00
|
|
|
if (l->lost_logs) {
|
|
|
|
int ll = l->lost_logs;
|
|
|
|
switch_event_t *event;
|
|
|
|
l->lost_logs = 0;
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Lost %d log lines!\n", ll);
|
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_event_add_header(event, SWITCH_STACK_BOTTOM, "info", "lost %d log lines", ll);
|
|
|
|
switch_event_fire(&event);
|
2008-01-25 23:09:33 +00:00
|
|
|
}
|
|
|
|
}
|
2006-07-22 21:49:52 +00:00
|
|
|
} else {
|
2009-08-22 19:26:58 +00:00
|
|
|
switch_log_node_free(&dnode);
|
2010-07-24 06:03:21 +00:00
|
|
|
if (++l->lost_logs > MAX_MISSED) {
|
2011-09-16 16:18:50 +00:00
|
|
|
kill_listener(l, NULL);
|
2010-07-24 06:03:21 +00:00
|
|
|
}
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-11-07 14:48:49 +00:00
|
|
|
switch_mutex_unlock(globals.listener_mutex);
|
2006-07-22 21:49:52 +00:00
|
|
|
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2008-10-29 19:15:14 +00:00
|
|
|
static void flush_listener(listener_t *listener, switch_bool_t flush_log, switch_bool_t flush_events)
|
|
|
|
{
|
|
|
|
void *pop;
|
|
|
|
|
|
|
|
if (listener->log_queue) {
|
|
|
|
while (switch_queue_trypop(listener->log_queue, &pop) == SWITCH_STATUS_SUCCESS) {
|
2008-12-20 14:56:08 +00:00
|
|
|
switch_log_node_t *dnode = (switch_log_node_t *) pop;
|
|
|
|
if (dnode) {
|
2009-08-22 19:26:58 +00:00
|
|
|
switch_log_node_free(&dnode);
|
2008-12-20 14:56:08 +00:00
|
|
|
}
|
2008-10-29 19:15:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (listener->event_queue) {
|
|
|
|
while (switch_queue_trypop(listener->event_queue, &pop) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_event_t *pevent = (switch_event_t *) pop;
|
2010-02-06 03:38:24 +00:00
|
|
|
if (!pop)
|
|
|
|
continue;
|
2008-10-29 19:15:14 +00:00
|
|
|
switch_event_destroy(&pevent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-10-23 21:58:09 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
static switch_status_t expire_listener(listener_t ** listener)
|
2008-10-23 21:58:09 +00:00
|
|
|
{
|
2009-11-21 06:17:05 +00:00
|
|
|
listener_t *l;
|
2009-11-06 20:17:31 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
if (!listener || !*listener)
|
|
|
|
return SWITCH_STATUS_FALSE;
|
2009-11-21 06:17:05 +00:00
|
|
|
l = *listener;
|
|
|
|
|
|
|
|
if (!l->expire_time) {
|
|
|
|
l->expire_time = switch_epoch_time_now(NULL);
|
2009-11-06 20:17:31 +00:00
|
|
|
}
|
|
|
|
|
2009-11-21 06:17:05 +00:00
|
|
|
if (switch_thread_rwlock_trywrlock(l->rwlock) != SWITCH_STATUS_SUCCESS) {
|
2009-11-06 20:17:31 +00:00
|
|
|
return SWITCH_STATUS_FALSE;
|
|
|
|
}
|
2009-11-21 06:17:05 +00:00
|
|
|
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(l->session), SWITCH_LOG_CRIT, "Stateful Listener %u has expired\n", l->id);
|
2009-11-06 20:17:31 +00:00
|
|
|
|
2008-10-29 19:15:14 +00:00
|
|
|
flush_listener(*listener, SWITCH_TRUE, SWITCH_TRUE);
|
2009-11-21 06:17:05 +00:00
|
|
|
switch_core_hash_destroy(&l->event_hash);
|
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
if (l->allowed_event_hash) {
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_core_hash_destroy(&l->allowed_event_hash);
|
|
|
|
}
|
2010-01-05 19:47:49 +00:00
|
|
|
|
|
|
|
if (l->allowed_api_hash) {
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_core_hash_destroy(&l->allowed_api_hash);
|
|
|
|
}
|
2010-01-05 19:47:49 +00:00
|
|
|
|
|
|
|
|
2009-11-21 06:17:05 +00:00
|
|
|
switch_mutex_lock(l->filter_mutex);
|
|
|
|
if (l->filters) {
|
|
|
|
switch_event_destroy(&l->filters);
|
2008-10-30 00:39:55 +00:00
|
|
|
}
|
2009-11-21 06:17:05 +00:00
|
|
|
|
|
|
|
switch_mutex_unlock(l->filter_mutex);
|
|
|
|
switch_thread_rwlock_unlock(l->rwlock);
|
|
|
|
switch_core_destroy_memory_pool(&l->pool);
|
|
|
|
|
2008-10-23 21:58:09 +00:00
|
|
|
*listener = NULL;
|
2009-11-06 20:17:31 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
2008-10-23 21:58:09 +00:00
|
|
|
}
|
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
static void event_handler(switch_event_t *event)
|
|
|
|
{
|
|
|
|
switch_event_t *clone = NULL;
|
2009-11-06 20:17:31 +00:00
|
|
|
listener_t *l, *lp, *last = NULL;
|
2009-11-21 06:17:05 +00:00
|
|
|
time_t now = switch_epoch_time_now(NULL);
|
2006-07-22 21:49:52 +00:00
|
|
|
|
2007-12-16 03:01:50 +00:00
|
|
|
switch_assert(event != NULL);
|
2006-07-22 21:49:52 +00:00
|
|
|
|
|
|
|
if (!listen_list.ready) {
|
|
|
|
return;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-23 21:58:09 +00:00
|
|
|
lp = listen_list.listeners;
|
|
|
|
|
2008-11-07 14:48:49 +00:00
|
|
|
switch_mutex_lock(globals.listener_mutex);
|
2010-02-06 03:38:24 +00:00
|
|
|
while (lp) {
|
2008-10-30 02:27:22 +00:00
|
|
|
int send = 0;
|
2009-11-06 20:17:31 +00:00
|
|
|
|
2008-10-23 21:58:09 +00:00
|
|
|
l = lp;
|
|
|
|
lp = lp->next;
|
2009-11-21 06:17:05 +00:00
|
|
|
|
|
|
|
if (switch_test_flag(l, LFLAG_STATEFUL) && (l->expire_time || (l->timeout && now - l->last_flush > l->timeout))) {
|
2009-11-06 20:17:31 +00:00
|
|
|
if (expire_listener(&l) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
if (last) {
|
|
|
|
last->next = lp;
|
|
|
|
} else {
|
|
|
|
listen_list.listeners = lp;
|
|
|
|
}
|
|
|
|
continue;
|
2009-05-02 00:58:51 +00:00
|
|
|
}
|
2008-10-23 17:31:22 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-11-21 06:17:05 +00:00
|
|
|
if (l->expire_time || !switch_test_flag(l, LFLAG_EVENTS)) {
|
|
|
|
last = l;
|
|
|
|
continue;
|
2010-02-06 03:38:24 +00:00
|
|
|
}
|
2009-11-21 06:17:05 +00:00
|
|
|
|
2007-06-08 15:17:43 +00:00
|
|
|
if (l->event_list[SWITCH_EVENT_ALL]) {
|
2006-07-25 14:14:07 +00:00
|
|
|
send = 1;
|
2007-06-08 15:17:43 +00:00
|
|
|
} else if ((l->event_list[event->event_id])) {
|
2008-07-01 23:41:09 +00:00
|
|
|
if (event->event_id != SWITCH_EVENT_CUSTOM || !event->subclass_name || (switch_core_hash_find(l->event_hash, event->subclass_name))) {
|
2007-03-29 22:31:56 +00:00
|
|
|
send = 1;
|
|
|
|
}
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2011-03-07 16:35:32 +00:00
|
|
|
if (send) {
|
2008-10-30 00:39:55 +00:00
|
|
|
switch_mutex_lock(l->filter_mutex);
|
2008-10-30 23:37:16 +00:00
|
|
|
|
2011-03-07 16:35:32 +00:00
|
|
|
if (l->filters && l->filters->headers) {
|
|
|
|
switch_event_header_t *hp;
|
|
|
|
const char *hval;
|
|
|
|
|
|
|
|
send = 0;
|
2011-03-17 17:36:27 +00:00
|
|
|
|
2011-03-07 16:35:32 +00:00
|
|
|
for (hp = l->filters->headers; hp; hp = hp->next) {
|
|
|
|
if ((hval = switch_event_get_header(event, hp->name))) {
|
|
|
|
const char *comp_to = hp->value;
|
|
|
|
int pos = 1, cmp = 0;
|
|
|
|
|
|
|
|
while (comp_to && *comp_to) {
|
|
|
|
if (*comp_to == '+') {
|
|
|
|
pos = 1;
|
|
|
|
} else if (*comp_to == '-') {
|
|
|
|
pos = 0;
|
|
|
|
} else if (*comp_to != ' ') {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
comp_to++;
|
|
|
|
}
|
2008-10-30 23:37:16 +00:00
|
|
|
|
2011-03-07 16:35:32 +00:00
|
|
|
if (send && pos) {
|
|
|
|
continue;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2011-03-07 16:35:32 +00:00
|
|
|
if (!comp_to) {
|
|
|
|
continue;
|
|
|
|
}
|
2008-10-30 23:37:16 +00:00
|
|
|
|
2011-03-07 16:35:32 +00:00
|
|
|
if (*hp->value == '/') {
|
|
|
|
switch_regex_t *re = NULL;
|
|
|
|
int ovector[30];
|
|
|
|
cmp = !!switch_regex_perform(hval, comp_to, &re, ovector, sizeof(ovector) / sizeof(ovector[0]));
|
|
|
|
switch_regex_safe_free(re);
|
2008-10-30 23:37:16 +00:00
|
|
|
} else {
|
2011-03-07 16:35:32 +00:00
|
|
|
cmp = !strcasecmp(hval, comp_to);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cmp) {
|
|
|
|
if (pos) {
|
|
|
|
send = 1;
|
|
|
|
} else {
|
|
|
|
send = 0;
|
|
|
|
break;
|
|
|
|
}
|
2008-10-30 00:39:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-03-17 17:36:27 +00:00
|
|
|
|
|
|
|
switch_mutex_unlock(l->filter_mutex);
|
2008-10-30 00:39:55 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
if (send && switch_test_flag(l, LFLAG_MYEVENTS)) {
|
|
|
|
char *uuid = switch_event_get_header(event, "unique-id");
|
|
|
|
if (!uuid || strcmp(uuid, switch_core_session_get_uuid(l->session))) {
|
2007-06-08 15:17:43 +00:00
|
|
|
send = 0;
|
2006-07-25 14:14:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (send) {
|
|
|
|
if (switch_event_dup(&clone, event) == SWITCH_STATUS_SUCCESS) {
|
2011-01-25 20:13:15 +00:00
|
|
|
if (switch_queue_trypush(l->event_queue, clone) == SWITCH_STATUS_SUCCESS) {
|
2008-01-25 23:09:33 +00:00
|
|
|
if (l->lost_events) {
|
|
|
|
int le = l->lost_events;
|
|
|
|
l->lost_events = 0;
|
2009-08-13 21:52:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(l->session), SWITCH_LOG_CRIT, "Lost %d events!\n", le);
|
2008-01-25 23:09:33 +00:00
|
|
|
clone = NULL;
|
|
|
|
if (switch_event_create(&clone, SWITCH_EVENT_TRAP) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_event_add_header(clone, SWITCH_STACK_BOTTOM, "info", "lost %d events", le);
|
|
|
|
switch_event_fire(&clone);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2010-07-24 06:03:21 +00:00
|
|
|
if (++l->lost_events > MAX_MISSED) {
|
2011-09-16 16:18:50 +00:00
|
|
|
kill_listener(l, NULL);
|
2010-07-24 06:03:21 +00:00
|
|
|
}
|
2008-01-25 23:09:33 +00:00
|
|
|
switch_event_destroy(&clone);
|
|
|
|
}
|
2006-07-25 14:14:07 +00:00
|
|
|
} else {
|
2009-08-13 21:52:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(l->session), SWITCH_LOG_ERROR, "Memory Error!\n");
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
|
|
|
}
|
2009-11-21 06:17:05 +00:00
|
|
|
last = l;
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
2008-11-07 14:48:49 +00:00
|
|
|
switch_mutex_unlock(globals.listener_mutex);
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
|
|
|
|
2007-06-20 07:53:33 +00:00
|
|
|
SWITCH_STANDARD_APP(socket_function)
|
2007-01-06 17:06:18 +00:00
|
|
|
{
|
2008-02-26 21:53:48 +00:00
|
|
|
char *host, *port_name, *path;
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_socket_t *new_sock;
|
|
|
|
switch_sockaddr_t *sa;
|
|
|
|
switch_port_t port = 8084;
|
|
|
|
listener_t *listener;
|
2007-01-06 17:06:18 +00:00
|
|
|
int argc = 0, x = 0;
|
2007-03-29 22:31:56 +00:00
|
|
|
char *argv[80] = { 0 };
|
2007-01-06 17:06:18 +00:00
|
|
|
char *mydata;
|
2008-02-26 21:53:48 +00:00
|
|
|
switch_channel_t *channel = NULL;
|
|
|
|
|
|
|
|
channel = switch_core_session_get_channel(session);
|
2007-01-06 17:06:18 +00:00
|
|
|
|
|
|
|
if (data && (mydata = switch_core_session_strdup(session, data))) {
|
|
|
|
argc = switch_separate_string(mydata, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
|
2007-03-29 22:31:56 +00:00
|
|
|
}
|
2007-01-06 17:06:18 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
if (argc < 1) {
|
2009-08-13 21:52:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Parse Error!\n");
|
2007-03-29 22:31:56 +00:00
|
|
|
return;
|
|
|
|
}
|
2007-01-06 17:06:18 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
host = argv[0];
|
2007-01-06 17:06:18 +00:00
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (zstr(host)) {
|
2009-08-13 21:52:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Missing Host!\n");
|
2007-03-29 22:31:56 +00:00
|
|
|
return;
|
|
|
|
}
|
2007-01-06 17:06:18 +00:00
|
|
|
|
2012-03-14 15:05:03 +00:00
|
|
|
if ((port_name = strrchr(host, ':'))) {
|
2007-03-29 22:31:56 +00:00
|
|
|
*port_name++ = '\0';
|
|
|
|
port = (switch_port_t) atoi(port_name);
|
|
|
|
}
|
2007-01-06 17:06:18 +00:00
|
|
|
|
2008-02-29 15:39:56 +00:00
|
|
|
if ((path = strchr((port_name ? port_name : host), '/'))) {
|
2008-02-26 21:53:48 +00:00
|
|
|
*path++ = '\0';
|
|
|
|
switch_channel_set_variable(channel, "socket_path", path);
|
|
|
|
}
|
|
|
|
|
2008-02-29 15:39:56 +00:00
|
|
|
switch_channel_set_variable(channel, "socket_host", host);
|
|
|
|
|
2012-03-14 15:05:03 +00:00
|
|
|
if (switch_sockaddr_info_get(&sa, host, SWITCH_UNSPEC, port, 0, switch_core_session_get_pool(session)) != SWITCH_STATUS_SUCCESS) {
|
2009-08-13 21:52:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Socket Error!\n");
|
2007-01-06 17:06:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-14 15:05:03 +00:00
|
|
|
if (switch_socket_create(&new_sock, switch_sockaddr_get_family(sa), SOCK_STREAM, SWITCH_PROTO_TCP, switch_core_session_get_pool(session))
|
2007-03-29 22:31:56 +00:00
|
|
|
!= SWITCH_STATUS_SUCCESS) {
|
2009-08-13 21:52:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Socket Error!\n");
|
2007-01-06 17:06:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_socket_opt_set(new_sock, SWITCH_SO_KEEPALIVE, 1);
|
2009-01-15 22:11:27 +00:00
|
|
|
switch_socket_opt_set(new_sock, SWITCH_SO_TCP_NODELAY, 1);
|
2007-01-06 17:06:18 +00:00
|
|
|
|
|
|
|
if (switch_socket_connect(new_sock, sa) != SWITCH_STATUS_SUCCESS) {
|
2009-08-13 21:52:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Socket Error!\n");
|
2007-03-29 22:31:56 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!(listener = switch_core_session_alloc(session, sizeof(*listener)))) {
|
2009-08-13 21:52:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Memory Error\n");
|
2007-01-06 17:06:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_thread_rwlock_create(&listener->rwlock, switch_core_session_get_pool(session));
|
2010-07-24 06:03:21 +00:00
|
|
|
switch_queue_create(&listener->event_queue, MAX_QUEUE_LEN, switch_core_session_get_pool(session));
|
|
|
|
switch_queue_create(&listener->log_queue, MAX_QUEUE_LEN, switch_core_session_get_pool(session));
|
2007-03-29 22:31:56 +00:00
|
|
|
|
|
|
|
listener->sock = new_sock;
|
|
|
|
listener->pool = switch_core_session_get_pool(session);
|
|
|
|
listener->format = EVENT_FORMAT_PLAIN;
|
|
|
|
listener->session = session;
|
2010-01-05 19:47:49 +00:00
|
|
|
switch_set_flag(listener, LFLAG_ALLOW_LOG);
|
2007-03-29 22:31:56 +00:00
|
|
|
|
|
|
|
switch_mutex_init(&listener->flag_mutex, SWITCH_MUTEX_NESTED, listener->pool);
|
2008-10-30 00:39:55 +00:00
|
|
|
switch_mutex_init(&listener->filter_mutex, SWITCH_MUTEX_NESTED, listener->pool);
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_core_hash_init(&listener->event_hash, listener->pool);
|
|
|
|
switch_set_flag(listener, LFLAG_AUTHED);
|
2008-12-12 15:44:37 +00:00
|
|
|
switch_set_flag(listener, LFLAG_OUTBOUND);
|
2007-03-29 22:31:56 +00:00
|
|
|
for (x = 1; x < argc; x++) {
|
|
|
|
if (argv[x] && !strcasecmp(argv[x], "full")) {
|
|
|
|
switch_set_flag(listener, LFLAG_FULL);
|
|
|
|
} else if (argv[x] && !strcasecmp(argv[x], "async")) {
|
|
|
|
switch_set_flag(listener, LFLAG_ASYNC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
if (switch_test_flag(listener, LFLAG_ASYNC)) {
|
2009-04-30 22:45:46 +00:00
|
|
|
const char *var;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
launch_listener_thread(listener);
|
2009-04-30 22:45:46 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
while (switch_channel_ready(channel) && !switch_test_flag(listener, LFLAG_CONNECTED)) {
|
2009-04-30 22:45:46 +00:00
|
|
|
switch_cond_next();
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_ivr_park(session, NULL);
|
2009-04-30 22:45:46 +00:00
|
|
|
|
2009-10-13 21:52:47 +00:00
|
|
|
switch_ivr_parse_all_events(session);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-04-30 22:45:46 +00:00
|
|
|
if (switch_test_flag(listener, LFLAG_RESUME) || ((var = switch_channel_get_variable(channel, "socket_resume")) && switch_true(var))) {
|
|
|
|
switch_channel_set_state(channel, CS_EXECUTE);
|
|
|
|
}
|
|
|
|
|
2008-11-11 13:32:11 +00:00
|
|
|
return;
|
2007-03-29 22:31:56 +00:00
|
|
|
} else {
|
|
|
|
listener_run(NULL, (void *) listener);
|
|
|
|
}
|
|
|
|
|
2009-02-25 03:41:18 +00:00
|
|
|
if (switch_channel_down(channel)) {
|
2008-11-11 13:32:11 +00:00
|
|
|
while (switch_test_flag(listener, LFLAG_SESSION)) {
|
|
|
|
switch_yield(100000);
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
}
|
2007-01-06 17:06:18 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
static void close_socket(switch_socket_t ** sock)
|
2007-03-29 22:31:56 +00:00
|
|
|
{
|
2006-08-29 20:27:43 +00:00
|
|
|
switch_mutex_lock(listen_list.sock_mutex);
|
2006-07-22 21:49:52 +00:00
|
|
|
if (*sock) {
|
2007-03-09 20:44:13 +00:00
|
|
|
switch_socket_shutdown(*sock, SWITCH_SHUTDOWN_READWRITE);
|
2006-07-22 21:49:52 +00:00
|
|
|
switch_socket_close(*sock);
|
|
|
|
*sock = NULL;
|
|
|
|
}
|
2006-08-29 20:27:43 +00:00
|
|
|
switch_mutex_unlock(listen_list.sock_mutex);
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
|
|
|
|
2007-06-13 17:06:10 +00:00
|
|
|
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_event_socket_shutdown)
|
2006-07-22 21:49:52 +00:00
|
|
|
{
|
2007-07-24 21:26:04 +00:00
|
|
|
int sanity = 0;
|
2006-07-25 14:14:07 +00:00
|
|
|
|
2006-11-09 05:39:04 +00:00
|
|
|
prefs.done = 1;
|
|
|
|
|
2009-02-20 01:10:59 +00:00
|
|
|
kill_all_listeners();
|
2008-07-11 14:35:08 +00:00
|
|
|
switch_log_unbind_logger(socket_logger);
|
|
|
|
|
2006-08-29 20:27:43 +00:00
|
|
|
close_socket(&listen_list.sock);
|
|
|
|
|
2008-05-27 04:54:52 +00:00
|
|
|
while (prefs.threads) {
|
2009-02-20 01:10:59 +00:00
|
|
|
switch_yield(100000);
|
|
|
|
kill_all_listeners();
|
|
|
|
if (++sanity >= 200) {
|
2007-07-24 21:26:04 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-08-29 20:27:43 +00:00
|
|
|
|
2009-02-20 01:10:59 +00:00
|
|
|
switch_event_unbind(&globals.node);
|
2006-07-22 21:49:52 +00:00
|
|
|
|
2009-02-23 19:17:24 +00:00
|
|
|
switch_safe_free(prefs.ip);
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_safe_free(prefs.password);
|
2009-02-23 19:17:24 +00:00
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2008-05-27 04:54:52 +00:00
|
|
|
static void add_listener(listener_t *listener)
|
2006-07-22 21:49:52 +00:00
|
|
|
{
|
|
|
|
/* add me to the listeners so I get events */
|
2008-11-07 14:48:49 +00:00
|
|
|
switch_mutex_lock(globals.listener_mutex);
|
2006-07-22 21:49:52 +00:00
|
|
|
listener->next = listen_list.listeners;
|
|
|
|
listen_list.listeners = listener;
|
2008-11-07 14:48:49 +00:00
|
|
|
switch_mutex_unlock(globals.listener_mutex);
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
|
|
|
|
2008-05-27 04:54:52 +00:00
|
|
|
static void remove_listener(listener_t *listener)
|
2006-07-22 21:49:52 +00:00
|
|
|
{
|
|
|
|
listener_t *l, *last = NULL;
|
|
|
|
|
2008-11-07 14:48:49 +00:00
|
|
|
switch_mutex_lock(globals.listener_mutex);
|
2006-07-22 21:49:52 +00:00
|
|
|
for (l = listen_list.listeners; l; l = l->next) {
|
|
|
|
if (l == listener) {
|
|
|
|
if (last) {
|
|
|
|
last->next = l->next;
|
|
|
|
} else {
|
|
|
|
listen_list.listeners = l->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
last = l;
|
|
|
|
}
|
2008-11-07 14:48:49 +00:00
|
|
|
switch_mutex_unlock(globals.listener_mutex);
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
|
|
|
|
2011-01-25 20:13:15 +00:00
|
|
|
static void send_disconnect(listener_t *listener, const char *message)
|
2010-07-24 06:03:21 +00:00
|
|
|
{
|
2011-01-25 20:13:15 +00:00
|
|
|
|
|
|
|
char disco_buf[512] = "";
|
|
|
|
switch_size_t len, mlen;
|
|
|
|
|
|
|
|
if (zstr(message)) {
|
|
|
|
message = "Disconnected.\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
mlen = strlen(message);
|
|
|
|
|
|
|
|
if (listener->session) {
|
|
|
|
switch_snprintf(disco_buf, sizeof(disco_buf), "Content-Type: text/disconnect-notice\n"
|
|
|
|
"Controlled-Session-UUID: %s\n"
|
|
|
|
"Content-Disposition: disconnect\n" "Content-Length: %d\n\n", switch_core_session_get_uuid(listener->session), mlen);
|
|
|
|
} else {
|
|
|
|
switch_snprintf(disco_buf, sizeof(disco_buf), "Content-Type: text/disconnect-notice\nContent-Length: %d\n\n", mlen);
|
|
|
|
}
|
|
|
|
|
|
|
|
len = strlen(disco_buf);
|
|
|
|
switch_socket_send(listener->sock, disco_buf, &len);
|
|
|
|
if (len > 0) {
|
|
|
|
len = mlen;
|
|
|
|
switch_socket_send(listener->sock, message, &len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void kill_listener(listener_t *l, const char *message)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (message) {
|
|
|
|
send_disconnect(l, message);
|
|
|
|
}
|
|
|
|
|
2010-07-24 06:03:21 +00:00
|
|
|
switch_clear_flag(l, LFLAG_RUNNING);
|
|
|
|
if (l->sock) {
|
|
|
|
switch_socket_shutdown(l->sock, SWITCH_SHUTDOWN_READWRITE);
|
|
|
|
switch_socket_close(l->sock);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2008-10-23 17:31:22 +00:00
|
|
|
|
2009-02-20 01:10:59 +00:00
|
|
|
static void kill_all_listeners(void)
|
|
|
|
{
|
|
|
|
listener_t *l;
|
|
|
|
|
|
|
|
switch_mutex_lock(globals.listener_mutex);
|
|
|
|
for (l = listen_list.listeners; l; l = l->next) {
|
2011-01-25 20:13:15 +00:00
|
|
|
kill_listener(l, "The system is being shut down.\n");
|
2009-02-20 01:10:59 +00:00
|
|
|
}
|
|
|
|
switch_mutex_unlock(globals.listener_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-23 17:31:22 +00:00
|
|
|
static listener_t *find_listener(uint32_t id)
|
|
|
|
{
|
|
|
|
listener_t *l, *r = NULL;
|
|
|
|
|
2008-11-07 14:48:49 +00:00
|
|
|
switch_mutex_lock(globals.listener_mutex);
|
2008-10-23 17:31:22 +00:00
|
|
|
for (l = listen_list.listeners; l; l = l->next) {
|
2009-11-06 20:17:31 +00:00
|
|
|
if (l->id && l->id == id && !l->expire_time) {
|
2008-10-23 17:31:22 +00:00
|
|
|
if (switch_thread_rwlock_tryrdlock(l->rwlock) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
r = l;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2008-11-07 14:48:49 +00:00
|
|
|
switch_mutex_unlock(globals.listener_mutex);
|
2008-10-23 17:31:22 +00:00
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
static void strip_cr(char *s)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
if ((p = strchr(s, '\r')) || (p = strchr(s, '\n'))) {
|
|
|
|
*p = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-23 17:31:22 +00:00
|
|
|
|
|
|
|
static void xmlize_listener(listener_t *listener, switch_stream_handle_t *stream)
|
|
|
|
{
|
|
|
|
stream->write_function(stream, " <listener>\n");
|
|
|
|
stream->write_function(stream, " <listen-id>%u</listen-id>\n", listener->id);
|
2010-06-17 16:43:09 +00:00
|
|
|
stream->write_function(stream, " <format>%s</format>\n", format2str(listener->format));
|
2008-10-23 17:31:22 +00:00
|
|
|
stream->write_function(stream, " <timeout>%u</timeout>\n", listener->timeout);
|
|
|
|
stream->write_function(stream, " </listener>\n");
|
|
|
|
}
|
|
|
|
|
2008-11-14 17:29:14 +00:00
|
|
|
SWITCH_STANDARD_API(event_sink_function)
|
2008-10-23 17:31:22 +00:00
|
|
|
{
|
|
|
|
char *http = NULL;
|
|
|
|
char *wcmd = NULL;
|
|
|
|
char *format = NULL;
|
|
|
|
listener_t *listener = NULL;
|
|
|
|
|
|
|
|
if (stream->param_event) {
|
2010-02-06 03:38:24 +00:00
|
|
|
http = switch_event_get_header(stream->param_event, "http-host");
|
2008-10-23 17:31:22 +00:00
|
|
|
wcmd = switch_event_get_header(stream->param_event, "command");
|
|
|
|
format = switch_event_get_header(stream->param_event, "format");
|
2010-02-06 03:38:24 +00:00
|
|
|
}
|
2008-10-23 17:31:22 +00:00
|
|
|
|
|
|
|
if (!http) {
|
2009-11-01 20:40:31 +00:00
|
|
|
stream->write_function(stream, "This is a web application!\n");
|
2010-02-06 03:38:24 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
2008-10-23 17:31:22 +00:00
|
|
|
}
|
|
|
|
stream->write_function(stream, "Content-Type: text/xml\n\n");
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-23 17:31:22 +00:00
|
|
|
stream->write_function(stream, "<?xml version=\"1.0\"?>\n");
|
|
|
|
stream->write_function(stream, "<root>\n");
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-23 17:31:22 +00:00
|
|
|
if (!wcmd) {
|
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">Missing command parameter!</reply></data>\n");
|
|
|
|
goto end;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-23 17:31:22 +00:00
|
|
|
if (!format) {
|
|
|
|
format = "xml";
|
|
|
|
}
|
|
|
|
|
2008-11-14 17:29:14 +00:00
|
|
|
|
|
|
|
if (!strcasecmp(wcmd, "filter")) {
|
2008-11-14 18:11:54 +00:00
|
|
|
char *action = switch_event_get_header(stream->param_event, "action");
|
|
|
|
char *header_name = switch_event_get_header(stream->param_event, "header-name");
|
|
|
|
char *header_val = switch_event_get_header(stream->param_event, "header-val");
|
|
|
|
char *id = switch_event_get_header(stream->param_event, "listen-id");
|
|
|
|
uint32_t idl = 0;
|
|
|
|
|
|
|
|
if (id) {
|
|
|
|
idl = (uint32_t) atol(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(listener = find_listener(idl))) {
|
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">Invalid Listen-ID</reply></data>\n");
|
2010-02-06 03:38:24 +00:00
|
|
|
goto end;
|
2008-11-14 18:11:54 +00:00
|
|
|
}
|
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (zstr(action)) {
|
2008-11-14 17:29:14 +00:00
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">Invalid Syntax</reply></data>\n");
|
2010-02-06 03:38:24 +00:00
|
|
|
goto end;
|
2008-11-14 17:29:14 +00:00
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_mutex_lock(listener->filter_mutex);
|
2008-11-14 17:29:14 +00:00
|
|
|
if (!listener->filters) {
|
2010-11-22 23:06:59 +00:00
|
|
|
switch_event_create_plain(&listener->filters, SWITCH_EVENT_CLONE);
|
2008-11-14 17:29:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcasecmp(action, "delete")) {
|
2009-10-23 16:03:42 +00:00
|
|
|
if (zstr(header_val)) {
|
2008-11-14 17:29:14 +00:00
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">Invalid Syntax</reply></data>\n");
|
|
|
|
goto filter_end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcasecmp(header_val, "all")) {
|
|
|
|
switch_event_destroy(&listener->filters);
|
2010-11-22 23:06:59 +00:00
|
|
|
switch_event_create_plain(&listener->filters, SWITCH_EVENT_CLONE);
|
2008-11-14 17:29:14 +00:00
|
|
|
} else {
|
|
|
|
switch_event_del_header(listener->filters, header_val);
|
|
|
|
}
|
|
|
|
stream->write_function(stream, "<data>\n <reply type=\"success\">filter deleted.</reply>\n<api-command>\n");
|
|
|
|
} else if (!strcasecmp(action, "add")) {
|
2009-10-23 16:03:42 +00:00
|
|
|
if (zstr(header_name) || zstr(header_val)) {
|
2008-11-14 17:29:14 +00:00
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">Invalid Syntax</reply></data>\n");
|
|
|
|
goto filter_end;
|
|
|
|
}
|
|
|
|
switch_event_add_header_string(listener->filters, SWITCH_STACK_BOTTOM, header_name, header_val);
|
|
|
|
stream->write_function(stream, "<data>\n <reply type=\"success\">filter added.</reply>\n<api-command>\n");
|
|
|
|
} else {
|
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">Invalid Syntax</reply></data>\n");
|
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
filter_end:
|
2008-11-14 17:29:14 +00:00
|
|
|
|
|
|
|
switch_mutex_unlock(listener->filter_mutex);
|
|
|
|
|
2008-12-31 22:44:23 +00:00
|
|
|
} else if (!strcasecmp(wcmd, "stop-logging")) {
|
|
|
|
char *id = switch_event_get_header(stream->param_event, "listen-id");
|
|
|
|
uint32_t idl = 0;
|
|
|
|
|
|
|
|
if (id) {
|
|
|
|
idl = (uint32_t) atol(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(listener = find_listener(idl))) {
|
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">Invalid Listen-ID</reply></data>\n");
|
2010-02-06 03:38:24 +00:00
|
|
|
goto end;
|
2008-12-31 22:44:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (switch_test_flag(listener, LFLAG_LOG)) {
|
|
|
|
switch_clear_flag_locked(listener, LFLAG_LOG);
|
|
|
|
stream->write_function(stream, "<data><reply type=\"success\">Not Logging</reply></data>\n");
|
|
|
|
} else {
|
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">Not Logging</reply></data>\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
} else if (!strcasecmp(wcmd, "set-loglevel")) {
|
|
|
|
char *loglevel = switch_event_get_header(stream->param_event, "loglevel");
|
|
|
|
char *id = switch_event_get_header(stream->param_event, "listen-id");
|
|
|
|
uint32_t idl = 0;
|
|
|
|
|
|
|
|
if (id) {
|
|
|
|
idl = (uint32_t) atol(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(listener = find_listener(idl))) {
|
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">Invalid Listen-ID</reply></data>\n");
|
2010-02-06 03:38:24 +00:00
|
|
|
goto end;
|
2008-12-31 22:44:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (loglevel) {
|
|
|
|
switch_log_level_t ltype = switch_log_str2level(loglevel);
|
|
|
|
if (ltype != SWITCH_LOG_INVALID) {
|
|
|
|
listener->level = ltype;
|
|
|
|
switch_set_flag(listener, LFLAG_LOG);
|
|
|
|
stream->write_function(stream, "<data><reply type=\"success\">Log Level %s</reply></data>\n", loglevel);
|
|
|
|
} else {
|
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">Invalid Level</reply></data>\n");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">Invalid Syntax</reply></data>\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
goto end;
|
|
|
|
|
2008-11-14 17:29:14 +00:00
|
|
|
} else if (!strcasecmp(wcmd, "create-listener")) {
|
2008-10-23 17:31:22 +00:00
|
|
|
char *events = switch_event_get_header(stream->param_event, "events");
|
2008-12-31 22:44:23 +00:00
|
|
|
char *loglevel = switch_event_get_header(stream->param_event, "loglevel");
|
2008-10-23 17:31:22 +00:00
|
|
|
switch_memory_pool_t *pool;
|
|
|
|
char *next, *cur;
|
|
|
|
uint32_t count = 0, key_count = 0;
|
|
|
|
uint8_t custom = 0;
|
|
|
|
char *edup;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (zstr(events) && zstr(loglevel)) {
|
2008-10-23 17:31:22 +00:00
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">Missing parameter!</reply></data>\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_core_new_memory_pool(&pool);
|
|
|
|
listener = switch_core_alloc(pool, sizeof(*listener));
|
|
|
|
listener->pool = pool;
|
|
|
|
listener->format = EVENT_FORMAT_PLAIN;
|
|
|
|
switch_mutex_init(&listener->flag_mutex, SWITCH_MUTEX_NESTED, listener->pool);
|
2008-10-30 00:39:55 +00:00
|
|
|
switch_mutex_init(&listener->filter_mutex, SWITCH_MUTEX_NESTED, listener->pool);
|
|
|
|
|
2008-10-23 17:31:22 +00:00
|
|
|
switch_core_hash_init(&listener->event_hash, listener->pool);
|
|
|
|
switch_set_flag(listener, LFLAG_AUTHED);
|
|
|
|
switch_set_flag(listener, LFLAG_STATEFUL);
|
2010-01-05 19:47:49 +00:00
|
|
|
switch_set_flag(listener, LFLAG_ALLOW_LOG);
|
2010-07-24 06:03:21 +00:00
|
|
|
switch_queue_create(&listener->event_queue, MAX_QUEUE_LEN, listener->pool);
|
|
|
|
switch_queue_create(&listener->log_queue, MAX_QUEUE_LEN, listener->pool);
|
2008-12-31 22:44:23 +00:00
|
|
|
|
|
|
|
if (loglevel) {
|
|
|
|
switch_log_level_t ltype = switch_log_str2level(loglevel);
|
|
|
|
if (ltype != SWITCH_LOG_INVALID) {
|
|
|
|
listener->level = ltype;
|
|
|
|
switch_set_flag(listener, LFLAG_LOG);
|
|
|
|
}
|
|
|
|
}
|
2008-10-23 17:31:22 +00:00
|
|
|
switch_thread_rwlock_create(&listener->rwlock, listener->pool);
|
|
|
|
listener->id = next_id();
|
|
|
|
listener->timeout = 60;
|
2009-01-25 21:23:07 +00:00
|
|
|
listener->last_flush = switch_epoch_time_now(NULL);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-12-31 22:44:23 +00:00
|
|
|
if (events) {
|
2009-01-02 17:39:31 +00:00
|
|
|
char delim = ',';
|
2008-10-23 17:31:22 +00:00
|
|
|
|
2008-12-31 22:44:23 +00:00
|
|
|
if (switch_stristr("xml", format)) {
|
|
|
|
listener->format = EVENT_FORMAT_XML;
|
2010-06-17 16:43:09 +00:00
|
|
|
} else if (switch_stristr("json", format)) {
|
|
|
|
listener->format = EVENT_FORMAT_JSON;
|
2008-12-31 22:44:23 +00:00
|
|
|
} else {
|
|
|
|
listener->format = EVENT_FORMAT_PLAIN;
|
2008-10-23 17:31:22 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-12-31 22:44:23 +00:00
|
|
|
edup = strdup(events);
|
2009-01-02 17:39:31 +00:00
|
|
|
|
|
|
|
if (strchr(edup, ' ')) {
|
|
|
|
delim = ' ';
|
|
|
|
}
|
|
|
|
|
2008-12-31 22:44:23 +00:00
|
|
|
for (cur = edup; cur; count++) {
|
|
|
|
switch_event_types_t type;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-01-02 17:39:31 +00:00
|
|
|
if ((next = strchr(cur, delim))) {
|
2008-12-31 22:44:23 +00:00
|
|
|
*next++ = '\0';
|
|
|
|
}
|
2008-10-23 17:31:22 +00:00
|
|
|
|
2008-12-31 22:44:23 +00:00
|
|
|
if (custom) {
|
|
|
|
switch_core_hash_insert(listener->event_hash, cur, MARKER);
|
|
|
|
} else if (switch_name_event(cur, &type) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
key_count++;
|
|
|
|
if (type == SWITCH_EVENT_ALL) {
|
|
|
|
uint32_t x = 0;
|
|
|
|
for (x = 0; x < SWITCH_EVENT_ALL; x++) {
|
|
|
|
listener->event_list[x] = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (type <= SWITCH_EVENT_ALL) {
|
|
|
|
listener->event_list[type] = 1;
|
|
|
|
}
|
|
|
|
if (type == SWITCH_EVENT_CUSTOM) {
|
|
|
|
custom++;
|
2008-10-23 17:31:22 +00:00
|
|
|
}
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-12-31 22:44:23 +00:00
|
|
|
cur = next;
|
2008-10-23 17:31:22 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-23 17:31:22 +00:00
|
|
|
|
2008-12-31 22:44:23 +00:00
|
|
|
switch_safe_free(edup);
|
2008-10-23 17:31:22 +00:00
|
|
|
|
2008-12-31 22:44:23 +00:00
|
|
|
if (!key_count) {
|
|
|
|
switch_core_hash_destroy(&listener->event_hash);
|
|
|
|
switch_core_destroy_memory_pool(&listener->pool);
|
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">No keywords supplied</reply></data>\n");
|
|
|
|
goto end;
|
|
|
|
}
|
2008-10-23 17:31:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch_set_flag_locked(listener, LFLAG_EVENTS);
|
|
|
|
add_listener(listener);
|
|
|
|
stream->write_function(stream, "<data>\n");
|
|
|
|
stream->write_function(stream, " <reply type=\"success\">Listener %u Created</reply>\n", listener->id);
|
|
|
|
xmlize_listener(listener, stream);
|
|
|
|
stream->write_function(stream, "</data>\n");
|
|
|
|
|
2009-05-02 00:58:51 +00:00
|
|
|
if (globals.debug > 0) {
|
2009-08-13 21:52:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Creating event-sink listener [%u]\n", listener->id);
|
2009-05-02 00:58:51 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-23 17:31:22 +00:00
|
|
|
goto end;
|
2010-02-06 03:38:24 +00:00
|
|
|
} else if (!strcasecmp(wcmd, "destroy-listener")) {
|
2008-10-23 17:31:22 +00:00
|
|
|
char *id = switch_event_get_header(stream->param_event, "listen-id");
|
2008-10-24 15:50:46 +00:00
|
|
|
uint32_t idl = 0;
|
|
|
|
|
|
|
|
if (id) {
|
|
|
|
idl = (uint32_t) atol(id);
|
|
|
|
}
|
2008-10-23 17:31:22 +00:00
|
|
|
|
|
|
|
if ((listener = find_listener(idl))) {
|
2009-05-02 00:58:51 +00:00
|
|
|
if (globals.debug > 0) {
|
2009-08-13 21:52:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Destroying event-sink listener [%u]\n", idl);
|
2009-05-02 00:58:51 +00:00
|
|
|
}
|
2008-10-23 17:31:22 +00:00
|
|
|
stream->write_function(stream, "<data>\n <reply type=\"success\">listener %u destroyed</reply>\n", listener->id);
|
|
|
|
xmlize_listener(listener, stream);
|
|
|
|
stream->write_function(stream, "</data>\n");
|
2009-11-06 20:17:31 +00:00
|
|
|
listener->expire_time = switch_epoch_time_now(NULL);
|
2008-10-23 17:31:22 +00:00
|
|
|
goto end;
|
|
|
|
} else {
|
2009-05-02 00:58:51 +00:00
|
|
|
if (globals.debug > 0) {
|
2009-08-13 21:52:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Request to destroy unknown event-sink listener [%u]\n", idl);
|
2009-05-02 00:58:51 +00:00
|
|
|
}
|
2008-10-23 17:31:22 +00:00
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">Can't find listener</reply></data>\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else if (!strcasecmp(wcmd, "check-listener")) {
|
|
|
|
char *id = switch_event_get_header(stream->param_event, "listen-id");
|
2008-10-24 15:50:46 +00:00
|
|
|
uint32_t idl = 0;
|
2008-10-23 17:31:22 +00:00
|
|
|
void *pop;
|
2008-10-24 15:50:46 +00:00
|
|
|
switch_event_t *pevent = NULL;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-24 15:50:46 +00:00
|
|
|
if (id) {
|
|
|
|
idl = (uint32_t) atol(id);
|
|
|
|
}
|
|
|
|
|
2008-10-23 17:31:22 +00:00
|
|
|
if (!(listener = find_listener(idl))) {
|
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">Can't find listener</reply></data>\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2009-01-25 21:23:07 +00:00
|
|
|
listener->last_flush = switch_epoch_time_now(NULL);
|
2010-02-06 03:38:24 +00:00
|
|
|
stream->write_function(stream, "<data>\n <reply type=\"success\">Current Events Follow</reply>\n");
|
2008-10-23 17:31:22 +00:00
|
|
|
xmlize_listener(listener, stream);
|
2008-12-31 22:44:23 +00:00
|
|
|
|
|
|
|
if (switch_test_flag(listener, LFLAG_LOG)) {
|
|
|
|
stream->write_function(stream, "<log_data>\n");
|
|
|
|
|
|
|
|
while (switch_queue_trypop(listener->log_queue, &pop) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_log_node_t *dnode = (switch_log_node_t *) pop;
|
|
|
|
int encode_len = (strlen(dnode->data) * 3) + 1;
|
|
|
|
char *encode_buf = malloc(encode_len);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-12-31 22:44:23 +00:00
|
|
|
switch_assert(encode_buf);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-12-31 22:44:23 +00:00
|
|
|
memset(encode_buf, 0, encode_len);
|
|
|
|
switch_url_encode((char *) dnode->data, encode_buf, encode_len);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
|
|
|
|
|
|
|
stream->write_function(stream,
|
|
|
|
"<log log-level=\"%d\" text-channel=\"%d\" log-file=\"%s\" log-func=\"%s\" log-line=\"%d\" user-data=\"%s\">%s</log>\n",
|
|
|
|
dnode->level, dnode->channel, dnode->file, dnode->func, dnode->line, switch_str_nil(dnode->userdata), encode_buf);
|
2008-12-31 22:44:23 +00:00
|
|
|
free(encode_buf);
|
2009-08-22 19:26:58 +00:00
|
|
|
switch_log_node_free(&dnode);
|
2008-12-31 22:44:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
stream->write_function(stream, "</log_data>\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
stream->write_function(stream, "<events>\n");
|
2008-10-23 17:31:22 +00:00
|
|
|
|
|
|
|
while (switch_queue_trypop(listener->event_queue, &pop) == SWITCH_STATUS_SUCCESS) {
|
2011-04-22 21:43:29 +00:00
|
|
|
//char *etype;
|
2008-10-24 15:50:46 +00:00
|
|
|
pevent = (switch_event_t *) pop;
|
2008-10-23 17:31:22 +00:00
|
|
|
|
|
|
|
if (listener->format == EVENT_FORMAT_PLAIN) {
|
2011-04-22 21:43:29 +00:00
|
|
|
//etype = "plain";
|
2008-10-23 17:31:22 +00:00
|
|
|
switch_event_serialize(pevent, &listener->ebuf, SWITCH_TRUE);
|
|
|
|
stream->write_function(stream, "<event type=\"plain\">\n%s</event>", listener->ebuf);
|
2010-06-17 16:43:09 +00:00
|
|
|
} else if (listener->format == EVENT_FORMAT_JSON) {
|
2011-04-22 21:43:29 +00:00
|
|
|
//etype = "json";
|
2010-06-17 16:43:09 +00:00
|
|
|
switch_event_serialize_json(pevent, &listener->ebuf);
|
2008-10-23 17:31:22 +00:00
|
|
|
} else {
|
|
|
|
switch_xml_t xml;
|
2011-04-22 21:43:29 +00:00
|
|
|
//etype = "xml";
|
2008-10-23 17:31:22 +00:00
|
|
|
|
2010-08-14 22:39:49 +00:00
|
|
|
if ((xml = switch_event_xmlize(pevent, SWITCH_VA_NONE))) {
|
2008-10-23 17:31:22 +00:00
|
|
|
listener->ebuf = switch_xml_toxml(xml, SWITCH_FALSE);
|
|
|
|
switch_xml_free(xml);
|
|
|
|
} else {
|
2008-10-23 21:58:09 +00:00
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">XML Render Error</reply></data>\n");
|
2008-10-23 17:31:22 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
stream->write_function(stream, "%s\n", listener->ebuf);
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-23 17:31:22 +00:00
|
|
|
switch_safe_free(listener->ebuf);
|
|
|
|
switch_event_destroy(&pevent);
|
|
|
|
}
|
|
|
|
|
|
|
|
stream->write_function(stream, " </events>\n</data>\n");
|
|
|
|
|
|
|
|
if (pevent) {
|
|
|
|
switch_event_destroy(&pevent);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_thread_rwlock_unlock(listener->rwlock);
|
|
|
|
} else if (!strcasecmp(wcmd, "exec-fsapi")) {
|
|
|
|
char *api_command = switch_event_get_header(stream->param_event, "fsapi-command");
|
|
|
|
char *api_args = switch_event_get_header(stream->param_event, "fsapi-args");
|
|
|
|
switch_event_t *event, *oevent;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-23 17:31:22 +00:00
|
|
|
if (!(api_command)) {
|
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">INVALID API COMMAND!</reply></data>\n");
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
stream->write_function(stream, "<data>\n <reply type=\"success\">Execute API Command</reply>\n<api-command>\n");
|
|
|
|
switch_event_create(&event, SWITCH_EVENT_REQUEST_PARAMS);
|
|
|
|
oevent = stream->param_event;
|
|
|
|
stream->param_event = event;
|
2009-02-27 16:35:42 +00:00
|
|
|
|
|
|
|
if (!strcasecmp(api_command, "unload") && !strcasecmp(api_args, "mod_event_socket")) {
|
|
|
|
api_command = "bgapi";
|
|
|
|
api_args = "unload mod_event_socket";
|
2009-02-27 20:21:48 +00:00
|
|
|
} else if (!strcasecmp(api_command, "reload") && !strcasecmp(api_args, "mod_event_socket")) {
|
|
|
|
api_command = "bgapi";
|
|
|
|
api_args = "reload mod_event_socket";
|
2009-02-27 16:35:42 +00:00
|
|
|
}
|
|
|
|
|
2008-10-23 17:31:22 +00:00
|
|
|
switch_api_execute(api_command, api_args, NULL, stream);
|
|
|
|
stream->param_event = oevent;
|
|
|
|
stream->write_function(stream, " </api-command>\n</data>");
|
|
|
|
} else {
|
|
|
|
stream->write_function(stream, "<data><reply type=\"error\">INVALID COMMAND!</reply></data\n");
|
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
end:
|
2008-10-23 17:31:22 +00:00
|
|
|
|
|
|
|
stream->write_function(stream, "</root>\n\n");
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-23 17:31:22 +00:00
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SWITCH_MODULE_LOAD_FUNCTION(mod_event_socket_load)
|
|
|
|
{
|
|
|
|
switch_application_interface_t *app_interface;
|
|
|
|
switch_api_interface_t *api_interface;
|
|
|
|
|
2009-02-23 19:17:24 +00:00
|
|
|
memset(&globals, 0, sizeof(globals));
|
|
|
|
|
2008-11-07 14:48:49 +00:00
|
|
|
switch_mutex_init(&globals.listener_mutex, SWITCH_MUTEX_NESTED, pool);
|
|
|
|
|
2008-12-31 19:07:20 +00:00
|
|
|
memset(&listen_list, 0, sizeof(listen_list));
|
|
|
|
switch_mutex_init(&listen_list.sock_mutex, SWITCH_MUTEX_NESTED, pool);
|
|
|
|
|
2008-11-07 23:25:38 +00:00
|
|
|
if (switch_event_bind_removable(modname, SWITCH_EVENT_ALL, SWITCH_EVENT_SUBCLASS_ANY, event_handler, NULL, &globals.node) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't bind!\n");
|
|
|
|
return SWITCH_STATUS_GENERR;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-11-07 23:25:38 +00:00
|
|
|
switch_log_bind_logger(socket_logger, SWITCH_LOG_DEBUG, SWITCH_FALSE);
|
|
|
|
|
2008-10-23 17:31:22 +00:00
|
|
|
/* connect my internal structure to the blank pointer passed to me */
|
|
|
|
*module_interface = switch_loadable_module_create_module_interface(pool, modname);
|
|
|
|
SWITCH_ADD_APP(app_interface, "socket", "Connect to a socket", "Connect to a socket", socket_function, "<ip>[:<port>]", SAF_SUPPORT_NOMEDIA);
|
2008-11-14 17:29:14 +00:00
|
|
|
SWITCH_ADD_API(api_interface, "event_sink", "event_sink", event_sink_function, "<web data>");
|
2008-10-23 17:31:22 +00:00
|
|
|
|
|
|
|
/* indicate that the module should continue to be loaded */
|
|
|
|
return SWITCH_STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2008-05-27 04:54:52 +00:00
|
|
|
static switch_status_t read_packet(listener_t *listener, switch_event_t **event, uint32_t timeout)
|
2006-07-25 14:14:07 +00:00
|
|
|
{
|
2006-09-28 01:39:42 +00:00
|
|
|
switch_size_t mlen, bytes = 0;
|
2011-10-20 15:19:39 +00:00
|
|
|
char *mbuf = NULL;
|
2006-07-25 14:14:07 +00:00
|
|
|
char buf[1024] = "";
|
|
|
|
switch_size_t len;
|
|
|
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
2006-09-28 01:39:42 +00:00
|
|
|
int count = 0;
|
2006-07-25 14:14:07 +00:00
|
|
|
uint32_t elapsed = 0;
|
|
|
|
time_t start = 0;
|
|
|
|
void *pop;
|
|
|
|
char *ptr;
|
|
|
|
uint8_t crcount = 0;
|
2011-10-20 15:19:39 +00:00
|
|
|
uint32_t max_len = 10485760, block_len = 2048, buf_len = 0;
|
2007-12-04 00:21:32 +00:00
|
|
|
switch_channel_t *channel = NULL;
|
2008-07-22 22:23:50 +00:00
|
|
|
int clen = 0;
|
2009-02-20 01:10:59 +00:00
|
|
|
|
2006-07-25 14:14:07 +00:00
|
|
|
*event = NULL;
|
2009-02-20 01:10:59 +00:00
|
|
|
|
|
|
|
if (prefs.done) {
|
2011-10-20 15:19:39 +00:00
|
|
|
switch_goto_status(SWITCH_STATUS_FALSE, end);
|
2009-02-20 01:10:59 +00:00
|
|
|
}
|
|
|
|
|
2011-10-20 15:19:39 +00:00
|
|
|
switch_zmalloc(mbuf, block_len);
|
|
|
|
switch_assert(mbuf);
|
|
|
|
buf_len = block_len;
|
|
|
|
|
2009-01-25 21:23:07 +00:00
|
|
|
start = switch_epoch_time_now(NULL);
|
2006-07-25 14:14:07 +00:00
|
|
|
ptr = mbuf;
|
|
|
|
|
2007-12-04 00:21:32 +00:00
|
|
|
if (listener->session) {
|
|
|
|
channel = switch_core_session_get_channel(listener->session);
|
|
|
|
}
|
|
|
|
|
2007-07-24 21:26:04 +00:00
|
|
|
while (listener->sock && !prefs.done) {
|
2006-07-25 14:14:07 +00:00
|
|
|
uint8_t do_sleep = 1;
|
|
|
|
mlen = 1;
|
|
|
|
|
2011-10-20 15:19:39 +00:00
|
|
|
if (bytes == buf_len - 1) {
|
|
|
|
char *tmp;
|
|
|
|
int pos;
|
|
|
|
|
|
|
|
pos = (ptr - mbuf);
|
|
|
|
buf_len += block_len;
|
|
|
|
tmp = realloc(mbuf, buf_len);
|
|
|
|
switch_assert(tmp);
|
|
|
|
mbuf = tmp;
|
|
|
|
memset(mbuf + bytes, 0, buf_len - bytes);
|
|
|
|
ptr = (mbuf + pos);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-02-21 23:19:58 +00:00
|
|
|
status = switch_socket_recv(listener->sock, ptr, &mlen);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-02-20 01:10:59 +00:00
|
|
|
if (prefs.done || (!SWITCH_STATUS_IS_BREAK(status) && status != SWITCH_STATUS_SUCCESS)) {
|
2011-10-20 15:19:39 +00:00
|
|
|
switch_goto_status(SWITCH_STATUS_FALSE, end);
|
2006-07-25 14:14:07 +00:00
|
|
|
}
|
|
|
|
|
2006-08-11 18:20:04 +00:00
|
|
|
if (mlen) {
|
2006-09-25 20:04:40 +00:00
|
|
|
bytes += mlen;
|
2006-08-11 18:20:04 +00:00
|
|
|
do_sleep = 0;
|
2006-07-25 14:14:07 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
if (*mbuf == '\r' || *mbuf == '\n') { /* bah */
|
2006-07-25 14:14:07 +00:00
|
|
|
ptr = mbuf;
|
2006-08-11 18:59:25 +00:00
|
|
|
mbuf[0] = '\0';
|
2006-09-25 20:04:40 +00:00
|
|
|
bytes = 0;
|
2006-07-25 14:14:07 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*ptr == '\n') {
|
|
|
|
crcount++;
|
|
|
|
} else if (*ptr != '\r') {
|
|
|
|
crcount = 0;
|
|
|
|
}
|
|
|
|
ptr++;
|
2006-09-25 20:04:40 +00:00
|
|
|
|
|
|
|
if (bytes >= max_len) {
|
|
|
|
crcount = 2;
|
|
|
|
}
|
|
|
|
|
2006-07-25 14:14:07 +00:00
|
|
|
if (crcount == 2) {
|
|
|
|
char *next;
|
|
|
|
char *cur = mbuf;
|
2006-09-25 20:04:40 +00:00
|
|
|
bytes = 0;
|
2007-03-29 22:31:56 +00:00
|
|
|
while (cur) {
|
2006-07-25 14:14:07 +00:00
|
|
|
if ((next = strchr(cur, '\r')) || (next = strchr(cur, '\n'))) {
|
|
|
|
while (*next == '\r' || *next == '\n') {
|
|
|
|
next++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
count++;
|
|
|
|
if (count == 1) {
|
2010-01-04 17:46:55 +00:00
|
|
|
switch_event_create(event, SWITCH_EVENT_SOCKET_DATA);
|
2009-04-21 01:02:45 +00:00
|
|
|
switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, "Command", mbuf);
|
2006-09-07 03:58:01 +00:00
|
|
|
} else if (cur) {
|
2006-07-25 14:14:07 +00:00
|
|
|
char *var, *val;
|
2006-09-07 03:58:01 +00:00
|
|
|
var = cur;
|
|
|
|
strip_cr(var);
|
2009-10-23 16:03:42 +00:00
|
|
|
if (!zstr(var)) {
|
2006-09-07 03:58:01 +00:00
|
|
|
if ((val = strchr(var, ':'))) {
|
|
|
|
*val++ = '\0';
|
2007-03-29 22:31:56 +00:00
|
|
|
while (*val == ' ') {
|
2006-09-07 03:58:01 +00:00
|
|
|
val++;
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
}
|
2006-09-07 03:58:01 +00:00
|
|
|
if (var && val) {
|
2008-08-16 02:19:43 +00:00
|
|
|
switch_event_add_header_string(*event, SWITCH_STACK_BOTTOM, var, val);
|
2008-07-22 22:23:50 +00:00
|
|
|
if (!strcasecmp(var, "content-length")) {
|
|
|
|
clen = atoi(val);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-07-22 22:23:50 +00:00
|
|
|
if (clen > 0) {
|
2008-07-23 13:45:35 +00:00
|
|
|
char *body;
|
2008-07-24 08:11:34 +00:00
|
|
|
char *p;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-07-23 13:45:35 +00:00
|
|
|
switch_zmalloc(body, clen + 1);
|
2008-07-22 22:23:50 +00:00
|
|
|
|
2008-07-24 08:11:34 +00:00
|
|
|
p = body;
|
2010-02-06 03:38:24 +00:00
|
|
|
while (clen > 0) {
|
2008-07-22 22:23:50 +00:00
|
|
|
mlen = clen;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-07-24 08:11:34 +00:00
|
|
|
status = switch_socket_recv(listener->sock, p, &mlen);
|
2008-07-22 22:23:50 +00:00
|
|
|
|
2009-02-20 01:10:59 +00:00
|
|
|
if (prefs.done || (!SWITCH_STATUS_IS_BREAK(status) && status != SWITCH_STATUS_SUCCESS)) {
|
2010-08-18 14:20:59 +00:00
|
|
|
free(body);
|
2011-10-20 15:19:39 +00:00
|
|
|
switch_goto_status(SWITCH_STATUS_FALSE, end);
|
2008-07-22 22:23:50 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-01-16 15:32:10 +00:00
|
|
|
/*
|
2010-02-06 03:38:24 +00:00
|
|
|
if (channel && !switch_channel_ready(channel)) {
|
|
|
|
status = SWITCH_STATUS_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*/
|
2008-07-22 22:23:50 +00:00
|
|
|
|
|
|
|
clen -= (int) mlen;
|
2008-07-24 08:11:34 +00:00
|
|
|
p += mlen;
|
2008-07-22 22:23:50 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-07-22 22:23:50 +00:00
|
|
|
switch_event_add_body(*event, "%s", body);
|
|
|
|
free(body);
|
|
|
|
}
|
|
|
|
}
|
2006-07-25 14:14:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-07-25 14:14:07 +00:00
|
|
|
cur = next;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-07-25 14:14:07 +00:00
|
|
|
if (timeout) {
|
2009-01-25 21:23:07 +00:00
|
|
|
elapsed = (uint32_t) (switch_epoch_time_now(NULL) - start);
|
2006-07-25 14:14:07 +00:00
|
|
|
if (elapsed >= timeout) {
|
|
|
|
switch_clear_flag_locked(listener, LFLAG_RUNNING);
|
2011-10-20 15:19:39 +00:00
|
|
|
switch_goto_status(SWITCH_STATUS_FALSE, end);
|
2006-07-25 14:14:07 +00:00
|
|
|
}
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-07-25 14:14:07 +00:00
|
|
|
if (!*mbuf) {
|
|
|
|
if (switch_test_flag(listener, LFLAG_LOG)) {
|
|
|
|
if (switch_queue_trypop(listener->log_queue, &pop) == SWITCH_STATUS_SUCCESS) {
|
2008-12-20 14:56:08 +00:00
|
|
|
switch_log_node_t *dnode = (switch_log_node_t *) pop;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-12-20 14:56:08 +00:00
|
|
|
if (dnode->data) {
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_snprintf(buf, sizeof(buf),
|
2008-12-20 14:56:08 +00:00
|
|
|
"Content-Type: log/data\n"
|
|
|
|
"Content-Length: %" SWITCH_SSIZE_T_FMT "\n"
|
|
|
|
"Log-Level: %d\n"
|
|
|
|
"Text-Channel: %d\n"
|
|
|
|
"Log-File: %s\n"
|
|
|
|
"Log-Func: %s\n"
|
2009-07-18 19:08:07 +00:00
|
|
|
"Log-Line: %d\n"
|
2009-08-13 20:35:02 +00:00
|
|
|
"User-Data: %s\n"
|
2008-12-20 14:56:08 +00:00
|
|
|
"\n",
|
|
|
|
strlen(dnode->data),
|
2010-02-06 03:38:24 +00:00
|
|
|
dnode->level, dnode->channel, dnode->file, dnode->func, dnode->line, switch_str_nil(dnode->userdata)
|
|
|
|
);
|
2006-10-13 14:32:38 +00:00
|
|
|
len = strlen(buf);
|
2006-07-25 14:14:07 +00:00
|
|
|
switch_socket_send(listener->sock, buf, &len);
|
2008-12-20 14:56:08 +00:00
|
|
|
len = strlen(dnode->data);
|
|
|
|
switch_socket_send(listener->sock, dnode->data, &len);
|
2006-07-25 14:14:07 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-08-22 19:26:58 +00:00
|
|
|
switch_log_node_free(&dnode);
|
2006-07-25 14:14:07 +00:00
|
|
|
do_sleep = 0;
|
|
|
|
}
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-02-21 23:19:58 +00:00
|
|
|
|
|
|
|
if (listener->session) {
|
2009-05-11 22:28:02 +00:00
|
|
|
switch_channel_t *chan = switch_core_session_get_channel(listener->session);
|
|
|
|
if (switch_channel_get_state(chan) < CS_HANGUP && switch_channel_test_flag(chan, CF_DIVERT_EVENTS)) {
|
2009-02-21 23:19:58 +00:00
|
|
|
switch_event_t *e = NULL;
|
|
|
|
while (switch_core_session_dequeue_event(listener->session, &e, SWITCH_TRUE) == SWITCH_STATUS_SUCCESS) {
|
2011-01-25 20:13:15 +00:00
|
|
|
if (switch_queue_trypush(listener->event_queue, e) != SWITCH_STATUS_SUCCESS) {
|
2009-02-21 23:19:58 +00:00
|
|
|
switch_core_session_queue_event(listener->session, &e);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-07-25 14:14:07 +00:00
|
|
|
if (switch_test_flag(listener, LFLAG_EVENTS)) {
|
2009-01-15 22:11:27 +00:00
|
|
|
while (switch_queue_trypop(listener->event_queue, &pop) == SWITCH_STATUS_SUCCESS) {
|
2006-07-25 14:14:07 +00:00
|
|
|
char hbuf[512];
|
2007-12-16 03:01:50 +00:00
|
|
|
switch_event_t *pevent = (switch_event_t *) pop;
|
2006-11-11 19:32:45 +00:00
|
|
|
char *etype;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-07-25 14:14:07 +00:00
|
|
|
do_sleep = 0;
|
|
|
|
if (listener->format == EVENT_FORMAT_PLAIN) {
|
|
|
|
etype = "plain";
|
2007-12-16 03:01:50 +00:00
|
|
|
switch_event_serialize(pevent, &listener->ebuf, SWITCH_TRUE);
|
2010-06-17 16:43:09 +00:00
|
|
|
} else if (listener->format == EVENT_FORMAT_JSON) {
|
|
|
|
etype = "json";
|
|
|
|
switch_event_serialize_json(pevent, &listener->ebuf);
|
2006-07-25 14:14:07 +00:00
|
|
|
} else {
|
|
|
|
switch_xml_t xml;
|
|
|
|
etype = "xml";
|
|
|
|
|
2010-08-14 22:39:49 +00:00
|
|
|
if ((xml = switch_event_xmlize(pevent, SWITCH_VA_NONE))) {
|
2007-11-30 23:45:27 +00:00
|
|
|
listener->ebuf = switch_xml_toxml(xml, SWITCH_FALSE);
|
2006-07-25 14:14:07 +00:00
|
|
|
switch_xml_free(xml);
|
|
|
|
} else {
|
2009-08-13 21:52:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(listener->session), SWITCH_LOG_ERROR, "XML ERROR!\n");
|
2008-01-20 22:39:08 +00:00
|
|
|
goto endloop;
|
2006-07-25 14:14:07 +00:00
|
|
|
}
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2009-01-15 22:11:27 +00:00
|
|
|
switch_assert(listener->ebuf);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-11-11 19:32:45 +00:00
|
|
|
len = strlen(listener->ebuf);
|
2006-07-25 14:14:07 +00:00
|
|
|
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(hbuf, sizeof(hbuf), "Content-Length: %" SWITCH_SSIZE_T_FMT "\n" "Content-Type: text/event-%s\n" "\n", len, etype);
|
2006-07-25 14:14:07 +00:00
|
|
|
|
2006-10-13 14:32:38 +00:00
|
|
|
len = strlen(hbuf);
|
2006-07-25 14:14:07 +00:00
|
|
|
switch_socket_send(listener->sock, hbuf, &len);
|
|
|
|
|
2006-11-11 19:32:45 +00:00
|
|
|
len = strlen(listener->ebuf);
|
|
|
|
switch_socket_send(listener->sock, listener->ebuf, &len);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-11-11 19:32:45 +00:00
|
|
|
switch_safe_free(listener->ebuf);
|
2008-05-27 04:54:52 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
endloop:
|
2008-10-17 18:44:26 +00:00
|
|
|
|
2008-01-20 22:39:08 +00:00
|
|
|
switch_event_destroy(&pevent);
|
2006-07-25 14:14:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-01-15 22:11:27 +00:00
|
|
|
|
2012-04-13 13:43:46 +00:00
|
|
|
if (switch_test_flag(listener, LFLAG_HANDLE_DISCO) &&
|
|
|
|
listener->linger_timeout != (time_t) -1 && switch_epoch_time_now(NULL) > listener->linger_timeout) {
|
2011-12-08 18:25:52 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(listener->session), SWITCH_LOG_DEBUG, "linger timeout, closing socket\n");
|
|
|
|
status = SWITCH_STATUS_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2009-02-25 03:41:18 +00:00
|
|
|
if (channel && switch_channel_down(channel) && !switch_test_flag(listener, LFLAG_HANDLE_DISCO)) {
|
2009-01-16 15:32:10 +00:00
|
|
|
switch_set_flag_locked(listener, LFLAG_HANDLE_DISCO);
|
|
|
|
if (switch_test_flag(listener, LFLAG_LINGER)) {
|
|
|
|
char message[128] = "";
|
|
|
|
char disco_buf[512] = "";
|
|
|
|
|
2012-04-13 13:43:46 +00:00
|
|
|
if (listener->linger_timeout != (time_t) -1) {
|
|
|
|
listener->linger_timeout += switch_epoch_time_now(NULL);
|
|
|
|
switch_snprintf(message, sizeof(message),
|
|
|
|
"Channel %s has disconnected, lingering %d seconds by request from remote.\n",
|
|
|
|
switch_channel_get_name(channel), listener->linger_timeout);
|
|
|
|
} else {
|
|
|
|
switch_snprintf(message, sizeof(message),
|
|
|
|
"Channel %s has disconnected, lingering by request from remote.\n",
|
|
|
|
switch_channel_get_name(channel));
|
|
|
|
}
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s", message);
|
|
|
|
|
2009-01-16 15:32:10 +00:00
|
|
|
mlen = strlen(message);
|
|
|
|
|
|
|
|
switch_snprintf(disco_buf, sizeof(disco_buf), "Content-Type: text/disconnect-notice\n"
|
|
|
|
"Controlled-Session-UUID: %s\n"
|
2010-02-06 03:38:24 +00:00
|
|
|
"Content-Disposition: linger\n" "Content-Length: %d\n\n", switch_core_session_get_uuid(listener->session), (int) mlen);
|
2009-01-16 15:32:10 +00:00
|
|
|
|
|
|
|
len = strlen(disco_buf);
|
|
|
|
switch_socket_send(listener->sock, disco_buf, &len);
|
|
|
|
len = mlen;
|
|
|
|
switch_socket_send(listener->sock, message, &len);
|
|
|
|
} else {
|
|
|
|
status = SWITCH_STATUS_FALSE;
|
|
|
|
break;
|
|
|
|
}
|
2009-01-15 22:11:27 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-07-25 14:14:07 +00:00
|
|
|
if (do_sleep) {
|
2008-11-14 23:31:21 +00:00
|
|
|
switch_cond_next();
|
2006-07-25 14:14:07 +00:00
|
|
|
}
|
|
|
|
}
|
2006-11-11 19:32:45 +00:00
|
|
|
|
2011-10-20 15:19:39 +00:00
|
|
|
end:
|
|
|
|
|
2011-11-17 17:47:14 +00:00
|
|
|
switch_safe_free(mbuf);
|
2006-07-25 14:14:07 +00:00
|
|
|
return status;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2006-09-07 03:58:01 +00:00
|
|
|
struct api_command_struct {
|
|
|
|
char *api_cmd;
|
|
|
|
char *arg;
|
|
|
|
listener_t *listener;
|
|
|
|
char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
|
2009-02-07 16:44:46 +00:00
|
|
|
int bg;
|
|
|
|
int ack;
|
2010-01-20 17:45:53 +00:00
|
|
|
int console_execute;
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_memory_pool_t *pool;
|
2006-09-07 03:58:01 +00:00
|
|
|
};
|
|
|
|
|
2008-05-27 04:54:52 +00:00
|
|
|
static void *SWITCH_THREAD_FUNC api_exec(switch_thread_t *thread, void *obj)
|
2006-09-07 03:58:01 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
struct api_command_struct *acs = (struct api_command_struct *) obj;
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_stream_handle_t stream = { 0 };
|
|
|
|
char *reply, *freply = NULL;
|
|
|
|
switch_status_t status;
|
2009-02-20 01:10:59 +00:00
|
|
|
|
|
|
|
switch_mutex_lock(globals.listener_mutex);
|
|
|
|
prefs.threads++;
|
|
|
|
switch_mutex_unlock(globals.listener_mutex);
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-05-27 20:04:04 +00:00
|
|
|
if (!acs) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Internal error.\n");
|
2009-02-20 01:10:59 +00:00
|
|
|
goto cleanup;
|
2008-05-27 20:04:04 +00:00
|
|
|
}
|
|
|
|
|
2009-02-07 16:44:46 +00:00
|
|
|
if (!acs->listener || !switch_test_flag(acs->listener, LFLAG_RUNNING) ||
|
|
|
|
!acs->listener->rwlock || switch_thread_rwlock_tryrdlock(acs->listener->rwlock) != SWITCH_STATUS_SUCCESS) {
|
2006-09-07 03:58:01 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error! cannot get read lock.\n");
|
2009-02-07 16:44:46 +00:00
|
|
|
acs->ack = -1;
|
2006-09-07 03:58:01 +00:00
|
|
|
goto done;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-02-07 16:44:46 +00:00
|
|
|
acs->ack = 1;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-09-07 03:58:01 +00:00
|
|
|
SWITCH_STANDARD_STREAM(stream);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-20 17:45:53 +00:00
|
|
|
if (acs->console_execute) {
|
|
|
|
if ((status = switch_console_execute(acs->api_cmd, 0, &stream)) != SWITCH_STATUS_SUCCESS) {
|
2010-11-08 16:14:46 +00:00
|
|
|
stream.write_function(&stream, "-ERR %s Command not found!\n", acs->api_cmd);
|
2010-01-20 17:45:53 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
status = switch_api_execute(acs->api_cmd, acs->arg, NULL, &stream);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (status == SWITCH_STATUS_SUCCESS) {
|
2007-03-29 22:31:56 +00:00
|
|
|
reply = stream.data;
|
|
|
|
} else {
|
2010-11-08 16:14:46 +00:00
|
|
|
freply = switch_mprintf("-ERR %s Command not found!\n", acs->api_cmd);
|
2007-03-29 22:31:56 +00:00
|
|
|
reply = freply;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!reply) {
|
|
|
|
reply = "Command returned no output!";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (acs->bg) {
|
|
|
|
switch_event_t *event;
|
|
|
|
|
|
|
|
if (switch_event_create(&event, SWITCH_EVENT_BACKGROUND_JOB) == SWITCH_STATUS_SUCCESS) {
|
2008-08-16 02:19:43 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-UUID", acs->uuid_str);
|
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-Command", acs->api_cmd);
|
2008-01-18 15:43:57 +00:00
|
|
|
if (acs->arg) {
|
2008-08-16 02:19:43 +00:00
|
|
|
switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-Command-Arg", acs->arg);
|
2008-01-18 15:43:57 +00:00
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_event_add_body(event, "%s", reply);
|
|
|
|
switch_event_fire(&event);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch_size_t rlen, blen;
|
|
|
|
char buf[1024] = "";
|
2008-03-06 18:12:38 +00:00
|
|
|
|
|
|
|
if (!(rlen = strlen(reply))) {
|
|
|
|
reply = "-ERR no reply\n";
|
|
|
|
rlen = strlen(reply);
|
|
|
|
}
|
|
|
|
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(buf, sizeof(buf), "Content-Type: api/response\nContent-Length: %" SWITCH_SSIZE_T_FMT "\n\n", rlen);
|
2007-03-29 22:31:56 +00:00
|
|
|
blen = strlen(buf);
|
|
|
|
switch_socket_send(acs->listener->sock, buf, &blen);
|
|
|
|
switch_socket_send(acs->listener->sock, reply, &rlen);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_safe_free(stream.data);
|
|
|
|
switch_safe_free(freply);
|
2006-09-07 03:58:01 +00:00
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
if (acs->listener->rwlock) {
|
|
|
|
switch_thread_rwlock_unlock(acs->listener->rwlock);
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2008-05-27 04:54:52 +00:00
|
|
|
done:
|
2009-02-07 16:44:46 +00:00
|
|
|
|
2008-05-27 20:04:04 +00:00
|
|
|
if (acs->bg) {
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_memory_pool_t *pool = acs->pool;
|
2009-02-07 16:44:46 +00:00
|
|
|
if (acs->ack == -1) {
|
|
|
|
int sanity = 2000;
|
2010-02-06 03:38:24 +00:00
|
|
|
while (acs->ack == -1) {
|
2009-02-07 16:44:46 +00:00
|
|
|
switch_cond_next();
|
2010-02-06 03:38:24 +00:00
|
|
|
if (--sanity <= 0)
|
|
|
|
break;
|
2009-02-07 16:44:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
acs = NULL;
|
|
|
|
switch_core_destroy_memory_pool(&pool);
|
|
|
|
pool = NULL;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-09-07 03:58:01 +00:00
|
|
|
}
|
2009-02-07 16:44:46 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
cleanup:
|
2009-02-20 01:10:59 +00:00
|
|
|
switch_mutex_lock(globals.listener_mutex);
|
|
|
|
prefs.threads--;
|
|
|
|
switch_mutex_unlock(globals.listener_mutex);
|
|
|
|
|
2006-09-07 03:58:01 +00:00
|
|
|
return NULL;
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-09-07 03:58:01 +00:00
|
|
|
}
|
2010-01-05 19:47:49 +00:00
|
|
|
|
|
|
|
static switch_bool_t auth_api_command(listener_t *listener, const char *api_cmd, const char *arg)
|
|
|
|
{
|
|
|
|
const char *check_cmd = api_cmd;
|
2010-02-25 19:02:42 +00:00
|
|
|
char *sneaky_commands[] = { "bgapi", "sched_api", "eval", "expand", "xml_wrap", NULL };
|
2010-01-05 19:47:49 +00:00
|
|
|
int x = 0;
|
|
|
|
char *dup_arg = NULL;
|
|
|
|
char *next = NULL;
|
|
|
|
switch_bool_t ok = SWITCH_TRUE;
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
top:
|
2010-12-29 20:44:05 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
if (!switch_core_hash_find(listener->allowed_api_hash, check_cmd)) {
|
|
|
|
ok = SWITCH_FALSE;
|
|
|
|
goto end;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
|
|
|
while (check_cmd) {
|
2010-01-05 19:47:49 +00:00
|
|
|
for (x = 0; sneaky_commands[x]; x++) {
|
|
|
|
if (!strcasecmp(sneaky_commands[x], check_cmd)) {
|
|
|
|
if (check_cmd == api_cmd) {
|
|
|
|
if (arg) {
|
2010-08-18 14:20:59 +00:00
|
|
|
switch_safe_free(dup_arg);
|
2010-01-05 19:47:49 +00:00
|
|
|
dup_arg = strdup(arg);
|
|
|
|
check_cmd = dup_arg;
|
|
|
|
if ((next = strchr(check_cmd, ' '))) {
|
|
|
|
*next++ = '\0';
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (next) {
|
|
|
|
check_cmd = next;
|
|
|
|
} else {
|
|
|
|
check_cmd = dup_arg;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
if ((next = strchr(check_cmd, ' '))) {
|
|
|
|
*next++ = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
goto top;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
end:
|
2010-01-05 19:47:49 +00:00
|
|
|
|
|
|
|
switch_safe_free(dup_arg);
|
|
|
|
return ok;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
}
|
|
|
|
|
2008-08-21 16:09:22 +00:00
|
|
|
static switch_status_t parse_command(listener_t *listener, switch_event_t **event, char *reply, uint32_t reply_len)
|
2006-07-22 21:49:52 +00:00
|
|
|
{
|
2006-07-25 14:14:07 +00:00
|
|
|
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
2008-08-21 16:09:22 +00:00
|
|
|
char *cmd = switch_event_get_header(*event, "command");
|
2009-02-27 20:21:48 +00:00
|
|
|
char unload_cheat[] = "api bgapi unload mod_event_socket";
|
|
|
|
char reload_cheat[] = "api bgapi reload mod_event_socket";
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
*reply = '\0';
|
|
|
|
|
2009-02-27 16:38:19 +00:00
|
|
|
if (switch_stristr("unload", cmd) && switch_stristr("mod_event_socket", cmd)) {
|
2009-02-27 20:21:48 +00:00
|
|
|
cmd = unload_cheat;
|
|
|
|
} else if (switch_stristr("reload", cmd) && switch_stristr("mod_event_socket", cmd)) {
|
|
|
|
cmd = reload_cheat;
|
2010-02-06 03:38:24 +00:00
|
|
|
}
|
2009-02-27 16:35:42 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
if (!strncasecmp(cmd, "exit", 4) || !strncasecmp(cmd, "...", 3)) {
|
2006-07-22 21:49:52 +00:00
|
|
|
switch_clear_flag_locked(listener, LFLAG_RUNNING);
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(reply, reply_len, "+OK bye");
|
2006-07-22 21:49:52 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!switch_test_flag(listener, LFLAG_AUTHED)) {
|
|
|
|
if (!strncasecmp(cmd, "auth ", 5)) {
|
2006-07-22 22:16:06 +00:00
|
|
|
char *pass;
|
2006-07-22 21:49:52 +00:00
|
|
|
strip_cr(cmd);
|
|
|
|
|
2006-07-22 22:16:06 +00:00
|
|
|
pass = cmd + 5;
|
2006-07-22 21:49:52 +00:00
|
|
|
|
|
|
|
if (!strcmp(prefs.password, pass)) {
|
|
|
|
switch_set_flag_locked(listener, LFLAG_AUTHED);
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(reply, reply_len, "+OK accepted");
|
2006-07-22 21:49:52 +00:00
|
|
|
} else {
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(reply, reply_len, "-ERR invalid");
|
2006-07-22 21:49:52 +00:00
|
|
|
switch_clear_flag_locked(listener, LFLAG_RUNNING);
|
|
|
|
}
|
|
|
|
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
if (!strncasecmp(cmd, "userauth ", 9)) {
|
|
|
|
const char *passwd;
|
|
|
|
const char *allowed_api;
|
|
|
|
const char *allowed_events;
|
|
|
|
switch_event_t *params;
|
2011-12-28 05:35:05 +00:00
|
|
|
char *user = NULL, *domain_name = NULL, *pass = NULL;
|
2010-01-05 19:47:49 +00:00
|
|
|
switch_xml_t x_domain = NULL, x_domain_root, x_user = NULL, x_params, x_param, x_group = NULL;
|
|
|
|
int authed = 0;
|
|
|
|
char *edup = NULL;
|
|
|
|
char event_reply[512] = "Allowed-Events: all\n";
|
|
|
|
char api_reply[512] = "Allowed-API: all\n";
|
|
|
|
char log_reply[512] = "";
|
|
|
|
int allowed_log = 1;
|
2011-01-12 21:32:05 +00:00
|
|
|
char *tmp;
|
2010-01-05 19:47:49 +00:00
|
|
|
|
|
|
|
switch_clear_flag(listener, LFLAG_ALLOW_LOG);
|
|
|
|
|
|
|
|
strip_cr(cmd);
|
|
|
|
|
|
|
|
user = cmd + 9;
|
|
|
|
|
2011-12-28 05:35:05 +00:00
|
|
|
if (user && (domain_name = strchr(user, '@'))) {
|
2010-12-29 20:44:05 +00:00
|
|
|
*domain_name++ = '\0';
|
|
|
|
}
|
|
|
|
|
2011-12-28 05:35:05 +00:00
|
|
|
if (domain_name && (pass = strchr(domain_name, ':'))) {
|
2010-12-29 19:59:12 +00:00
|
|
|
*pass++ = '\0';
|
|
|
|
}
|
2010-12-29 20:13:06 +00:00
|
|
|
|
2011-01-12 21:32:05 +00:00
|
|
|
if ((tmp = strchr(user, ':'))) {
|
|
|
|
*tmp++ = '\0';
|
|
|
|
pass = tmp;
|
2010-12-29 20:13:06 +00:00
|
|
|
}
|
2010-12-29 19:59:12 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
if (zstr(user) || zstr(domain_name)) {
|
|
|
|
switch_snprintf(reply, reply_len, "-ERR invalid");
|
|
|
|
switch_clear_flag_locked(listener, LFLAG_RUNNING);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
passwd = NULL;
|
|
|
|
allowed_events = NULL;
|
|
|
|
allowed_api = NULL;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
params = NULL;
|
|
|
|
x_domain_root = NULL;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
|
|
|
|
switch_event_create(¶ms, SWITCH_EVENT_REQUEST_PARAMS);
|
|
|
|
switch_assert(params);
|
|
|
|
switch_event_add_header_string(params, SWITCH_STACK_BOTTOM, "action", "event_socket_auth");
|
|
|
|
|
|
|
|
if (switch_xml_locate_user("id", user, domain_name, NULL, &x_domain_root, &x_domain, &x_user, &x_group, params) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_xml_t list[3];
|
|
|
|
int x = 0;
|
|
|
|
|
|
|
|
list[0] = x_domain;
|
|
|
|
list[1] = x_group;
|
|
|
|
list[2] = x_user;
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
for (x = 0; x < 3; x++) {
|
2010-01-05 19:47:49 +00:00
|
|
|
if ((x_params = switch_xml_child(list[x], "params"))) {
|
|
|
|
for (x_param = switch_xml_child(x_params, "param"); x_param; x_param = x_param->next) {
|
|
|
|
const char *var = switch_xml_attr_soft(x_param, "name");
|
|
|
|
const char *val = switch_xml_attr_soft(x_param, "value");
|
|
|
|
|
|
|
|
if (!strcasecmp(var, "esl-password")) {
|
|
|
|
passwd = val;
|
|
|
|
} else if (!strcasecmp(var, "esl-allowed-log")) {
|
|
|
|
allowed_log = switch_true(val);
|
|
|
|
} else if (!strcasecmp(var, "esl-allowed-events")) {
|
|
|
|
allowed_events = val;
|
|
|
|
} else if (!strcasecmp(var, "esl-allowed-api")) {
|
|
|
|
allowed_api = val;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
authed = 0;
|
|
|
|
goto bot;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
if (!zstr(passwd) && !zstr(pass) && !strcmp(passwd, pass)) {
|
|
|
|
authed = 1;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
if (allowed_events) {
|
|
|
|
char delim = ',';
|
|
|
|
char *cur, *next;
|
|
|
|
int count = 0, custom = 0, key_count = 0;
|
|
|
|
|
|
|
|
switch_set_flag(listener, LFLAG_AUTH_EVENTS);
|
|
|
|
|
|
|
|
switch_snprintf(event_reply, sizeof(event_reply), "Allowed-Events: %s\n", allowed_events);
|
|
|
|
|
|
|
|
switch_core_hash_init(&listener->allowed_event_hash, listener->pool);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
edup = strdup(allowed_events);
|
|
|
|
cur = edup;
|
|
|
|
|
|
|
|
if (strchr(edup, ' ')) {
|
|
|
|
delim = ' ';
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
for (cur = edup; cur; count++) {
|
|
|
|
switch_event_types_t type;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
if ((next = strchr(cur, delim))) {
|
|
|
|
*next++ = '\0';
|
|
|
|
}
|
2010-01-06 16:59:53 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
if (custom) {
|
|
|
|
switch_core_hash_insert(listener->allowed_event_hash, cur, MARKER);
|
|
|
|
} else if (switch_name_event(cur, &type) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
key_count++;
|
|
|
|
if (type == SWITCH_EVENT_ALL) {
|
|
|
|
uint32_t x = 0;
|
|
|
|
switch_set_flag(listener, LFLAG_ALL_EVENTS_AUTHED);
|
|
|
|
for (x = 0; x < SWITCH_EVENT_ALL; x++) {
|
|
|
|
listener->allowed_event_list[x] = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (type <= SWITCH_EVENT_ALL) {
|
|
|
|
listener->allowed_event_list[type] = 1;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
if (type == SWITCH_EVENT_CUSTOM) {
|
|
|
|
custom++;
|
|
|
|
}
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
cur = next;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
switch_safe_free(edup);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_snprintf(log_reply, sizeof(log_reply), "Allowed-LOG: %s\n", allowed_log ? "true" : "false");
|
|
|
|
|
|
|
|
if (allowed_log) {
|
|
|
|
switch_set_flag(listener, LFLAG_ALLOW_LOG);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (allowed_api) {
|
|
|
|
char delim = ',';
|
|
|
|
char *cur, *next;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
switch_snprintf(api_reply, sizeof(api_reply), "Allowed-API: %s\n", allowed_api);
|
|
|
|
|
|
|
|
switch_core_hash_init(&listener->allowed_api_hash, listener->pool);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
edup = strdup(allowed_api);
|
|
|
|
cur = edup;
|
|
|
|
|
|
|
|
if (strchr(edup, ' ')) {
|
|
|
|
delim = ' ';
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
for (cur = edup; cur; count++) {
|
|
|
|
if ((next = strchr(cur, delim))) {
|
|
|
|
*next++ = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_core_hash_insert(listener->allowed_api_hash, cur, MARKER);
|
|
|
|
|
|
|
|
cur = next;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
switch_safe_free(edup);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
|
|
|
|
bot:
|
2010-01-05 19:47:49 +00:00
|
|
|
|
|
|
|
if (params) {
|
|
|
|
switch_event_destroy(¶ms);
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
if (authed) {
|
|
|
|
switch_set_flag_locked(listener, LFLAG_AUTHED);
|
|
|
|
switch_snprintf(reply, reply_len, "~Reply-Text: +OK accepted\n%s%s%s\n", event_reply, api_reply, log_reply);
|
|
|
|
} else {
|
|
|
|
switch_snprintf(reply, reply_len, "-ERR invalid");
|
|
|
|
switch_clear_flag_locked(listener, LFLAG_RUNNING);
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
if (x_domain_root) {
|
|
|
|
switch_xml_free(x_domain_root);
|
2010-02-06 03:38:24 +00:00
|
|
|
}
|
2010-01-05 19:47:49 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
goto done;
|
|
|
|
}
|
2006-09-22 13:52:36 +00:00
|
|
|
|
2008-10-30 00:39:55 +00:00
|
|
|
if (!strncasecmp(cmd, "filter ", 7)) {
|
|
|
|
char *header_name = cmd + 7;
|
2010-01-28 01:00:04 +00:00
|
|
|
char *header_val = NULL;
|
2008-10-30 00:39:55 +00:00
|
|
|
|
|
|
|
strip_cr(header_name);
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
while (header_name && *header_name && *header_name == ' ')
|
|
|
|
header_name++;
|
|
|
|
|
2010-01-28 01:00:04 +00:00
|
|
|
if ((header_val = strchr(header_name, ' '))) {
|
|
|
|
*header_val++ = '\0';
|
2008-10-30 00:39:55 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
|
|
|
switch_mutex_lock(listener->filter_mutex);
|
2008-10-30 00:39:55 +00:00
|
|
|
if (!listener->filters) {
|
2010-11-22 23:06:59 +00:00
|
|
|
switch_event_create_plain(&listener->filters, SWITCH_EVENT_CLONE);
|
2011-02-14 16:50:14 +00:00
|
|
|
switch_clear_flag(listener->filters, EF_UNIQ_HEADERS);
|
2008-10-30 00:39:55 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2010-02-04 15:50:04 +00:00
|
|
|
if (!strcasecmp(header_name, "delete") && header_val) {
|
2010-01-28 01:00:04 +00:00
|
|
|
header_name = header_val;
|
|
|
|
if ((header_val = strchr(header_name, ' '))) {
|
|
|
|
*header_val++ = '\0';
|
|
|
|
}
|
|
|
|
if (!strcasecmp(header_name, "all")) {
|
2008-10-30 00:39:55 +00:00
|
|
|
switch_event_destroy(&listener->filters);
|
2010-11-22 23:06:59 +00:00
|
|
|
switch_event_create_plain(&listener->filters, SWITCH_EVENT_CLONE);
|
2008-10-30 00:39:55 +00:00
|
|
|
} else {
|
2010-01-28 01:00:04 +00:00
|
|
|
switch_event_del_header_val(listener->filters, header_name, header_val);
|
|
|
|
}
|
|
|
|
switch_snprintf(reply, reply_len, "+OK filter deleted. [%s][%s]", header_name, switch_str_nil(header_val));
|
|
|
|
} else if (header_val) {
|
|
|
|
if (!strcasecmp(header_name, "add")) {
|
|
|
|
header_name = header_val;
|
|
|
|
if ((header_val = strchr(header_name, ' '))) {
|
|
|
|
*header_val++ = '\0';
|
|
|
|
}
|
2008-10-30 00:39:55 +00:00
|
|
|
}
|
|
|
|
switch_event_add_header_string(listener->filters, SWITCH_STACK_BOTTOM, header_name, header_val);
|
|
|
|
switch_snprintf(reply, reply_len, "+OK filter added. [%s]=[%s]", header_name, header_val);
|
2010-01-28 01:00:04 +00:00
|
|
|
} else {
|
|
|
|
switch_snprintf(reply, reply_len, "-ERR invalid syntax");
|
2008-10-30 00:39:55 +00:00
|
|
|
}
|
|
|
|
switch_mutex_unlock(listener->filter_mutex);
|
|
|
|
|
|
|
|
goto done;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-04-30 22:45:46 +00:00
|
|
|
if (listener->session && !strncasecmp(cmd, "resume", 6)) {
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_set_flag_locked(listener, LFLAG_RESUME);
|
2009-04-30 22:45:46 +00:00
|
|
|
switch_channel_set_variable(switch_core_session_get_channel(listener->session), "socket_resume", "true");
|
|
|
|
switch_snprintf(reply, reply_len, "+OK");
|
|
|
|
goto done;
|
|
|
|
}
|
2006-09-22 13:52:36 +00:00
|
|
|
|
2008-10-22 16:32:55 +00:00
|
|
|
if (listener->session || !strncasecmp(cmd, "myevents ", 9)) {
|
|
|
|
switch_channel_t *channel = NULL;
|
|
|
|
|
|
|
|
if (listener->session) {
|
|
|
|
channel = switch_core_session_get_channel(listener->session);
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
|
|
|
if (!strncasecmp(cmd, "connect", 7)) {
|
2009-03-23 19:53:57 +00:00
|
|
|
switch_event_t *call_event;
|
|
|
|
char *event_str;
|
|
|
|
switch_size_t len;
|
2009-04-30 22:45:46 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_set_flag_locked(listener, LFLAG_CONNECTED);
|
2009-03-23 19:53:57 +00:00
|
|
|
switch_event_create(&call_event, SWITCH_EVENT_CHANNEL_DATA);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-05-11 22:28:02 +00:00
|
|
|
if (channel) {
|
|
|
|
switch_caller_profile_event_set_data(switch_channel_get_caller_profile(channel), "Channel", call_event);
|
|
|
|
switch_channel_event_set_data(channel, call_event);
|
|
|
|
}
|
2009-03-23 19:53:57 +00:00
|
|
|
switch_event_add_header_string(call_event, SWITCH_STACK_BOTTOM, "Content-Type", "command/reply");
|
|
|
|
switch_event_add_header_string(call_event, SWITCH_STACK_BOTTOM, "Reply-Text", "+OK\n");
|
|
|
|
switch_event_add_header_string(call_event, SWITCH_STACK_BOTTOM, "Socket-Mode", switch_test_flag(listener, LFLAG_ASYNC) ? "async" : "static");
|
|
|
|
switch_event_add_header_string(call_event, SWITCH_STACK_BOTTOM, "Control", switch_test_flag(listener, LFLAG_FULL) ? "full" : "single-channel");
|
|
|
|
|
|
|
|
switch_event_serialize(call_event, &event_str, SWITCH_TRUE);
|
|
|
|
switch_assert(event_str);
|
|
|
|
len = strlen(event_str);
|
|
|
|
switch_socket_send(listener->sock, event_str, &len);
|
|
|
|
switch_safe_free(event_str);
|
2009-09-16 21:23:00 +00:00
|
|
|
switch_event_destroy(&call_event);
|
2009-03-23 19:53:57 +00:00
|
|
|
//switch_snprintf(reply, reply_len, "+OK");
|
|
|
|
goto done_noreply;
|
2007-03-29 22:31:56 +00:00
|
|
|
} else if (!strncasecmp(cmd, "getvar", 6)) {
|
|
|
|
char *arg;
|
2007-11-01 11:28:26 +00:00
|
|
|
const char *val = "";
|
2007-03-29 22:31:56 +00:00
|
|
|
|
|
|
|
strip_cr(cmd);
|
|
|
|
|
|
|
|
if ((arg = strchr(cmd, ' '))) {
|
|
|
|
*arg++ = '\0';
|
|
|
|
if (!(val = switch_channel_get_variable(channel, arg))) {
|
|
|
|
val = "";
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(reply, reply_len, "%s", val);
|
2007-03-29 22:31:56 +00:00
|
|
|
goto done;
|
|
|
|
} else if (!strncasecmp(cmd, "myevents", 8)) {
|
2008-10-22 16:32:55 +00:00
|
|
|
if (switch_test_flag(listener, LFLAG_MYEVENTS)) {
|
|
|
|
switch_snprintf(reply, reply_len, "-ERR aready enabled.");
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!listener->session) {
|
|
|
|
char *uuid;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-22 16:32:55 +00:00
|
|
|
if ((uuid = cmd + 9)) {
|
2011-09-09 19:31:02 +00:00
|
|
|
char *fmt;
|
2008-10-22 16:32:55 +00:00
|
|
|
strip_cr(uuid);
|
2011-09-09 19:31:02 +00:00
|
|
|
|
|
|
|
if ((fmt = strchr(uuid, ' '))) {
|
|
|
|
*fmt++ = '\0';
|
|
|
|
}
|
|
|
|
|
2008-10-22 16:32:55 +00:00
|
|
|
if (!(listener->session = switch_core_session_locate(uuid))) {
|
2011-09-09 19:31:02 +00:00
|
|
|
if (fmt) {
|
|
|
|
switch_snprintf(reply, reply_len, "-ERR invalid uuid");
|
|
|
|
goto done;
|
|
|
|
} else {
|
|
|
|
fmt = uuid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((fmt = strchr(uuid, ' '))) {
|
|
|
|
if (!strcasecmp(fmt, "xml")) {
|
|
|
|
listener->format = EVENT_FORMAT_XML;
|
|
|
|
} else if (!strcasecmp(fmt, "plain")) {
|
|
|
|
listener->format = EVENT_FORMAT_PLAIN;
|
|
|
|
} else if (!strcasecmp(fmt, "json")) {
|
|
|
|
listener->format = EVENT_FORMAT_JSON;
|
|
|
|
}
|
2008-10-22 16:32:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch_set_flag_locked(listener, LFLAG_SESSION);
|
|
|
|
switch_set_flag_locked(listener, LFLAG_ASYNC);
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-10-22 16:32:55 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2008-10-27 15:10:22 +00:00
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_ANSWER] = 1;
|
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_APPLICATION] = 1;
|
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_BRIDGE] = 1;
|
2007-03-29 22:31:56 +00:00
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_CREATE] = 1;
|
2008-10-27 15:10:22 +00:00
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_DATA] = 1;
|
2007-03-29 22:31:56 +00:00
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_DESTROY] = 1;
|
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_EXECUTE] = 1;
|
2007-06-23 05:41:07 +00:00
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_EXECUTE_COMPLETE] = 1;
|
2008-10-27 15:10:22 +00:00
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_HANGUP] = 1;
|
2009-09-29 02:23:08 +00:00
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_HANGUP_COMPLETE] = 1;
|
2008-10-27 15:10:22 +00:00
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_ORIGINATE] = 1;
|
2008-11-04 16:46:33 +00:00
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_UUID] = 1;
|
2007-03-29 22:31:56 +00:00
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_OUTGOING] = 1;
|
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_PARK] = 1;
|
2008-10-27 15:10:22 +00:00
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_PROGRESS] = 1;
|
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_PROGRESS_MEDIA] = 1;
|
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_STATE] = 1;
|
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_UNBRIDGE] = 1;
|
2007-03-29 22:31:56 +00:00
|
|
|
listener->event_list[SWITCH_EVENT_CHANNEL_UNPARK] = 1;
|
2008-10-27 15:10:22 +00:00
|
|
|
listener->event_list[SWITCH_EVENT_DETECTED_SPEECH] = 1;
|
2007-03-29 22:31:56 +00:00
|
|
|
listener->event_list[SWITCH_EVENT_DTMF] = 1;
|
|
|
|
listener->event_list[SWITCH_EVENT_NOTALK] = 1;
|
2008-10-27 15:10:22 +00:00
|
|
|
listener->event_list[SWITCH_EVENT_TALK] = 1;
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_set_flag_locked(listener, LFLAG_MYEVENTS);
|
|
|
|
switch_set_flag_locked(listener, LFLAG_EVENTS);
|
|
|
|
if (strstr(cmd, "xml") || strstr(cmd, "XML")) {
|
|
|
|
listener->format = EVENT_FORMAT_XML;
|
|
|
|
}
|
2010-06-17 16:43:09 +00:00
|
|
|
if (strstr(cmd, "json") || strstr(cmd, "JSON")) {
|
|
|
|
listener->format = EVENT_FORMAT_JSON;
|
|
|
|
}
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(reply, reply_len, "+OK Events Enabled");
|
2007-03-29 22:31:56 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
2007-01-06 17:06:18 +00:00
|
|
|
|
2007-12-03 16:06:47 +00:00
|
|
|
|
2009-02-21 23:19:58 +00:00
|
|
|
if (!strncasecmp(cmd, "divert_events", 13)) {
|
|
|
|
char *onoff = cmd + 13;
|
|
|
|
switch_channel_t *channel;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-02-21 23:19:58 +00:00
|
|
|
if (!listener->session) {
|
|
|
|
switch_snprintf(reply, reply_len, "-ERR not controlling a session.");
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
channel = switch_core_session_get_channel(listener->session);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-02-21 23:19:58 +00:00
|
|
|
if (onoff) {
|
2010-02-06 03:38:24 +00:00
|
|
|
while (*onoff == ' ') {
|
2009-02-21 23:19:58 +00:00
|
|
|
onoff++;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-02-21 23:19:58 +00:00
|
|
|
if (*onoff == '\r' || *onoff == '\n') {
|
|
|
|
onoff = NULL;
|
|
|
|
} else {
|
|
|
|
strip_cr(onoff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (zstr(onoff)) {
|
2009-02-21 23:19:58 +00:00
|
|
|
switch_snprintf(reply, reply_len, "-ERR missing value.");
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-02-21 23:19:58 +00:00
|
|
|
if (!strcasecmp(onoff, "on")) {
|
|
|
|
switch_snprintf(reply, reply_len, "+OK events diverted");
|
|
|
|
switch_channel_set_flag(channel, CF_DIVERT_EVENTS);
|
|
|
|
} else {
|
|
|
|
switch_snprintf(reply, reply_len, "+OK events not diverted");
|
|
|
|
switch_channel_clear_flag(channel, CF_DIVERT_EVENTS);
|
|
|
|
}
|
|
|
|
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2008-12-12 15:44:37 +00:00
|
|
|
if (!strncasecmp(cmd, "sendmsg", 7)) {
|
2006-09-07 03:58:01 +00:00
|
|
|
switch_core_session_t *session;
|
2008-12-12 15:44:37 +00:00
|
|
|
char *uuid = cmd + 7;
|
2009-03-24 18:01:58 +00:00
|
|
|
const char *async_var = switch_event_get_header(*event, "async");
|
|
|
|
int async = switch_test_flag(listener, LFLAG_ASYNC);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-03-24 18:01:58 +00:00
|
|
|
if (switch_true(async_var)) {
|
|
|
|
async = 1;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-09-07 03:58:01 +00:00
|
|
|
if (uuid) {
|
2007-03-29 22:31:56 +00:00
|
|
|
while (*uuid == ' ') {
|
2006-09-07 03:58:01 +00:00
|
|
|
uuid++;
|
|
|
|
}
|
2006-10-19 19:09:51 +00:00
|
|
|
|
|
|
|
if (*uuid == '\r' || *uuid == '\n') {
|
|
|
|
uuid = NULL;
|
|
|
|
} else {
|
|
|
|
strip_cr(uuid);
|
|
|
|
}
|
2006-09-07 03:58:01 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (zstr(uuid)) {
|
2008-08-21 16:09:22 +00:00
|
|
|
uuid = switch_event_get_header(*event, "session-id");
|
2006-09-07 03:58:01 +00:00
|
|
|
}
|
2008-12-12 15:44:37 +00:00
|
|
|
|
2009-03-24 18:01:58 +00:00
|
|
|
if (uuid && listener->session && !strcmp(uuid, switch_core_session_get_uuid(listener->session))) {
|
|
|
|
uuid = NULL;
|
|
|
|
}
|
2009-02-17 14:13:32 +00:00
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (zstr(uuid) && listener->session) {
|
2009-02-17 14:13:32 +00:00
|
|
|
if (async) {
|
2009-12-10 01:29:02 +00:00
|
|
|
if ((status = switch_core_session_queue_private_event(listener->session, event, SWITCH_FALSE)) == SWITCH_STATUS_SUCCESS) {
|
2008-12-08 16:08:37 +00:00
|
|
|
switch_snprintf(reply, reply_len, "+OK");
|
|
|
|
} else {
|
|
|
|
switch_snprintf(reply, reply_len, "-ERR memory error");
|
|
|
|
}
|
2006-09-07 03:58:01 +00:00
|
|
|
} else {
|
2008-12-08 16:08:37 +00:00
|
|
|
switch_ivr_parse_event(listener->session, *event);
|
|
|
|
switch_snprintf(reply, reply_len, "+OK");
|
2006-09-07 03:58:01 +00:00
|
|
|
}
|
|
|
|
} else {
|
2009-10-23 16:03:42 +00:00
|
|
|
if (!zstr(uuid) && (session = switch_core_session_locate(uuid))) {
|
2009-12-10 01:29:02 +00:00
|
|
|
if ((status = switch_core_session_queue_private_event(session, event, SWITCH_FALSE)) == SWITCH_STATUS_SUCCESS) {
|
2008-12-08 16:08:37 +00:00
|
|
|
switch_snprintf(reply, reply_len, "+OK");
|
|
|
|
} else {
|
|
|
|
switch_snprintf(reply, reply_len, "-ERR memory error");
|
|
|
|
}
|
|
|
|
switch_core_session_rwunlock(session);
|
|
|
|
} else {
|
|
|
|
switch_snprintf(reply, reply_len, "-ERR invalid session id [%s]", switch_str_nil(uuid));
|
|
|
|
}
|
2006-09-07 03:58:01 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-09-07 03:58:01 +00:00
|
|
|
goto done;
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2008-12-12 15:44:37 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-12-12 15:44:37 +00:00
|
|
|
if (switch_test_flag(listener, LFLAG_OUTBOUND) && !switch_test_flag(listener, LFLAG_FULL)) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!strncasecmp(cmd, "sendevent", 9)) {
|
|
|
|
char *ename;
|
2009-09-15 19:18:20 +00:00
|
|
|
const char *uuid = NULL;
|
|
|
|
|
2008-12-12 15:44:37 +00:00
|
|
|
strip_cr(cmd);
|
|
|
|
|
|
|
|
ename = cmd + 9;
|
|
|
|
|
|
|
|
while (ename && (*ename == '\t' || *ename == ' ')) {
|
|
|
|
++ename;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ename && (*ename == '\r' || *ename == '\n')) {
|
|
|
|
ename = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ename) {
|
|
|
|
switch_event_types_t etype;
|
|
|
|
if (switch_name_event(ename, &etype) == SWITCH_STATUS_SUCCESS) {
|
2009-07-24 20:13:36 +00:00
|
|
|
const char *subclass_name = switch_event_get_header(*event, "Event-Subclass");
|
2008-12-12 15:44:37 +00:00
|
|
|
(*event)->event_id = etype;
|
2009-07-24 20:13:36 +00:00
|
|
|
|
|
|
|
if (etype == SWITCH_EVENT_CUSTOM && subclass_name) {
|
|
|
|
switch_event_set_subclass_name(*event, subclass_name);
|
|
|
|
}
|
2008-12-12 15:44:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-15 19:18:20 +00:00
|
|
|
if ((uuid = switch_event_get_header(*event, "unique-id"))) {
|
|
|
|
switch_core_session_t *dsession;
|
|
|
|
if ((dsession = switch_core_session_locate(uuid))) {
|
|
|
|
switch_core_session_queue_event(dsession, event);
|
|
|
|
switch_core_session_rwunlock(dsession);
|
|
|
|
}
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-09-15 19:18:20 +00:00
|
|
|
if (*event) {
|
|
|
|
switch_event_fire(event);
|
|
|
|
}
|
2008-12-12 15:44:37 +00:00
|
|
|
switch_snprintf(reply, reply_len, "+OK");
|
|
|
|
goto done;
|
2006-09-07 03:58:01 +00:00
|
|
|
} else if (!strncasecmp(cmd, "api ", 4)) {
|
2007-03-29 22:31:56 +00:00
|
|
|
struct api_command_struct acs = { 0 };
|
2010-01-20 17:45:53 +00:00
|
|
|
char *console_execute = switch_event_get_header(*event, "console_execute");
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
char *api_cmd = cmd + 4;
|
2006-09-07 03:58:01 +00:00
|
|
|
char *arg = NULL;
|
|
|
|
strip_cr(api_cmd);
|
2006-07-22 21:49:52 +00:00
|
|
|
|
2010-12-29 20:44:05 +00:00
|
|
|
if (listener->allowed_api_hash) {
|
|
|
|
char *api_copy = strdup(api_cmd);
|
|
|
|
char *arg_copy = NULL;
|
|
|
|
int ok = 0;
|
|
|
|
|
|
|
|
if ((arg_copy = strchr(api_copy, ' '))) {
|
|
|
|
*arg_copy++ = '\0';
|
2010-01-20 17:45:53 +00:00
|
|
|
}
|
2010-12-29 20:44:05 +00:00
|
|
|
|
|
|
|
ok = auth_api_command(listener, api_copy, arg_copy);
|
|
|
|
free(api_copy);
|
2006-07-22 21:49:52 +00:00
|
|
|
|
2010-12-29 20:44:05 +00:00
|
|
|
if (!ok) {
|
2010-01-05 19:47:49 +00:00
|
|
|
switch_snprintf(reply, reply_len, "-ERR permission denied");
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
2010-12-29 20:44:05 +00:00
|
|
|
|
|
|
|
if (!(acs.console_execute = switch_true(console_execute))) {
|
|
|
|
if ((arg = strchr(api_cmd, ' '))) {
|
|
|
|
*arg++ = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-09-07 03:58:01 +00:00
|
|
|
acs.listener = listener;
|
|
|
|
acs.api_cmd = api_cmd;
|
|
|
|
acs.arg = arg;
|
|
|
|
acs.bg = 0;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-09-07 03:58:01 +00:00
|
|
|
|
|
|
|
api_exec(NULL, (void *) &acs);
|
2006-07-22 21:49:52 +00:00
|
|
|
|
2008-08-21 16:09:22 +00:00
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
goto done_noreply;
|
2006-09-07 03:58:01 +00:00
|
|
|
} else if (!strncasecmp(cmd, "bgapi ", 6)) {
|
2007-09-29 01:06:08 +00:00
|
|
|
struct api_command_struct *acs = NULL;
|
2006-09-07 03:58:01 +00:00
|
|
|
char *api_cmd = cmd + 6;
|
|
|
|
char *arg = NULL;
|
2007-03-29 22:31:56 +00:00
|
|
|
char *uuid_str = NULL;
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_memory_pool_t *pool;
|
|
|
|
switch_thread_t *thread;
|
|
|
|
switch_threadattr_t *thd_attr = NULL;
|
|
|
|
switch_uuid_t uuid;
|
2009-02-07 16:44:46 +00:00
|
|
|
int sanity;
|
2007-09-29 01:06:08 +00:00
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
strip_cr(api_cmd);
|
|
|
|
|
|
|
|
if ((arg = strchr(api_cmd, ' '))) {
|
|
|
|
*arg++ = '\0';
|
|
|
|
}
|
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
if (listener->allowed_api_hash) {
|
|
|
|
if (!auth_api_command(listener, api_cmd, arg)) {
|
|
|
|
switch_snprintf(reply, reply_len, "-ERR permission denied");
|
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_core_new_memory_pool(&pool);
|
|
|
|
acs = switch_core_alloc(pool, sizeof(*acs));
|
2007-12-16 03:01:50 +00:00
|
|
|
switch_assert(acs);
|
2007-09-29 01:06:08 +00:00
|
|
|
acs->pool = pool;
|
|
|
|
acs->listener = listener;
|
2010-01-20 17:45:53 +00:00
|
|
|
acs->console_execute = 0;
|
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
if (api_cmd) {
|
|
|
|
acs->api_cmd = switch_core_strdup(acs->pool, api_cmd);
|
|
|
|
}
|
|
|
|
if (arg) {
|
|
|
|
acs->arg = switch_core_strdup(acs->pool, arg);
|
|
|
|
}
|
|
|
|
acs->bg = 1;
|
2008-04-14 16:18:49 +00:00
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_threadattr_create(&thd_attr, acs->pool);
|
|
|
|
switch_threadattr_detach_set(thd_attr, 1);
|
|
|
|
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
2008-04-14 16:18:49 +00:00
|
|
|
|
2008-08-21 16:09:22 +00:00
|
|
|
if ((uuid_str = switch_event_get_header(*event, "job-uuid"))) {
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_copy_string(acs->uuid_str, uuid_str, sizeof(acs->uuid_str));
|
2006-09-07 03:58:01 +00:00
|
|
|
} else {
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_uuid_get(&uuid);
|
|
|
|
switch_uuid_format(acs->uuid_str, &uuid);
|
2006-09-07 03:58:01 +00:00
|
|
|
}
|
2008-06-06 16:14:29 +00:00
|
|
|
switch_snprintf(reply, reply_len, "~Reply-Text: +OK Job-UUID: %s\nJob-UUID: %s\n\n", acs->uuid_str, acs->uuid_str);
|
2008-04-14 16:18:49 +00:00
|
|
|
switch_thread_create(&thread, thd_attr, api_exec, acs, acs->pool);
|
2009-02-07 16:44:46 +00:00
|
|
|
sanity = 2000;
|
2010-02-06 03:38:24 +00:00
|
|
|
while (!acs->ack) {
|
2009-02-07 16:44:46 +00:00
|
|
|
switch_cond_next();
|
2010-02-06 03:38:24 +00:00
|
|
|
if (--sanity <= 0)
|
|
|
|
break;
|
2009-02-07 16:44:46 +00:00
|
|
|
}
|
|
|
|
if (acs->ack == -1) {
|
|
|
|
acs->ack--;
|
|
|
|
}
|
2008-05-27 04:54:52 +00:00
|
|
|
|
2008-08-21 16:09:22 +00:00
|
|
|
status = SWITCH_STATUS_SUCCESS;
|
|
|
|
goto done_noreply;
|
2006-07-22 21:49:52 +00:00
|
|
|
} else if (!strncasecmp(cmd, "log", 3)) {
|
|
|
|
|
|
|
|
char *level_s;
|
2007-12-10 19:16:50 +00:00
|
|
|
switch_log_level_t ltype = SWITCH_LOG_DEBUG;
|
2006-10-19 18:52:46 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
if (!switch_test_flag(listener, LFLAG_ALLOW_LOG)) {
|
|
|
|
switch_snprintf(reply, reply_len, "-ERR permission denied");
|
|
|
|
goto done;
|
|
|
|
}
|
2006-10-19 18:52:46 +00:00
|
|
|
//pull off the first newline/carriage return
|
2006-07-22 21:49:52 +00:00
|
|
|
strip_cr(cmd);
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-10-19 18:52:46 +00:00
|
|
|
//move past the command
|
|
|
|
level_s = cmd + 3;
|
2006-07-22 21:49:52 +00:00
|
|
|
|
2006-10-19 18:52:46 +00:00
|
|
|
//see if we got an argument
|
2009-10-23 16:03:42 +00:00
|
|
|
if (!zstr(level_s)) {
|
2006-10-19 18:52:46 +00:00
|
|
|
//if so move to the argument
|
|
|
|
level_s++;
|
|
|
|
}
|
|
|
|
//see if we lined up on an argument or not
|
2009-10-23 16:03:42 +00:00
|
|
|
if (!zstr(level_s)) {
|
2007-12-10 19:16:50 +00:00
|
|
|
ltype = switch_log_str2level(level_s);
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
|
|
|
|
2008-12-31 19:07:20 +00:00
|
|
|
if (ltype != SWITCH_LOG_INVALID) {
|
2007-12-10 19:16:50 +00:00
|
|
|
listener->level = ltype;
|
2006-07-22 21:49:52 +00:00
|
|
|
switch_set_flag(listener, LFLAG_LOG);
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(reply, reply_len, "+OK log level %s [%d]", level_s, listener->level);
|
2006-07-22 21:49:52 +00:00
|
|
|
} else {
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(reply, reply_len, "-ERR invalid log level");
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
2009-01-16 15:32:10 +00:00
|
|
|
} else if (!strncasecmp(cmd, "linger", 6)) {
|
|
|
|
if (listener->session) {
|
2012-04-13 13:43:46 +00:00
|
|
|
time_t linger_time = 600; /* sounds reasonable? */
|
2011-12-08 18:25:52 +00:00
|
|
|
if (*(cmd+6) == ' ' && *(cmd+7)) { /*how long do you want to linger?*/
|
2012-04-13 13:43:46 +00:00
|
|
|
linger_time = (time_t) atoi(cmd+7);
|
|
|
|
} else {
|
|
|
|
linger_time = (time_t) -1;
|
2011-12-08 18:25:52 +00:00
|
|
|
}
|
|
|
|
|
2012-04-13 13:43:46 +00:00
|
|
|
listener->linger_timeout = linger_time;
|
2009-01-16 15:32:10 +00:00
|
|
|
switch_set_flag_locked(listener, LFLAG_LINGER);
|
2012-04-13 13:43:46 +00:00
|
|
|
if (listener->linger_timeout != (time_t) -1) {
|
|
|
|
switch_snprintf(reply, reply_len, "+OK will linger %d seconds", linger_time);
|
|
|
|
} else {
|
|
|
|
switch_snprintf(reply, reply_len, "+OK will linger");
|
|
|
|
}
|
2009-01-16 15:32:10 +00:00
|
|
|
} else {
|
|
|
|
switch_snprintf(reply, reply_len, "-ERR not controlling a session");
|
|
|
|
}
|
2009-07-15 16:45:12 +00:00
|
|
|
} else if (!strncasecmp(cmd, "nolinger", 8)) {
|
2009-01-16 15:32:10 +00:00
|
|
|
if (listener->session) {
|
|
|
|
switch_clear_flag_locked(listener, LFLAG_LINGER);
|
|
|
|
switch_snprintf(reply, reply_len, "+OK will not linger");
|
|
|
|
} else {
|
|
|
|
switch_snprintf(reply, reply_len, "-ERR not controlling a session");
|
|
|
|
}
|
2006-07-22 21:49:52 +00:00
|
|
|
} else if (!strncasecmp(cmd, "nolog", 5)) {
|
2008-10-29 19:15:14 +00:00
|
|
|
flush_listener(listener, SWITCH_TRUE, SWITCH_FALSE);
|
2006-07-22 21:49:52 +00:00
|
|
|
if (switch_test_flag(listener, LFLAG_LOG)) {
|
|
|
|
switch_clear_flag_locked(listener, LFLAG_LOG);
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(reply, reply_len, "+OK no longer logging");
|
2006-07-22 21:49:52 +00:00
|
|
|
} else {
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(reply, reply_len, "-ERR not loging");
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
|
|
|
} else if (!strncasecmp(cmd, "event", 5)) {
|
|
|
|
char *next, *cur;
|
|
|
|
uint32_t count = 0, key_count = 0;
|
|
|
|
uint8_t custom = 0;
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
strip_cr(cmd);
|
|
|
|
cur = cmd + 5;
|
|
|
|
|
|
|
|
if (cur && (cur = strchr(cur, ' '))) {
|
2007-03-29 22:31:56 +00:00
|
|
|
for (cur++; cur; count++) {
|
2006-07-22 21:49:52 +00:00
|
|
|
switch_event_types_t type;
|
|
|
|
|
|
|
|
if ((next = strchr(cur, ' '))) {
|
|
|
|
*next++ = '\0';
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
if (!count) {
|
|
|
|
if (!strcasecmp(cur, "xml")) {
|
|
|
|
listener->format = EVENT_FORMAT_XML;
|
|
|
|
goto end;
|
|
|
|
} else if (!strcasecmp(cur, "plain")) {
|
|
|
|
listener->format = EVENT_FORMAT_PLAIN;
|
|
|
|
goto end;
|
2010-06-17 16:43:09 +00:00
|
|
|
} else if (!strcasecmp(cur, "json")) {
|
|
|
|
listener->format = EVENT_FORMAT_JSON;
|
|
|
|
goto end;
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
if (custom) {
|
2010-01-06 16:59:53 +00:00
|
|
|
if (!listener->allowed_event_hash || switch_core_hash_find(listener->allowed_event_hash, cur)) {
|
2010-01-05 19:47:49 +00:00
|
|
|
switch_core_hash_insert(listener->event_hash, cur, MARKER);
|
|
|
|
} else {
|
|
|
|
switch_snprintf(reply, reply_len, "-ERR permission denied");
|
|
|
|
goto done;
|
|
|
|
}
|
2006-07-22 21:49:52 +00:00
|
|
|
} else if (switch_name_event(cur, &type) == SWITCH_STATUS_SUCCESS) {
|
2010-02-06 03:38:24 +00:00
|
|
|
if (switch_test_flag(listener, LFLAG_AUTH_EVENTS) && !listener->allowed_event_list[type] &&
|
2010-01-05 19:47:49 +00:00
|
|
|
!switch_test_flag(listener, LFLAG_ALL_EVENTS_AUTHED)) {
|
|
|
|
switch_snprintf(reply, reply_len, "-ERR permission denied");
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
key_count++;
|
2006-09-20 14:57:13 +00:00
|
|
|
if (type == SWITCH_EVENT_ALL) {
|
|
|
|
uint32_t x = 0;
|
|
|
|
for (x = 0; x < SWITCH_EVENT_ALL; x++) {
|
2007-07-24 21:26:04 +00:00
|
|
|
listener->event_list[x] = 1;
|
2006-09-20 14:57:13 +00:00
|
|
|
}
|
|
|
|
}
|
2007-12-16 03:01:50 +00:00
|
|
|
if (type <= SWITCH_EVENT_ALL) {
|
|
|
|
listener->event_list[type] = 1;
|
|
|
|
}
|
2006-07-22 21:49:52 +00:00
|
|
|
if (type == SWITCH_EVENT_CUSTOM) {
|
|
|
|
custom++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-27 04:54:52 +00:00
|
|
|
end:
|
2006-07-22 21:49:52 +00:00
|
|
|
cur = next;
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
}
|
2006-07-22 21:49:52 +00:00
|
|
|
|
|
|
|
if (!key_count) {
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(reply, reply_len, "-ERR no keywords supplied");
|
2006-07-22 21:49:52 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!switch_test_flag(listener, LFLAG_EVENTS)) {
|
|
|
|
switch_set_flag_locked(listener, LFLAG_EVENTS);
|
|
|
|
}
|
|
|
|
|
2010-06-17 16:43:09 +00:00
|
|
|
switch_snprintf(reply, reply_len, "+OK event listener enabled %s", format2str(listener->format));
|
2006-09-20 14:57:13 +00:00
|
|
|
|
|
|
|
} else if (!strncasecmp(cmd, "nixevent", 8)) {
|
|
|
|
char *next, *cur;
|
|
|
|
uint32_t count = 0, key_count = 0;
|
|
|
|
uint8_t custom = 0;
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-09-20 14:57:13 +00:00
|
|
|
strip_cr(cmd);
|
|
|
|
cur = cmd + 5;
|
|
|
|
|
|
|
|
if (cur && (cur = strchr(cur, ' '))) {
|
2007-03-29 22:31:56 +00:00
|
|
|
for (cur++; cur; count++) {
|
2006-09-20 14:57:13 +00:00
|
|
|
switch_event_types_t type;
|
|
|
|
|
|
|
|
if ((next = strchr(cur, ' '))) {
|
|
|
|
*next++ = '\0';
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-09-20 14:57:13 +00:00
|
|
|
if (custom) {
|
|
|
|
switch_core_hash_delete(listener->event_hash, cur);
|
|
|
|
} else if (switch_name_event(cur, &type) == SWITCH_STATUS_SUCCESS) {
|
|
|
|
uint32_t x = 0;
|
|
|
|
key_count++;
|
|
|
|
|
2007-07-24 21:26:04 +00:00
|
|
|
if (type == SWITCH_EVENT_CUSTOM) {
|
|
|
|
custom++;
|
|
|
|
} else if (type == SWITCH_EVENT_ALL) {
|
2006-09-20 14:57:13 +00:00
|
|
|
for (x = 0; x <= SWITCH_EVENT_ALL; x++) {
|
|
|
|
listener->event_list[x] = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (listener->event_list[SWITCH_EVENT_ALL]) {
|
|
|
|
listener->event_list[SWITCH_EVENT_ALL] = 0;
|
|
|
|
for (x = 0; x < SWITCH_EVENT_ALL; x++) {
|
|
|
|
listener->event_list[x] = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
listener->event_list[type] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cur = next;
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
}
|
2006-09-20 14:57:13 +00:00
|
|
|
|
|
|
|
if (!key_count) {
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(reply, reply_len, "-ERR no keywords supplied");
|
2006-09-20 14:57:13 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!switch_test_flag(listener, LFLAG_EVENTS)) {
|
|
|
|
switch_set_flag_locked(listener, LFLAG_EVENTS);
|
|
|
|
}
|
|
|
|
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(reply, reply_len, "+OK events nixed");
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
} else if (!strncasecmp(cmd, "noevents", 8)) {
|
2008-10-29 19:15:14 +00:00
|
|
|
flush_listener(listener, SWITCH_FALSE, SWITCH_TRUE);
|
2006-08-11 18:59:25 +00:00
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
if (switch_test_flag(listener, LFLAG_EVENTS)) {
|
|
|
|
uint8_t x = 0;
|
|
|
|
switch_clear_flag_locked(listener, LFLAG_EVENTS);
|
|
|
|
for (x = 0; x <= SWITCH_EVENT_ALL; x++) {
|
|
|
|
listener->event_list[x] = 0;
|
|
|
|
}
|
|
|
|
/* wipe the hash */
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_core_hash_destroy(&listener->event_hash);
|
2006-07-22 21:49:52 +00:00
|
|
|
switch_core_hash_init(&listener->event_hash, listener->pool);
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(reply, reply_len, "+OK no longer listening for events");
|
2006-07-22 21:49:52 +00:00
|
|
|
} else {
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(reply, reply_len, "-ERR not listening for events");
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
done:
|
2006-07-25 14:14:07 +00:00
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (zstr(reply)) {
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(reply, reply_len, "-ERR command not found");
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
done_noreply:
|
2008-08-21 16:09:22 +00:00
|
|
|
|
|
|
|
if (event) {
|
|
|
|
switch_event_destroy(event);
|
|
|
|
}
|
|
|
|
|
2006-07-25 14:14:07 +00:00
|
|
|
return status;
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
|
|
|
|
2008-05-27 04:54:52 +00:00
|
|
|
static void *SWITCH_THREAD_FUNC listener_run(switch_thread_t *thread, void *obj)
|
2006-07-22 21:49:52 +00:00
|
|
|
{
|
|
|
|
listener_t *listener = (listener_t *) obj;
|
|
|
|
char buf[1024];
|
|
|
|
switch_size_t len;
|
|
|
|
switch_status_t status;
|
2006-07-25 14:14:07 +00:00
|
|
|
switch_event_t *event;
|
2006-07-22 21:49:52 +00:00
|
|
|
char reply[512] = "";
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_core_session_t *session = NULL;
|
|
|
|
switch_channel_t *channel = NULL;
|
2008-08-20 19:10:04 +00:00
|
|
|
switch_event_t *revent = NULL;
|
2009-04-30 22:45:46 +00:00
|
|
|
const char *var;
|
2012-01-05 14:49:56 +00:00
|
|
|
int locked = 1;
|
2008-03-26 22:14:09 +00:00
|
|
|
|
2008-11-07 14:48:49 +00:00
|
|
|
switch_mutex_lock(globals.listener_mutex);
|
2007-07-24 21:26:04 +00:00
|
|
|
prefs.threads++;
|
2008-11-07 14:48:49 +00:00
|
|
|
switch_mutex_unlock(globals.listener_mutex);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2007-12-16 03:01:50 +00:00
|
|
|
switch_assert(listener != NULL);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-11-11 13:32:11 +00:00
|
|
|
if ((session = listener->session)) {
|
2009-01-09 20:34:01 +00:00
|
|
|
if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) {
|
2012-01-05 14:49:56 +00:00
|
|
|
locked = 0;
|
2009-01-09 20:34:01 +00:00
|
|
|
goto done;
|
|
|
|
}
|
2008-11-11 13:32:11 +00:00
|
|
|
}
|
2006-07-22 21:49:52 +00:00
|
|
|
|
2009-01-15 22:11:27 +00:00
|
|
|
switch_socket_opt_set(listener->sock, SWITCH_SO_TCP_NODELAY, TRUE);
|
|
|
|
switch_socket_opt_set(listener->sock, SWITCH_SO_NONBLOCK, TRUE);
|
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (prefs.acl_count && listener->sa && !zstr(listener->remote_ip)) {
|
2008-03-31 16:05:32 +00:00
|
|
|
uint32_t x = 0;
|
2008-05-27 04:54:52 +00:00
|
|
|
|
|
|
|
for (x = 0; x < prefs.acl_count; x++) {
|
2008-03-26 22:14:09 +00:00
|
|
|
if (!switch_check_network_list_ip(listener->remote_ip, prefs.acl[x])) {
|
|
|
|
const char message[] = "Access Denied, go away.\n";
|
|
|
|
int mlen = strlen(message);
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "IP %s Rejected by acl \"%s\"\n", listener->remote_ip,
|
|
|
|
prefs.acl[x]);
|
2008-03-26 22:14:09 +00:00
|
|
|
|
2008-12-11 15:25:59 +00:00
|
|
|
switch_snprintf(buf, sizeof(buf), "Content-Type: text/rude-rejection\nContent-Length: %d\n\n", mlen);
|
2008-03-26 22:14:09 +00:00
|
|
|
len = strlen(buf);
|
|
|
|
switch_socket_send(listener->sock, buf, &len);
|
|
|
|
len = mlen;
|
|
|
|
switch_socket_send(listener->sock, message, &len);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-05-02 00:58:51 +00:00
|
|
|
if (globals.debug > 0) {
|
2009-10-23 16:03:42 +00:00
|
|
|
if (zstr(listener->remote_ip)) {
|
2009-08-13 21:52:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Connection Open\n");
|
2009-05-02 00:58:51 +00:00
|
|
|
} else {
|
2010-02-06 03:38:24 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Connection Open from %s:%d\n", listener->remote_ip,
|
|
|
|
listener->remote_port);
|
2009-05-02 00:58:51 +00:00
|
|
|
}
|
2008-03-26 22:14:09 +00:00
|
|
|
}
|
2006-07-22 21:49:52 +00:00
|
|
|
|
2007-03-09 20:44:13 +00:00
|
|
|
switch_socket_opt_set(listener->sock, SWITCH_SO_NONBLOCK, TRUE);
|
2006-07-22 21:49:52 +00:00
|
|
|
switch_set_flag_locked(listener, LFLAG_RUNNING);
|
|
|
|
add_listener(listener);
|
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
if (session && switch_test_flag(listener, LFLAG_AUTHED)) {
|
2009-03-23 19:53:57 +00:00
|
|
|
switch_event_t *ievent = NULL;
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_set_flag_locked(listener, LFLAG_SESSION);
|
2007-12-16 03:01:50 +00:00
|
|
|
status = read_packet(listener, &ievent, 25);
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2007-12-16 03:01:50 +00:00
|
|
|
if (status != SWITCH_STATUS_SUCCESS || !ievent) {
|
2009-08-13 21:52:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Socket Error!\n");
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_clear_flag_locked(listener, LFLAG_RUNNING);
|
|
|
|
goto done;
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2008-08-21 16:09:22 +00:00
|
|
|
if (parse_command(listener, &ievent, reply, sizeof(reply)) != SWITCH_STATUS_SUCCESS) {
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_clear_flag_locked(listener, LFLAG_RUNNING);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} else {
|
2007-12-12 21:53:32 +00:00
|
|
|
switch_snprintf(buf, sizeof(buf), "Content-Type: auth/request\n\n");
|
2007-03-29 22:31:56 +00:00
|
|
|
|
|
|
|
len = strlen(buf);
|
|
|
|
switch_socket_send(listener->sock, buf, &len);
|
|
|
|
|
|
|
|
while (!switch_test_flag(listener, LFLAG_AUTHED)) {
|
|
|
|
status = read_packet(listener, &event, 25);
|
|
|
|
if (status != SWITCH_STATUS_SUCCESS) {
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
if (!event) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2008-08-21 16:09:22 +00:00
|
|
|
if (parse_command(listener, &event, reply, sizeof(reply)) != SWITCH_STATUS_SUCCESS) {
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_clear_flag_locked(listener, LFLAG_RUNNING);
|
|
|
|
goto done;
|
|
|
|
}
|
2007-08-03 21:29:01 +00:00
|
|
|
if (*reply != '\0') {
|
2008-06-06 16:14:29 +00:00
|
|
|
if (*reply == '~') {
|
|
|
|
switch_snprintf(buf, sizeof(buf), "Content-Type: command/reply\n%s", reply + 1);
|
|
|
|
} else {
|
|
|
|
switch_snprintf(buf, sizeof(buf), "Content-Type: command/reply\nReply-Text: %s\n\n", reply);
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
len = strlen(buf);
|
|
|
|
switch_socket_send(listener->sock, buf, &len);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-20 01:10:59 +00:00
|
|
|
while (!prefs.done && switch_test_flag(listener, LFLAG_RUNNING) && listen_list.ready) {
|
2006-07-22 21:49:52 +00:00
|
|
|
len = sizeof(buf);
|
|
|
|
memset(buf, 0, len);
|
2007-12-16 03:01:50 +00:00
|
|
|
status = read_packet(listener, &revent, 0);
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-07-25 14:14:07 +00:00
|
|
|
if (status != SWITCH_STATUS_SUCCESS) {
|
2006-07-22 21:49:52 +00:00
|
|
|
break;
|
|
|
|
}
|
2006-07-25 14:14:07 +00:00
|
|
|
|
2007-12-16 03:01:50 +00:00
|
|
|
if (!revent) {
|
2006-07-22 21:49:52 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2008-08-21 16:09:22 +00:00
|
|
|
if (parse_command(listener, &revent, reply, sizeof(reply)) != SWITCH_STATUS_SUCCESS) {
|
2006-07-25 14:14:07 +00:00
|
|
|
switch_clear_flag_locked(listener, LFLAG_RUNNING);
|
|
|
|
break;
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
|
|
|
|
2008-08-21 17:32:57 +00:00
|
|
|
if (revent) {
|
|
|
|
switch_event_destroy(&revent);
|
|
|
|
}
|
2008-08-20 19:10:04 +00:00
|
|
|
|
2007-08-03 21:29:01 +00:00
|
|
|
if (*reply != '\0') {
|
2008-06-06 16:14:29 +00:00
|
|
|
if (*reply == '~') {
|
|
|
|
switch_snprintf(buf, sizeof(buf), "Content-Type: command/reply\n%s", reply + 1);
|
|
|
|
} else {
|
|
|
|
switch_snprintf(buf, sizeof(buf), "Content-Type: command/reply\nReply-Text: %s\n\n", reply);
|
|
|
|
}
|
2006-10-13 14:32:38 +00:00
|
|
|
len = strlen(buf);
|
2006-07-25 14:14:07 +00:00
|
|
|
switch_socket_send(listener->sock, buf, &len);
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
|
|
|
|
2008-05-27 04:54:52 +00:00
|
|
|
done:
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2008-08-21 17:32:57 +00:00
|
|
|
if (revent) {
|
|
|
|
switch_event_destroy(&revent);
|
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
remove_listener(listener);
|
|
|
|
|
2009-05-02 00:58:51 +00:00
|
|
|
if (globals.debug > 0) {
|
2009-08-13 21:52:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Session complete, waiting for children\n");
|
2009-05-02 00:58:51 +00:00
|
|
|
}
|
2006-09-07 03:58:01 +00:00
|
|
|
|
|
|
|
switch_thread_rwlock_wrlock(listener->rwlock);
|
2008-10-29 19:15:14 +00:00
|
|
|
flush_listener(listener, SWITCH_TRUE, SWITCH_TRUE);
|
2008-10-30 00:39:55 +00:00
|
|
|
switch_mutex_lock(listener->filter_mutex);
|
|
|
|
if (listener->filters) {
|
|
|
|
switch_event_destroy(&listener->filters);
|
|
|
|
}
|
|
|
|
switch_mutex_unlock(listener->filter_mutex);
|
2009-04-30 22:45:46 +00:00
|
|
|
|
2009-12-21 22:48:33 +00:00
|
|
|
if (listener->session) {
|
2009-04-30 22:45:46 +00:00
|
|
|
channel = switch_core_session_get_channel(listener->session);
|
2009-12-21 22:48:33 +00:00
|
|
|
}
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2009-12-21 22:48:33 +00:00
|
|
|
if (channel && (switch_test_flag(listener, LFLAG_RESUME) || ((var = switch_channel_get_variable(channel, "socket_resume")) && switch_true(var)))) {
|
2009-04-30 22:45:46 +00:00
|
|
|
switch_channel_set_state(channel, CS_RESET);
|
|
|
|
}
|
2009-12-21 22:48:33 +00:00
|
|
|
|
2008-10-20 16:33:46 +00:00
|
|
|
if (listener->sock) {
|
2011-01-25 20:13:15 +00:00
|
|
|
send_disconnect(listener, "Disconnected, goodbye.\nSee you at ClueCon! http://www.cluecon.com/\n");
|
2008-10-20 16:33:46 +00:00
|
|
|
close_socket(&listener->sock);
|
|
|
|
}
|
|
|
|
|
2006-09-07 03:58:01 +00:00
|
|
|
switch_thread_rwlock_unlock(listener->rwlock);
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2009-05-02 00:58:51 +00:00
|
|
|
if (globals.debug > 0) {
|
2009-08-13 21:52:05 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Connection Closed\n");
|
2009-05-02 00:58:51 +00:00
|
|
|
}
|
|
|
|
|
2007-09-29 01:06:08 +00:00
|
|
|
switch_core_hash_destroy(&listener->event_hash);
|
2006-07-22 21:49:52 +00:00
|
|
|
|
2010-01-05 19:47:49 +00:00
|
|
|
if (listener->allowed_event_hash) {
|
|
|
|
switch_core_hash_destroy(&listener->allowed_event_hash);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (listener->allowed_api_hash) {
|
|
|
|
switch_core_hash_destroy(&listener->allowed_api_hash);
|
|
|
|
}
|
|
|
|
|
2008-10-22 16:32:55 +00:00
|
|
|
if (listener->session) {
|
|
|
|
switch_channel_clear_flag(switch_core_session_get_channel(listener->session), CF_CONTROLLED);
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_clear_flag_locked(listener, LFLAG_SESSION);
|
2012-01-05 14:49:56 +00:00
|
|
|
if (locked) {
|
|
|
|
switch_core_session_rwunlock(listener->session);
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
} else if (listener->pool) {
|
2006-07-22 21:49:52 +00:00
|
|
|
switch_memory_pool_t *pool = listener->pool;
|
|
|
|
switch_core_destroy_memory_pool(&pool);
|
|
|
|
}
|
|
|
|
|
2008-11-07 14:48:49 +00:00
|
|
|
switch_mutex_lock(globals.listener_mutex);
|
2007-07-24 21:26:04 +00:00
|
|
|
prefs.threads--;
|
2008-11-07 14:48:49 +00:00
|
|
|
switch_mutex_unlock(globals.listener_mutex);
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-08-29 20:27:43 +00:00
|
|
|
/* Create a thread for the socket and launch it */
|
2008-05-27 04:54:52 +00:00
|
|
|
static void launch_listener_thread(listener_t *listener)
|
2006-07-22 21:49:52 +00:00
|
|
|
{
|
|
|
|
switch_thread_t *thread;
|
|
|
|
switch_threadattr_t *thd_attr = NULL;
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
switch_threadattr_create(&thd_attr, listener->pool);
|
|
|
|
switch_threadattr_detach_set(thd_attr, 1);
|
|
|
|
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
|
|
|
|
switch_thread_create(&thread, thd_attr, listener_run, listener, listener->pool);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int config(void)
|
|
|
|
{
|
|
|
|
char *cf = "event_socket.conf";
|
|
|
|
switch_xml_t cfg, xml, settings, param;
|
|
|
|
|
|
|
|
memset(&prefs, 0, sizeof(prefs));
|
|
|
|
|
|
|
|
if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
|
2008-10-11 06:19:56 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Open of %s failed\n", cf);
|
2006-07-22 21:49:52 +00:00
|
|
|
} else {
|
|
|
|
if ((settings = switch_xml_child(cfg, "settings"))) {
|
|
|
|
for (param = switch_xml_child(settings, "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")) {
|
|
|
|
set_pref_ip(val);
|
2009-05-02 00:58:51 +00:00
|
|
|
} else if (!strcmp(var, "debug")) {
|
|
|
|
globals.debug = atoi(val);
|
2009-06-03 14:25:35 +00:00
|
|
|
} else if (!strcmp(var, "nat-map")) {
|
2011-02-02 21:43:26 +00:00
|
|
|
if (switch_true(val) && switch_nat_get_type()) {
|
2009-06-03 14:25:35 +00:00
|
|
|
prefs.nat_map = 1;
|
|
|
|
}
|
2006-07-22 21:49:52 +00:00
|
|
|
} else if (!strcmp(var, "listen-port")) {
|
2007-03-29 22:31:56 +00:00
|
|
|
prefs.port = (uint16_t) atoi(val);
|
2006-07-22 21:49:52 +00:00
|
|
|
} else if (!strcmp(var, "password")) {
|
|
|
|
set_pref_pass(val);
|
2011-07-05 16:57:13 +00:00
|
|
|
} else if (!strcasecmp(var, "apply-inbound-acl") && ! zstr(val)) {
|
2008-03-26 22:14:09 +00:00
|
|
|
if (prefs.acl_count < MAX_ACL) {
|
|
|
|
prefs.acl[prefs.acl_count++] = strdup(val);
|
|
|
|
} else {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Max acl records of %d reached\n", MAX_ACL);
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
}
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
switch_xml_free(xml);
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (zstr(prefs.ip)) {
|
2006-07-22 21:49:52 +00:00
|
|
|
set_pref_ip("127.0.0.1");
|
|
|
|
}
|
|
|
|
|
2009-10-23 16:03:42 +00:00
|
|
|
if (zstr(prefs.password)) {
|
2006-07-22 21:49:52 +00:00
|
|
|
set_pref_pass("ClueCon");
|
|
|
|
}
|
|
|
|
|
2009-06-03 14:25:35 +00:00
|
|
|
if (!prefs.nat_map) {
|
|
|
|
prefs.nat_map = 0;
|
|
|
|
}
|
|
|
|
|
2009-06-08 23:28:51 +00:00
|
|
|
if (prefs.nat_map) {
|
2009-06-03 19:42:53 +00:00
|
|
|
prefs.nat_map = 0;
|
|
|
|
}
|
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
if (!prefs.port) {
|
|
|
|
prefs.port = 8021;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-13 17:06:10 +00:00
|
|
|
SWITCH_MODULE_RUNTIME_FUNCTION(mod_event_socket_runtime)
|
2006-07-22 21:49:52 +00:00
|
|
|
{
|
|
|
|
switch_memory_pool_t *pool = NULL, *listener_pool = NULL;
|
2007-03-29 22:31:56 +00:00
|
|
|
switch_status_t rv;
|
|
|
|
switch_sockaddr_t *sa;
|
|
|
|
switch_socket_t *inbound_socket = NULL;
|
2006-07-22 21:49:52 +00:00
|
|
|
listener_t *listener;
|
2008-03-31 16:05:32 +00:00
|
|
|
uint32_t x = 0;
|
2009-11-25 19:59:26 +00:00
|
|
|
uint32_t errs = 0;
|
2006-07-22 21:49:52 +00:00
|
|
|
|
|
|
|
if (switch_core_new_memory_pool(&pool) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "OH OH no pool\n");
|
|
|
|
return SWITCH_STATUS_TERM;
|
|
|
|
}
|
|
|
|
|
2008-12-31 19:07:20 +00:00
|
|
|
config();
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
while (!prefs.done) {
|
2012-03-14 15:05:03 +00:00
|
|
|
rv = switch_sockaddr_info_get(&sa, prefs.ip, SWITCH_UNSPEC, prefs.port, 0, pool);
|
2007-03-29 22:31:56 +00:00
|
|
|
if (rv)
|
|
|
|
goto fail;
|
2007-03-30 00:13:31 +00:00
|
|
|
rv = switch_socket_create(&listen_list.sock, switch_sockaddr_get_family(sa), SOCK_STREAM, SWITCH_PROTO_TCP, pool);
|
2007-03-29 22:31:56 +00:00
|
|
|
if (rv)
|
|
|
|
goto sock_fail;
|
2006-09-07 03:58:01 +00:00
|
|
|
rv = switch_socket_opt_set(listen_list.sock, SWITCH_SO_REUSEADDR, 1);
|
2007-03-29 22:31:56 +00:00
|
|
|
if (rv)
|
|
|
|
goto sock_fail;
|
2006-07-22 21:49:52 +00:00
|
|
|
rv = switch_socket_bind(listen_list.sock, sa);
|
2007-03-29 22:31:56 +00:00
|
|
|
if (rv)
|
|
|
|
goto sock_fail;
|
2006-07-22 21:49:52 +00:00
|
|
|
rv = switch_socket_listen(listen_list.sock, 5);
|
2007-03-29 22:31:56 +00:00
|
|
|
if (rv)
|
|
|
|
goto sock_fail;
|
2006-07-22 21:49:52 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Socket up listening on %s:%u\n", prefs.ip, prefs.port);
|
2009-06-03 14:25:35 +00:00
|
|
|
|
|
|
|
if (prefs.nat_map) {
|
2009-06-30 18:59:05 +00:00
|
|
|
switch_nat_add_mapping(prefs.port, SWITCH_NAT_TCP, NULL, SWITCH_FALSE);
|
2009-06-03 14:25:35 +00:00
|
|
|
}
|
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
break;
|
2008-05-27 04:54:52 +00:00
|
|
|
sock_fail:
|
2008-04-21 15:25:09 +00:00
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error! Could not listen on %s:%u\n", prefs.ip, prefs.port);
|
2006-09-07 03:58:01 +00:00
|
|
|
switch_yield(100000);
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
listen_list.ready = 1;
|
|
|
|
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
while (!prefs.done) {
|
2006-07-22 21:49:52 +00:00
|
|
|
if (switch_core_new_memory_pool(&listener_pool) != SWITCH_STATUS_SUCCESS) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "OH OH no pool\n");
|
|
|
|
goto fail;
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
if ((rv = switch_socket_accept(&inbound_socket, listen_list.sock, listener_pool))) {
|
2006-11-09 05:39:04 +00:00
|
|
|
if (prefs.done) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting Down\n");
|
2009-11-25 19:59:26 +00:00
|
|
|
goto end;
|
2006-11-09 05:39:04 +00:00
|
|
|
} else {
|
2009-11-25 19:59:26 +00:00
|
|
|
/* I wish we could use strerror_r here but its not defined everywhere =/ */
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Socket Error [%s]\n", strerror(errno));
|
|
|
|
if (++errs > 100) {
|
|
|
|
goto end;
|
|
|
|
}
|
2006-11-09 05:39:04 +00:00
|
|
|
}
|
2009-11-25 19:59:26 +00:00
|
|
|
} else {
|
|
|
|
errs = 0;
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
if (!(listener = switch_core_alloc(listener_pool, sizeof(*listener)))) {
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Memory Error\n");
|
|
|
|
break;
|
|
|
|
}
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2006-09-07 03:58:01 +00:00
|
|
|
switch_thread_rwlock_create(&listener->rwlock, listener_pool);
|
2010-07-24 06:03:21 +00:00
|
|
|
switch_queue_create(&listener->event_queue, MAX_QUEUE_LEN, listener_pool);
|
|
|
|
switch_queue_create(&listener->log_queue, MAX_QUEUE_LEN, listener_pool);
|
2006-07-22 21:49:52 +00:00
|
|
|
|
|
|
|
listener->sock = inbound_socket;
|
|
|
|
listener->pool = listener_pool;
|
2006-08-29 20:27:43 +00:00
|
|
|
listener_pool = NULL;
|
2006-07-22 21:49:52 +00:00
|
|
|
listener->format = EVENT_FORMAT_PLAIN;
|
2008-12-12 15:44:37 +00:00
|
|
|
switch_set_flag(listener, LFLAG_FULL);
|
2010-01-05 19:47:49 +00:00
|
|
|
switch_set_flag(listener, LFLAG_ALLOW_LOG);
|
|
|
|
|
2006-08-29 20:27:43 +00:00
|
|
|
switch_mutex_init(&listener->flag_mutex, SWITCH_MUTEX_NESTED, listener->pool);
|
2008-10-30 00:39:55 +00:00
|
|
|
switch_mutex_init(&listener->filter_mutex, SWITCH_MUTEX_NESTED, listener->pool);
|
|
|
|
|
2006-08-29 20:27:43 +00:00
|
|
|
switch_core_hash_init(&listener->event_hash, listener->pool);
|
2007-03-29 22:31:56 +00:00
|
|
|
|
2010-05-13 15:03:49 +00:00
|
|
|
if (switch_socket_addr_get(&listener->sa, SWITCH_TRUE, listener->sock) == SWITCH_STATUS_SUCCESS && listener->sa) {
|
|
|
|
switch_get_addr(listener->remote_ip, sizeof(listener->remote_ip), listener->sa);
|
|
|
|
if (listener->sa && (listener->remote_port = switch_sockaddr_get_port(listener->sa))) {
|
|
|
|
launch_listener_thread(listener);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error initilizing connection\n");
|
|
|
|
close_socket(&listener->sock);
|
|
|
|
expire_listener(&listener);
|
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
}
|
|
|
|
|
2010-02-06 03:38:24 +00:00
|
|
|
end:
|
2009-11-25 19:59:26 +00:00
|
|
|
|
2006-07-22 21:49:52 +00:00
|
|
|
close_socket(&listen_list.sock);
|
2010-02-06 03:38:24 +00:00
|
|
|
|
2011-02-02 21:43:26 +00:00
|
|
|
if (prefs.nat_map && switch_nat_get_type()) {
|
2009-06-03 14:25:35 +00:00
|
|
|
switch_nat_del_mapping(prefs.port, SWITCH_NAT_TCP);
|
|
|
|
}
|
2006-07-22 21:49:52 +00:00
|
|
|
|
|
|
|
if (pool) {
|
|
|
|
switch_core_destroy_memory_pool(&pool);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (listener_pool) {
|
|
|
|
switch_core_destroy_memory_pool(&listener_pool);
|
|
|
|
}
|
|
|
|
|
2008-03-26 22:14:09 +00:00
|
|
|
|
2008-05-27 04:54:52 +00:00
|
|
|
for (x = 0; x < prefs.acl_count; x++) {
|
2008-03-26 22:14:09 +00:00
|
|
|
switch_safe_free(prefs.acl[x]);
|
|
|
|
}
|
|
|
|
|
2008-05-27 04:54:52 +00:00
|
|
|
fail:
|
2006-07-22 21:49:52 +00:00
|
|
|
return SWITCH_STATUS_TERM;
|
|
|
|
}
|
|
|
|
|
2006-11-27 22:30:48 +00:00
|
|
|
/* For Emacs:
|
|
|
|
* Local Variables:
|
|
|
|
* mode:c
|
2008-02-03 22:14:57 +00:00
|
|
|
* indent-tabs-mode:t
|
2006-11-27 22:30:48 +00:00
|
|
|
* tab-width:4
|
|
|
|
* c-basic-offset:4
|
|
|
|
* End:
|
|
|
|
* For VIM:
|
2008-07-03 19:12:26 +00:00
|
|
|
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
2006-11-27 22:30:48 +00:00
|
|
|
*/
|