@ -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 " ;
@ -142,6 +143,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"
@ -164,6 +166,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 */
@ -254,6 +257,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 .
*
@ -316,6 +361,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 ) ;
}
@ -457,6 +503,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 {
@ -671,6 +718,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 ) {
@ -791,6 +839,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 ) ) ) {
@ -1509,6 +1558,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 ( ) ;
@ -2054,8 +2104,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 ;
@ -2268,6 +2320,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 ;
@ -2409,6 +2463,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 ;
}
@ -2426,6 +2482,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 */