struct mi_root *run_rcv_mi_cmd(str *cmd_name, str *cmd_params, int nr_params) { struct mi_cmd *f; struct mi_root *cmd_root = NULL, *cmd_rpl; int i; f = lookup_mi_cmd(cmd_name->s, cmd_name->len); if (!f) { LM_ERR("MI command to be run not found\n"); return NULL; } if (f->flags & MI_NO_INPUT_FLAG && nr_params) { LM_ERR("MI command should not have parameters\n"); return NULL; } if (!(f->flags & MI_NO_INPUT_FLAG)) { cmd_root = init_mi_tree(0,0,0); if (!cmd_root) { LM_ERR("the MI tree for the command to be run cannot be initialized!\n"); return NULL; } } for (i = 0; i < nr_params; i++) if (!add_mi_node_child(&cmd_root->node, 0, 0, 0, cmd_params[i].s, cmd_params[i].len)) { free_mi_tree(cmd_root); LM_ERR("cannot add child node to the tree of the MI command to be run\n"); return NULL; } if ((cmd_rpl = run_mi_cmd(f, cmd_root, 0, 0)) == NULL) { if (cmd_root) free_mi_tree(cmd_root); return NULL; } if (cmd_root) free_mi_tree(cmd_root); return cmd_rpl; }
static struct mi_root *run_mi_cmd_local(struct mi_cmd *f, str *cmd_params, int nr_params, struct mi_handler *async_hdl) { struct mi_root *cmd_root = NULL, *cmd_rpl; int i; if (f->flags & MI_NO_INPUT_FLAG && nr_params) return init_mi_tree(400, MI_SSTR(MI_MISSING_PARM_S)); if (!(f->flags & MI_NO_INPUT_FLAG)) { cmd_root = init_mi_tree(0,0,0); if (!cmd_root) { LM_ERR("the MI tree for the command to be run cannot be initialized!\n"); return init_mi_tree(400, MI_SSTR(MI_INTERNAL_ERR)); } cmd_root->async_hdl = async_hdl; } for (i = 0; i < nr_params; i++) if (!add_mi_node_child(&cmd_root->node, 0, 0, 0, cmd_params[i].s, cmd_params[i].len)) { LM_ERR("cannot add child node to the tree of the MI command to be run\n"); free_mi_tree(cmd_root); return init_mi_tree(400, MI_SSTR(MI_INTERNAL_ERR)); } if ((cmd_rpl = run_mi_cmd(f, cmd_root, 0, 0)) == NULL) { if (cmd_root) free_mi_tree(cmd_root); return init_mi_tree(400, MI_SSTR("MI command to be run failed")); } if (cmd_root) free_mi_tree(cmd_root); return cmd_rpl; }
void mi_fifo_server(FILE *fifo_stream) { struct mi_root *mi_cmd; struct mi_root *mi_rpl; struct mi_handler *hdl; int line_len; char *file_sep, *command, *file; struct mi_cmd *f; FILE *reply_stream; while(1) { reply_stream = NULL; /* commands must look this way ':<command>:[filename]' */ if (mi_read_line(mi_buf,MAX_MI_FIFO_BUFFER,fifo_stream, &line_len)) { LM_ERR("failed to read command\n"); continue; } /* trim from right */ while(line_len) { if(mi_buf[line_len-1]=='\n' || mi_buf[line_len-1]=='\r' || mi_buf[line_len-1]==' ' || mi_buf[line_len-1]=='\t' ) { line_len--; mi_buf[line_len]=0; } else break; } if (line_len==0) { LM_DBG("command empty\n"); continue; } if (line_len<3) { LM_ERR("command must have at least 3 chars\n"); continue; } if (*mi_buf!=MI_CMD_SEPARATOR) { LM_ERR("command must begin with %c: %.*s\n", MI_CMD_SEPARATOR, line_len, mi_buf ); goto consume1; } command = mi_buf+1; file_sep=strchr(command, MI_CMD_SEPARATOR ); if (file_sep==NULL) { LM_ERR("file separator missing\n"); goto consume1; } if (file_sep==command) { LM_ERR("empty command\n"); goto consume1; } if (*(file_sep+1)==0) { file = NULL; } else { file = file_sep+1; file = get_reply_filename(file, mi_buf+line_len-file); if (file==NULL) { LM_ERR("trimming filename\n"); goto consume1; } } /* make command zero-terminated */ *file_sep=0; f=lookup_mi_cmd( command, strlen(command) ); if (f==0) { LM_ERR("command %s is not available\n", command); mi_open_reply( file, reply_stream, consume1); mi_fifo_reply( reply_stream, "500 command '%s' not available\n", command); goto consume2; } /* if asyncron cmd, build the async handler */ if (f->flags&MI_ASYNC_RPL_FLAG) { hdl = build_async_handler( file, strlen(file) ); if (hdl==0) { LM_ERR("failed to build async handler\n"); mi_open_reply( file, reply_stream, consume1); mi_fifo_reply( reply_stream, "500 Internal server error\n"); goto consume2; } } else { hdl = 0; mi_open_reply( file, reply_stream, consume1); } if (f->flags&MI_NO_INPUT_FLAG) { mi_cmd = 0; mi_do_consume(); } else { mi_cmd = mi_parse_tree(fifo_stream); if (mi_cmd==NULL) { LM_ERR("error parsing MI tree\n"); if (!reply_stream) mi_open_reply( file, reply_stream, consume3); mi_fifo_reply( reply_stream, "400 parse error in " "command '%s'\n", command); goto consume3; } mi_cmd->async_hdl = hdl; } LM_DBG("done parsing the mi tree\n"); if ( (mi_rpl=run_mi_cmd(f, mi_cmd, (mi_flush_f *)mi_flush_tree, reply_stream))==0 ) { if (!reply_stream) mi_open_reply( file, reply_stream, failure); mi_fifo_reply(reply_stream, "500 command '%s' failed\n", command); LM_ERR("command (%s) processing failed\n", command ); } else if (mi_rpl!=MI_ROOT_ASYNC_RPL) { if (!reply_stream) mi_open_reply( file, reply_stream, failure); mi_write_tree( reply_stream, mi_rpl); free_mi_tree( mi_rpl ); } else { if (mi_cmd) free_mi_tree( mi_cmd ); continue; } free_async_handler(hdl); /* close reply fifo */ fclose(reply_stream); /* destroy request tree */ if (mi_cmd) free_mi_tree( mi_cmd ); continue; failure: free_async_handler(hdl); /* destroy request tree */ if (mi_cmd) free_mi_tree( mi_cmd ); /* destroy the reply tree */ if (mi_rpl) free_mi_tree(mi_rpl); continue; consume3: free_async_handler(hdl); if (reply_stream) consume2: fclose(reply_stream); consume1: mi_do_consume(); } }
void mi_datagram_server(int rx_sock, int tx_sock) { struct mi_root *mi_cmd; struct mi_root *mi_rpl; struct mi_handler *hdl; struct mi_cmd * f; datagram_stream dtgram; int ret, len; ret = 0; f = 0; while(1){/*read the datagram*/ memset(mi_buf, 0, DATAGRAM_SOCK_BUF_SIZE); reply_addr_len = sizeof(reply_addr); /* get the client's address */ ret = recvfrom(rx_sock, mi_buf, DATAGRAM_SOCK_BUF_SIZE, 0, (struct sockaddr*)&reply_addr, &reply_addr_len); if (ret == -1) { LM_ERR("recvfrom: (%d) %s\n", errno, strerror(errno)); if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == ECONNREFUSED)) { LM_DBG("got %d (%s), going on\n", errno, strerror(errno)); continue; } LM_DBG("error in recvfrom\n"); continue; } if(ret == 0) continue; LM_DBG("received %.*s\n", ret, mi_buf); if(ret> DATAGRAM_SOCK_BUF_SIZE){ LM_ERR("buffer overflow\n"); continue; } LM_DBG("mi_buf is %s and we have received %i bytes\n",mi_buf, ret); dtgram.start = mi_buf; dtgram.len = ret; dtgram.current = dtgram.start; ret = identify_command(&dtgram, &f); /*analyze the command--from the first line*/ if(ret != 0) { LM_ERR("command not available\n"); mi_send_dgram(tx_sock, MI_COMMAND_NOT_AVAILABLE, MI_COMMAND_AVAILABLE_LEN, (struct sockaddr* )&reply_addr, reply_addr_len, mi_socket_timeout); continue; } LM_DBG("we have a valid command \n"); /* if asyncron cmd, build the async handler */ if (f->flags&MI_ASYNC_RPL_FLAG) { hdl = build_async_handler(mi_socket_domain, &reply_addr, reply_addr_len, tx_sock); if (hdl==0) { LM_ERR("failed to build async handler\n"); mi_send_dgram(tx_sock, MI_INTERNAL_ERROR, MI_INTERNAL_ERROR_LEN,(struct sockaddr* )&reply_addr, reply_addr_len, mi_socket_timeout); continue; } } else{ hdl = 0; } LM_DBG("after identifing the command, the received datagram is %s\n", dtgram.current); /*if no params required*/ if (f->flags&MI_NO_INPUT_FLAG) { LM_DBG("the command has no params\n"); mi_cmd = 0; } else { LM_DBG("parsing the command's params\n"); mi_cmd = mi_datagram_parse_tree(&dtgram); if (mi_cmd==NULL){ LM_ERR("failed to parse the MI tree\n"); mi_send_dgram(tx_sock, MI_PARSE_ERROR, MI_PARSE_ERROR_LEN, (struct sockaddr* )&reply_addr, reply_addr_len, mi_socket_timeout); free_async_handler(hdl); continue; } mi_cmd->async_hdl = hdl; } LM_DBG("done parsing the mi tree\n"); if ( (mi_rpl=run_mi_cmd(f, mi_cmd, (mi_flush_f *)mi_datagram_flush_tree, &dtgram))==0 ) { /*error while running the command*/ LM_ERR("failed to process the command\n"); mi_send_dgram(tx_sock, MI_COMMAND_FAILED, MI_COMMAND_FAILED_LEN, (struct sockaddr* )&reply_addr, reply_addr_len, mi_socket_timeout); goto failure; } /*the command exited well*/ LM_DBG("command process (%s)succeded\n",f->name.s); if (mi_rpl!=MI_ROOT_ASYNC_RPL) { if(mi_datagram_write_tree(&dtgram , mi_rpl) != 0){ LM_ERR("failed to build the response \n"); goto failure; } len = dtgram.current - dtgram.start; ret = mi_send_dgram(tx_sock, dtgram.start,len, (struct sockaddr* )&reply_addr, reply_addr_len, mi_socket_timeout); if (ret>0){ LM_DBG("the response: %s has been sent in %i octets\n", dtgram.start, ret); }else{ LM_ERR("failed to send the response: %s (%d)\n", strerror(errno), errno); } free_mi_tree( mi_rpl ); free_async_handler(hdl); if (mi_cmd) free_mi_tree( mi_cmd ); }else { if (mi_cmd) free_mi_tree( mi_cmd ); } continue; failure: free_async_handler(hdl); /* destroy request tree */ if (mi_cmd) free_mi_tree( mi_cmd ); /* destroy the reply tree */ if (mi_rpl) free_mi_tree(mi_rpl); continue; } }
static void rpc_mi_exec(rpc_t *rpc, void *ctx, enum mi_rpc_print_mode mode) { str cmd; struct mi_cmd *mic; struct mi_root *mi_req; struct mi_root *mi_rpl; struct mi_handler* mi_async_h; struct mi_rpc_handler_param* mi_handler_param; if (rpc->scan(ctx, "S", &cmd) < 1) { LM_ERR("command parameter not found\n"); rpc->fault(ctx, 500, "command parameter missing"); return; } mi_async_h=0; mi_req = 0; mi_rpl=0; mic = lookup_mi_cmd(cmd.s, cmd.len); if(mic==0) { LM_ERR("mi command %.*s is not available\n", cmd.len, cmd.s); rpc->fault(ctx, 500, "command not available"); return; } if (mic->flags&MI_ASYNC_RPL_FLAG) { if (rpc->capabilities==0 || !(rpc->capabilities(ctx) & RPC_DELAYED_REPLY)) { rpc->fault(ctx, 500, "this rpc transport does not support async mode"); return; } } if(!(mic->flags&MI_NO_INPUT_FLAG)) { mi_req = mi_rpc_read_params(rpc, ctx); if(mi_req==NULL) { LM_ERR("cannot parse parameters\n"); rpc->fault(ctx, 500, "cannot parse parameters"); goto error; } if (mic->flags&MI_ASYNC_RPL_FLAG) { /* build mi async handler */ mi_handler_param=shm_malloc(sizeof(*mi_handler_param)); if (mi_handler_param==0) { rpc->fault(ctx, 500, "out of memory"); return; } mi_async_h=shm_malloc(sizeof(*mi_async_h)); if (mi_async_h==0) { shm_free(mi_handler_param); mi_handler_param=0; rpc->fault(ctx, 500, "out of memory"); return; } memset(mi_async_h, 0, sizeof(*mi_async_h)); mi_async_h->handler_f=mi_rpc_async_close; mi_handler_param->mode=mode; mi_handler_param->dctx=rpc->delayed_ctx_new(ctx); if (mi_handler_param->dctx==0) { rpc->fault(ctx, 500, "internal error: async ctx" " creation failed"); goto error; } /* switch context, since replies are not allowed anymore on the original one */ rpc=&mi_handler_param->dctx->rpc; ctx=mi_handler_param->dctx->reply_ctx; mi_async_h->param=mi_handler_param; } mi_req->async_hdl=mi_async_h; } mi_rpl=run_mi_cmd(mic, mi_req); if(mi_rpl == 0) { rpc->fault(ctx, 500, "execution failed"); goto error; } if (mi_rpl!=MI_ROOT_ASYNC_RPL) { mi_rpc_print_tree(rpc, ctx, mi_rpl, mode); goto end; } else if (mi_async_h==0) { /* async reply, but command not listed as async */ rpc->fault(ctx, 500, "bad mi command: unexpected async reply"); goto error; } mi_async_h=0; /* don't delete it */ end: error: if (mi_req) free_mi_tree(mi_req); if (mi_rpl && mi_rpl!=MI_ROOT_ASYNC_RPL) free_mi_tree(mi_rpl); if (mi_async_h) { if (mi_async_h->param) { if (((struct mi_rpc_handler_param*)mi_async_h->param)->dctx) rpc->delayed_ctx_close(((struct mi_rpc_handler_param*) mi_async_h->param)->dctx); shm_free(mi_async_h->param); } shm_free(mi_async_h); } return; }
xmlrpc_value* default_method (xmlrpc_env* env, const char* host, const char* methodName, xmlrpc_value* paramArray, void* serverInfo) #endif { xmlrpc_value* ret = NULL; struct mi_root* mi_cmd = NULL; struct mi_root* mi_rpl = NULL; struct mi_handler *hdl = NULL; struct mi_cmd* f; char* response = 0; int is_shm = 0; LM_DBG("starting up.....\n"); f = lookup_mi_cmd((char*)methodName, strlen(methodName)); if ( f == 0 ) { LM_ERR("command %s is not available!\n", methodName); xmlrpc_env_set_fault_formatted(env, XMLRPC_NO_SUCH_METHOD_ERROR, "Requested command (%s) is not available!", methodName); goto error; } LM_DBG("done looking the mi command.\n"); /* if asyncron cmd, build the async handler */ if (f->flags&MI_ASYNC_RPL_FLAG) { hdl = build_async_handler( ); if (hdl==0) { LM_ERR("failed to build async handler\n"); if ( !env->fault_occurred ) xmlrpc_env_set_fault(env, XMLRPC_INTERNAL_ERROR, "Internal server error while processing request"); goto error; } } else { hdl = NULL; } if (f->flags&MI_NO_INPUT_FLAG) { mi_cmd = 0; } else { mi_cmd = xr_parse_tree(env, paramArray); if ( mi_cmd == NULL ){ LM_ERR("failed to parse MI tree\n"); if ( !env->fault_occurred ) xmlrpc_env_set_fault(env, XMLRPC_INTERNAL_ERROR, "The xmlrpc request could not be parsed into a MI tree!"); goto error; } mi_cmd->async_hdl = hdl; } LM_DBG("done parsing the mi tree.\n"); if ( ( mi_rpl = run_mi_cmd(f, mi_cmd) ) == 0 ){ LM_ERR("command (%s) processing failed.\n", methodName); xmlrpc_env_set_fault_formatted(env, XMLRPC_INTERNAL_ERROR, "Command (%s) processing failed.\n", methodName); goto error; } else if (mi_rpl==MI_ROOT_ASYNC_RPL) { mi_rpl = wait_async_reply(hdl); hdl = 0; if (mi_rpl==0) { xmlrpc_env_set_fault_formatted(env, XMLRPC_INTERNAL_ERROR, "Command (%s) processing failed (async).\n", methodName); goto error; } is_shm = 1; } LM_DBG("done running the mi command.\n"); if ( rpl_opt == 1 ) { if ( xr_build_response_array( env, mi_rpl ) != 0 ){ if ( !env->fault_occurred ) { LM_ERR("failed parsing the xmlrpc response from the mi tree\n"); xmlrpc_env_set_fault(env, XMLRPC_INTERNAL_ERROR, "Failed to parse the xmlrpc response from the mi tree."); } goto error; } LM_DBG("done building response array.\n"); ret = xr_response; } else { if ( (response = xr_build_response( env, mi_rpl )) == 0 ){ if ( !env->fault_occurred ) { LM_ERR("failed parsing the xmlrpc response from the mi tree\n"); xmlrpc_env_set_fault_formatted(env, XMLRPC_INTERNAL_ERROR, "Failed to parse the xmlrpc response from the mi tree."); } goto error; } LM_DBG("done building response.\n"); ret = xmlrpc_build_value(env, "s", response); } error: free_async_handler(hdl); if ( mi_cmd ) free_mi_tree( mi_cmd ); if ( mi_rpl ) { is_shm?free_shm_mi_tree(mi_rpl):free_mi_tree(mi_rpl);} return ret; }