aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2008-07-11 17:29:24 +0000
committertilghman <tilghman@f38db490-d61c-443f-a65b-d21fe96a405b>2008-07-11 17:29:24 +0000
commit802d09a41e12f28f64a4f6be443ecf0db251b28d (patch)
tree67cf765cb83dbbd6357fd61354671e756e43c97d
parent73b88aaa7161f0da15bdefe4d55b53c85103fd82 (diff)
Merged revisions 130102 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r130102 | tilghman | 2008-07-11 11:50:42 -0500 (Fri, 11 Jul 2008) | 9 lines 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: http://svn.digium.com/svn/asterisk/trunk@130126 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--channels/chan_agent.c60
1 files changed, 59 insertions, 1 deletions
diff --git a/channels/chan_agent.c b/channels/chan_agent.c
index 277ebda09..5ca44251c 100644
--- a/channels/chan_agent.c
+++ b/channels/chan_agent.c
@@ -67,6 +67,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/devicestate.h"
#include "asterisk/monitor.h"
#include "asterisk/stringfields.h"
+#include "asterisk/event.h"
static const char tdesc[] = "Call Agent Proxy Channel";
static const char config[] = "agents.conf";
@@ -147,6 +148,7 @@ static char urlprefix[AST_MAX_BUF] = "";
static char savecallsin[AST_MAX_BUF] = "";
static int updatecdr = 0;
static char beep[AST_MAX_BUF] = "beep";
+struct ast_event_sub *agent_devicestate_sub = NULL;
#define GETAGENTBYCALLERID "AGENTBYCALLERID"
@@ -171,6 +173,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 */
@@ -261,6 +264,48 @@ static const struct ast_channel_tech agent_tech = {
.set_base_channel = agent_set_base_channel,
};
+static void agent_devicestate_cb(const struct ast_event *event, void *unused)
+{
+ int res, i;
+ struct agent_pvt *p;
+ char basename[AST_CHANNEL_NAME], *tmp;
+ const char *device;
+ enum ast_device_state state;
+
+ /* 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;
+ }
+
+ state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
+ device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
+
+ if (ast_strlen_zero(device)) {
+ return;
+ }
+
+ 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, device) == 0 || strcasecmp(basename, device) == 0) {
+ p->inherited_devicestate = state;
+ ast_device_state_changed("Agent/%s", p->agent);
+ }
+ }
+ ast_mutex_unlock(&p->lock);
+ }
+ AST_LIST_UNLOCK(&agents);
+}
+
/*!
* Adds an agent to the global list of agents.
*
@@ -323,6 +368,7 @@ static struct agent_pvt *add_agent(const 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);
}
@@ -466,6 +512,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 {
@@ -680,6 +727,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) {
@@ -800,6 +848,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_debug(1, "Hungup, howlong is %d, autologoff is %d\n", howlong, p->autologoff);
if ((p->deferlogoff) || (howlong && p->autologoff && (howlong > p->autologoff))) {
@@ -1523,6 +1572,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();
@@ -2078,8 +2128,10 @@ static int login_exec(struct ast_channel *chan, void *data)
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;
@@ -2292,6 +2344,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;
@@ -2433,6 +2487,8 @@ static int load_module(void)
/* Dialplan Functions */
ast_custom_function_register(&agent_function);
+ agent_devicestate_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, agent_devicestate_cb, NULL);
+
return AST_MODULE_LOAD_SUCCESS;
}
@@ -2450,6 +2506,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 */
+ agent_devicestate_sub = ast_event_unsubscribe(agent_devicestate_sub);
/* Unregister dialplan functions */
ast_custom_function_unregister(&agent_function);
/* Unregister CLI commands */