]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Pass the devicestate from an underlying channel up through the Agent channel.
authorTilghman Lesher <tilghman@meg.abyt.es>
Fri, 11 Jul 2008 16:50:42 +0000 (16:50 +0000)
committerTilghman Lesher <tilghman@meg.abyt.es>
Fri, 11 Jul 2008 16:50:42 +0000 (16:50 +0000)
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

channels/chan_agent.c

index b2353f0397a91de5b8fe2cda5b5eb105687267a6..cd431a6423c898609b27e71d816af09588a4f545 100644 (file)
@@ -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 */