diff options
Diffstat (limited to 'src/ctrl')
| -rw-r--r-- | src/ctrl/control_cmd.c | 60 | ||||
| -rw-r--r-- | src/ctrl/control_if.c | 17 | 
2 files changed, 77 insertions, 0 deletions
| diff --git a/src/ctrl/control_cmd.c b/src/ctrl/control_cmd.c index 88a30a2a..4e156b81 100644 --- a/src/ctrl/control_cmd.c +++ b/src/ctrl/control_cmd.c @@ -487,3 +487,63 @@ err:  	msgb_free(msg);  	return NULL;  } + +struct ctrl_cmd_def * +ctrl_cmd_def_make(const void *ctx, struct ctrl_cmd *cmd, void *data, unsigned int secs) +{ +	struct ctrl_cmd_def *cd; + +	if (!cmd->ccon) +		return NULL; + +	cd = talloc_zero(ctx, struct ctrl_cmd_def); + +	cd->cmd = cmd; +	cd->data = data; + +	/* add to per-connection list of deferred commands */ +	llist_add(&cd->list, &cmd->ccon->def_cmds); + +	return cd; +} + +int ctrl_cmd_def_is_zombie(struct ctrl_cmd_def *cd) +{ +	/* luckily we're still alive */ +	if (cd->cmd) +		return 0; + +	/* if we are a zombie, make sure we really die */ +	llist_del(&cd->list); +	talloc_free(cd); + +	return 1; +} + +int ctrl_cmd_def_send(struct ctrl_cmd_def *cd) +{ +	struct ctrl_cmd *cmd = cd->cmd; + +	int rc; + +	/* Deferred commands can only be responses to GET/SET or ERROR, but +	 * never TRAP or anything else */ +	switch (cmd->type) { +	case CTRL_TYPE_GET: +		cmd->type = CTRL_TYPE_GET_REPLY; +		break; +	case CTRL_TYPE_SET: +		cmd->type = CTRL_TYPE_SET_REPLY; +		break; +	default: +		cmd->type = CTRL_TYPE_ERROR; +	} + +	rc = ctrl_cmd_send(&cmd->ccon->write_queue, cmd); + +	talloc_free(cmd); +	llist_del(&cd->list); +	talloc_free(cd); + +	return rc; +} diff --git a/src/ctrl/control_if.c b/src/ctrl/control_if.c index 59cf2552..c20c1e0f 100644 --- a/src/ctrl/control_if.c +++ b/src/ctrl/control_if.c @@ -128,6 +128,8 @@ struct ctrl_cmd *ctrl_cmd_trap(struct ctrl_cmd *cmd)  static void control_close_conn(struct ctrl_connection *ccon)  { +	struct ctrl_cmd_def *cd, *cd2; +  	osmo_wqueue_clear(&ccon->write_queue);  	close(ccon->write_queue.bfd.fd);  	osmo_fd_unregister(&ccon->write_queue.bfd); @@ -135,6 +137,19 @@ static void control_close_conn(struct ctrl_connection *ccon)  	if (ccon->closed_cb)  		ccon->closed_cb(ccon);  	msgb_free(ccon->pending_msg); + +	/* clean up deferred commands */ +	llist_for_each_entry_safe(cd, cd2, &ccon->def_cmds, list) { +		/* delete from list of def_cmds for this ccon */ +		llist_del(&cd->list); +		/* not strictly needed as this is a slave to the ccon which we +		 * are about to free anyway */ +		talloc_free(cd->cmd); +		/* set the CMD to null, this is the indication to the user that +		 * the connection for this command has gone */ +		cd->cmd = NULL; +	} +  	talloc_free(ccon);  } @@ -338,6 +353,8 @@ static struct ctrl_connection *ctrl_connection_alloc(void *ctx)  	/* Error handling here? */  	INIT_LLIST_HEAD(&ccon->cmds); +	INIT_LLIST_HEAD(&ccon->def_cmds); +  	return ccon;  } | 
