@ -352,7 +352,8 @@ struct queue_ent {
} ;
struct member {
char interface [ 80 ] ; /*!< Technology/Location */
char interface [ 80 ] ; /*!< Technology/Location to dial to reach this member*/
char state_interface [ 80 ] ; /*!< Technology/Location from which to read devicestate changes */
char membername [ 80 ] ; /*!< Member name to use in queue logs */
int penalty ; /*!< Are we a last resort? */
int calls ; /*!< Number of calls serviced by this member */
@ -690,7 +691,7 @@ static void *handle_statechange(struct statechange *sc)
while ( ( cur = ao2_iterator_next ( & mem_iter ) ) ) {
char * interface ;
char * slash_pos ;
interface = ast_strdupa ( cur - > interface) ;
interface = ast_strdupa ( cur - > state_ interface) ;
if ( ( slash_pos = strchr ( interface , ' / ' ) ) )
if ( ( slash_pos = strchr ( slash_pos + 1 , ' / ' ) ) )
* slash_pos = ' \0 ' ;
@ -815,7 +816,7 @@ static void device_state_cb(const struct ast_event *event, void *unused)
statechange_queue ( device , state ) ;
}
static struct member * create_queue_member ( const char * interface , const char * membername , int penalty , int paused )
static struct member * create_queue_member ( const char * interface , const char * membername , int penalty , int paused , const char * state_interface )
{
struct member * cur ;
@ -823,6 +824,10 @@ static struct member *create_queue_member(const char *interface, const char *mem
cur - > penalty = penalty ;
cur - > paused = paused ;
ast_copy_string ( cur - > interface , interface , sizeof ( cur - > interface ) ) ;
if ( ! ast_strlen_zero ( state_interface ) )
ast_copy_string ( cur - > state_interface , state_interface , sizeof ( cur - > state_interface ) ) ;
else
ast_copy_string ( cur - > state_interface , interface , sizeof ( cur - > state_interface ) ) ;
if ( ! ast_strlen_zero ( membername ) )
ast_copy_string ( cur - > membername , membername , sizeof ( cur - > membername ) ) ;
else
@ -958,20 +963,20 @@ static int interface_exists_global(const char *interface)
{
struct call_queue * q ;
struct member * mem , tmpmem ;
struct ao2_iterator queue_iter ;
struct ao2_iterator queue_iter , mem_iter ;
int ret = 0 ;
ast_copy_string ( tmpmem . interface , interface , sizeof ( tmpmem . interface ) ) ;
queue_iter = ao2_iterator_init ( queues , 0 ) ;
while ( ( q = ao2_iterator_next ( & queue_iter ) ) ) {
ao2_lock ( q ) ;
if ( ( mem = ao2_find ( q - > members , & tmpmem , OBJ_POINTER ) ) ) {
ao2_ref ( mem , - 1 ) ;
ao2_unlock ( q ) ;
queue_unref ( q ) ;
ret = 1 ;
break ;
mem_iter = ao2_iterator_init ( q - > members , 0 ) ;
while ( ( mem = ao2_iterator_next ( & mem_iter ) ) ) {
if ( ! strcasecmp ( mem - > state_interface , interface ) ) {
ao2_ref ( mem , - 1 ) ;
ret = 1 ;
break ;
}
}
ao2_unlock ( q ) ;
queue_unref ( q ) ;
@ -991,7 +996,7 @@ static int remove_from_interfaces(const char *interface)
ast_debug ( 1 , " Removing %s from the list of interfaces that make up all of our queue members. \n " , interface ) ;
AST_LIST_REMOVE_CURRENT ( list ) ;
ast_free ( curint ) ;
}
}
break ;
}
}
@ -1256,7 +1261,7 @@ static void queue_set_param(struct call_queue *q, const char *param, const char
}
}
static void rt_handle_member_record ( struct call_queue * q , char * interface , const char * membername , const char * penalty_str , const char * paused_str )
static void rt_handle_member_record ( struct call_queue * q , char * interface , const char * membername , const char * penalty_str , const char * paused_str , const char * state_interface )
{
struct member * m , tmpmem ;
int penalty = 0 ;
@ -1280,10 +1285,10 @@ static void rt_handle_member_record(struct call_queue *q, char *interface, const
/* Create a new one if not found, else update penalty */
if ( ! m ) {
if ( ( m = create_queue_member ( interface , membername , penalty , paused )) ) {
if ( ( m = create_queue_member ( interface , membername , penalty , paused , state_interface )) ) {
m - > dead = 0 ;
m - > realtime = 1 ;
add_to_interfaces ( interface) ;
add_to_interfaces ( state_ interface) ;
ao2_link ( q - > members , m ) ;
ao2_ref ( m , - 1 ) ;
m = NULL ;
@ -1293,6 +1298,11 @@ static void rt_handle_member_record(struct call_queue *q, char *interface, const
m - > dead = 0 ; /* Do not delete this one. */
if ( paused_str )
m - > paused = paused ;
if ( strcasecmp ( state_interface , m - > state_interface ) ) {
remove_from_interfaces ( m - > state_interface ) ;
ast_copy_string ( m - > state_interface , state_interface , sizeof ( m - > state_interface ) ) ;
add_to_interfaces ( m - > state_interface ) ;
}
m - > penalty = penalty ;
ao2_ref ( m , - 1 ) ;
}
@ -1307,7 +1317,7 @@ static void free_members(struct call_queue *q, int all)
while ( ( cur = ao2_iterator_next ( & mem_iter ) ) ) {
if ( all | | ! cur - > dynamic ) {
ao2_unlink ( q - > members , cur ) ;
remove_from_interfaces ( cur - > interface) ;
remove_from_interfaces ( cur - > state_ interface) ;
q - > membercount - - ;
}
ao2_ref ( cur , - 1 ) ;
@ -1436,7 +1446,8 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as
rt_handle_member_record ( q , interface ,
ast_variable_retrieve ( member_config , interface , " membername " ) ,
ast_variable_retrieve ( member_config , interface , " penalty " ) ,
ast_variable_retrieve ( member_config , interface , " paused " ) ) ;
ast_variable_retrieve ( member_config , interface , " paused " ) ,
ast_variable_retrieve ( member_config , interface , " state_interface " ) ) ;
}
/* Delete all realtime members that have been deleted in DB. */
@ -1444,9 +1455,7 @@ static struct call_queue *find_queue_by_name_rt(const char *queuename, struct as
while ( ( m = ao2_iterator_next ( & mem_iter ) ) ) {
if ( m - > dead ) {
ao2_unlink ( q - > members , m ) ;
ao2_unlock ( q ) ;
remove_from_interfaces ( m - > interface ) ;
ao2_lock ( q ) ;
remove_from_interfaces ( m - > state_interface ) ;
q - > membercount - - ;
}
ao2_ref ( m , - 1 ) ;
@ -1549,7 +1558,8 @@ static void update_realtime_members(struct call_queue *q)
rt_handle_member_record ( q , interface ,
S_OR ( ast_variable_retrieve ( member_config , interface , " membername " ) , interface ) ,
ast_variable_retrieve ( member_config , interface , " penalty " ) ,
ast_variable_retrieve ( member_config , interface , " paused " ) ) ;
ast_variable_retrieve ( member_config , interface , " paused " ) ,
ast_variable_retrieve ( member_config , interface , " state_interface " ) ) ;
}
/* Delete all realtime members that have been deleted in DB. */
@ -1557,9 +1567,7 @@ static void update_realtime_members(struct call_queue *q)
while ( ( m = ao2_iterator_next ( & mem_iter ) ) ) {
if ( m - > dead ) {
ao2_unlink ( q - > members , m ) ;
ao2_unlock ( q ) ;
remove_from_interfaces ( m - > interface ) ;
ao2_lock ( q ) ;
remove_from_interfaces ( m - > state_interface ) ;
q - > membercount - - ;
}
ao2_ref ( m , - 1 ) ;
@ -3578,6 +3586,7 @@ static int remove_from_queue(const char *queuename, const char *interface)
" MemberName: %s \r \n " ,
q - > name , mem - > interface , mem - > membername ) ;
ao2_unlink ( q - > members , mem ) ;
remove_from_interfaces ( mem - > state_interface ) ;
ao2_ref ( mem , - 1 ) ;
if ( queue_persistent_members )
@ -3591,14 +3600,11 @@ static int remove_from_queue(const char *queuename, const char *interface)
queue_unref ( q ) ;
}
if ( res = = RES_OKAY )
remove_from_interfaces ( interface ) ;
return res ;
}
static int add_to_queue ( const char * queuename , const char * interface , const char * membername , int penalty , int paused , int dump )
static int add_to_queue ( const char * queuename , const char * interface , const char * membername , int penalty , int paused , int dump , const char * state_interface )
{
struct call_queue * q ;
struct member * new_member , * old_member ;
@ -3613,8 +3619,8 @@ static int add_to_queue(const char *queuename, const char *interface, const char
ao2_lock ( q ) ;
if ( ( old_member = interface_exists ( q , interface ) ) = = NULL ) {
add_to_interfaces ( interface ) ;
if ( ( new_member = create_queue_member ( interface , membername , penalty , paused ) ) ) {
if ( ( new_member = create_queue_member ( interface , membername , penalty , paused , state_interface ) ) ) {
add_to_interfaces ( state_interface ) ;
new_member - > dynamic = 1 ;
ao2_link ( q - > members , new_member ) ;
q - > membercount + + ;
@ -3797,6 +3803,7 @@ static void reload_queue_members(void)
char * member ;
char * interface ;
char * membername = NULL ;
char * state_interface ;
char * penalty_tok ;
int penalty = 0 ;
char * paused_tok ;
@ -3846,6 +3853,7 @@ static void reload_queue_members(void)
penalty_tok = strsep ( & member , " ; " ) ;
paused_tok = strsep ( & member , " ; " ) ;
membername = strsep ( & member , " ; " ) ;
state_interface = strsep ( & member , " ; " ) ;
if ( ! penalty_tok ) {
ast_log ( LOG_WARNING , " Error parsing persistent member string for '%s' (penalty) \n " , queue_name ) ;
@ -3866,12 +3874,10 @@ static void reload_queue_members(void)
ast_log ( LOG_WARNING , " Error converting paused: %s: Expected 0 or 1. \n " , paused_tok ) ;
break ;
}
if ( ast_strlen_zero ( membername ) )
membername = interface ;
ast_debug ( 1 , " Reload Members: Queue: %s Member: %s Name: %s Penalty: %d Paused: %d \n " , queue_name , interface , membername , penalty , paused ) ;
if ( add_to_queue ( queue_name , interface , membername , penalty , paused , 0 ) = = RES_OUTOFMEMORY ) {
if ( add_to_queue ( queue_name , interface , membername , penalty , paused , 0 , state_interface ) = = RES_OUTOFMEMORY ) {
ast_log ( LOG_ERROR , " Out of Memory when reloading persistent queue member \n " ) ;
break ;
}
@ -4020,6 +4026,7 @@ static int aqm_exec(struct ast_channel *chan, void *data)
AST_APP_ARG ( penalty ) ;
AST_APP_ARG ( options ) ;
AST_APP_ARG ( membername ) ;
AST_APP_ARG ( state_interface ) ;
) ;
int penalty = 0 ;
@ -4046,7 +4053,7 @@ static int aqm_exec(struct ast_channel *chan, void *data)
}
}
switch ( add_to_queue ( args . queuename , args . interface , args . membername , penalty , 0 , queue_persistent_members )) {
switch ( add_to_queue ( args . queuename , args . interface , args . membername , penalty , 0 , queue_persistent_members , args . state_interface )) {
case RES_OKAY :
ast_queue_log ( args . queuename , chan - > uniqueid , args . interface , " ADDMEMBER " , " %s " , " " ) ;
ast_log ( LOG_NOTICE , " Added interface '%s' to queue '%s' \n " , args . interface , args . queuename ) ;
@ -4803,7 +4810,7 @@ static int reload_queues(int reload)
int new ;
const char * general_val = NULL ;
char parse [ 80 ] ;
char * interface ;
char * interface , * state_interface ;
char * membername = NULL ;
int penalty ;
struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 } ;
@ -4812,6 +4819,7 @@ static int reload_queues(int reload)
AST_APP_ARG ( interface ) ;
AST_APP_ARG ( penalty ) ;
AST_APP_ARG ( membername ) ;
AST_APP_ARG ( state_interface ) ;
) ;
/*First things first. Let's load queuerules.conf*/
@ -4880,8 +4888,10 @@ static int reload_queues(int reload)
/* Check if a queue with this name already exists */
if ( q - > found ) {
ast_log ( LOG_WARNING , " Queue '%s' already defined! Skipping! \n " , cat ) ;
if ( ! new )
if ( ! new ) {
ao2_unlock ( q ) ;
queue_unref ( q ) ;
}
continue ;
}
/* Due to the fact that the "linear" strategy will have a different allocation
@ -4933,11 +4943,22 @@ static int reload_queues(int reload)
while ( * membername & & * membername < 33 ) membername + + ;
}
if ( ! ast_strlen_zero ( args . state_interface ) ) {
state_interface = args . state_interface ;
while ( * state_interface & & * state_interface < 33 ) state_interface + + ;
} else
state_interface = interface ;
/* Find the old position in the list */
ast_copy_string ( tmpmem . interface , interface , sizeof ( tmpmem . interface ) ) ;
cur = ao2_find ( q - > members , & tmpmem , OBJ_POINTER | OBJ_UNLINK ) ;
newm = create_queue_member ( interface , membername , penalty , cur ? cur - > paused : 0 ) ;
/* Only attempt removing from interfaces list if the new state_interface is different than the old one */
if ( cur & & strcasecmp ( cur - > state_interface , state_interface ) ) {
remove_from_interfaces ( cur - > state_interface ) ;
}
newm = create_queue_member ( interface , membername , penalty , cur ? cur - > paused : 0 , state_interface ) ;
if ( ! cur | | ( cur & & strcasecmp ( cur - > state_interface , state_interface ) ) )
add_to_interfaces ( state_interface ) ;
ao2_link ( q - > members , newm ) ;
ao2_ref ( newm , - 1 ) ;
newm = NULL ;
@ -4945,8 +4966,6 @@ static int reload_queues(int reload)
if ( cur )
ao2_ref ( cur , - 1 ) ;
else {
/* Add them to the master int list if necessary */
add_to_interfaces ( interface ) ;
q - > membercount + + ;
}
} else {
@ -4961,16 +4980,16 @@ static int reload_queues(int reload)
ao2_ref ( cur , - 1 ) ;
continue ;
}
remove_from_interfaces ( cur - > interface ) ;
ast_log ( LOG_DEBUG , " %s in queue marked as delme, we should be deleting... \n " , cur - > interface ) ;
q - > membercount - - ;
ao2_unlink ( q - > members , cur ) ;
remove_from_interfaces ( cur - > interface ) ;
ao2_ref ( cur , - 1 ) ;
}
if ( new ) {
ao2_link ( queues , q ) ;
} else
} else
ao2_unlock ( q ) ;
queue_unref ( q ) ;
}
@ -5352,7 +5371,7 @@ static int manager_queues_status(struct mansession *s, const struct message *m)
static int manager_add_queue_member ( struct mansession * s , const struct message * m )
{
const char * queuename , * interface , * penalty_s , * paused_s , * membername ;
const char * queuename , * interface , * penalty_s , * paused_s , * membername , * state_interface ;
int paused , penalty = 0 ;
queuename = astman_get_header ( m , " Queue " ) ;
@ -5360,6 +5379,7 @@ static int manager_add_queue_member(struct mansession *s, const struct message *
penalty_s = astman_get_header ( m , " Penalty " ) ;
paused_s = astman_get_header ( m , " Paused " ) ;
membername = astman_get_header ( m , " MemberName " ) ;
state_interface = astman_get_header ( m , " StateInterface " ) ;
if ( ast_strlen_zero ( queuename ) ) {
astman_send_error ( s , m , " 'Queue' not specified. " ) ;
@ -5381,7 +5401,7 @@ static int manager_add_queue_member(struct mansession *s, const struct message *
else
paused = abs ( ast_true ( paused_s ) ) ;
switch ( add_to_queue ( queuename , interface , membername , penalty , paused , queue_persistent_members )) {
switch ( add_to_queue ( queuename , interface , membername , penalty , paused , queue_persistent_members , state_interface )) {
case RES_OKAY :
ast_queue_log ( queuename , " MANAGER " , interface , " ADDMEMBER " , " %s " , " " ) ;
astman_send_ack ( s , m , " Added interface to queue " ) ;
@ -5537,26 +5557,28 @@ static int manager_queue_member_penalty(struct mansession *s, const struct messa
static char * handle_queue_add_member ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
{
char * queuename , * interface , * membername = NULL ;
char * queuename , * interface , * membername = NULL , * state_interface ;
int penalty ;
switch ( cmd ) {
case CLI_INIT :
e - > command = " queue add member " ;
e - > usage =
" Usage: queue add member <channel> to <queue> [ penalty <penalty>]\n " ;
" Usage: queue add member <channel> to <queue> [ [[ penalty <penalty>] as <membername>] state_interface <interface >]\n " ;
return NULL ;
case CLI_GENERATE :
return complete_queue_add_member ( a - > line , a - > word , a - > pos , a - > n ) ;
}
if ( ( a - > argc ! = 6 ) & & ( a - > argc ! = 8 ) & & ( a - > argc ! = 10 ) ) {
if ( ( a - > argc ! = 6 ) & & ( a - > argc ! = 8 ) & & ( a - > argc ! = 10 ) & & ( a - > argc ! = 12 ) ) {
return CLI_SHOWUSAGE ;
} else if ( strcmp ( a - > argv [ 4 ] , " to " ) ) {
return CLI_SHOWUSAGE ;
} else if ( ( a - > argc = = 8 ) & & strcmp ( a - > argv [ 6 ] , " penalty " ) ) {
} else if ( ( a - > argc > = 8 ) & & strcmp ( a - > argv [ 6 ] , " penalty " ) ) {
return CLI_SHOWUSAGE ;
} else if ( ( a - > argc > = 10 ) & & strcmp ( a - > argv [ 8 ] , " as " ) ) {
return CLI_SHOWUSAGE ;
} else if ( ( a - > argc = = 10 ) & & strcmp ( a - > argv [ 8 ] , " as " ) ) {
} else if ( ( a - > argc = = 1 2 ) & & strcmp ( a - > argv [ 10] , " state_interface " ) ) {
return CLI_SHOWUSAGE ;
}
@ -5580,7 +5602,11 @@ static char *handle_queue_add_member(struct ast_cli_entry *e, int cmd, struct as
membername = a - > argv [ 9 ] ;
}
switch ( add_to_queue ( queuename , interface , membername , penalty , 0 , queue_persistent_members ) ) {
if ( a - > argc > = 12 ) {
state_interface = a - > argv [ 11 ] ;
}
switch ( add_to_queue ( queuename , interface , membername , penalty , 0 , queue_persistent_members , state_interface ) ) {
case RES_OKAY :
ast_queue_log ( queuename , " CLI " , interface , " ADDMEMBER " , " %s " , " " ) ;
ast_cli ( a - > fd , " Added interface '%s' to queue '%s' \n " , interface , queuename ) ;