int ei_helper_send(ei_node_t *ei_node, erlang_pid *to, ei_x_buff *buf) { int ret = 0; if (ei_node->nodefd) { #ifdef EI_DEBUG ei_x_print_msg(buf, to, 1); #endif ret = ei_send(ei_node->nodefd, to, buf->buff, buf->index); } return ret; }
int ei_sendto(ei_cnode * ec, int fd, struct erlang_process *process, ei_x_buff * buf) { int ret; if (process->type == ERLANG_PID) { ret = ei_send(fd, &process->pid, buf->buff, buf->index); #ifdef EI_DEBUG ei_x_print_msg(buf, &process->pid, 1); #endif } else if (process->type == ERLANG_REG_PROCESS) { ret = ei_reg_send(ec, fd, process->reg_name, buf->buff, buf->index); #ifdef EI_DEBUG ei_x_print_reg_msg(buf, process->reg_name, 1); #endif } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid process type!\n"); /* wuh-oh */ ret = -1; } return ret; }
static void *SWITCH_THREAD_FUNC api_exec(switch_thread_t *thread, void *obj) { switch_bool_t r = SWITCH_TRUE; struct api_command_struct *acs = (struct api_command_struct *) obj; switch_stream_handle_t stream = { 0 }; char *reply, *freply = NULL; switch_status_t status; if (!acs) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Internal error.\n"); return NULL; } if (!acs->listener || !acs->listener->rwlock || switch_thread_rwlock_tryrdlock(acs->listener->rwlock) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error! cannot get read lock.\n"); goto done; } SWITCH_STANDARD_STREAM(stream); if ((status = switch_api_execute(acs->api_cmd, acs->arg, NULL, &stream)) == SWITCH_STATUS_SUCCESS) { reply = stream.data; } else { freply = switch_mprintf("%s: Command not found!\n", acs->api_cmd); reply = freply; r = SWITCH_FALSE; } if (!reply) { reply = "Command returned no output!"; r = SWITCH_FALSE; } if (*reply == '-') r = SWITCH_FALSE; if (acs->bg) { switch_event_t *event; if (switch_event_create(&event, SWITCH_EVENT_BACKGROUND_JOB) == SWITCH_STATUS_SUCCESS) { ei_x_buff ebuf; 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); ei_x_new_with_version(&ebuf); if (acs->arg) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-Command-Arg", acs->arg); } switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "Job-Successful", r ? "true" : "false"); switch_event_add_body(event, "%s", reply); switch_event_fire(&event); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Sending bgapi reply to %s\n", acs->pid.node); ei_x_encode_tuple_header(&ebuf, 3); if (r) ei_x_encode_atom(&ebuf, "bgok"); else ei_x_encode_atom(&ebuf, "bgerror"); _ei_x_encode_string(&ebuf, acs->uuid_str); _ei_x_encode_string(&ebuf, reply); switch_mutex_lock(acs->listener->sock_mutex); ei_send(acs->listener->sockfd, &acs->pid, ebuf.buff, ebuf.index); switch_mutex_unlock(acs->listener->sock_mutex); #ifdef EI_DEBUG ei_x_print_msg(&ebuf, &acs->pid, 1); #endif ei_x_free(&ebuf); } } else { ei_x_buff rbuf; ei_x_new_with_version(&rbuf); ei_x_encode_tuple_header(&rbuf, 2); if (!strlen(reply)) { reply = "Command returned no output!"; r = SWITCH_FALSE; } if (r) { ei_x_encode_atom(&rbuf, "ok"); } else { ei_x_encode_atom(&rbuf, "error"); } _ei_x_encode_string(&rbuf, reply); switch_mutex_lock(acs->listener->sock_mutex); ei_send(acs->listener->sockfd, &acs->pid, rbuf.buff, rbuf.index); switch_mutex_unlock(acs->listener->sock_mutex); #ifdef EI_DEBUG ei_x_print_msg(&rbuf, &acs->pid, 1); #endif ei_x_free(&rbuf); } switch_safe_free(stream.data); switch_safe_free(freply); if (acs->listener->rwlock) { switch_thread_rwlock_unlock(acs->listener->rwlock); } done: if (acs->bg) { switch_memory_pool_t *pool = acs->pool; acs = NULL; switch_core_destroy_memory_pool(&pool); pool = NULL; } return NULL; }
/* {'$gen_call', {<[email protected]>, #Ref<254770.4.0>}, {is_auth, cpx@freecpx} */ static switch_status_t handle_net_kernel_msg(listener_t *listener, erlang_msg * msg, ei_x_buff * buf, ei_x_buff * rbuf) { int version, size, type, arity; char atom[MAXATOMLEN]; erlang_ref ref; erlang_pid pid; buf->index = 0; ei_decode_version(buf->buff, &buf->index, &version); ei_get_type(buf->buff, &buf->index, &type, &size); if (type != ERL_SMALL_TUPLE_EXT && type != ERL_SMALL_TUPLE_EXT) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "not a tuple\n"); return SWITCH_STATUS_FALSE; } ei_decode_tuple_header(buf->buff, &buf->index, &arity); if (arity != 3) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "wrong arity\n"); return SWITCH_STATUS_FALSE; } if (ei_decode_atom(buf->buff, &buf->index, atom) || strncmp(atom, "$gen_call", MAXATOMLEN)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "not gen_call\n"); return SWITCH_STATUS_FALSE; } ei_get_type(buf->buff, &buf->index, &type, &size); if (type != ERL_SMALL_TUPLE_EXT && type != ERL_SMALL_TUPLE_EXT) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "not a tuple\n"); return SWITCH_STATUS_FALSE; } ei_decode_tuple_header(buf->buff, &buf->index, &arity); if (arity != 2) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "wrong arity\n"); return SWITCH_STATUS_FALSE; } if (ei_decode_pid(buf->buff, &buf->index, &pid) || ei_decode_ref(buf->buff, &buf->index, &ref)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "decoding pid and ref error\n"); return SWITCH_STATUS_FALSE; } ei_get_type(buf->buff, &buf->index, &type, &size); if (type != ERL_SMALL_TUPLE_EXT && type != ERL_SMALL_TUPLE_EXT) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "not a tuple\n"); return SWITCH_STATUS_FALSE; } ei_decode_tuple_header(buf->buff, &buf->index, &arity); if (arity != 2) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "bad arity\n"); return SWITCH_STATUS_FALSE; } if (ei_decode_atom(buf->buff, &buf->index, atom) || strncmp(atom, "is_auth", MAXATOMLEN)) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "not is_auth\n"); return SWITCH_STATUS_FALSE; } /* To ! {Tag, Reply} */ ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_ref(rbuf, &ref); ei_x_encode_atom(rbuf, "yes"); switch_mutex_lock(listener->sock_mutex); ei_send(listener->sockfd, &pid, rbuf->buff, rbuf->index); switch_mutex_unlock(listener->sock_mutex); #ifdef EI_DEBUG ei_x_print_msg(rbuf, &pid, 1); #endif return SWITCH_STATUS_FALSE; }
int handle_msg(listener_t *listener, erlang_msg * msg, ei_x_buff * buf, ei_x_buff * rbuf) { int type, type2, size, version, arity, tmpindex; switch_status_t ret = SWITCH_STATUS_SUCCESS; if (msg->msgtype == ERL_REG_SEND && !strncmp(msg->toname, "net_kernel", MAXATOMLEN)) { /* try to respond to ping stuff */ ret = handle_net_kernel_msg(listener, msg, buf, rbuf); } else { buf->index = 0; ei_decode_version(buf->buff, &buf->index, &version); ei_get_type(buf->buff, &buf->index, &type, &size); switch (type) { case ERL_SMALL_TUPLE_EXT: case ERL_LARGE_TUPLE_EXT: tmpindex = buf->index; ei_decode_tuple_header(buf->buff, &tmpindex, &arity); ei_get_type(buf->buff, &tmpindex, &type2, &size); switch (type2) { case ERL_ATOM_EXT: ret = handle_msg_tuple(listener, msg, buf, rbuf); break; case ERL_REFERENCE_EXT: case ERL_NEW_REFERENCE_EXT: ret = handle_ref_tuple(listener, msg, buf, rbuf); break; default: switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "WEEEEEEEE %d %d\n", type, type2); /* some other kind of erlang term */ ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "undef"); break; } break; case ERL_ATOM_EXT: ret = handle_msg_atom(listener, msg, buf, rbuf); break; default: /* some other kind of erlang term */ ei_x_encode_tuple_header(rbuf, 2); ei_x_encode_atom(rbuf, "error"); ei_x_encode_atom(rbuf, "undef"); break; } } if (SWITCH_STATUS_FALSE == ret) { return 0; } else if (rbuf->index > 1) { switch_mutex_lock(listener->sock_mutex); ei_send(listener->sockfd, &msg->from, rbuf->buff, rbuf->index); switch_mutex_unlock(listener->sock_mutex); #ifdef EI_DEBUG ei_x_print_msg(rbuf, &msg->from, 1); #endif if (SWITCH_STATUS_SUCCESS == ret) return 0; else /* SWITCH_STATUS_TERM */ return 1; } else { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Empty reply, supressing\n"); return 0; } }