From 528134b01cd731d861b8e3c00554fdedf1e0b58f Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Thu, 21 Aug 2014 15:13:08 +0200 Subject: libctrl: Move bulk of control node lookup inti libosmoctrl The control interface user now only has to register a very short node lookup function callback. This function is optional, and only required if hierarchical command lookup should be supported. --- include/osmocom/ctrl/control_if.h | 11 ++-- src/ctrl/control_if.c | 130 +++++++++++++++++++++++++++++++++++++- 2 files changed, 134 insertions(+), 7 deletions(-) diff --git a/include/osmocom/ctrl/control_if.h b/include/osmocom/ctrl/control_if.h index 318e181f..5e10a039 100644 --- a/include/osmocom/ctrl/control_if.h +++ b/include/osmocom/ctrl/control_if.h @@ -4,13 +4,16 @@ #include #include -typedef int (*ctrl_cmd_handler)(struct ctrl_cmd *, void *); +int ctrl_parse_get_num(vector vline, int i, long *num); + +typedef int (*ctrl_cmd_lookup)(void *data, vector vline, int *node_type, + void **node_data, int *i); struct ctrl_handle { struct osmo_fd listen_fd; void *data; - ctrl_cmd_handler handler; + ctrl_cmd_lookup lookup; /* List of control connections */ struct llist_head ccon_list; @@ -19,9 +22,9 @@ struct ctrl_handle { int ctrl_cmd_send(struct osmo_wqueue *queue, struct ctrl_cmd *cmd); struct ctrl_handle *controlif_setup(void *data, uint16_t port, - ctrl_cmd_handler handler); + ctrl_cmd_lookup lookup); -int bsc_ctrl_cmd_handle(struct ctrl_cmd *cmd, void *data); +int ctrl_cmd_handle(struct ctrl_handle *ctrl, struct ctrl_cmd *cmd, void *data); #endif /* _CONTROL_IF_H */ diff --git a/src/ctrl/control_if.c b/src/ctrl/control_if.c index 5db2eead..bb690e55 100644 --- a/src/ctrl/control_if.c +++ b/src/ctrl/control_if.c @@ -56,6 +56,25 @@ vector ctrl_node_vec; +int ctrl_parse_get_num(vector vline, int i, long *num) +{ + char *token, *tmp; + + if (i >= vector_active(vline)) + return 0; + token = vector_slot(vline, i); + + errno = 0; + if (token[0] == '\0') + return 0; + + *num = strtol(token, &tmp, 10); + if (tmp[0] != '\0' || errno != 0) + return 0; + + return 1; +} + /* Send command to all */ int ctrl_cmd_send_to_all(struct ctrl_handle *ctrl, struct ctrl_cmd *cmd) { @@ -118,6 +137,111 @@ static void control_close_conn(struct ctrl_connection *ccon) talloc_free(ccon); } +int ctrl_cmd_handle(struct ctrl_handle *ctrl, struct ctrl_cmd *cmd, + void *data) +{ + char *request; + int i, j, ret, node; + + vector vline, cmdvec, cmds_vec; + + ret = CTRL_CMD_ERROR; + cmd->reply = NULL; + node = CTRL_NODE_ROOT; + cmd->node = data; + + request = talloc_strdup(cmd, cmd->variable); + if (!request) + goto err; + + for (i=0;ireply = "cmd_make_strvec failed."; + goto err; + } + + for (i=0;ilookup) + rc = ctrl->lookup(data, vline, &node, &cmd->node, &i); + else + rc = 0; + + if (rc == 1) { + /* do nothing */ + } else if (rc == -ENODEV) + goto err_missing; + else if (rc == -ERANGE) + goto err_index; + else { + /* If we're here the rest must be the command */ + cmdvec = vector_init(vector_active(vline)-i); + for (j=i; jreply = "Command not found."; + vector_free(cmdvec); + break; + } + + ret = ctrl_cmd_exec(cmdvec, cmd, cmds_vec, data); + + vector_free(cmdvec); + break; + } + + if (i+1 == vector_active(vline)) + cmd->reply = "Command not present."; + } + + cmd_free_strvec(vline); + +err: + if (!cmd->reply) { + if (ret == CTRL_CMD_ERROR) { + cmd->reply = "An error has occured."; + LOGP(DLCTRL, LOGL_NOTICE, + "%s: cmd->reply has not been set (ERROR).\n", + cmd->variable); + } else if (ret == CTRL_CMD_REPLY) { + LOGP(DLCTRL, LOGL_NOTICE, + "%s: cmd->reply has not been set (type = %d).\n", + cmd->variable, cmd->type); + cmd->reply = ""; + } else { + cmd->reply = "Command has been handled."; + } + } + + if (ret == CTRL_CMD_ERROR) + cmd->type = CTRL_TYPE_ERROR; + return ret; + +err_missing: + cmd_free_strvec(vline); + cmd->type = CTRL_TYPE_ERROR; + cmd->reply = "Error while resolving object"; + return ret; +err_index: + cmd_free_strvec(vline); + cmd->type = CTRL_TYPE_ERROR; + cmd->reply = "Error while parsing the index."; + return ret; +} + + static int handle_control_read(struct osmo_fd * bfd) { int ret = -1; @@ -167,7 +291,7 @@ static int handle_control_read(struct osmo_fd * bfd) if (cmd) { cmd->ccon = ccon; - if (ctrl->handler(cmd, ctrl->data) != CTRL_CMD_HANDLED) { + if (ctrl_cmd_handle(ctrl, cmd, ctrl->data) != CTRL_CMD_HANDLED) { ctrl_cmd_send(queue, cmd); talloc_free(cmd); } @@ -523,7 +647,7 @@ static int verify_counter(struct ctrl_cmd *cmd, const char *value, void *data) } struct ctrl_handle *controlif_setup(void *data, uint16_t port, - ctrl_cmd_handler handler) + ctrl_cmd_lookup lookup) { int ret; struct ctrl_handle *ctrl; @@ -535,7 +659,7 @@ struct ctrl_handle *controlif_setup(void *data, uint16_t port, INIT_LLIST_HEAD(&ctrl->ccon_list); ctrl->data = data; - ctrl->handler = handler; + ctrl->lookup = lookup; ctrl_node_vec = vector_init(5); if (!ctrl_node_vec) -- cgit v1.2.3