char msgbuf[2048];
char *s;
int index = 0;
+ switch_size_t send_len;
int status = SWITCH_STATUS_SUCCESS;
switch_socket_t *sock = NULL;
switch_os_sock_put(&sock, &listener->sockdes, listener->pool);
/* sum: 542 */
switch_mutex_lock(listener->sock_mutex);
- status = switch_socket_send(sock, msgbuf, (switch_size_t *) &index);
+ send_len = (switch_size_t)index;
+ status = switch_socket_send(sock, msgbuf, &send_len);
if (status != SWITCH_STATUS_SUCCESS) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to link to process on %s\n", listener->peer_nodename);
}
/* convert an erlang reference to some kind of hashed string so we can store it as a hash key */
void ei_hash_ref(erlang_ref * ref, char *output)
{
- /* very lazy */
- sprintf(output, "%d.%d.%d@%s", ref->n[0], ref->n[1], ref->n[2], ref->node);
+ snprintf(output, EI_HASH_REF_LEN, "%d.%d.%d@%s", ref->n[0], ref->n[1], ref->n[2], ref->node);
}
%% sent to calling process after it is received. This function
%% returns the result of the initial bgapi call or `timeout' if FreeSWITCH fails
%% to respond.
--spec(bgapi/3 :: (Node :: atom(), Cmd :: atom(), Args :: string()) -> {'ok', string()} | {'error', any()} | 'timeout').
+-spec bgapi(Node :: atom(), Cmd :: atom(), Args :: string()) -> {'ok', string()} | {'error', any()} | 'timeout'.
bgapi(Node, Cmd, Args) ->
Self = self(),
% spawn a new process so that both responses go here instead of directly to
%% passed as the argument to `Fun' after it is received. This function
%% returns the result of the initial bgapi call or `timeout' if FreeSWITCH fails
%% to respond.
--spec(bgapi/4 :: (Node :: atom(), Cmd :: atom(), Args :: string(), Fun :: fun()) -> 'ok' | {'error', any()} | 'timeout').
+-spec bgapi(Node :: atom(), Cmd :: atom(), Args :: string(), Fun :: fun()) -> 'ok' | {'error', any()} | 'timeout'.
bgapi(Node, Cmd, Args, Fun) ->
Self = self(),
% spawn a new process so that both responses go here instead of directly to
} else {
switch_event_types_t etype;
if (switch_name_event(ename, &etype) == SWITCH_STATUS_SUCCESS) {
- switch_event_t *event;
+ switch_event_t *event = NULL;
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;
- int type;
- int size;
+ char *value = NULL;
+ int type;
+ int size;
int i = 0;
switch_bool_t fail = SWITCH_FALSE;
value = malloc(size + 1);
if (ei_decode_string(buf->buff, &buf->index, value)) {
- fail = SWITCH_TRUE;
+ switch_safe_free(value);
+ fail = SWITCH_TRUE;
break;
}
- if (!fail && !strcmp(key, "body")) {
+ if (!strcmp(key, "body")) {
switch_safe_free(event->body);
event->body = value;
- } else if (!fail) {
+ } else {
switch_event_add_header_string_nodup(event, SWITCH_STACK_BOTTOM, key, value);
}
value = malloc(size + 1);
if (ei_decode_string(buf->buff, &buf->index, value)) {
+ switch_safe_free(value);
fail = SWITCH_TRUE;
break;
}
- if (!fail) {
- switch_event_add_header_string_nodup(event, SWITCH_STACK_BOTTOM, key, value);
- }
+ switch_event_add_header_string_nodup(event, SWITCH_STACK_BOTTOM, key, value);
}
if (headerlength != i || fail) {
{
erlang_ref ref;
erlang_pid pid;
- char hash[100];
+ char hash[EI_HASH_REF_LEN];
int arity;
const void *key;
void *val;
for (iter = switch_core_hash_first(listener->sessions); iter; iter = switch_core_hash_next(&iter)) {
switch_core_hash_this(iter, &key, NULL, &val);
se = (session_elem_t*)val;
- if (switch_test_flag(se, LFLAG_WAITING_FOR_PID) && se->spawn_reply && !strncmp(se->spawn_reply->hash, hash, 100)) {
+ if (switch_test_flag(se, LFLAG_WAITING_FOR_PID) && se->spawn_reply && !strncmp(se->spawn_reply->hash, hash, EI_HASH_REF_LEN)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "found matching session for %s : %s\n", hash, se->uuid_str);
break;
case ERL_REFERENCE_EXT:
case ERL_NEW_REFERENCE_EXT:
+ case ERL_NEWER_REFERENCE_EXT:
ret = handle_ref_tuple(listener, msg, buf, rbuf);
break;
default:
static void listener_main_loop(listener_t *listener)
{
int status = 1;
+ int recv_erl_errno = ETIMEDOUT;
int msgs_sent = 0; /* how many messages we sent in a loop */
- while ((status >= 0 || erl_errno == ETIMEDOUT || erl_errno == EAGAIN) && !prefs.done) {
+ while ((status >= 0 || recv_erl_errno == ETIMEDOUT || recv_erl_errno == EAGAIN) && !prefs.done) {
erlang_msg msg;
ei_x_buff buf;
ei_x_buff rbuf;
/* do we need the mutex when reading? */
/*switch_mutex_lock(listener->sock_mutex); */
status = ei_xreceive_msg_tmo(listener->sockdes, &msg, &buf, 1);
+ /* snapshot erl_errno before any outbound ei call (queue flushers below)
+ clobbers this thread-local slot. */
+ recv_erl_errno = erl_errno;
/*switch_mutex_unlock(listener->sock_mutex); */
switch (status) {
if (handle_msg(listener, &msg, &buf, &rbuf)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "handle_msg requested exit\n");
+ ei_x_free(&buf);
+ ei_x_free(&rbuf);
return;
}
break;
if (handle_msg(listener, &msg, &buf, &rbuf)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "handle_msg requested exit\n");
+ ei_x_free(&buf);
+ ei_x_free(&rbuf);
return;
}
break;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "erl_unlink\n");
break;
case ERL_EXIT:
+ case ERL_EXIT2:
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "erl_exit from %s <%d.%d.%d>\n", msg.from.node, msg.from.creation, msg.from.num,
msg.from.serial);
}
break;
case ERL_ERROR:
- if (erl_errno != ETIMEDOUT && erl_errno != EAGAIN) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "erl_error: status=%d, erl_errno=%d errno=%d\n", status, erl_errno, errno);
+ if (recv_erl_errno != ETIMEDOUT && recv_erl_errno != EAGAIN) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "erl_error: status=%d, erl_errno=%d errno=%d\n", status, recv_erl_errno, errno);
}
break;
default:
if (prefs.done) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "shutting down listener\n");
} else {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "listener exit: status=%d, erl_errno=%d errno=%d\n", status, erl_errno, errno);
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "listener exit: status=%d, erl_errno=%d errno=%d\n", status, recv_erl_errno, errno);
}
}
{
/* create a session list element */
session_elem_t *session_element = session_elem_create(listener, session);
- char hash[100];
+ char hash[EI_HASH_REF_LEN];
spawn_reply_t *p;
erlang_ref ref;
ei_x_buff buf;
listener_t *listener;
- ei_x_new_with_version(&buf);
-
/* process app arguments */
if (data && (mydata = switch_core_session_strdup(session, data))) {
argc = switch_separate_string(mydata, ' ', argv, 3);
/*switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "sendmsg: {%s, %s} ! %s\n", reg_name, node, argv[2]); */
+ ei_x_new_with_version(&buf);
ei_x_encode_tuple_header(&buf, 2);
ei_x_encode_atom(&buf, "freeswitch_sendmsg");
_ei_x_encode_string(&buf, argv[2]);
switch_thread_rwlock_unlock(listener->rwlock);
}
+
+ ei_x_free(&buf);
}
int handle_msg(listener_t *listener, erlang_msg * msg, ei_x_buff * buf, ei_x_buff * rbuf);
/* ei_helpers.c */
+#define EI_HASH_REF_LEN (MAXATOMLEN_UTF8 + 64)
void ei_link(listener_t *listener, erlang_pid * from, erlang_pid * to);
void ei_encode_switch_event_headers(ei_x_buff * ebuf, switch_event_t *event);
void ei_encode_switch_event_tag(ei_x_buff * ebuf, switch_event_t *event, char *tag);