aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2014-08-21 15:13:08 +0200
committerHarald Welte <laforge@gnumonks.org>2014-08-21 15:34:18 +0200
commit528134b01cd731d861b8e3c00554fdedf1e0b58f (patch)
tree0bf13a3e50f381c7f7c2d43d4996e97f5e6f1cc2
parentc78e74e3d022400c66da05015e716ccb7fa18a63 (diff)
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.
-rw-r--r--include/osmocom/ctrl/control_if.h11
-rw-r--r--src/ctrl/control_if.c130
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 <osmocom/core/write_queue.h>
#include <osmocom/ctrl/control_cmd.h>
-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;i<strlen(request);i++) {
+ if (request[i] == '.')
+ request[i] = ' ';
+ }
+
+ vline = cmd_make_strvec(request);
+ talloc_free(request);
+ if (!vline) {
+ cmd->reply = "cmd_make_strvec failed.";
+ goto err;
+ }
+
+ for (i=0;i<vector_active(vline);i++) {
+ int rc;
+
+ if (ctrl->lookup)
+ 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; j<vector_active(vline); j++) {
+ vector_set(cmdvec, vector_slot(vline, j));
+ }
+
+ /* Get the command vector of the right node */
+ cmds_vec = vector_lookup(ctrl_node_vec, node);
+
+ if (!cmds_vec) {
+ cmd->reply = "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)