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();
    }
}
Exemple #4
0
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;
	}
}
Exemple #5
0
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;
}
Exemple #6
0
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;
}