aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--channels/chan_agent.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/channels/chan_agent.c b/channels/chan_agent.c
index b2353f039..cd431a642 100644
--- a/channels/chan_agent.c
+++ b/channels/chan_agent.c
@@ -193,6 +193,7 @@ struct agent_pvt {
char agent[AST_MAX_AGENT]; /*!< Agent ID */
char password[AST_MAX_AGENT]; /*!< Password for Agent login */
char name[AST_MAX_AGENT];
+ int inherited_devicestate; /*!< Does the underlying channel have a devicestate to pass? */
ast_mutex_t app_lock; /**< Synchronization between owning applications */
volatile pthread_t owning_app; /**< Owning application thread id */
volatile int app_sleep_cond; /**< Sleep condition for the login app */
@@ -282,6 +283,40 @@ static const struct ast_channel_tech agent_tech = {
.set_base_channel = agent_set_base_channel,
};
+static int agent_devicestate_cb(const char *dev, int state, void *data)
+{
+ int res, i;
+ struct agent_pvt *p;
+ char basename[AST_CHANNEL_NAME], *tmp;
+
+ /* Try to be safe, but don't deadlock */
+ for (i = 0; i < 10; i++) {
+ if ((res = AST_LIST_TRYLOCK(&agents)) == 0) {
+ break;
+ }
+ }
+ if (res) {
+ return -1;
+ }
+
+ AST_LIST_TRAVERSE(&agents, p, list) {
+ ast_mutex_lock(&p->lock);
+ if (p->chan) {
+ ast_copy_string(basename, p->chan->name, sizeof(basename));
+ if ((tmp = strrchr(basename, '-'))) {
+ *tmp = '\0';
+ }
+ if (strcasecmp(p->chan->name, dev) == 0 || strcasecmp(basename, dev) == 0) {
+ p->inherited_devicestate = state;
+ ast_device_state_changed("Agent/%s", p->agent);
+ }
+ }
+ ast_mutex_unlock(&p->lock);
+ }
+ AST_LIST_UNLOCK(&agents);
+ return 0;
+}
+
/*!
* Adds an agent to the global list of agents.
*
@@ -344,6 +379,7 @@ static struct agent_pvt *add_agent(char *agent, int pending)
p->app_sleep_cond = 1;
p->group = group;
p->pending = pending;
+ p->inherited_devicestate = -1;
AST_LIST_INSERT_TAIL(&agents, p, list);
}
@@ -485,6 +521,7 @@ static struct ast_frame *agent_read(struct ast_channel *ast)
p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000));
}
p->chan = NULL;
+ p->inherited_devicestate = -1;
p->acknowledged = 0;
}
} else {
@@ -706,6 +743,7 @@ static int agent_call(struct ast_channel *ast, char *dest, int timeout)
} else {
/* Agent hung-up */
p->chan = NULL;
+ p->inherited_devicestate = -1;
}
if (!res) {
@@ -828,6 +866,7 @@ static int agent_hangup(struct ast_channel *ast)
/* Recognize the hangup and pass it along immediately */
ast_hangup(p->chan);
p->chan = NULL;
+ p->inherited_devicestate = -1;
}
ast_log(LOG_DEBUG, "Hungup, howlong is %d, autologoff is %d\n", howlong, p->autologoff);
if ((p->deferlogoff) || (howlong && p->autologoff && (howlong > p->autologoff))) {
@@ -1577,6 +1616,7 @@ static void agent_logoff_maintenance(struct agent_pvt *p, char *loginchan, long
set_agentbycallerid(p->logincallerid, NULL);
p->loginchan[0] ='\0';
p->logincallerid[0] = '\0';
+ p->inherited_devicestate = -1;
ast_device_state_changed("Agent/%s", p->agent);
if (persistent_agents)
dump_agents();
@@ -2217,8 +2257,10 @@ static int __login_exec(struct ast_channel *chan, void *data, int callbackmode)
if (res && p->owner)
ast_log(LOG_WARNING, "Huh? We broke out when there was still an owner?\n");
/* Log us off if appropriate */
- if (p->chan == chan)
+ if (p->chan == chan) {
p->chan = NULL;
+ p->inherited_devicestate = -1;
+ }
p->acknowledged = 0;
logintime = time(NULL) - p->loginstart;
p->loginstart = 0;
@@ -2598,6 +2640,8 @@ static int agent_devicestate(void *data)
if (p->owner) {
if (res != AST_DEVICE_INUSE)
res = AST_DEVICE_BUSY;
+ } else if (p->inherited_devicestate > -1) {
+ res = p->inherited_devicestate;
} else {
if (res == AST_DEVICE_BUSY)
res = AST_DEVICE_INUSE;
@@ -2741,6 +2785,8 @@ static int load_module(void)
/* Dialplan Functions */
ast_custom_function_register(&agent_function);
+ ast_devstate_add(agent_devicestate_cb, NULL);
+
return 0;
}
@@ -2757,6 +2803,8 @@ static int unload_module(void)
struct agent_pvt *p;
/* First, take us out of the channel loop */
ast_channel_unregister(&agent_tech);
+ /* Delete devicestate subscription */
+ ast_devstate_del(agent_devicestate_cb, NULL);
/* Unregister dialplan functions */
ast_custom_function_unregister(&agent_function);
/* Unregister CLI commands */