diff options
| author | Harald Welte <laforge@gnumonks.org> | 2014-08-21 15:13:08 +0200 | 
|---|---|---|
| committer | Harald Welte <laforge@gnumonks.org> | 2014-08-21 15:34:18 +0200 | 
| commit | 528134b01cd731d861b8e3c00554fdedf1e0b58f (patch) | |
| tree | 0bf13a3e50f381c7f7c2d43d4996e97f5e6f1cc2 /src/ctrl | |
| parent | c78e74e3d022400c66da05015e716ccb7fa18a63 (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.
Diffstat (limited to 'src/ctrl')
| -rw-r--r-- | src/ctrl/control_if.c | 130 | 
1 files changed, 127 insertions, 3 deletions
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)  | 
