Pass the devicestate from an underlying channel up through the Agent channel.

This should make the Agent always report the correct device state, even when
the underlying channel is used for other purposes.
(closes issue #12773)
 Reported by: davidw
 Patches: 
       20080710__bug12773.diff.txt uploaded by Corydon76 (license 14)
 Tested by: davidw


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@130102 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Tilghman Lesher
2008-07-11 16:50:42 +00:00
parent 92ef406265
commit f29986aac8

View File

@@ -193,6 +193,7 @@ struct agent_pvt {
char agent[AST_MAX_AGENT]; /*!< Agent ID */ char agent[AST_MAX_AGENT]; /*!< Agent ID */
char password[AST_MAX_AGENT]; /*!< Password for Agent login */ char password[AST_MAX_AGENT]; /*!< Password for Agent login */
char name[AST_MAX_AGENT]; 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 */ ast_mutex_t app_lock; /**< Synchronization between owning applications */
volatile pthread_t owning_app; /**< Owning application thread id */ volatile pthread_t owning_app; /**< Owning application thread id */
volatile int app_sleep_cond; /**< Sleep condition for the login app */ 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, .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. * 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->app_sleep_cond = 1;
p->group = group; p->group = group;
p->pending = pending; p->pending = pending;
p->inherited_devicestate = -1;
AST_LIST_INSERT_TAIL(&agents, p, list); 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->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000));
} }
p->chan = NULL; p->chan = NULL;
p->inherited_devicestate = -1;
p->acknowledged = 0; p->acknowledged = 0;
} }
} else { } else {
@@ -706,6 +743,7 @@ static int agent_call(struct ast_channel *ast, char *dest, int timeout)
} else { } else {
/* Agent hung-up */ /* Agent hung-up */
p->chan = NULL; p->chan = NULL;
p->inherited_devicestate = -1;
} }
if (!res) { if (!res) {
@@ -828,6 +866,7 @@ static int agent_hangup(struct ast_channel *ast)
/* Recognize the hangup and pass it along immediately */ /* Recognize the hangup and pass it along immediately */
ast_hangup(p->chan); ast_hangup(p->chan);
p->chan = NULL; p->chan = NULL;
p->inherited_devicestate = -1;
} }
ast_log(LOG_DEBUG, "Hungup, howlong is %d, autologoff is %d\n", howlong, p->autologoff); ast_log(LOG_DEBUG, "Hungup, howlong is %d, autologoff is %d\n", howlong, p->autologoff);
if ((p->deferlogoff) || (howlong && p->autologoff && (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); set_agentbycallerid(p->logincallerid, NULL);
p->loginchan[0] ='\0'; p->loginchan[0] ='\0';
p->logincallerid[0] = '\0'; p->logincallerid[0] = '\0';
p->inherited_devicestate = -1;
ast_device_state_changed("Agent/%s", p->agent); ast_device_state_changed("Agent/%s", p->agent);
if (persistent_agents) if (persistent_agents)
dump_agents(); dump_agents();
@@ -2217,8 +2257,10 @@ static int __login_exec(struct ast_channel *chan, void *data, int callbackmode)
if (res && p->owner) if (res && p->owner)
ast_log(LOG_WARNING, "Huh? We broke out when there was still an owner?\n"); ast_log(LOG_WARNING, "Huh? We broke out when there was still an owner?\n");
/* Log us off if appropriate */ /* Log us off if appropriate */
if (p->chan == chan) if (p->chan == chan) {
p->chan = NULL; p->chan = NULL;
p->inherited_devicestate = -1;
}
p->acknowledged = 0; p->acknowledged = 0;
logintime = time(NULL) - p->loginstart; logintime = time(NULL) - p->loginstart;
p->loginstart = 0; p->loginstart = 0;
@@ -2598,6 +2640,8 @@ static int agent_devicestate(void *data)
if (p->owner) { if (p->owner) {
if (res != AST_DEVICE_INUSE) if (res != AST_DEVICE_INUSE)
res = AST_DEVICE_BUSY; res = AST_DEVICE_BUSY;
} else if (p->inherited_devicestate > -1) {
res = p->inherited_devicestate;
} else { } else {
if (res == AST_DEVICE_BUSY) if (res == AST_DEVICE_BUSY)
res = AST_DEVICE_INUSE; res = AST_DEVICE_INUSE;
@@ -2741,6 +2785,8 @@ static int load_module(void)
/* Dialplan Functions */ /* Dialplan Functions */
ast_custom_function_register(&agent_function); ast_custom_function_register(&agent_function);
ast_devstate_add(agent_devicestate_cb, NULL);
return 0; return 0;
} }
@@ -2757,6 +2803,8 @@ static int unload_module(void)
struct agent_pvt *p; struct agent_pvt *p;
/* First, take us out of the channel loop */ /* First, take us out of the channel loop */
ast_channel_unregister(&agent_tech); ast_channel_unregister(&agent_tech);
/* Delete devicestate subscription */
ast_devstate_del(agent_devicestate_cb, NULL);
/* Unregister dialplan functions */ /* Unregister dialplan functions */
ast_custom_function_unregister(&agent_function); ast_custom_function_unregister(&agent_function);
/* Unregister CLI commands */ /* Unregister CLI commands */