Index: channels/chan_agent.c =================================================================== --- channels/chan_agent.c (revision 129044) +++ channels/chan_agent.c (working copy) @@ -193,6 +193,7 @@ 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 @@ .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 @@ 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 @@ 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 @@ } else { /* Agent hung-up */ p->chan = NULL; + p->inherited_devicestate = -1; } if (!res) { @@ -828,6 +866,7 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ /* Dialplan Functions */ ast_custom_function_register(&agent_function); + ast_devstate_add(agent_devicestate_cb, NULL); + return 0; } @@ -2757,6 +2803,8 @@ 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 */