@ -344,7 +344,6 @@ static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
static struct ast_channel * agent_bridgedchannel ( struct ast_channel * chan , struct ast_channel * bridge ) ;
static char * complete_agent_logoff_cmd ( const char * line , const char * word , int pos , int state ) ;
static struct ast_channel * agent_get_base_channel ( struct ast_channel * chan ) ;
static int agent_set_base_channel ( struct ast_channel * chan , struct ast_channel * base ) ;
static int agent_logoff ( const char * agent , int soft ) ;
/*! \brief Channel interface description for PBX integration */
@ -368,7 +367,6 @@ static struct ast_channel_tech agent_tech = {
. fixup = agent_fixup ,
. bridged_channel = agent_bridgedchannel ,
. get_base_channel = agent_get_base_channel ,
. set_base_channel = agent_set_base_channel ,
} ;
/*!
@ -625,17 +623,10 @@ static struct ast_frame *agent_read(struct ast_channel *ast)
ast_copy_flags ( ast_channel_flags ( p - > chan ) , ast_channel_flags ( ast ) , AST_FLAG_EXCEPTION ) ;
ast_channel_fdno_set ( p - > chan , ( ast_channel_fdno ( ast ) = = AST_AGENT_FD ) ? AST_TIMING_FD : ast_channel_fdno ( ast ) ) ;
f = ast_read ( p - > chan ) ;
ast_channel_fdno_set ( ast , - 1 ) ;
} else
f = & ast_null_frame ;
if ( ! f ) {
/* If there's a channel, make it NULL */
if ( p - > chan ) {
ast_channel_internal_bridged_channel_set ( p - > chan , NULL ) ;
p - > chan = NULL ;
ast_devstate_changed ( AST_DEVICE_UNAVAILABLE , AST_DEVSTATE_CACHABLE , " Agent/%s " , p - > agent ) ;
p - > acknowledged = 0 ;
}
} else {
if ( f ) {
/* if acknowledgement is not required, and the channel is up, we may have missed
an AST_CONTROL_ANSWER ( if there was one ) , so mark the call acknowledged anyway */
if ( ! p - > ackcall & & ! p - > acknowledged & & p - > chan & & ( ast_channel_state ( p - > chan ) = = AST_STATE_UP ) ) {
@ -840,9 +831,8 @@ static int agent_digit_end(struct ast_channel *ast, char digit, unsigned int dur
static int agent_call ( struct ast_channel * ast , const char * dest , int timeout )
{
struct agent_pvt * p = ast_channel_tech_pvt ( ast ) ;
int res = - 1 ;
int res ;
int newstate = 0 ;
struct ast_channel * chan ;
ast_mutex_lock ( & p - > lock ) ;
p - > acknowledged = 0 ;
@ -854,29 +844,20 @@ static int agent_call(struct ast_channel *ast, const char *dest, int timeout)
return 0 ;
}
if ( ! p - > chan ) {
ast_log ( LOG_DEBUG , " Agent disconnected while we were connecting the call \n " ) ;
ast_mutex_unlock ( & p - > lock ) ;
return res ;
}
ast_assert ( p - > chan ! = NULL ) ;
ast_verb ( 3 , " agent_call, call to agent '%s' call on '%s' \n " , p - > agent , ast_channel_name ( p - > chan ) ) ;
ast_debug ( 3 , " Playing beep, lang '%s' \n " , ast_channel_language ( p - > chan ) ) ;
chan = p - > chan ;
ast_mutex_unlock ( & p - > lock ) ;
res = ast_streamfile ( chan, beep , ast_channel_language ( chan ) ) ;
res = ast_streamfile ( p- > chan, beep , ast_channel_language ( p - > chan ) ) ;
ast_debug ( 3 , " Played beep, result '%d' \n " , res ) ;
if ( ! res ) {
res = ast_waitstream ( chan, " " ) ;
res = ast_waitstream ( p- > chan, " " ) ;
ast_debug ( 3 , " Waited for stream, result '%d' \n " , res ) ;
}
ast_mutex_lock ( & p - > lock ) ;
if ( ! p - > chan ) {
/* chan went away while we were streaming, this shouldn't be possible */
res = - 1 ;
}
if ( ! res ) {
struct ast_format tmpfmt ;
@ -884,10 +865,6 @@ static int agent_call(struct ast_channel *ast, const char *dest, int timeout)
ast_debug ( 3 , " Set read format, result '%d' \n " , res ) ;
if ( res )
ast_log ( LOG_WARNING , " Unable to set read format to %s \n " , ast_getformatname ( & tmpfmt ) ) ;
} else {
/* Agent hung-up */
p - > chan = NULL ;
ast_devstate_changed ( AST_DEVICE_UNAVAILABLE , AST_DEVSTATE_CACHABLE , " Agent/%s " , p - > agent ) ;
}
if ( ! res ) {
@ -912,7 +889,7 @@ static int agent_call(struct ast_channel *ast, const char *dest, int timeout)
ast_mutex_unlock ( & p - > lock ) ;
if ( newstate )
ast_setstate ( ast , newstate ) ;
return res ;
return res ? - 1 : 0 ;
}
/*! \brief return the channel or base channel if one exists. This function assumes the channel it is called on is already locked */
@ -932,23 +909,6 @@ struct ast_channel* agent_get_base_channel(struct ast_channel *chan)
return base ;
}
int agent_set_base_channel ( struct ast_channel * chan , struct ast_channel * base )
{
struct agent_pvt * p = NULL ;
if ( ! chan | | ! base ) {
ast_log ( LOG_ERROR , " whoa, you need a channel (0x%ld) and a base channel (0x%ld) for setting. \n " , ( long ) chan , ( long ) base ) ;
return - 1 ;
}
p = ast_channel_tech_pvt ( chan ) ;
if ( ! p ) {
ast_log ( LOG_ERROR , " whoa, channel %s is missing his tech_pvt structure!!. \n " , ast_channel_name ( chan ) ) ;
return - 1 ;
}
p - > chan = base ;
return 0 ;
}
static int agent_hangup ( struct ast_channel * ast )
{
struct agent_pvt * p = ast_channel_tech_pvt ( ast ) ;
@ -964,13 +924,8 @@ static int agent_hangup(struct ast_channel *ast)
ast_mutex_lock ( & p - > lock ) ;
p - > owner = NULL ;
ast_channel_tech_pvt_set ( ast , NULL ) ;
p - > app_sleep_cond = 1 ;
p - > acknowledged = 0 ;
/* Release ownership of the agent to other threads (presumably running the login app). */
p - > app_lock_flag = 0 ;
ast_cond_signal ( & p - > app_complete_cond ) ;
/* if they really are hung up then set start to 0 so the test
* later if we ' re called on an already downed channel
* doesn ' t cause an agent to be logged out like when
@ -999,26 +954,26 @@ static int agent_hangup(struct ast_channel *ast)
indicate_chan = ast_channel_unref ( indicate_chan ) ;
}
/* Only register a device state change if the agent is still logged in */
if ( p - > loginstart ) {
ast_devstate_changed ( AST_DEVICE_NOT_INUSE , AST_DEVSTATE_CACHABLE , " Agent/%s " , p - > agent ) ;
}
ast_mutex_lock ( & p - > lock ) ;
if ( p - > abouttograb ) {
/* Let the "about to grab" thread know this isn't valid anymore, and let it
kill it later */
p - > abouttograb = 0 ;
} else if ( p - > dead ) {
ast_mutex_unlock ( & p - > lock ) ;
agent_pvt_destroy ( p ) ;
return 0 ;
} else {
if ( p - > chan ) {
/* Not dead -- check availability now */
ast_mutex_lock ( & p - > lock ) ;
/* Store last disconnect time */
p - > lastdisc = ast_tvadd ( ast_tvnow ( ) , ast_samp2tv ( p - > wrapuptime , 1000 ) ) ;
ast_mutex_unlock ( & p - > lock ) ;
}
/* Store last disconnect time */
p - > lastdisc = ast_tvadd ( ast_tvnow ( ) , ast_samp2tv ( p - > wrapuptime , 1000 ) ) ;
}
/* Release ownership of the agent to other threads (presumably running the login app). */
p - > app_sleep_cond = 1 ;
p - > app_lock_flag = 0 ;
ast_cond_signal ( & p - > app_complete_cond ) ;
ast_mutex_unlock ( & p - > lock ) ;
return 0 ;
}
@ -1450,7 +1405,8 @@ static struct ast_channel *agent_request(const char *type, struct ast_format_cap
hasagent + + ;
}
now = ast_tvnow ( ) ;
if ( ! p - > lastdisc . tv_sec | | ( now . tv_sec > = p - > lastdisc . tv_sec ) ) {
if ( p - > loginstart
& & ( ! p - > lastdisc . tv_sec | | ast_tvdiff_ms ( now , p - > lastdisc ) > 0 ) ) {
p - > lastdisc = ast_tv ( 0 , 0 ) ;
/* Agent must be registered, but not have any active call, and not be in a waiting state */
if ( ! p - > owner & & p - > chan ) {
@ -1499,10 +1455,10 @@ static struct ast_channel *agent_request(const char *type, struct ast_format_cap
}
if ( ! p - > chan ) {
ast_log ( LOG_DEBUG , " Agent disconnected while we were connecting the call \n " ) ;
* cause = AST_CAUSE_UNREGISTERED ;
ast_debug ( 1 , " Agent disconnected before we could connect the call \n " ) ;
ast_mutex_unlock ( & p - > lock ) ;
agent_hangup ( chan ) ;
ast_hangup ( chan ) ;
* cause = AST_CAUSE_UNREGISTERED ;
return NULL ;
}
@ -1510,18 +1466,14 @@ static struct ast_channel *agent_request(const char *type, struct ast_format_cap
* thread */
p - > app_sleep_cond = 0 ;
p - > app_lock_flag = 1 ;
ast_queue_frame ( p - > chan , & ast_null_frame ) ;
ast_cond_wait ( & p - > login_wait_cond , & p - > lock ) ;
if ( ! p - > chan ) {
ast_log ( LOG_DEBUG , " Agent disconnected while we were connecting the call \n " ) ;
p - > app_sleep_cond = 1 ;
p - > app_lock_flag = 0 ;
ast_cond_signal ( & p - > app_complete_cond ) ;
ast_debug ( 1 , " Agent disconnected while we were connecting the call \n " ) ;
ast_mutex_unlock ( & p - > lock ) ;
ast_hangup ( chan ) ;
* cause = AST_CAUSE_UNREGISTERED ;
agent_hangup ( chan ) ;
return NULL ;
}
@ -1933,10 +1885,9 @@ static int login_exec(struct ast_channel *chan, const char *data)
int tries = 0 ;
int max_login_tries = maxlogintries ;
struct agent_pvt * p ;
char user [ AST_MAX_AGENT ] = " " ;
char user [ AST_MAX_AGENT ] ;
char pass [ AST_MAX_AGENT ] ;
char agent [ AST_MAX_AGENT ] = " " ;
char xpass [ AST_MAX_AGENT ] = " " ;
char xpass [ AST_MAX_AGENT ] ;
char * errmsg ;
char * parse ;
AST_DECLARE_APP_ARGS ( args ,
@ -1948,7 +1899,9 @@ static int login_exec(struct ast_channel *chan, const char *data)
int play_announcement = 1 ;
char agent_goodbye [ AST_MAX_FILENAME_LEN ] ;
int update_cdr = updatecdr ;
char * filename = " agent-loginok " ;
user [ 0 ] = ' \0 ' ;
xpass [ 0 ] = ' \0 ' ;
parse = ast_strdupa ( data ) ;
@ -2020,15 +1973,12 @@ static int login_exec(struct ast_channel *chan, const char *data)
AST_LIST_LOCK ( & agents ) ;
AST_LIST_TRAVERSE ( & agents , p , list ) {
int unlock_channel = 1 ;
ast_channel_lock ( chan ) ;
ast_mutex_lock ( & p - > lock ) ;
if ( ! strcmp ( p - > agent , user ) & &
! strcmp ( p - > password , pass ) & & ! p - > pending ) {
/* Ensure we can't be gotten until we're done */
p - > lastdisc = ast_tvnow ( ) ;
p - > lastdisc . tv_sec + + ;
/* Set Channel Specific Agent Overrides */
if ( ! ast_strlen_zero ( pbx_builtin_getvar_helper ( chan , " AGENTACKCALL " ) ) ) {
if ( ast_true ( pbx_builtin_getvar_helper ( chan , " AGENTACKCALL " ) ) ) {
@ -2077,20 +2027,13 @@ static int login_exec(struct ast_channel *chan, const char *data)
ast_channel_unlock ( chan ) ;
unlock_channel = 0 ;
/* End Channel Specific Agent Overrides */
if ( ! p - > chan ) {
long logintime ;
snprintf ( agent , sizeof ( agent ) , " Agent/%s " , p - > agent ) ;
/* Ensure nobody else can be this agent until we're done. */
p - > chan = chan ;
p - > acknowledged = 0 ;
ast_mutex_unlock ( & p - > lock ) ;
AST_LIST_UNLOCK ( & agents ) ;
if ( ! res & & play_announcement = = 1 )
res = ast_streamfile ( chan , filename , ast_channel_language ( chan ) ) ;
if ( ! res )
ast_waitstream ( chan , " " ) ;
AST_LIST_LOCK ( & agents ) ;
ast_mutex_lock ( & p - > lock ) ;
if ( ! res ) {
struct ast_format tmpfmt ;
res = ast_set_read_format_from_cap ( chan , ast_channel_nativeformats ( chan ) ) ;
@ -2105,15 +2048,32 @@ static int login_exec(struct ast_channel *chan, const char *data)
ast_log ( LOG_WARNING , " Unable to set write format to %s \n " , ast_getformatname ( & tmpfmt ) ) ;
}
}
/* Check once more just in case */
if ( p - > chan )
res = - 1 ;
if ( ! res & & play_announcement = = 1 ) {
ast_mutex_unlock ( & p - > lock ) ;
AST_LIST_UNLOCK ( & agents ) ;
res = ast_streamfile ( chan , " agent-loginok " , ast_channel_language ( chan ) ) ;
if ( ! res ) {
ast_waitstream ( chan , " " ) ;
}
AST_LIST_LOCK ( & agents ) ;
ast_mutex_lock ( & p - > lock ) ;
}
if ( ! res ) {
long logintime ;
char agent [ AST_MAX_AGENT ] ;
snprintf ( agent , sizeof ( agent ) , " Agent/%s " , p - > agent ) ;
/* Login this channel and wait for it to go away */
ast_indicate_data ( chan , AST_CONTROL_HOLD ,
S_OR ( p - > moh , NULL ) ,
! ast_strlen_zero ( p - > moh ) ? strlen ( p - > moh ) + 1 : 0 ) ;
if ( p - > loginstart = = 0 )
time ( & p - > loginstart ) ;
/* Must be done after starting HOLD. */
p - > lastdisc = ast_tvnow ( ) ;
time ( & p - > loginstart ) ;
/*** DOCUMENTATION
< managerEventInstance >
< synopsis > Raised when an Agent has logged in . < / synopsis >
@ -2134,41 +2094,31 @@ static int login_exec(struct ast_channel *chan, const char *data)
" Uniqueid: %s \r \n " ,
p - > agent , ast_channel_name ( chan ) , ast_channel_uniqueid ( chan ) ) ;
if ( update_cdr & & ast_channel_cdr ( chan ) )
snprintf ( ast_channel_cdr ( chan ) - > channel , sizeof ( ast_channel_cdr ( chan ) - > channel ) , " Agent/ %s" , p - > agent ) ;
snprintf ( ast_channel_cdr ( chan ) - > channel , sizeof ( ast_channel_cdr ( chan ) - > channel ) , " %s" , agent ) ;
ast_queue_log ( " NONE " , ast_channel_uniqueid ( chan ) , agent , " AGENTLOGIN " , " %s " , ast_channel_name ( chan ) ) ;
ast_verb ( 2 , " Agent '%s' logged in (format %s/%s) \n " , p - > agent ,
ast_getformatname ( ast_channel_readformat ( chan ) ) , ast_getformatname ( ast_channel_writeformat ( chan ) ) ) ;
/* Login this channel and wait for it to go away */
p - > chan = chan ;
if ( p - > ackcall ) {
check_beep ( p , 0 ) ;
} else {
check_availability ( p , 0 ) ;
}
ast_mutex_unlock ( & p - > lock ) ;
AST_LIST_UNLOCK ( & agents ) ;
ast_devstate_changed ( AST_DEVICE_NOT_INUSE , AST_DEVSTATE_CACHABLE , " Agent/%s " , p - > agent ) ;
while ( res > = 0 ) {
ast_mutex_lock ( & p - > lock ) ;
if ( p - > deferlogoff & & p - > chan ) {
ast_softhangup ( p - > chan , AST_SOFTHANGUP_EXPLICIT ) ;
if ( p - > deferlogoff ) {
p - > deferlogoff = 0 ;
ast_softhangup ( chan , AST_SOFTHANGUP_EXPLICIT ) ;
ast_mutex_unlock ( & p - > lock ) ;
break ;
}
if ( p - > chan ! = chan )
res = - 1 ;
ast_mutex_unlock ( & p - > lock ) ;
/* Yield here so other interested threads can kick in. */
sched_yield ( ) ;
if ( res )
break ;
AST_LIST_LOCK ( & agents ) ;
ast_mutex_lock ( & p - > lock ) ;
if ( p - > lastdisc . tv_sec ) {
if ( ast_tvdiff_ms ( ast_tvnow ( ) , p - > lastdisc ) > 0 ) {
ast_debug ( 1 , " Wrapup time for %s expired! \n " , p- > agent) ;
ast_debug ( 1 , " Wrapup time for %s expired! \n " , agent) ;
p - > lastdisc = ast_tv ( 0 , 0 ) ;
ast_devstate_changed ( AST_DEVICE_ NOT_INUSE , AST_DEVSTATE_CACHABLE , " Agent/ %s" , p - > agent ) ;
ast_devstate_changed ( AST_DEVICE_ UNKNOWN , AST_DEVSTATE_CACHABLE , " %s" , agent ) ;
if ( p - > ackcall ) {
check_beep ( p , 0 ) ;
} else {
@ -2179,47 +2129,53 @@ static int login_exec(struct ast_channel *chan, const char *data)
ast_mutex_unlock ( & p - > lock ) ;
AST_LIST_UNLOCK ( & agents ) ;
/* Synchronize channel ownership between call to agent and itself. */
/* Synchronize channel ownership between call to agent and itself. */
ast_mutex_lock ( & p - > lock ) ;
if ( p - > app_lock_flag = = 1 ) {
if ( p - > app_lock_flag ) {
ast_cond_signal ( & p - > login_wait_cond ) ;
ast_cond_wait ( & p - > app_complete_cond , & p - > lock ) ;
if ( ast_check_hangup ( chan ) ) {
/* Agent hungup */
ast_mutex_unlock ( & p - > lock ) ;
break ;
}
}
ast_mutex_unlock ( & p - > lock ) ;
if ( p - > ackcall ) {
res = agent_ack_sleep ( p ) ;
if ( res = = 1 ) {
AST_LIST_LOCK ( & agents ) ;
ast_mutex_lock ( & p - > lock ) ;
check_availability ( p , 0 ) ;
ast_mutex_unlock ( & p - > lock ) ;
AST_LIST_UNLOCK ( & agents ) ;
}
} else {
res = ast_safe_sleep_conditional ( chan , 1000 , agent_cont_sleep , p ) ;
}
if ( p - > ackcall & & ( res = = 1 ) ) {
AST_LIST_LOCK ( & agents ) ;
ast_mutex_lock ( & p - > lock ) ;
check_availability ( p , 0 ) ;
ast_mutex_unlock ( & p - > lock ) ;
AST_LIST_UNLOCK ( & agents ) ;
res = 0 ;
}
sched_yield ( ) ;
}
ast_mutex_lock ( & p - > lock ) ;
/* Log us off if appropriate */
if ( p - > chan = = chan ) {
p - > chan = NULL ;
}
/* Logoff this channel */
p - > chan = NULL ;
logintime = time ( NULL ) - p - > loginstart ;
p - > loginstart = 0 ;
/* Synchronize channel ownership between call to agent and itself. */
if ( p - > app_lock_flag = = 1 ) {
if ( p - > app_lock_flag ) {
ast_cond_signal ( & p - > login_wait_cond ) ;
ast_cond_wait ( & p - > app_complete_cond , & p - > lock ) ;
}
if ( res & & p- > owner )
if ( p- > owner ) {
ast_log ( LOG_WARNING , " Huh? We broke out when there was still an owner? \n " ) ;
}
p - > acknowledged = 0 ;
logintime = time ( NULL ) - p - > loginstart ;
p - > loginstart = 0 ;
ast_mutex_unlock ( & p - > lock ) ;
ast_devstate_changed ( AST_DEVICE_UNKNOWN , AST_DEVSTATE_CACHABLE , " %s " , agent ) ;
/*** DOCUMENTATION
< managerEventInstance >
< synopsis > Raised when an Agent has logged off . < / synopsis >
@ -2238,21 +2194,22 @@ static int login_exec(struct ast_channel *chan, const char *data)
p - > agent , logintime , ast_channel_uniqueid ( chan ) ) ;
ast_queue_log ( " NONE " , ast_channel_uniqueid ( chan ) , agent , " AGENTLOGOFF " , " %s|%ld " , ast_channel_name ( chan ) , logintime ) ;
ast_verb ( 2 , " Agent '%s' logged out \n " , p - > agent ) ;
/* If there is no owner, go ahead and kill it now */
ast_devstate_changed ( AST_DEVICE_UNAVAILABLE , AST_DEVSTATE_CACHABLE , " Agent/%s " , p - > agent ) ;
if ( p - > dead & & ! p - > owner ) {
agent_pvt_destroy ( p ) ;
}
}
else {
AST_LIST_LOCK ( & agents ) ;
} else {
/* Agent hung up before could be logged in. */
p - > chan = NULL ;
ast_mutex_unlock ( & p - > lock ) ;
p = NULL ;
}
res = - 1 ;
} else {
ast_mutex_unlock ( & p - > lock ) ;
errmsg = " agent-alreadyon " ;
p = NULL ;
}
break ;
}
@ -2261,8 +2218,7 @@ static int login_exec(struct ast_channel *chan, const char *data)
ast_channel_unlock ( chan ) ;
}
}
if ( ! p )
AST_LIST_UNLOCK ( & agents ) ;
AST_LIST_UNLOCK ( & agents ) ;
if ( ! res & & ( max_login_tries = = 0 | | tries < max_login_tries ) )
res = ast_app_getdata ( chan , errmsg , user , sizeof ( user ) - 1 , 0 ) ;
@ -2338,40 +2294,33 @@ static int agentmonitoroutgoing_exec(struct ast_channel *chan, const char *data)
static int agent_devicestate ( const char * data )
{
struct agent_pvt * p ;
const char * s ;
ast_group_t groupmatch ;
int groupoff ;
const char * device = data ;
int res = AST_DEVICE_INVALID ;
s = data ;
if ( ( s [ 0 ] = = ' @ ' ) & & ( sscanf ( s + 1 , " %30d " , & groupoff ) = = 1 ) )
groupmatch = ( 1 < < groupoff ) ;
else if ( ( s [ 0 ] = = ' : ' ) & & ( sscanf ( s + 1 , " %30d " , & groupoff ) = = 1 ) ) {
groupmatch = ( 1 < < groupoff ) ;
} else
groupmatch = 0 ;
/* Check actual logged in agents first */
if ( device [ 0 ] = = ' @ ' | | device [ 0 ] = = ' : ' ) {
/* Device state of groups not supported. */
return AST_DEVICE_INVALID ;
}
/* Want device state of a specific agent. */
AST_LIST_LOCK ( & agents ) ;
AST_LIST_TRAVERSE ( & agents , p , list ) {
ast_mutex_lock ( & p - > lock ) ;
if ( ! p - > pending & & ( ( groupmatch & & ( p - > group & groupmatch ) ) | | ! strcmp ( data , p - > agent ) ) ) {
if ( ! p - > pending & & ! strcmp ( device , p - > agent ) ) {
if ( p - > owner ) {
if ( res ! = AST_DEVICE_INUSE )
res = AST_DEVICE_BUSY ;
} else {
if ( res = = AST_DEVICE_BUSY )
res = AST_DEVICE_BUSY ;
} else if ( p - > chan ) {
if ( p - > lastdisc . tv_sec | | p - > deferlogoff ) {
/* Agent is in wrapup time so unavailable for another call. */
res = AST_DEVICE_INUSE ;
if ( p - > chan ) {
if ( res = = AST_DEVICE_INVALID )
res = AST_DEVICE_UNKNOWN ;
} else if ( res = = AST_DEVICE_INVALID )
res = AST_DEVICE_UNAVAILABLE ;
}
if ( ! strcmp ( data , p - > agent ) ) {
ast_mutex_unlock ( & p - > lock ) ;
break ;
} else {
res = AST_DEVICE_NOT_INUSE ;
}
} else {
res = AST_DEVICE_UNAVAILABLE ;
}
ast_mutex_unlock ( & p - > lock ) ;
break ;
}
ast_mutex_unlock ( & p - > lock ) ;
}