diff options
-rw-r--r-- | channels/chan_agent.c | 60 |
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 */ |