From 994f9a8ca622aa301250413760997b7ba3c25218 Mon Sep 17 00:00:00 2001 From: Darren Schreiber Date: Fri, 30 Sep 2011 21:57:25 -0400 Subject: [PATCH] Fixed a memory leak, too short of connect times across data centers, a deadlock condition with the globals.bindings_rwlock not being released, a buffer overrun possibility or 4, and added the ability to send a body when injecting an event --- .../mod_erlang_event/handle_msg.c | 89 ++++++++++++++++--- .../mod_erlang_event/mod_erlang_event.c | 5 +- 2 files changed, 79 insertions(+), 15 deletions(-) diff --git a/src/mod/event_handlers/mod_erlang_event/handle_msg.c b/src/mod/event_handlers/mod_erlang_event/handle_msg.c index 87f91fc51b..2f45ea6203 100644 --- a/src/mod/event_handlers/mod_erlang_event/handle_msg.c +++ b/src/mod/event_handlers/mod_erlang_event/handle_msg.c @@ -26,6 +26,8 @@ * Anthony Minessale II * Andrew Thompson * Rob Charlton + * Darren Schreiber + * Mike Jerris * * * handle_msg.c -- handle messages received from erlang nodes @@ -590,13 +592,29 @@ static switch_status_t handle_msg_session_setevent(listener_t *listener, erlang_ static switch_status_t handle_msg_api(listener_t *listener, erlang_msg * msg, int arity, ei_x_buff * buf, ei_x_buff * rbuf) { char api_cmd[MAXATOMLEN]; - char arg[1024]; - if (arity < 3 || ei_decode_atom(buf->buff, &buf->index, api_cmd) || ei_decode_string(buf->buff, &buf->index, arg)) { - ei_x_encode_tuple_header(rbuf, 2); - ei_x_encode_atom(rbuf, "error"); - ei_x_encode_atom(rbuf, "badarg"); - return SWITCH_STATUS_SUCCESS; - } else { + int type; + int size; + char *arg; + switch_bool_t fail = SWITCH_FALSE; + + if (arity < 3) { + fail = SWITCH_TRUE; + } + + ei_get_type(buf->buff, &buf->index, &type, &size); + + if ((size > (sizeof(api_cmd) - 1)) || ei_decode_atom(buf->buff, &buf->index, api_cmd)) { + fail = SWITCH_TRUE; + } + + ei_get_type(buf->buff, &buf->index, &type, &size); + arg = malloc(size + 1); + + if (ei_decode_string(buf->buff, &buf->index, arg)) { + fail = SWITCH_TRUE; + } + + if (!fail) { struct api_command_struct acs = { 0 }; acs.listener = listener; acs.api_cmd = api_cmd; @@ -604,8 +622,17 @@ static switch_status_t handle_msg_api(listener_t *listener, erlang_msg * msg, in acs.bg = 0; acs.pid = msg->from; api_exec(NULL, (void *) &acs); + + switch_safe_free(arg); + /* don't reply */ return SWITCH_STATUS_FALSE; + } else { + ei_x_encode_tuple_header(rbuf, 2); + ei_x_encode_atom(rbuf, "error"); + ei_x_encode_atom(rbuf, "badarg"); + return SWITCH_STATUS_SUCCESS; + } } @@ -670,18 +697,38 @@ static switch_status_t handle_msg_sendevent(listener_t *listener, int arity, ei_ if ((strlen(esname) && switch_event_create_subclass(&event, etype, esname) == SWITCH_STATUS_SUCCESS) || switch_event_create(&event, etype) == SWITCH_STATUS_SUCCESS) { char key[1024]; - char value[1024]; + char *value; + int type; + int size; int i = 0; switch_bool_t fail = SWITCH_FALSE; while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && arity == 2) { i++; - if (ei_decode_string(buf->buff, &buf->index, key) || ei_decode_string(buf->buff, &buf->index, value)) { + + ei_get_type(buf->buff, &buf->index, &type, &size); + + if ((size > (sizeof(key) - 1)) || ei_decode_string(buf->buff, &buf->index, key)) { fail = SWITCH_TRUE; break; } - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, key, value); + ei_get_type(buf->buff, &buf->index, &type, &size); + value = malloc(size + 1); + + if (ei_decode_string(buf->buff, &buf->index, value)) { + fail = SWITCH_TRUE; + break; + } + + if (!fail && !strcmp(key, "body")) { + switch_safe_free(event->body); + event->body = value; + } else if (!fail) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, key, value); + } + + /* Do not free malloc here! The above commands utilize the raw allocated memory and skip any copying/duplication. Faster. */ } if (headerlength != i || fail) { @@ -715,16 +762,32 @@ static switch_status_t handle_msg_sendmsg(listener_t *listener, int arity, ei_x_ if (switch_event_create(&event, SWITCH_EVENT_SEND_MESSAGE) == SWITCH_STATUS_SUCCESS) { char key[1024]; - char value[1024]; + char *value; + int type; + int size; int i = 0; switch_bool_t fail = SWITCH_FALSE; + while (!ei_decode_tuple_header(buf->buff, &buf->index, &arity) && arity == 2) { i++; - if (ei_decode_string(buf->buff, &buf->index, key) || ei_decode_string(buf->buff, &buf->index, value)) { + ei_get_type(buf->buff, &buf->index, &type, &size); + + if ((size > (sizeof(key) - 1)) || ei_decode_string(buf->buff, &buf->index, key)) { fail = SWITCH_TRUE; break; } - switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, key, value); + + ei_get_type(buf->buff, &buf->index, &type, &size); + value = malloc(size + 1); + + if (ei_decode_string(buf->buff, &buf->index, value)) { + fail = SWITCH_TRUE; + break; + } + + if (!fail) { + switch_event_add_header_string(event, SWITCH_STACK_BOTTOM | SWITCH_STACK_NODUP, key, value); + } } if (headerlength != i || fail) { diff --git a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c index 92e30ecfb6..2ed139862c 100644 --- a/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c +++ b/src/mod/event_handlers/mod_erlang_event/mod_erlang_event.c @@ -389,6 +389,7 @@ static switch_xml_t erlang_fetch(const char *sectionstr, const char *tag_name, c if (!ptr->listener) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "NULL pointer binding!\n"); + switch_thread_rwlock_unlock(globals.bindings_rwlock); goto cleanup; /* our pointer is trash */ } @@ -820,7 +821,7 @@ static void listener_main_loop(listener_t *listener) /* do we need the mutex when reading? */ /*switch_mutex_lock(listener->sock_mutex); */ - status = ei_xreceive_msg_tmo(listener->sockfd, &msg, &buf, 100); + status = ei_xreceive_msg_tmo(listener->sockfd, &msg, &buf, 500); /*switch_mutex_unlock(listener->sock_mutex); */ switch (status) { @@ -1818,7 +1819,7 @@ SWITCH_MODULE_RUNTIME_FUNCTION(mod_erlang_event_runtime) #else errno = 0; #endif - if ((clientfd = ei_accept_tmo(&ec, (int) listen_list.sockfd, &conn, 100)) == ERL_ERROR) { + if ((clientfd = ei_accept_tmo(&ec, (int) listen_list.sockfd, &conn, 500)) == ERL_ERROR) { if (prefs.done) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "Shutting Down\n"); } else if (erl_errno == ETIMEDOUT) {