@ -1023,6 +1023,13 @@ ASTERISK_REGISTER_FILE()
< parameter name = " LastCall " >
< para > The time this member last took a call , expressed in seconds since 00 : 00 , Jan 1 , 1970 UTC . < / para >
< / parameter >
< parameter name = " InCall " >
< para > Set to 1 if member is in call . Set to 0 after LastCall time is updated . < / para >
< enumlist >
< enum name = " 0 " / >
< enum name = " 1 " / >
< / enumlist >
< / parameter >
< parameter name = " Status " >
< para > The numeric device state status of the queue member . < / para >
< enumlist >
@ -1540,6 +1547,7 @@ struct member {
char reason_paused [ 80 ] ; /*!< Reason of paused if member is paused */
int queuepos ; /*!< In what order (pertains to certain strategies) should this member be called? */
time_t lastcall ; /*!< When last successful call was hungup */
unsigned int in_call : 1 ; /*!< True if member is still in call. (so lastcall is not actual) */
struct call_queue * lastqueue ; /*!< Last queue we received a call */
unsigned int dead : 1 ; /*!< Used to detect members deleted in realtime */
unsigned int delme : 1 ; /*!< Flag to delete entry on reload */
@ -2177,7 +2185,7 @@ static void queue_publish_member_blob(struct stasis_message_type *type, struct a
static struct ast_json * queue_member_blob_create ( struct call_queue * q , struct member * mem )
{
return ast_json_pack ( " {s: s, s: s, s: s, s: s, s: s, s: i, s: i, s: i, s: i, s: i, s: s, s: i}" ,
return ast_json_pack ( " {s: s, s: s, s: s, s: s, s: s, s: i, s: i, s: i, s: i, s: i, s: i, s: s, s: i}" ,
" Queue " , q - > name ,
" MemberName " , mem - > membername ,
" Interface " , mem - > interface ,
@ -2186,6 +2194,7 @@ static struct ast_json *queue_member_blob_create(struct call_queue *q, struct me
" Penalty " , mem - > penalty ,
" CallsTaken " , mem - > calls ,
" LastCall " , ( int ) mem - > lastcall ,
" InCall " , mem - > in_call ,
" Status " , mem - > status ,
" Paused " , mem - > paused ,
" PausedReason " , mem - > reason_paused ,
@ -2249,6 +2258,10 @@ static int get_member_status(struct call_queue *q, int max_penalty, int min_pena
if ( member - > paused & & ( conditions & QUEUE_EMPTY_PAUSED ) ) {
ast_debug ( 4 , " %s is unavailable because he is paused' \n " , member - > membername ) ;
break ;
} else if ( ( conditions & QUEUE_EMPTY_WRAPUP ) & & member - > in_call & & q - > wrapuptime ) {
ast_debug ( 4 , " %s is unavailable because still in call, so we can`t check "
" wrapuptime (%d) \n " , member - > membername , q - > wrapuptime ) ;
break ;
} else if ( ( conditions & QUEUE_EMPTY_WRAPUP ) & & member - > lastcall & & q - > wrapuptime & & ( time ( NULL ) - q - > wrapuptime < member - > lastcall ) ) {
ast_debug ( 4 , " %s is unavailable because it has only been %d seconds since his last call (wrapup time is %d) \n " , member - > membername , ( int ) ( time ( NULL ) - member - > lastcall ) , q - > wrapuptime ) ;
break ;
@ -2316,6 +2329,9 @@ static int is_member_available(struct call_queue *q, struct member *mem)
}
/* Let wrapuptimes override device state availability */
if ( q - > wrapuptime & & mem - > in_call ) {
available = 0 ; /* member is still in call, cant check wrapuptime to lastcall time */
}
if ( mem - > lastcall & & q - > wrapuptime & & ( time ( NULL ) - q - > wrapuptime < mem - > lastcall ) ) {
available = 0 ;
}
@ -2668,6 +2684,7 @@ static void clear_queue(struct call_queue *q)
while ( ( mem = ao2_iterator_next ( & mem_iter ) ) ) {
mem - > calls = 0 ;
mem - > lastcall = 0 ;
mem - > in_call = 0 ;
ao2_ref ( mem , - 1 ) ;
}
ao2_iterator_destroy ( & mem_iter ) ;
@ -4165,6 +4182,12 @@ static int can_ring_entry(struct queue_ent *qe, struct callattempt *call)
return 0 ;
}
if ( call - > member - > in_call & & call - > lastqueue - > wrapuptime ) {
ast_debug ( 1 , " %s is in call, so not available (wrapuptime %d) \n " ,
call - > interface , call - > lastqueue - > wrapuptime ) ;
return 0 ;
}
if ( ( call - > lastqueue & & call - > lastqueue - > wrapuptime & & ( time ( NULL ) - call - > lastcall < call - > lastqueue - > wrapuptime ) )
| | ( ! call - > lastqueue & & qe - > parent - > wrapuptime & & ( time ( NULL ) - call - > lastcall < qe - > parent - > wrapuptime ) ) ) {
ast_debug ( 1 , " Wrapuptime not yet expired on queue %s for %s \n " ,
@ -5387,6 +5410,9 @@ static int update_queue(struct call_queue *q, struct member *member, int callcom
time ( & mem - > lastcall ) ;
mem - > calls + + ;
mem - > lastqueue = q ;
mem - > in_call = 0 ;
ast_debug ( 4 , " Marked member %s as NOT in_call. Lastcall time: %ld \n " ,
mem - > membername , ( long ) mem - > lastcall ) ;
ao2_ref ( mem , - 1 ) ;
}
ao2_unlock ( qtmp ) ;
@ -5398,6 +5424,9 @@ static int update_queue(struct call_queue *q, struct member *member, int callcom
time ( & member - > lastcall ) ;
member - > calls + + ;
member - > lastqueue = q ;
member - > in_call = 0 ;
ast_debug ( 4 , " Marked member %s as NOT in_call. Lastcall time: %ld \n " ,
member - > membername , ( long ) member - > lastcall ) ;
ao2_unlock ( q ) ;
}
ao2_lock ( q ) ;
@ -6376,6 +6405,9 @@ static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_a
int callcompletedinsl ;
struct ao2_iterator memi ;
struct queue_end_bridge * queue_end_bridge = NULL ;
struct ao2_iterator queue_iter ; /* to iterate through all queues (for shared_lastcall)*/
struct member * mem ;
struct call_queue * queuetmp ;
memset ( & bridge_config , 0 , sizeof ( bridge_config ) ) ;
tmpid [ 0 ] = 0 ;
@ -6801,6 +6833,28 @@ static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_a
}
}
qe - > handled + + ;
/** mark member as "in_call" in all queues */
if ( shared_lastcall ) {
queue_iter = ao2_iterator_init ( queues , 0 ) ;
while ( ( queuetmp = ao2_t_iterator_next ( & queue_iter , " Iterate through queues " ) ) ) {
ao2_lock ( queuetmp ) ;
if ( ( mem = ao2_find ( queuetmp - > members , member , OBJ_POINTER ) ) ) {
mem - > in_call = 1 ;
ast_debug ( 4 , " Marked member %s as in_call \n " , mem - > membername ) ;
ao2_ref ( mem , - 1 ) ;
}
ao2_unlock ( queuetmp ) ;
queue_t_unref ( queuetmp , " Done with iterator " ) ;
}
ao2_iterator_destroy ( & queue_iter ) ;
} else {
ao2_lock ( qe - > parent ) ;
member - > in_call = 1 ;
ast_debug ( 4 , " Marked member %s as in_call \n " , member - > membername ) ;
ao2_unlock ( qe - > parent ) ;
}
ast_queue_log ( queuename , ast_channel_uniqueid ( qe - > chan ) , member - > membername , " CONNECT " , " %ld|%s|%ld " , ( long ) ( time ( NULL ) - qe - > start ) , ast_channel_uniqueid ( peer ) ,
( long ) ( orig - to > 0 ? ( orig - to ) / 1000 : 0 ) ) ;
@ -9255,9 +9309,10 @@ static char *__queues_show(struct mansession *s, int fd, int argc, const char *
ast_str_append ( & out , 0 , " (ringinuse %s) " , mem - > ringinuse ? " enabled " : " disabled " ) ;
ast_str_append ( & out , 0 , " %s%s%s%s%s%s " ,
ast_str_append ( & out , 0 , " %s%s%s%s%s%s %s%s%s " ,
mem - > dynamic ? ast_term_color ( COLOR_CYAN , COLOR_BLACK ) : " " , mem - > dynamic ? " (dynamic) " : " " , ast_term_reset ( ) ,
mem - > realtime ? ast_term_color ( COLOR_MAGENTA , COLOR_BLACK ) : " " , mem - > realtime ? " (realtime) " : " " , ast_term_reset ( ) ) ;
mem - > realtime ? ast_term_color ( COLOR_MAGENTA , COLOR_BLACK ) : " " , mem - > realtime ? " (realtime) " : " " , ast_term_reset ( ) ,
mem - > in_call ? ast_term_color ( COLOR_BROWN , COLOR_BLACK ) : " " , mem - > in_call ? " (in call) " : " " , ast_term_reset ( ) ) ;
if ( mem - > paused ) {
if ( ast_strlen_zero ( mem - > reason_paused ) ) {
ast_str_append ( & out , 0 , " %s(paused)%s " ,
@ -9636,13 +9691,15 @@ static int manager_queues_status(struct mansession *s, const struct message *m)
" Penalty: %d \r \n "
" CallsTaken: %d \r \n "
" LastCall: %d \r \n "
" InCall: %d \r \n "
" Status: %d \r \n "
" Paused: %d \r \n "
" PausedReason: %s \r \n "
" %s "
" \r \n " ,
q - > name , mem - > membername , mem - > interface , mem - > state_interface , mem - > dynamic ? " dynamic " : " static " ,
mem - > penalty , mem - > calls , ( int ) mem - > lastcall , mem - > status , mem - > paused , mem - > reason_paused , idText ) ;
mem - > penalty , mem - > calls , ( int ) mem - > lastcall , mem - > in_call , mem - > status ,
mem - > paused , mem - > reason_paused , idText ) ;
+ + q_items ;
}
ao2_ref ( mem , - 1 ) ;