Example #1
0
struct mi_root *mi_help(struct mi_root *root, void *param)
{
	struct mi_root *rpl_tree = 0;
	struct mi_node *node;
	struct mi_node *rpl;
	struct mi_cmd *cmd;

	if (!root) {
		LM_ERR("invalid MI command\n");
		return 0;
	}
	node = root->node.kids;
	if (!node || !node->value.len || !node->value.s) {
		rpl_tree = init_mi_tree(200, MI_SSTR(MI_OK));
		if (!rpl_tree) {
			LM_ERR("cannot init mi tree\n");
			return 0;
		}
		rpl = &rpl_tree->node;
		if (!add_mi_node_child(rpl, 0, "Usage", 5, MI_SSTR(MI_HELP_STR))) {
			LM_ERR("cannot add new child\n");
			goto error;
		}
	} else {
		/* search the command */
		cmd = lookup_mi_cmd(node->value.s, node->value.len);
		if (!cmd)
			return init_mi_tree(404, MI_SSTR(MI_UNKNOWN_CMD));
		rpl_tree = init_mi_tree(200, MI_SSTR(MI_OK));
		if (!rpl_tree) {
			LM_ERR("cannot init mi tree\n");
			return 0;
		}
		rpl = &rpl_tree->node;
		if (!addf_mi_node_child(rpl, 0, "Help", 4, "%s", cmd->help.s ?
					cmd->help.s : MI_NO_HELP)) {
			LM_ERR("cannot add new child\n");
			goto error;
		}
		if (cmd->module.len && cmd->module.s &&
				!add_mi_node_child(rpl, 0, "Exported by", 11,
					cmd->module.s, cmd->module.len)) {
			LM_ERR("cannot add new child\n");
			goto error;
		}
	}

	return rpl_tree;

error:
	if (rpl_tree)
		free_mi_tree(rpl_tree);
	return 0;
}
Example #2
0
static struct mi_root* cluster_bcast_mi(struct mi_root *cmd, void *param)
{
	struct mi_node *node, *cmd_params_n;
	struct mi_cmd *f;
	unsigned int cluster_id;
	int rc;
	str cl_cmd_name;
	str cl_cmd_params[MI_CMD_MAX_NR_PARAMS];
	int no_params = 0;

	node = cmd->node.kids;

	if (node == NULL || node->next == NULL || node->next->next == NULL)
		return init_mi_tree(400, MI_SSTR(MI_MISSING_PARM));

	rc = str2int(&node->value, &cluster_id);
	if (rc < 0 || cluster_id < 1)
		return init_mi_tree(400, MI_SSTR(MI_BAD_PARM));

	cl_cmd_name = node->next->value;

	f = lookup_mi_cmd(cl_cmd_name.s, cl_cmd_name.len);
	if (!f)
		return init_mi_tree(400, MI_SSTR("MI command to be run not found"));

	cmd_params_n = node->next->next;
	for (; cmd_params_n; cmd_params_n = cmd_params_n->next, no_params++)
		cl_cmd_params[no_params] = cmd_params_n->value;

	/* send MI cmd in cluster */
	rc = send_mi_cmd(cluster_id, 0, cl_cmd_name, cl_cmd_params, no_params);
	switch (rc) {
		case CLUSTERER_SEND_SUCCES:
			LM_DBG("MI command <%.*s> sent\n", cl_cmd_name.len, cl_cmd_name.s);
			break;
		case CLUSTERER_CURR_DISABLED:
			LM_INFO("Local node disabled, MI command <%.*s> not sent\n",
				cl_cmd_name.len, cl_cmd_name.s);
			break;
		case CLUSTERER_DEST_DOWN:
			LM_ERR("All nodes down, MI command <%.*s> not sent\n",
				cl_cmd_name.len, cl_cmd_name.s);
			break;
		case CLUSTERER_SEND_ERR:
			LM_ERR("Error sending MI command <%.*s>+\n",
				cl_cmd_name.len, cl_cmd_name.s);
			break;
	}

	/* run MI cmd locally */
	return run_mi_cmd_local(f, cl_cmd_params, no_params, cmd->async_hdl);
}
Example #3
0
/*function that verifyes that the function from the datagram's first 
 * line is correct and exists*/
static int identify_command(datagram_stream * dtgram, struct mi_cmd * *f)
{
	char *command,*p, *start;

	/* default offset for the command: 0 */
	p= dtgram->start;
	start = p;
	if (!p){
		LM_ERR("null pointer  \n");
		return -1;
	}
	
	/*if no command*/
	if ( dtgram->len ==0 ){
		LM_DBG("command empty case1 \n");
		goto error;
	}
	if (*p != MI_CMD_SEPARATOR){
		LM_ERR("command must begin with: %c \n", MI_CMD_SEPARATOR);
		goto error;
	}
	command = p+1;

	LM_DBG("the command starts here: %s\n", command);
	p=strchr(command, MI_CMD_SEPARATOR );
	if (!p ){
		LM_ERR("empty command \n");
		goto error;
	}
	if(*(p+1)!='\n'){
		LM_ERR("the request's first line is invalid :no newline after "
				"the second %c\n",MI_CMD_SEPARATOR);
		goto error;
	}

	/* make command zero-terminated */
	*p=0;
	LM_DBG("the command is %s\n",command);
	/*search for the appropiate command*/
	*f=lookup_mi_cmd( command, p-command);
	if(!*f)
		goto error;
	/*the current offset has changed*/
	LM_DBG("dtgram->len is %i\n", dtgram->len);
	dtgram->current = p+2 ;
	dtgram->len -=p+2 - dtgram->start;
	LM_DBG("dtgram->len is %i\n",dtgram->len);

	return 0;
error:
	return -1;
}
Example #4
0
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;
}
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();
    }
}
Example #6
0
void mi_json_answer_to_connection (void *cls, void *connection,
    const char *url, const char *method,
    const char *version, const char *upload_data,
    size_t *upload_data_size, void **con_cls,
    str *buffer, str *page)
{
	str command = {NULL, 0};
	str params = {NULL, 0};
	struct mi_cmd *f = NULL;
	struct mi_root *tree = NULL;
	struct mi_handler *async_hdl;

	LM_DBG("START *** cls=%p, connection=%p, url=%s, method=%s, "
			"versio=%s, upload_data[%d]=%p, *con_cls=%p\n",
			cls, connection, url, method, version,
			(int)*upload_data_size, upload_data, *con_cls);
	if (strncmp(method, "GET", 3)==0) {
		if(url && url[0] == '/' && url[1] != '\0') {
			command.s = (char*)url+1;
			command.len = strlen(command.s);
		}
		httpd_api.lookup_arg(connection, "params", *con_cls, &params);
		if (command.s) {

			f = lookup_mi_cmd(command.s, command.len);
			if (f == NULL) {
				LM_ERR("unable to find mi command [%.*s]\n", command.len, command.s);
				*page = MI_HTTP_U_NOT_FOUND;
			} else {

				tree = mi_json_run_mi_cmd(f, &command,&params,
						page, buffer, &async_hdl);
				if (tree == NULL) {
					LM_ERR("no reply\n");
					*page = MI_HTTP_U_ERROR;
				} else if (tree == MI_ROOT_ASYNC_RPL) {
					LM_DBG("got an async reply\n");
					tree = NULL;
				} else {
					LM_DBG("building on page [%p:%d]\n",
							page->s, page->len);
					if(0!=mi_json_build_page(page, buffer->len, tree)){
						LM_ERR("unable to build response\n");
						*page = MI_HTTP_U_ERROR;
					}
				}
			}
		} else {
			page->s = buffer->s;
			LM_ERR("unable to build response for empty request\n");
			*page = MI_HTTP_U_ERROR;
		}
		if (tree) {
			free_mi_tree(tree);
			tree = NULL;
		}
	} else {
		LM_ERR("unexpected method [%s]\n", method);
		*page = MI_HTTP_U_METHOD;
	}

	return;
}
Example #7
0
static mi_response_t *cl_run_mi_cmd(str *cmd_name, mi_item_t *item_params_arr,
										str *str_params_arr, int no_params)
{
	struct mi_cmd *cmd = NULL;
	mi_response_t *resp = NULL;
	mi_request_t req_item;
	mi_item_t *param_item;
	int i;
	str val;

	memset(&req_item, 0, sizeof req_item);

	req_item.req_obj = cJSON_CreateObject();
	if (!req_item.req_obj) {
		LM_ERR("Failed to build temporary json request\n");
		return NULL;
	}

	cmd = lookup_mi_cmd(cmd_name->s, cmd_name->len);
	if (!cmd) {
		resp = init_mi_error(400, MI_SSTR("Command to be run not found"));
		goto out;
	}

	if (cmd->flags & MI_ASYNC_RPL_FLAG) {
		resp = init_mi_error(400, MI_SSTR("Async commands not supported"));
		goto out;
	}
	if (cmd->flags & MI_NAMED_PARAMS_ONLY) {
		resp = init_mi_error(400, MI_SSTR("Commands requiring named params not supported"));
		goto out;
	}

	if (no_params) {
		req_item.params = cJSON_CreateArray();
		if (!req_item.params) {
			LM_ERR("Failed to add 'params' to temporary json request\n");
			goto out;
		}
		cJSON_AddItemToObject(req_item.req_obj, JSONRPC_PARAMS_S,
			req_item.params);
	}

	for (i = 0; i < no_params; i++) {
		if (item_params_arr) {
			if (get_mi_arr_param_string(item_params_arr, i, &val.s, &val.len) < 0) {
				resp = init_mi_param_error();
				goto out;
			}
		} else {
			val.s = str_params_arr[i].s;
			val.len = str_params_arr[i].len;
		}

		param_item = cJSON_CreateStr(val.s, val.len);
		if (!param_item) {
			LM_ERR("Failed to create string item in temporary json request\n");
			goto out;
		}

		cJSON_AddItemToArray(req_item.params, param_item);
	}

	resp = handle_mi_request(&req_item, cmd, NULL);
	LM_DBG("got mi response = [%p]\n", resp);

out:
	cJSON_Delete(req_item.req_obj);
	return resp;
}
Example #8
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;
}
Example #9
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;
}