Asterisk - The Open Source Telephony Project GIT-master-0644429
Data Structures | Macros | Enumerations | Functions | Variables
app_queue.c File Reference

True call queues with optional send URL on answer. More...

#include "asterisk.h"
#include <sys/time.h>
#include <signal.h>
#include <netinet/in.h>
#include <ctype.h>
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/app.h"
#include "asterisk/linkedlists.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"
#include "asterisk/say.h"
#include "asterisk/features.h"
#include "asterisk/musiconhold.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/config.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/astdb.h"
#include "asterisk/devicestate.h"
#include "asterisk/stringfields.h"
#include "asterisk/astobj2.h"
#include "asterisk/strings.h"
#include "asterisk/taskprocessor.h"
#include "asterisk/aoc.h"
#include "asterisk/callerid.h"
#include "asterisk/term.h"
#include "asterisk/dial.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/stasis_message_router.h"
#include "asterisk/bridge_after.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/core_local.h"
#include "asterisk/mixmonitor.h"
#include "asterisk/bridge_basic.h"
#include "asterisk/max_forwards.h"
Include dependency graph for app_queue.c:

Go to the source code of this file.

Data Structures

struct  autopause
 
struct  call_queue
 
struct  callattempt
 We define a custom "local user" structure because we use it not only for keeping track of what is in use but also for keeping track of who we're dialing. More...
 
struct  local_optimization
 Structure representing relevant data during a local channel optimization. More...
 
struct  member
 
struct  penalty_rule
 
struct  queue_end_bridge
 
struct  queue_ent
 
struct  queue_stasis_data
 User data for stasis subscriptions used for queue calls. More...
 
struct  rule_list
 
struct  rule_lists
 
struct  strategy
 

Macros

#define ANNOUNCEHOLDTIME_ALWAYS   1
 
#define ANNOUNCEHOLDTIME_ONCE   2
 
#define ANNOUNCEPOSITION_LIMIT   4
 
#define ANNOUNCEPOSITION_MORE_THAN   3
 
#define ANNOUNCEPOSITION_NO   2
 
#define ANNOUNCEPOSITION_YES   1
 
#define AST_MAX_WATCHERS   256
 
#define DEFAULT_MIN_ANNOUNCE_FREQUENCY   15
 The minimum number of seconds between position announcements. More...
 
#define DEFAULT_RETRY   5
 
#define DEFAULT_TIMEOUT   15
 
#define MAX_CALL_ATTEMPT_BUCKETS   353
 
#define MAX_PERIODIC_ANNOUNCEMENTS   10
 
#define MAX_QUEUE_BUCKETS   53
 
#define QUEUE_EVENT_VARIABLES   3
 
#define QUEUE_PAUSED_DEVSTATE   AST_DEVICE_INUSE
 
#define queue_ref(q)   ao2_bump(q)
 
#define queue_t_ref(q, tag)   ao2_t_bump(q, tag)
 
#define queue_t_unref(q, tag)   ({ ao2_t_cleanup(q, tag); NULL; })
 
#define QUEUE_UNKNOWN_PAUSED_DEVSTATE   AST_DEVICE_NOT_INUSE
 
#define QUEUE_UNPAUSED_DEVSTATE   AST_DEVICE_NOT_INUSE
 
#define queue_unref(q)   ({ ao2_cleanup(q); NULL; })
 
#define queues_t_link(c, q, tag)   ao2_t_link(c, q, tag)
 
#define queues_t_unlink(c, q, tag)   ao2_t_unlink(c, q, tag)
 
#define RECHECK   1
 
#define RES_EXISTS   (-1)
 
#define RES_NOSUCHQUEUE   (-3)
 
#define RES_NOT_CALLER   (-5)
 
#define RES_NOT_DYNAMIC   (-4)
 
#define RES_OKAY   0
 
#define RES_OUTOFMEMORY   (-2)
 

Enumerations

enum  {
  OPT_MARK_AS_ANSWERED = (1 << 0) , OPT_GO_ON = (1 << 1) , OPT_DATA_QUALITY = (1 << 2) , OPT_CALLEE_GO_ON = (1 << 3) ,
  OPT_CALLEE_HANGUP = (1 << 4) , OPT_CALLER_HANGUP = (1 << 5) , OPT_IGNORE_CALL_FW = (1 << 6) , OPT_IGNORE_CONNECTEDLINE = (1 << 7) ,
  OPT_CALLEE_PARK = (1 << 8) , OPT_CALLER_PARK = (1 << 9) , OPT_NO_RETRY = (1 << 10) , OPT_RINGING = (1 << 11) ,
  OPT_RING_WHEN_RINGING = (1 << 12) , OPT_CALLEE_TRANSFER = (1 << 13) , OPT_CALLER_TRANSFER = (1 << 14) , OPT_CALLEE_AUTOMIXMON = (1 << 15) ,
  OPT_CALLER_AUTOMIXMON = (1 << 16) , OPT_CALLEE_AUTOMON = (1 << 17) , OPT_CALLER_AUTOMON = (1 << 18) , OPT_PREDIAL_CALLEE = (1 << 19) ,
  OPT_PREDIAL_CALLER = (1 << 20) , OPT_MUSICONHOLD_CLASS = (1 << 21)
}
 
enum  {
  OPT_ARG_CALLEE_GO_ON = 0 , OPT_ARG_PREDIAL_CALLEE , OPT_ARG_PREDIAL_CALLER , OPT_ARG_MUSICONHOLD_CLASS ,
  OPT_ARG_ARRAY_SIZE
}
 
enum  {
  QUEUE_STRATEGY_RINGALL = 0 , QUEUE_STRATEGY_LEASTRECENT , QUEUE_STRATEGY_FEWESTCALLS , QUEUE_STRATEGY_RANDOM ,
  QUEUE_STRATEGY_RRMEMORY , QUEUE_STRATEGY_LINEAR , QUEUE_STRATEGY_WRANDOM , QUEUE_STRATEGY_RRORDERED
}
 
enum  { QUEUE_AUTOPAUSE_OFF = 0 , QUEUE_AUTOPAUSE_ON , QUEUE_AUTOPAUSE_ALL }
 
enum  agent_complete_reason { CALLER , AGENT , TRANSFER }
 
enum  empty_conditions {
  QUEUE_EMPTY_PENALTY = (1 << 0) , QUEUE_EMPTY_PAUSED = (1 << 1) , QUEUE_EMPTY_INUSE = (1 << 2) , QUEUE_EMPTY_RINGING = (1 << 3) ,
  QUEUE_EMPTY_UNAVAILABLE = (1 << 4) , QUEUE_EMPTY_INVALID = (1 << 5) , QUEUE_EMPTY_UNKNOWN = (1 << 6) , QUEUE_EMPTY_WRAPUP = (1 << 7)
}
 
enum  member_properties { MEMBER_PENALTY = 0 , MEMBER_RINGINUSE = 1 }
 
enum  queue_reload_mask { QUEUE_RELOAD_PARAMETERS = (1 << 0) , QUEUE_RELOAD_MEMBER = (1 << 1) , QUEUE_RELOAD_RULES = (1 << 2) , QUEUE_RESET_STATS = (1 << 3) }
 
enum  queue_result {
  QUEUE_UNKNOWN = 0 , QUEUE_TIMEOUT = 1 , QUEUE_JOINEMPTY = 2 , QUEUE_LEAVEEMPTY = 3 ,
  QUEUE_JOINUNAVAIL = 4 , QUEUE_LEAVEUNAVAIL = 5 , QUEUE_FULL = 6 , QUEUE_CONTINUE = 7 ,
  QUEUE_WITHDRAW = 8
}
 
enum  queue_timeout_priority { TIMEOUT_PRIORITY_APP , TIMEOUT_PRIORITY_CONF }
 

Functions

static char * __queues_show (struct mansession *s, int fd, int argc, const char *const *argv)
 Show queue(s) status and statistics. More...
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
static int add_to_queue (const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface, const char *reason_paused, int wrapuptime)
 Add member to queue. More...
 
static struct call_queuealloc_queue (const char *queuename)
 
 AO2_STRING_FIELD_SORT_FN (call_queue, name)
 
static int aqm_exec (struct ast_channel *chan, const char *data)
 AddQueueMember application. More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int autopause2int (const char *autopause)
 
static int calc_metric (struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
 Calculate the metric of each member in the outgoing callattempts. More...
 
static void callattempt_free (struct callattempt *doomed)
 
static int can_ring_entry (struct queue_ent *qe, struct callattempt *call)
 
static int change_priority_caller_on_queue (const char *queuename, const char *caller, int priority, int immediate)
 Change priority caller into a queue. More...
 
static void clear_queue (struct call_queue *q)
 
static int clear_stats (const char *queuename)
 Facilitates resetting statistics for a queue. More...
 
static int compare_weight (struct call_queue *rq, struct member *member)
 
static char * complete_queue (const char *line, const char *word, int pos, int state, ptrdiff_t word_list_offset)
 Check if a given word is in a space-delimited list. More...
 
static char * complete_queue_add_member (const char *line, const char *word, int pos, int state)
 
static char * complete_queue_pause_member (const char *line, const char *word, int pos, int state)
 
static char * complete_queue_remove_member (const char *line, const char *word, int pos, int state)
 
static char * complete_queue_rule_show (const char *line, const char *word, int pos, int state)
 
static char * complete_queue_set_member_value (const char *line, const char *word, int pos, int state)
 
static char * complete_queue_show (const char *line, const char *word, int pos, int state)
 
static int compress_char (const char c)
 
static int context_included (const char *parent, const char *child)
 Returns if one context includes another context. More...
 
static void copy_rules (struct queue_ent *qe, const char *rulename)
 Copy rule from global list into specified queue. More...
 
static struct membercreate_queue_member (const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse, int wrapuptime)
 allocate space for new queue member and set fields based on parameters passed More...
 
static void destroy_queue (void *obj)
 Free queue's member list then its string fields. More...
 
static void destroy_queue_member_cb (void *obj)
 
static void device_state_cb (void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
 set a member's status based on device state of that member's interface More...
 
static void do_hang (struct callattempt *o)
 common hangup actions More...
 
static void do_print (struct mansession *s, int fd, const char *str)
 direct output to manager or cli with proper terminator More...
 
static void dump_queue_members (struct call_queue *pm_queue)
 Dump all members in a specific queue to the database. More...
 
static void end_bridge_callback (void *data)
 
static void end_bridge_callback_data_fixup (struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
 
static void escape_and_substitute (struct ast_channel *chan, const char *input, char *output, size_t size)
 
static int extension_state_cb (const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
 
static int extensionstate2devicestate (int state)
 Helper function which converts from extension state to device state values. More...
 
static struct callattemptfind_best (struct callattempt *outgoing)
 find the entry with the best metric, or NULL More...
 
static struct call_queuefind_load_queue_rt_friendly (const char *queuename)
 
static struct memberfind_member_by_queuename_and_interface (const char *queuename, const char *interface)
 Find a member by looking up queuename and interface. More...
 
static struct call_queuefind_queue_by_name_rt (const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
 Reload a single queue via realtime. More...
 
static void free_members (struct call_queue *q, int all)
 Iterate through queue's member list and delete them. More...
 
static struct memberget_interface_helper (struct call_queue *q, const char *interface)
 
static int get_member_penalty (char *queuename, char *interface)
 Gets members penalty. More...
 
static int get_member_status (struct call_queue *q, int max_penalty, int min_penalty, int raise_penalty, enum empty_conditions conditions, int devstate)
 Check if members are available. More...
 
static int get_queue_member_status (struct member *cur)
 Return the current state of a member. More...
 
static int get_wrapuptime (struct call_queue *q, struct member *member)
 Return wrapuptime. More...
 
static void handle_attended_transfer (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
 Handle an attended transfer event. More...
 
static void handle_blind_transfer (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
 Handle a blind transfer event. More...
 
static void handle_bridge_enter (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
 
static void handle_hangup (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
 
static void handle_local_optimization_begin (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
 
static void handle_local_optimization_end (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
 
static void handle_masquerade (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
 
static char * handle_queue_add_member (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_queue_change_priority_caller (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_queue_pause_member (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_queue_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_queue_remove_member (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_queue_reset (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_queue_rule_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_queue_set_member_penalty (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_queue_set_member_ringinuse (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void hangupcalls (struct queue_ent *qe, struct callattempt *outgoing, struct ast_channel *exception, int cancel_answered_elsewhere)
 Hang up a list of outgoing calls. More...
 
static void init_queue (struct call_queue *q)
 Initialize Queue default values. More...
 
static void insert_entry (struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
 Insert the 'new' entry after the 'prev' entry of queue 'q'. More...
 
static int insert_penaltychange (const char *list_name, const char *content, const int linenum)
 Change queue penalty by adding rule. More...
 
static const char * int2strat (int strategy)
 
static struct memberinterface_exists (struct call_queue *q, const char *interface)
 
static int is_longest_waiting_caller (struct queue_ent *caller, struct member *member)
 
static int is_member_available (struct call_queue *q, struct member *mem)
 
static int is_our_turn (struct queue_ent *qe)
 Check if we should start attempting to call queue members. More...
 
static int join_queue (char *queuename, struct queue_ent *qe, enum queue_result *reason, int position)
 
static int kill_dead_members (void *obj, void *arg, int flags)
 
static int kill_if_unfound (void *obj, void *arg, int flags)
 
static void leave_queue (struct queue_ent *qe)
 Caller leaving queue. More...
 
static int load_module (void)
 Load the module. More...
 
static void load_realtime_queues (const char *queuename)
 
static int load_realtime_rules (void)
 Load queue rules from realtime. More...
 
static void log_attended_transfer (struct queue_stasis_data *queue_data, struct ast_attended_transfer_message *atxfer_msg)
 
static int manager_add_queue_member (struct mansession *s, const struct message *m)
 
static int manager_change_priority_caller_on_queue (struct mansession *s, const struct message *m)
 
static int manager_pause_queue_member (struct mansession *s, const struct message *m)
 
static int manager_queue_log_custom (struct mansession *s, const struct message *m)
 
static int manager_queue_member_penalty (struct mansession *s, const struct message *m)
 
static int manager_queue_member_ringinuse (struct mansession *s, const struct message *m)
 
static int manager_queue_reload (struct mansession *s, const struct message *m)
 
static int manager_queue_reset (struct mansession *s, const struct message *m)
 
static int manager_queue_rule_show (struct mansession *s, const struct message *m)
 
static int manager_queues_status (struct mansession *s, const struct message *m)
 Queue status info via AMI. More...
 
static int manager_queues_summary (struct mansession *s, const struct message *m)
 Summary of queue info via the AMI. More...
 
static int manager_remove_queue_member (struct mansession *s, const struct message *m)
 
static int manager_request_withdraw_caller_from_queue (struct mansession *s, const struct message *m)
 
static int mark_member_dead (void *obj, void *arg, int flags)
 
static int mark_unfound (void *obj, void *arg, int flags)
 
static void member_add_to_queue (struct call_queue *queue, struct member *mem)
 
static int member_cmp_fn (void *obj1, void *obj2, int flags)
 
static int member_hash_fn (const void *obj, const int flags)
 
static void member_remove_from_queue (struct call_queue *queue, struct member *mem)
 
static int member_status_available (int status)
 
static int num_available_members (struct call_queue *q)
 Get the number of members available to accept a call. More...
 
static void parse_empty_options (const char *value, enum empty_conditions *empty, int joinempty)
 
static int pending_members_cmp (void *obj, void *arg, int flags)
 
static int pending_members_hash (const void *obj, const int flags)
 
static void pending_members_remove (struct member *mem)
 
static int play_file (struct ast_channel *chan, const char *filename)
 
static int pqm_exec (struct ast_channel *chan, const char *data)
 PauseQueueMember application. More...
 
static void print_queue (struct mansession *s, int fd, struct call_queue *q)
 Print a single queue to AMI or the CLI. More...
 
static void publish_dial_end_event (struct ast_channel *in, struct callattempt *outgoing, struct ast_channel *exception, const char *status)
 
static int publish_queue_member_pause (struct call_queue *q, struct member *member)
 
static int ql_exec (struct ast_channel *chan, const char *data)
 QueueLog application. More...
 
static struct ast_manager_event_blobqueue_agent_called_to_ami (struct stasis_message *message)
 
static void queue_agent_cb (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
 
static struct ast_manager_event_blobqueue_agent_complete_to_ami (struct stasis_message *message)
 
static struct ast_manager_event_blobqueue_agent_connect_to_ami (struct stasis_message *message)
 
static struct ast_manager_event_blobqueue_agent_dump_to_ami (struct stasis_message *message)
 
static struct ast_manager_event_blobqueue_agent_ringnoanswer_to_ami (struct stasis_message *message)
 
static void queue_bridge_cb (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
 
static struct ast_manager_event_blobqueue_caller_abandon_to_ami (struct stasis_message *message)
 
static struct ast_manager_event_blobqueue_caller_join_to_ami (struct stasis_message *message)
 
static struct ast_manager_event_blobqueue_caller_leave_to_ami (struct stasis_message *message)
 
static void queue_channel_cb (void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
 
static struct ast_manager_event_blobqueue_channel_to_ami (const char *type, struct stasis_message *message)
 
static int queue_cmp_cb (void *obj, void *arg, int flags)
 
static int queue_delme_members_decrement_followers (void *obj, void *arg, int flag)
 
static int queue_exec (struct ast_channel *chan, const char *data)
 The starting point for all queue calls. More...
 
static int queue_function_exists (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 Check if a given queue exists. More...
 
static int queue_function_mem_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 Get number either busy / free / ready or total members of a specific queue. More...
 
static int queue_function_mem_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 Dialplan function QUEUE_MEMBER() Sets the members penalty / paused / ringinuse. More...
 
static int queue_function_memberpenalty_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 Dialplan function QUEUE_MEMBER_PENALTY() Gets the members penalty. More...
 
static int queue_function_memberpenalty_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 Dialplan function QUEUE_MEMBER_PENALTY() Sets the members penalty. More...
 
static int queue_function_qac_dep (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 Get the total number of members in a specific queue (Deprecated) More...
 
static int queue_function_queuegetchannel (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 Dialplan function QUEUE_GET_CHANNEL() Get caller channel waiting at specified position in the queue. More...
 
static int queue_function_queuememberlist (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 Dialplan function QUEUE_MEMBER_LIST() Get list of members in a specific queue. More...
 
static int queue_function_queuewaitingcount (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 Dialplan function QUEUE_WAITING_COUNT() Get number callers waiting in a specific queue. More...
 
static int queue_function_var (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 create interface var with all queue details. More...
 
static int queue_hash_cb (const void *obj, const int flags)
 
static struct ast_manager_event_blobqueue_member_added_to_ami (struct stasis_message *message)
 
static struct ast_jsonqueue_member_blob_create (struct call_queue *q, struct member *mem)
 
static int queue_member_decrement_followers (void *obj, void *arg, int flag)
 
static void queue_member_follower_removal (struct call_queue *queue, struct member *mem)
 
static struct ast_manager_event_blobqueue_member_pause_to_ami (struct stasis_message *message)
 
static struct ast_manager_event_blobqueue_member_penalty_to_ami (struct stasis_message *message)
 
static struct ast_manager_event_blobqueue_member_removed_to_ami (struct stasis_message *message)
 
static struct ast_manager_event_blobqueue_member_ringinuse_to_ami (struct stasis_message *message)
 
static struct ast_manager_event_blobqueue_member_status_to_ami (struct stasis_message *message)
 
static struct ast_manager_event_blobqueue_member_to_ami (const char *type, struct stasis_message *message)
 
static struct ast_manager_event_blobqueue_multi_channel_to_ami (const char *type, struct stasis_message *message)
 
static void queue_publish_member_blob (struct stasis_message_type *type, struct ast_json *blob)
 
static void queue_publish_multi_channel_blob (struct ast_channel *caller, struct ast_channel *agent, struct stasis_message_type *type, struct ast_json *blob)
 
static void queue_publish_multi_channel_snapshot_blob (struct stasis_topic *topic, struct ast_channel_snapshot *caller_snapshot, struct ast_channel_snapshot *agent_snapshot, struct stasis_message_type *type, struct ast_json *blob)
 
static void queue_reset_global_params (void)
 
static void queue_rules_reset_global_params (void)
 
static void queue_rules_set_global_params (struct ast_config *cfg)
 
static void queue_set_global_params (struct ast_config *cfg)
 
static void queue_set_param (struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
 Configure a queue parameter. More...
 
static char * queue_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static struct queue_stasis_dataqueue_stasis_data_alloc (struct queue_ent *qe, struct ast_channel *peer, struct member *mem, time_t holdstart, time_t starttime, int callcompletedinsl)
 
static void queue_stasis_data_destructor (void *obj)
 
static int qupd_exec (struct ast_channel *chan, const char *data)
 Update Queue with data of an outgoing call. More...
 
static void recalc_holdtime (struct queue_ent *qe, int newholdtime)
 
static void record_abandoned (struct queue_ent *qe)
 Record that a caller gave up on waiting in queue. More...
 
static int reload (void)
 
static int reload_handler (int reload, struct ast_flags *mask, const char *queuename)
 The command center for all reload operations. More...
 
static void reload_queue_members (void)
 Reload dynamic queue members persisted into the astdb. More...
 
static int reload_queue_rules (int reload)
 Reload the rules defined in queuerules.conf. More...
 
static int reload_queues (int reload, struct ast_flags *mask, const char *queuename)
 reload the queues.conf file More...
 
static void reload_single_member (const char *memberdata, struct call_queue *q)
 reload information pertaining to a single member More...
 
static void reload_single_queue (struct ast_config *cfg, struct ast_flags *mask, const char *queuename)
 Reload information pertaining to a particular queue. More...
 
static int remove_from_queue (const char *queuename, const char *interface)
 Remove member from queue. More...
 
static void remove_stasis_subscriptions (struct queue_stasis_data *queue_data)
 
static int request_withdraw_caller_from_queue (const char *queuename, const char *caller, const char *withdraw_info)
 Request to withdraw a caller from a queue. More...
 
static int ring_entry (struct queue_ent *qe, struct callattempt *tmp, int *busies)
 Part 2 of ring_one. More...
 
static int ring_one (struct queue_ent *qe, struct callattempt *outgoing, int *busies)
 Place a call to a queue member. More...
 
static void rna (int rnatime, struct queue_ent *qe, struct ast_channel *peer, char *interface, char *membername, int autopause)
 RNA == Ring No Answer. Common code that is executed when we try a queue member and they don't answer. More...
 
static int rqm_exec (struct ast_channel *chan, const char *data)
 RemoveQueueMember application. More...
 
static void rt_handle_member_record (struct call_queue *q, char *category, struct ast_config *member_config)
 Find rt member record to update otherwise create one. More...
 
static int say_periodic_announcement (struct queue_ent *qe, int ringing)
 Playback announcement to queued members if period has elapsed. More...
 
static int say_position (struct queue_ent *qe, int ringing)
 
static void send_agent_complete (const char *queuename, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const struct member *member, time_t holdstart, time_t callstart, enum agent_complete_reason rsn)
 Send out AMI message with member call completion status information. More...
 
static int set_member_paused (const char *queuename, const char *interface, const char *reason, int paused)
 
static int set_member_penalty_help_members (struct call_queue *q, const char *interface, int penalty)
 
static int set_member_ringinuse_help_members (struct call_queue *q, const char *interface, int ringinuse)
 
static int set_member_value (const char *queuename, const char *interface, int property, int value)
 
static int set_member_value_help_members (struct call_queue *q, const char *interface, int property, int value)
 
static void set_queue_member_pause (struct call_queue *q, struct member *mem, const char *reason, int paused)
 
static void set_queue_member_ringinuse (struct call_queue *q, struct member *mem, int ringinuse)
 
static void set_queue_result (struct ast_channel *chan, enum queue_result res)
 sets the QUEUESTATUS channel variable More...
 
static void set_queue_variables (struct call_queue *q, struct ast_channel *chan)
 Set variables of queue. More...
 
static void setup_mixmonitor (struct queue_ent *qe, const char *filename)
 
static void setup_peer_after_bridge_goto (struct ast_channel *chan, struct ast_channel *peer, struct ast_flags *opts, char *opt_args[])
 
static int setup_stasis_subs (struct queue_ent *qe, struct ast_channel *peer, struct member *mem, time_t holdstart, time_t starttime, int callcompletedinsl)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (queue_agent_called_type,.to_ami=queue_agent_called_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (queue_agent_complete_type,.to_ami=queue_agent_complete_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (queue_agent_connect_type,.to_ami=queue_agent_connect_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (queue_agent_dump_type,.to_ami=queue_agent_dump_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (queue_agent_ringnoanswer_type,.to_ami=queue_agent_ringnoanswer_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (queue_caller_abandon_type,.to_ami=queue_caller_abandon_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (queue_caller_join_type,.to_ami=queue_caller_join_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (queue_caller_leave_type,.to_ami=queue_caller_leave_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (queue_member_added_type,.to_ami=queue_member_added_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (queue_member_pause_type,.to_ami=queue_member_pause_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (queue_member_penalty_type,.to_ami=queue_member_penalty_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (queue_member_removed_type,.to_ami=queue_member_removed_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (queue_member_ringinuse_type,.to_ami=queue_member_ringinuse_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (queue_member_status_type,.to_ami=queue_member_status_to_ami,)
 
static int store_next_lin (struct queue_ent *qe, struct callattempt *outgoing)
 Search for best metric and add to Linear queue. More...
 
static int store_next_rr (struct queue_ent *qe, struct callattempt *outgoing)
 Search for best metric and add to Round Robbin queue. More...
 
static int strat2int (const char *strategy)
 
static int try_calling (struct queue_ent *qe, struct ast_flags opts, char **opt_args, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *gosub, int ringing)
 
static int unload_module (void)
 
static void update_connected_line_from_peer (struct ast_channel *chan, struct ast_channel *peer, int is_caller)
 
static void update_qe_rule (struct queue_ent *qe)
 update rules for queues More...
 
static int update_queue (struct call_queue *q, struct member *member, int callcompletedinsl, time_t starttime)
 update the queue status More...
 
static int update_realtime_member_field (struct member *mem, const char *queue_name, const char *field, const char *value)
 
static void update_realtime_members (struct call_queue *q)
 
static void update_status (struct call_queue *q, struct member *m, const int status)
 set a member's status based on device state of that member's state_interface. More...
 
static int upqm_exec (struct ast_channel *chan, const char *data)
 UnpauseQueueMember application. More...
 
static int valid_exit (struct queue_ent *qe, char digit)
 Check for valid exit from queue via goto. More...
 
static int wait_a_bit (struct queue_ent *qe)
 
static struct callattemptwait_for_answer (struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
 Wait for a member to answer the call. More...
 
static int wait_our_turn (struct queue_ent *qe, int ringing, enum queue_result *reason)
 The waiting areas for callers who are not actively calling members. More...
 
static int word_in_list (const char *list, const char *word)
 Check if a given word is in a space-delimited list. More...
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "True Call Queueing" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_CONSUMER, }
 
static struct stasis_message_routeragent_router
 
static char * app = "Queue"
 
static char * app_aqm = "AddQueueMember"
 
static char * app_pqm = "PauseQueueMember"
 
static char * app_ql = "QueueLog"
 
static char * app_qupd = "QueueUpdate"
 
static char * app_rqm = "RemoveQueueMember"
 
static char * app_upqm = "UnpauseQueueMember"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static int autofill_default
 queues.conf [general] option More...
 
static const struct autopause autopausesmodes []
 
static struct ast_cli_entry cli_queue []
 
static struct stasis_subscriptiondevice_state_sub
 Subscription to device state change messages. More...
 
static int force_longest_waiting_caller
 queues.conf [general] option More...
 
static int log_membername_as_agent
 queues.conf [general] option More...
 
static int montype_default
 queues.conf [general] option More...
 
static int negative_penalty_invalid
 queues.conf [general] option More...
 
static struct ao2_containerpending_members
 
static const char *const pm_family = "Queue/PersistentMembers"
 Persistent Members astdb family. More...
 
static const struct ast_app_option queue_exec_options [128] = { [ 'b' ] = { .flag = OPT_PREDIAL_CALLEE , .arg_index = OPT_ARG_PREDIAL_CALLEE + 1 }, [ 'B' ] = { .flag = OPT_PREDIAL_CALLER , .arg_index = OPT_ARG_PREDIAL_CALLER + 1 }, [ 'C' ] = { .flag = OPT_MARK_AS_ANSWERED }, [ 'c' ] = { .flag = OPT_GO_ON }, [ 'd' ] = { .flag = OPT_DATA_QUALITY }, [ 'F' ] = { .flag = OPT_CALLEE_GO_ON , .arg_index = OPT_ARG_CALLEE_GO_ON + 1 }, [ 'h' ] = { .flag = OPT_CALLEE_HANGUP }, [ 'H' ] = { .flag = OPT_CALLER_HANGUP }, [ 'i' ] = { .flag = OPT_IGNORE_CALL_FW }, [ 'I' ] = { .flag = OPT_IGNORE_CONNECTEDLINE }, [ 'k' ] = { .flag = OPT_CALLEE_PARK }, [ 'K' ] = { .flag = OPT_CALLER_PARK }, [ 'm' ] = { .flag = OPT_MUSICONHOLD_CLASS , .arg_index = OPT_ARG_MUSICONHOLD_CLASS + 1 }, [ 'n' ] = { .flag = OPT_NO_RETRY }, [ 'r' ] = { .flag = OPT_RINGING }, [ 'R' ] = { .flag = OPT_RING_WHEN_RINGING }, [ 't' ] = { .flag = OPT_CALLEE_TRANSFER }, [ 'T' ] = { .flag = OPT_CALLER_TRANSFER }, [ 'x' ] = { .flag = OPT_CALLEE_AUTOMIXMON }, [ 'X' ] = { .flag = OPT_CALLER_AUTOMIXMON }, [ 'w' ] = { .flag = OPT_CALLEE_AUTOMON }, [ 'W' ] = { .flag = OPT_CALLER_AUTOMON }, }
 
static int queue_persistent_members
 queues.conf [general] option More...
 
struct {
   enum queue_result   id
 
   char *   text
 
queue_results []
 
static struct ast_custom_function queueexists_function
 
static struct ast_custom_function queuegetchannel_function
 
static struct ast_custom_function queuemembercount_dep
 
static struct ast_custom_function queuemembercount_function
 
static struct ast_custom_function queuememberlist_function
 
static struct ast_custom_function queuememberpenalty_function
 
static struct ao2_containerqueues
 
static struct ast_custom_function queuevar_function
 
static struct ast_custom_function queuewaitingcount_function
 
static int realtime_reason_paused
 does realtime backend support reason_paused More...
 
static char * realtime_ringinuse_field
 name of the ringinuse field in the realtime database More...
 
static int realtime_rules
 queuerules.conf [general] option More...
 
static struct rule_lists rule_lists = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} } , }
 
static int shared_lastcall
 queues.conf [general] option More...
 
static const struct strategy strategies []
 
static struct stasis_forwardtopic_forwarder
 
static int use_weight
 Records that one or more queues use weight. More...
 

Detailed Description

True call queues with optional send URL on answer.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Development notes
Note
2004-11-25: Persistent Dynamic Members added by: NetNation Communications (www.netnation.com) Kevin Lindsay kevin.nosp@m.l@ne.nosp@m.tnati.nosp@m.on.c.nosp@m.om

Each dynamic agent in each queue is now stored in the astdb. When asterisk is restarted, each agent will be automatically readded into their recorded queues. This feature can be configured with the 'persistent_members=<1|0>' setting in the '[general]' category in queues.conf. The default is on.

Note
2004-06-04: Priorities in queues added by inAccess Networks (work funded by Hellas On Line (HOL) www.hol.gr).
These features added by David C. Troy dave@.nosp@m.toad.nosp@m..net:
  • Per-queue holdtime calculation
  • Estimated holdtime announcement
  • Position announcement
  • Abandoned/completed call counters
  • Failout timer passed as optional app parameter

Patch Version 1.07 2003-12-24 01

Added servicelevel statistic by Michiel Betel michi.nosp@m.el@b.nosp@m.etel..nosp@m.nl Added Priority jumping code for adding and removing queue members by Jonathan Stanton aster.nosp@m.isk@.nosp@m.doilo.nosp@m.okli.nosp@m.keica.nosp@m.re.c.nosp@m.om

Fixed to work with CVS as of 2004-02-25 and released as 1.07a by Matthew Enger m.eng.nosp@m.er@x.nosp@m.i.com.nosp@m..au

Definition in file app_queue.c.

Macro Definition Documentation

◆ ANNOUNCEHOLDTIME_ALWAYS

#define ANNOUNCEHOLDTIME_ALWAYS   1

Definition at line 1771 of file app_queue.c.

◆ ANNOUNCEHOLDTIME_ONCE

#define ANNOUNCEHOLDTIME_ONCE   2

Definition at line 1772 of file app_queue.c.

◆ ANNOUNCEPOSITION_LIMIT

#define ANNOUNCEPOSITION_LIMIT   4

We not announce position more than <limit>

Definition at line 1789 of file app_queue.c.

◆ ANNOUNCEPOSITION_MORE_THAN

#define ANNOUNCEPOSITION_MORE_THAN   3

We say "Currently there are more than <limit>"

Definition at line 1788 of file app_queue.c.

◆ ANNOUNCEPOSITION_NO

#define ANNOUNCEPOSITION_NO   2

We don't announce position

Definition at line 1787 of file app_queue.c.

◆ ANNOUNCEPOSITION_YES

#define ANNOUNCEPOSITION_YES   1

We announce position

Definition at line 1786 of file app_queue.c.

◆ AST_MAX_WATCHERS

#define AST_MAX_WATCHERS   256

Definition at line 5191 of file app_queue.c.

◆ DEFAULT_MIN_ANNOUNCE_FREQUENCY

#define DEFAULT_MIN_ANNOUNCE_FREQUENCY   15

The minimum number of seconds between position announcements.

Note
The default value of 15 provides backwards compatibility.

Definition at line 1561 of file app_queue.c.

◆ DEFAULT_RETRY

#define DEFAULT_RETRY   5

Definition at line 1553 of file app_queue.c.

◆ DEFAULT_TIMEOUT

#define DEFAULT_TIMEOUT   15

Definition at line 1554 of file app_queue.c.

◆ MAX_CALL_ATTEMPT_BUCKETS

#define MAX_CALL_ATTEMPT_BUCKETS   353

Definition at line 2514 of file app_queue.c.

◆ MAX_PERIODIC_ANNOUNCEMENTS

#define MAX_PERIODIC_ANNOUNCEMENTS   10

The maximum periodic announcements we can have

Definition at line 1556 of file app_queue.c.

◆ MAX_QUEUE_BUCKETS

#define MAX_QUEUE_BUCKETS   53

Definition at line 1563 of file app_queue.c.

◆ QUEUE_EVENT_VARIABLES

#define QUEUE_EVENT_VARIABLES   3

Definition at line 1773 of file app_queue.c.

◆ QUEUE_PAUSED_DEVSTATE

#define QUEUE_PAUSED_DEVSTATE   AST_DEVICE_INUSE

Definition at line 3536 of file app_queue.c.

◆ queue_ref

#define queue_ref (   q)    ao2_bump(q)

Definition at line 2055 of file app_queue.c.

◆ queue_t_ref

#define queue_t_ref (   q,
  tag 
)    ao2_t_bump(q, tag)

Definition at line 2057 of file app_queue.c.

◆ queue_t_unref

#define queue_t_unref (   q,
  tag 
)    ({ ao2_t_cleanup(q, tag); NULL; })

Definition at line 2058 of file app_queue.c.

◆ QUEUE_UNKNOWN_PAUSED_DEVSTATE

#define QUEUE_UNKNOWN_PAUSED_DEVSTATE   AST_DEVICE_NOT_INUSE

Definition at line 3538 of file app_queue.c.

◆ QUEUE_UNPAUSED_DEVSTATE

#define QUEUE_UNPAUSED_DEVSTATE   AST_DEVICE_NOT_INUSE

Definition at line 3537 of file app_queue.c.

◆ queue_unref

#define queue_unref (   q)    ({ ao2_cleanup(q); NULL; })

Definition at line 2056 of file app_queue.c.

◆ queues_t_link

#define queues_t_link (   c,
  q,
  tag 
)    ao2_t_link(c, q, tag)

Definition at line 2059 of file app_queue.c.

◆ queues_t_unlink

#define queues_t_unlink (   c,
  q,
  tag 
)    ao2_t_unlink(c, q, tag)

Definition at line 2060 of file app_queue.c.

◆ RECHECK

#define RECHECK   1

Recheck every second to see we we're at the top yet

Definition at line 1555 of file app_queue.c.

◆ RES_EXISTS

#define RES_EXISTS   (-1)

Entry already exists

Definition at line 1566 of file app_queue.c.

◆ RES_NOSUCHQUEUE

#define RES_NOSUCHQUEUE   (-3)

No such queue

Definition at line 1568 of file app_queue.c.

◆ RES_NOT_CALLER

#define RES_NOT_CALLER   (-5)

Caller not found

Definition at line 1570 of file app_queue.c.

◆ RES_NOT_DYNAMIC

#define RES_NOT_DYNAMIC   (-4)

Member is not dynamic

Definition at line 1569 of file app_queue.c.

◆ RES_OKAY

#define RES_OKAY   0

Action completed

Definition at line 1565 of file app_queue.c.

◆ RES_OUTOFMEMORY

#define RES_OUTOFMEMORY   (-2)

Out of memory

Definition at line 1567 of file app_queue.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Please read before modifying this file.
There are three locks which are regularly used throughout this file, the queue list lock, the lock for each individual queue, and the interface list lock. Please be extra careful to always lock in the following order 1) queue list lock 2) individual queue lock 3) interface list lock This order has sort of "evolved" over the lifetime of this application, but it is now in place this way, so please adhere to this order!
Enumerator
OPT_MARK_AS_ANSWERED 
OPT_GO_ON 
OPT_DATA_QUALITY 
OPT_CALLEE_GO_ON 
OPT_CALLEE_HANGUP 
OPT_CALLER_HANGUP 
OPT_IGNORE_CALL_FW 
OPT_IGNORE_CONNECTEDLINE 
OPT_CALLEE_PARK 
OPT_CALLER_PARK 
OPT_NO_RETRY 
OPT_RINGING 
OPT_RING_WHEN_RINGING 
OPT_CALLEE_TRANSFER 
OPT_CALLER_TRANSFER 
OPT_CALLEE_AUTOMIXMON 
OPT_CALLER_AUTOMIXMON 
OPT_CALLEE_AUTOMON 
OPT_CALLER_AUTOMON 
OPT_PREDIAL_CALLEE 
OPT_PREDIAL_CALLER 
OPT_MUSICONHOLD_CLASS 

Definition at line 1446 of file app_queue.c.

1446 {
1447 OPT_MARK_AS_ANSWERED = (1 << 0),
1448 OPT_GO_ON = (1 << 1),
1449 OPT_DATA_QUALITY = (1 << 2),
1450 OPT_CALLEE_GO_ON = (1 << 3),
1451 OPT_CALLEE_HANGUP = (1 << 4),
1452 OPT_CALLER_HANGUP = (1 << 5),
1453 OPT_IGNORE_CALL_FW = (1 << 6),
1454 OPT_IGNORE_CONNECTEDLINE = (1 << 7),
1455 OPT_CALLEE_PARK = (1 << 8),
1456 OPT_CALLER_PARK = (1 << 9),
1457 OPT_NO_RETRY = (1 << 10),
1458 OPT_RINGING = (1 << 11),
1459 OPT_RING_WHEN_RINGING = (1 << 12),
1460 OPT_CALLEE_TRANSFER = (1 << 13),
1461 OPT_CALLER_TRANSFER = (1 << 14),
1462 OPT_CALLEE_AUTOMIXMON = (1 << 15),
1463 OPT_CALLER_AUTOMIXMON = (1 << 16),
1464 OPT_CALLEE_AUTOMON = (1 << 17),
1465 OPT_CALLER_AUTOMON = (1 << 18),
1466 OPT_PREDIAL_CALLEE = (1 << 19),
1467 OPT_PREDIAL_CALLER = (1 << 20),
1468 OPT_MUSICONHOLD_CLASS = (1 << 21),
1469};
@ OPT_CALLER_AUTOMON
Definition: app_queue.c:1465
@ OPT_CALLEE_PARK
Definition: app_queue.c:1455
@ OPT_PREDIAL_CALLER
Definition: app_queue.c:1467
@ OPT_GO_ON
Definition: app_queue.c:1448
@ OPT_IGNORE_CONNECTEDLINE
Definition: app_queue.c:1454
@ OPT_CALLEE_AUTOMON
Definition: app_queue.c:1464
@ OPT_CALLEE_TRANSFER
Definition: app_queue.c:1460
@ OPT_CALLEE_GO_ON
Definition: app_queue.c:1450
@ OPT_MARK_AS_ANSWERED
Definition: app_queue.c:1447
@ OPT_IGNORE_CALL_FW
Definition: app_queue.c:1453
@ OPT_CALLER_PARK
Definition: app_queue.c:1456
@ OPT_NO_RETRY
Definition: app_queue.c:1457
@ OPT_DATA_QUALITY
Definition: app_queue.c:1449
@ OPT_CALLER_HANGUP
Definition: app_queue.c:1452
@ OPT_MUSICONHOLD_CLASS
Definition: app_queue.c:1468
@ OPT_CALLEE_AUTOMIXMON
Definition: app_queue.c:1462
@ OPT_CALLEE_HANGUP
Definition: app_queue.c:1451
@ OPT_CALLER_AUTOMIXMON
Definition: app_queue.c:1463
@ OPT_RINGING
Definition: app_queue.c:1458
@ OPT_CALLER_TRANSFER
Definition: app_queue.c:1461
@ OPT_PREDIAL_CALLEE
Definition: app_queue.c:1466
@ OPT_RING_WHEN_RINGING
Definition: app_queue.c:1459

◆ anonymous enum

anonymous enum
Enumerator
OPT_ARG_CALLEE_GO_ON 
OPT_ARG_PREDIAL_CALLEE 
OPT_ARG_PREDIAL_CALLER 
OPT_ARG_MUSICONHOLD_CLASS 
OPT_ARG_ARRAY_SIZE 

Definition at line 1471 of file app_queue.c.

1471 {
1476 /* note: this entry _MUST_ be the last one in the enum */
1478};
@ OPT_ARG_CALLEE_GO_ON
Definition: app_queue.c:1472
@ OPT_ARG_PREDIAL_CALLEE
Definition: app_queue.c:1473
@ OPT_ARG_MUSICONHOLD_CLASS
Definition: app_queue.c:1475
@ OPT_ARG_PREDIAL_CALLER
Definition: app_queue.c:1474
@ OPT_ARG_ARRAY_SIZE
Definition: app_queue.c:1477

◆ anonymous enum

anonymous enum
Enumerator
QUEUE_STRATEGY_RINGALL 
QUEUE_STRATEGY_LEASTRECENT 
QUEUE_STRATEGY_FEWESTCALLS 
QUEUE_STRATEGY_RANDOM 
QUEUE_STRATEGY_RRMEMORY 
QUEUE_STRATEGY_LINEAR 
QUEUE_STRATEGY_WRANDOM 
QUEUE_STRATEGY_RRORDERED 

Definition at line 1505 of file app_queue.c.

1505 {
1514};
@ QUEUE_STRATEGY_RINGALL
Definition: app_queue.c:1506
@ QUEUE_STRATEGY_RRMEMORY
Definition: app_queue.c:1510
@ QUEUE_STRATEGY_LINEAR
Definition: app_queue.c:1511
@ QUEUE_STRATEGY_LEASTRECENT
Definition: app_queue.c:1507
@ QUEUE_STRATEGY_RANDOM
Definition: app_queue.c:1509
@ QUEUE_STRATEGY_FEWESTCALLS
Definition: app_queue.c:1508
@ QUEUE_STRATEGY_RRORDERED
Definition: app_queue.c:1513
@ QUEUE_STRATEGY_WRANDOM
Definition: app_queue.c:1512

◆ anonymous enum

anonymous enum
Enumerator
QUEUE_AUTOPAUSE_OFF 
QUEUE_AUTOPAUSE_ON 
QUEUE_AUTOPAUSE_ALL 

Definition at line 1516 of file app_queue.c.

1516 {
1520};
@ QUEUE_AUTOPAUSE_ON
Definition: app_queue.c:1518
@ QUEUE_AUTOPAUSE_OFF
Definition: app_queue.c:1517
@ QUEUE_AUTOPAUSE_ALL
Definition: app_queue.c:1519

◆ agent_complete_reason

Enumerator
CALLER 
AGENT 
TRANSFER 

Definition at line 6122 of file app_queue.c.

6122 {
6123 CALLER,
6124 AGENT,
6125 TRANSFER
6126};
@ AGENT
Definition: app_queue.c:6124
@ CALLER
Definition: app_queue.c:6123
@ TRANSFER
Definition: app_queue.c:6125

◆ empty_conditions

Enumerator
QUEUE_EMPTY_PENALTY 
QUEUE_EMPTY_PAUSED 
QUEUE_EMPTY_INUSE 
QUEUE_EMPTY_RINGING 
QUEUE_EMPTY_UNAVAILABLE 
QUEUE_EMPTY_INVALID 
QUEUE_EMPTY_UNKNOWN 
QUEUE_EMPTY_WRAPUP 

Definition at line 1754 of file app_queue.c.

1754 {
1755 QUEUE_EMPTY_PENALTY = (1 << 0),
1756 QUEUE_EMPTY_PAUSED = (1 << 1),
1757 QUEUE_EMPTY_INUSE = (1 << 2),
1758 QUEUE_EMPTY_RINGING = (1 << 3),
1759 QUEUE_EMPTY_UNAVAILABLE = (1 << 4),
1760 QUEUE_EMPTY_INVALID = (1 << 5),
1761 QUEUE_EMPTY_UNKNOWN = (1 << 6),
1762 QUEUE_EMPTY_WRAPUP = (1 << 7),
1763};
@ QUEUE_EMPTY_INVALID
Definition: app_queue.c:1760
@ QUEUE_EMPTY_UNKNOWN
Definition: app_queue.c:1761
@ QUEUE_EMPTY_PENALTY
Definition: app_queue.c:1755
@ QUEUE_EMPTY_RINGING
Definition: app_queue.c:1758
@ QUEUE_EMPTY_INUSE
Definition: app_queue.c:1757
@ QUEUE_EMPTY_UNAVAILABLE
Definition: app_queue.c:1759
@ QUEUE_EMPTY_WRAPUP
Definition: app_queue.c:1762
@ QUEUE_EMPTY_PAUSED
Definition: app_queue.c:1756

◆ member_properties

Enumerator
MEMBER_PENALTY 
MEMBER_RINGINUSE 

Definition at line 1765 of file app_queue.c.

1765 {
1766 MEMBER_PENALTY = 0,
1767 MEMBER_RINGINUSE = 1,
1768};
@ MEMBER_RINGINUSE
Definition: app_queue.c:1767
@ MEMBER_PENALTY
Definition: app_queue.c:1766

◆ queue_reload_mask

Enumerator
QUEUE_RELOAD_PARAMETERS 
QUEUE_RELOAD_MEMBER 
QUEUE_RELOAD_RULES 
QUEUE_RESET_STATS 

Definition at line 1522 of file app_queue.c.

1522 {
1523 QUEUE_RELOAD_PARAMETERS = (1 << 0),
1524 QUEUE_RELOAD_MEMBER = (1 << 1),
1525 QUEUE_RELOAD_RULES = (1 << 2),
1526 QUEUE_RESET_STATS = (1 << 3),
1527};
@ QUEUE_RELOAD_RULES
Definition: app_queue.c:1525
@ QUEUE_RELOAD_MEMBER
Definition: app_queue.c:1524
@ QUEUE_RESET_STATS
Definition: app_queue.c:1526
@ QUEUE_RELOAD_PARAMETERS
Definition: app_queue.c:1523

◆ queue_result

Enumerator
QUEUE_UNKNOWN 
QUEUE_TIMEOUT 
QUEUE_JOINEMPTY 
QUEUE_LEAVEEMPTY 
QUEUE_JOINUNAVAIL 
QUEUE_LEAVEUNAVAIL 
QUEUE_FULL 
QUEUE_CONTINUE 
QUEUE_WITHDRAW 

Definition at line 1625 of file app_queue.c.

1625 {
1626 QUEUE_UNKNOWN = 0,
1627 QUEUE_TIMEOUT = 1,
1628 QUEUE_JOINEMPTY = 2,
1629 QUEUE_LEAVEEMPTY = 3,
1632 QUEUE_FULL = 6,
1633 QUEUE_CONTINUE = 7,
1634 QUEUE_WITHDRAW = 8,
1635};
@ QUEUE_FULL
Definition: app_queue.c:1632
@ QUEUE_UNKNOWN
Definition: app_queue.c:1626
@ QUEUE_WITHDRAW
Definition: app_queue.c:1634
@ QUEUE_CONTINUE
Definition: app_queue.c:1633
@ QUEUE_LEAVEEMPTY
Definition: app_queue.c:1629
@ QUEUE_LEAVEUNAVAIL
Definition: app_queue.c:1631
@ QUEUE_JOINUNAVAIL
Definition: app_queue.c:1630
@ QUEUE_JOINEMPTY
Definition: app_queue.c:1628
@ QUEUE_TIMEOUT
Definition: app_queue.c:1627

◆ queue_timeout_priority

Enumerator
TIMEOUT_PRIORITY_APP 
TIMEOUT_PRIORITY_CONF 

Definition at line 1652 of file app_queue.c.

1652 {
1655};
@ TIMEOUT_PRIORITY_CONF
Definition: app_queue.c:1654
@ TIMEOUT_PRIORITY_APP
Definition: app_queue.c:1653

Function Documentation

◆ __queues_show()

static char * __queues_show ( struct mansession s,
int  fd,
int  argc,
const char *const *  argv 
)
static

Show queue(s) status and statistics.

List the queues strategy, calls processed, members logged in, other queue statistics such as avg hold time.

Definition at line 10138 of file app_queue.c.

10139{
10140 struct call_queue *q;
10141 struct ast_str *out = ast_str_alloca(512);
10142 struct ao2_container *sorted_queues;
10143
10144 struct ao2_iterator queue_iter;
10145 int found = 0;
10146
10147 if (argc != 2 && argc != 3) {
10148 return CLI_SHOWUSAGE;
10149 }
10150
10151 if (argc == 3) { /* specific queue */
10152 if ((q = find_load_queue_rt_friendly(argv[2]))) {
10153 ao2_lock(q);
10154 print_queue(s, fd, q);
10155 ao2_unlock(q);
10156 queue_unref(q);
10157 } else {
10158 ast_str_set(&out, 0, "No such queue: %s.", argv[2]);
10159 do_print(s, fd, ast_str_buffer(out));
10160 }
10161 return CLI_SUCCESS;
10162 }
10163
10164 if (ast_check_realtime("queues")) {
10165 /* This block is to find any queues which are defined in realtime but
10166 * which have not yet been added to the in-core container
10167 */
10168 struct ast_config *cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
10169 if (cfg) {
10170 char *category = NULL;
10171 while ((category = ast_category_browse(cfg, category))) {
10172 const char *queuename = ast_variable_retrieve(cfg, category, "name");
10173 if (ast_strlen_zero(queuename)) {
10174 ast_log(LOG_WARNING, "Ignoring realtime queue with a NULL or empty 'name.'\n");
10175 continue;
10176 }
10177 if ((q = find_load_queue_rt_friendly(queuename))) {
10178 queue_t_unref(q, "Done with temporary pointer");
10179 }
10180 }
10181 ast_config_destroy(cfg);
10182 }
10183 }
10184
10185 /*
10186 * Snapping a copy of the container prevents having to lock both the queues container
10187 * and the queue itself at the same time. It also allows us to sort the entries.
10188 */
10189 sorted_queues = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, call_queue_sort_fn, NULL);
10190 if (!sorted_queues) {
10191 return CLI_SUCCESS;
10192 }
10193 if (ao2_container_dup(sorted_queues, queues, 0)) {
10194 ao2_ref(sorted_queues, -1);
10195 return CLI_SUCCESS;
10196 }
10197
10198 /*
10199 * No need to lock the container since it's temporary and static.
10200 * We also unlink the entries as we use them so the container is
10201 * empty when the iterator finishes. We can then just unref the container.
10202 */
10203 queue_iter = ao2_iterator_init(sorted_queues, AO2_ITERATOR_DONTLOCK | AO2_ITERATOR_UNLINK);
10204 while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
10205 struct call_queue *realtime_queue = NULL;
10206 ao2_lock(q);
10207 /* This check is to make sure we don't print information for realtime
10208 * queues which have been deleted from realtime but which have not yet
10209 * been deleted from the in-core container. Only do this if we're not
10210 * looking for a specific queue.
10211 */
10212 if (q->realtime) {
10213 realtime_queue = find_load_queue_rt_friendly(q->name);
10214 if (!realtime_queue) {
10215 ao2_unlock(q);
10216 queue_t_unref(q, "Done with iterator");
10217 continue;
10218 }
10219 queue_t_unref(realtime_queue, "Queue is already in memory");
10220 }
10221
10222 found = 1;
10223 print_queue(s, fd, q);
10224
10225 ao2_unlock(q);
10226 queue_t_unref(q, "Done with iterator"); /* Unref the iterator's reference */
10227 }
10228 ao2_iterator_destroy(&queue_iter);
10229 ao2_ref(sorted_queues, -1);
10230 if (!found) {
10231 ast_str_set(&out, 0, "No queues.");
10232 do_print(s, fd, ast_str_buffer(out));
10233 }
10234 return CLI_SUCCESS;
10235}
static void print_queue(struct mansession *s, int fd, struct call_queue *q)
Print a single queue to AMI or the CLI.
Definition: app_queue.c:10030
static struct ao2_container * queues
Definition: app_queue.c:1901
#define queue_t_unref(q, tag)
Definition: app_queue.c:2058
#define queue_unref(q)
Definition: app_queue.c:2056
static void do_print(struct mansession *s, int fd, const char *str)
direct output to manager or cli with proper terminator
Definition: app_queue.c:10020
static struct call_queue * find_load_queue_rt_friendly(const char *queuename)
Definition: app_queue.c:3895
#define ast_log
Definition: astobj2.c:42
int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
Copy all object references in the src container into the dest container.
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
#define ao2_t_iterator_next(iter, tag)
Definition: astobj2.h:1909
@ AO2_ITERATOR_UNLINK
Definition: astobj2.h:1863
@ AO2_ITERATOR_DONTLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1852
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn)
Allocate and initialize a red-black tree container.
Definition: astobj2.h:1349
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
#define SENTINEL
Definition: compiler.h:87
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: main/config.c:3623
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: main/config.c:3531
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:784
#define LOG_WARNING
#define NULL
Definition: resample.c:96
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_str_alloca(init_len)
Definition: strings.h:848
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Support for dynamic strings.
Definition: strings.h:623
unsigned int realtime
Definition: app_queue.c:1845
unsigned int found
Definition: app_queue.c:1846
const ast_string_field name
Definition: app_queue.c:1829
FILE * out
Definition: utils/frame.c:33

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_container_alloc_rbtree, ao2_container_dup(), ao2_iterator_destroy(), AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), AO2_ITERATOR_UNLINK, ao2_lock, ao2_ref, ao2_t_iterator_next, ao2_unlock, ast_category_browse(), ast_check_realtime(), ast_config_destroy(), ast_load_realtime_multientry(), ast_log, ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_strlen_zero(), ast_variable_retrieve(), CLI_SHOWUSAGE, CLI_SUCCESS, do_print(), find_load_queue_rt_friendly(), call_queue::found, LOG_WARNING, call_queue::name, NULL, out, print_queue(), queue_t_unref, queue_unref, queues, call_queue::realtime, and SENTINEL.

Referenced by queue_show().

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 11947 of file app_queue.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 11947 of file app_queue.c.

◆ add_to_queue()

static int add_to_queue ( const char *  queuename,
const char *  interface,
const char *  membername,
int  penalty,
int  paused,
int  dump,
const char *  state_interface,
const char *  reason_paused,
int  wrapuptime 
)
static

Add member to queue.

Return values
RES_NOT_DYNAMICwhen they aren't a RT member
RES_NOSUCHQUEUEqueue does not exist
RES_OKAYadded member from queue
RES_EXISTSqueue exists but no members
RES_OUT_OF_MEMORYqueue exists but not enough memory to create member
Note
Ensure the appropriate realtime queue is loaded. Note that this short-circuits if the queue is already in memory.

Definition at line 7593 of file app_queue.c.

7594{
7595 struct call_queue *q;
7596 struct member *new_member, *old_member;
7597 int res = RES_NOSUCHQUEUE;
7598
7599 /*! \note Ensure the appropriate realtime queue is loaded. Note that this
7600 * short-circuits if the queue is already in memory. */
7601 if (!(q = find_load_queue_rt_friendly(queuename))) {
7602 return res;
7603 }
7604
7605 ao2_lock(q);
7606 if ((old_member = interface_exists(q, interface)) == NULL) {
7608 new_member->dynamic = 1;
7609 if (reason_paused) {
7610 ast_copy_string(new_member->reason_paused, reason_paused, sizeof(new_member->reason_paused));
7611 }
7612 member_add_to_queue(q, new_member);
7613 queue_publish_member_blob(queue_member_added_type(), queue_member_blob_create(q, new_member));
7614
7615 if (is_member_available(q, new_member)) {
7617 }
7618
7619 ao2_ref(new_member, -1);
7620 new_member = NULL;
7621
7622 if (dump) {
7624 }
7625
7626 res = RES_OKAY;
7627 } else {
7628 res = RES_OUTOFMEMORY;
7629 }
7630 } else {
7631 ao2_ref(old_member, -1);
7632 res = RES_EXISTS;
7633 }
7634 ao2_unlock(q);
7635 queue_t_unref(q, "Expiring temporary reference");
7636
7637 return res;
7638}
static struct member * create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse, int wrapuptime)
allocate space for new queue member and set fields based on parameters passed
Definition: app_queue.c:2865
static struct member * interface_exists(struct call_queue *q, const char *interface)
Definition: app_queue.c:7458
static void dump_queue_members(struct call_queue *pm_queue)
Dump all members in a specific queue to the database.
Definition: app_queue.c:7485
static int is_member_available(struct call_queue *q, struct member *mem)
Definition: app_queue.c:2606
#define RES_OUTOFMEMORY
Definition: app_queue.c:1567
#define RES_NOSUCHQUEUE
Definition: app_queue.c:1568
#define RES_OKAY
Definition: app_queue.c:1565
static void member_add_to_queue(struct call_queue *queue, struct member *mem)
Definition: app_queue.c:3546
static struct ast_json * queue_member_blob_create(struct call_queue *q, struct member *mem)
Definition: app_queue.c:2395
#define RES_EXISTS
Definition: app_queue.c:1566
static void queue_publish_member_blob(struct stasis_message_type *type, struct ast_json *blob)
Definition: app_queue.c:2371
@ AST_DEVSTATE_CACHABLE
Definition: devicestate.h:70
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:510
@ AST_DEVICE_NOT_INUSE
Definition: devicestate.h:54
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
unsigned int ringinuse
Definition: app_queue.c:1833
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1727
int dynamic
Definition: app_queue.c:1735
char membername[80]
Definition: app_queue.c:1732
int penalty
Definition: app_queue.c:1733
int paused
Definition: app_queue.c:1738
int wrapuptime
Definition: app_queue.c:1742
char reason_paused[80]
Definition: app_queue.c:1739
char state_interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1730

References ao2_lock, ao2_ref, ao2_unlock, ast_copy_string(), AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), create_queue_member(), dump_queue_members(), member::dynamic, find_load_queue_rt_friendly(), member::interface, interface_exists(), is_member_available(), member_add_to_queue(), member::membername, call_queue::name, NULL, member::paused, member::penalty, queue_member_blob_create(), queue_publish_member_blob(), queue_t_unref, member::reason_paused, RES_EXISTS, RES_NOSUCHQUEUE, RES_OKAY, RES_OUTOFMEMORY, call_queue::ringinuse, member::state_interface, and member::wrapuptime.

Referenced by aqm_exec(), handle_queue_add_member(), manager_add_queue_member(), and reload_queue_members().

◆ alloc_queue()

static struct call_queue * alloc_queue ( const char *  queuename)
static

Definition at line 3727 of file app_queue.c.

3728{
3729 struct call_queue *q;
3730
3731 if ((q = ao2_t_alloc(sizeof(*q), destroy_queue, "Allocate queue"))) {
3732 if (ast_string_field_init(q, 64)) {
3733 queue_t_unref(q, "String field allocation failed");
3734 return NULL;
3735 }
3736 ast_string_field_set(q, name, queuename);
3737 }
3738 return q;
3739}
static void destroy_queue(void *obj)
Free queue's member list then its string fields.
Definition: app_queue.c:3712
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Definition: astobj2.h:407
static const char name[]
Definition: format_mp3.c:68
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359

References ao2_t_alloc, ast_string_field_init, ast_string_field_set, destroy_queue(), name, NULL, and queue_t_unref.

Referenced by find_queue_by_name_rt(), and reload_single_queue().

◆ AO2_STRING_FIELD_SORT_FN()

AO2_STRING_FIELD_SORT_FN ( call_queue  ,
name   
)

◆ aqm_exec()

static int aqm_exec ( struct ast_channel chan,
const char *  data 
)
static

AddQueueMember application.

Definition at line 8354 of file app_queue.c.

8355{
8356 int res=-1;
8357 char *parse, *tmp, *temppos = NULL;
8359 AST_APP_ARG(queuename);
8360 AST_APP_ARG(interface);
8361 AST_APP_ARG(penalty);
8363 AST_APP_ARG(membername);
8364 AST_APP_ARG(state_interface);
8365 AST_APP_ARG(wrapuptime);
8366 );
8367 int penalty = 0;
8368 int wrapuptime;
8369
8370 if (ast_strlen_zero(data)) {
8371 ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename[,interface[,penalty[,options[,membername[,stateinterface][,wrapuptime]]]]])\n");
8372 return -1;
8373 }
8374
8375 parse = ast_strdupa(data);
8376
8378
8379 if (ast_strlen_zero(args.interface)) {
8380 args.interface = ast_strdupa(ast_channel_name(chan));
8381 temppos = strrchr(args.interface, '-');
8382 if (temppos) {
8383 *temppos = '\0';
8384 }
8385 }
8386
8387 if (!ast_strlen_zero(args.penalty)) {
8388 if ((sscanf(args.penalty, "%30d", &penalty) != 1) || penalty < 0) {
8389 ast_log(LOG_WARNING, "Penalty '%s' is invalid, must be an integer >= 0\n", args.penalty);
8390 penalty = 0;
8391 }
8392 }
8393
8394 if (!ast_strlen_zero(args.wrapuptime)) {
8395 tmp = args.wrapuptime;
8396 ast_strip(tmp);
8397 wrapuptime = atoi(tmp);
8398 if (wrapuptime < 0) {
8399 wrapuptime = 0;
8400 }
8401 } else {
8402 wrapuptime = 0;
8403 }
8404
8405 switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, 0, queue_persistent_members, args.state_interface, NULL, wrapuptime)) {
8406 case RES_OKAY:
8407 if (ast_strlen_zero(args.membername) || !log_membername_as_agent) {
8408 ast_queue_log(args.queuename, ast_channel_uniqueid(chan), args.interface, "ADDMEMBER", "%s", "");
8409 } else {
8410 ast_queue_log(args.queuename, ast_channel_uniqueid(chan), args.membername, "ADDMEMBER", "%s", "");
8411 }
8412 ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", args.interface, args.queuename);
8413 pbx_builtin_setvar_helper(chan, "AQMSTATUS", "ADDED");
8414 res = 0;
8415 break;
8416 case RES_EXISTS:
8417 ast_log(LOG_WARNING, "Unable to add interface '%s' to queue '%s': Already there\n", args.interface, args.queuename);
8418 pbx_builtin_setvar_helper(chan, "AQMSTATUS", "MEMBERALREADY");
8419 res = 0;
8420 break;
8421 case RES_NOSUCHQUEUE:
8422 ast_log(LOG_WARNING, "Unable to add interface to queue '%s': No such queue\n", args.queuename);
8423 pbx_builtin_setvar_helper(chan, "AQMSTATUS", "NOSUCHQUEUE");
8424 res = 0;
8425 break;
8426 case RES_OUTOFMEMORY:
8427 ast_log(LOG_ERROR, "Out of memory adding interface %s to queue %s\n", args.interface, args.queuename);
8428 break;
8429 }
8430
8431 return res;
8432}
static int queue_persistent_members
queues.conf [general] option
Definition: app_queue.c:1590
static int log_membername_as_agent
queues.conf [general] option
Definition: app_queue.c:1614
static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface, const char *reason_paused, int wrapuptime)
Add member to queue.
Definition: app_queue.c:7593
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
static int tmp()
Definition: bt_open.c:389
const char * ast_channel_name(const struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:965
#define LOG_ERROR
#define LOG_NOTICE
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
const char * args
static struct test_options options

References add_to_queue(), args, AST_APP_ARG, ast_channel_name(), ast_channel_uniqueid(), AST_DECLARE_APP_ARGS, ast_log, ast_queue_log(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strip(), ast_strlen_zero(), member::interface, LOG_ERROR, log_membername_as_agent, LOG_NOTICE, LOG_WARNING, member::membername, NULL, options, pbx_builtin_setvar_helper(), member::penalty, queue_persistent_members, RES_EXISTS, RES_NOSUCHQUEUE, RES_OKAY, RES_OUTOFMEMORY, member::state_interface, tmp(), and member::wrapuptime.

Referenced by load_module().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 11947 of file app_queue.c.

◆ autopause2int()

static int autopause2int ( const char *  autopause)
static

Definition at line 1948 of file app_queue.c.

1949{
1950 int x;
1951 /*This 'double check' that default value is OFF */
1953 return QUEUE_AUTOPAUSE_OFF;
1954 }
1955
1956 /*This 'double check' is to ensure old values works */
1957 if(ast_true(autopause)) {
1958 return QUEUE_AUTOPAUSE_ON;
1959 }
1960
1961 for (x = 0; x < ARRAY_LEN(autopausesmodes); x++) {
1962 if (!strcasecmp(autopause, autopausesmodes[x].name)) {
1963 return autopausesmodes[x].autopause;
1964 }
1965 }
1966
1967 /*This 'double check' that default value is OFF */
1968 return QUEUE_AUTOPAUSE_OFF;
1969}
static const struct autopause autopausesmodes[]
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
int autopause
Definition: app_queue.c:1545
#define ARRAY_LEN(a)
Definition: utils.h:666

References ARRAY_LEN, ast_strlen_zero(), ast_true(), autopause::autopause, autopausesmodes, name, QUEUE_AUTOPAUSE_OFF, and QUEUE_AUTOPAUSE_ON.

Referenced by queue_set_param().

◆ calc_metric()

static int calc_metric ( struct call_queue q,
struct member mem,
int  pos,
struct queue_ent qe,
struct callattempt tmp 
)
static

Calculate the metric of each member in the outgoing callattempts.

A numeric metric is given to each member depending on the ring strategy used by the queue. Members with lower metrics will be called before members with higher metrics

Return values
-1if penalties are exceeded
0otherwise

Definition at line 6044 of file app_queue.c.

6045{
6046 /* disregarding penalty on too few members? */
6047 int membercount = ao2_container_count(q->members);
6048 unsigned char usepenalty = (membercount <= q->penaltymemberslimit) ? 0 : 1;
6049 int penalty = mem->penalty;
6050
6051 if (usepenalty) {
6052 if (qe->raise_penalty != INT_MAX && penalty < qe->raise_penalty) {
6053 /* Low penalty is raised up to the current minimum */
6054 penalty = qe->raise_penalty;
6055 }
6056 if ((qe->max_penalty != INT_MAX && penalty > qe->max_penalty) ||
6057 (qe->min_penalty != INT_MAX && penalty < qe->min_penalty)) {
6058 return -1;
6059 }
6060 } else {
6061 ast_debug(1, "Disregarding penalty, %d members and %d in penaltymemberslimit.\n",
6062 membercount, q->penaltymemberslimit);
6063 }
6064
6065 switch (q->strategy) {
6067 /* Everyone equal, except for penalty */
6068 tmp->metric = penalty * 1000000 * usepenalty;
6069 break;
6071 if (pos < qe->linpos) {
6072 tmp->metric = 1000 + pos;
6073 } else {
6074 if (pos > qe->linpos) {
6075 /* Indicate there is another priority */
6076 qe->linwrapped = 1;
6077 }
6078 tmp->metric = pos;
6079 }
6080 tmp->metric += penalty * 1000000 * usepenalty;
6081 break;
6084 pos = mem->queuepos;
6085 if (pos < q->rrpos) {
6086 tmp->metric = 1000 + pos;
6087 } else {
6088 if (pos > q->rrpos) {
6089 /* Indicate there is another priority */
6090 q->wrapped = 1;
6091 }
6092 tmp->metric = pos;
6093 }
6094 tmp->metric += penalty * 1000000 * usepenalty;
6095 break;
6097 tmp->metric = ast_random() % 1000;
6098 tmp->metric += penalty * 1000000 * usepenalty;
6099 break;
6101 tmp->metric = ast_random() % ((1 + penalty) * 1000);
6102 break;
6104 tmp->metric = mem->calls;
6105 tmp->metric += penalty * 1000000 * usepenalty;
6106 break;
6108 if (!mem->lastcall) {
6109 tmp->metric = 0;
6110 } else {
6111 tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
6112 }
6113 tmp->metric += penalty * 1000000 * usepenalty;
6114 break;
6115 default:
6116 ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
6117 break;
6118 }
6119 return 0;
6120}
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
#define ast_debug(level,...)
Log a DEBUG message.
struct ao2_container * members
Definition: app_queue.c:1887
int penaltymemberslimit
Definition: app_queue.c:1871
unsigned int wrapped
Definition: app_queue.c:1839
int strategy
Definition: app_queue.c:1844
int queuepos
Definition: app_queue.c:1740
time_t lastcall
Definition: app_queue.c:1744
int calls
Definition: app_queue.c:1734
int linpos
Definition: app_queue.c:1713
int max_penalty
Definition: app_queue.c:1710
int raise_penalty
Definition: app_queue.c:1712
int min_penalty
Definition: app_queue.c:1711
int linwrapped
Definition: app_queue.c:1714
long int ast_random(void)
Definition: utils.c:2312

References ao2_container_count(), ast_debug, ast_log, ast_random(), member::calls, member::lastcall, queue_ent::linpos, queue_ent::linwrapped, LOG_WARNING, queue_ent::max_penalty, call_queue::members, queue_ent::min_penalty, NULL, member::penalty, call_queue::penaltymemberslimit, QUEUE_STRATEGY_FEWESTCALLS, QUEUE_STRATEGY_LEASTRECENT, QUEUE_STRATEGY_LINEAR, QUEUE_STRATEGY_RANDOM, QUEUE_STRATEGY_RINGALL, QUEUE_STRATEGY_RRMEMORY, QUEUE_STRATEGY_RRORDERED, QUEUE_STRATEGY_WRANDOM, member::queuepos, queue_ent::raise_penalty, call_queue::rrpos, call_queue::strategy, tmp(), and call_queue::wrapped.

Referenced by try_calling().

◆ callattempt_free()

static void callattempt_free ( struct callattempt doomed)
static

Definition at line 4447 of file app_queue.c.

4448{
4449 if (doomed->member) {
4450 ao2_ref(doomed->member, -1);
4451 }
4453 ast_free(doomed->orig_chan_name);
4454 ast_free(doomed);
4455}
#define ast_free(a)
Definition: astmm.h:180
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2091
struct ast_party_connected_line connected
Definition: app_queue.c:1677
char * orig_chan_name
Definition: app_queue.c:1688
struct member * member
Definition: app_queue.c:1675

References ao2_ref, ast_free, ast_party_connected_line_free(), callattempt::connected, callattempt::member, and callattempt::orig_chan_name.

Referenced by hangupcalls(), and try_calling().

◆ can_ring_entry()

static int can_ring_entry ( struct queue_ent qe,
struct callattempt call 
)
static

Definition at line 4657 of file app_queue.c.

4658{
4659 struct member *memberp = call->member;
4660 int wrapuptime;
4661
4662 if (memberp->paused) {
4663 ast_debug(1, "%s paused, can't receive call\n", call->interface);
4664 return 0;
4665 }
4666
4667 if (!memberp->ringinuse && !member_status_available(memberp->status)) {
4668 ast_debug(1, "%s not available, can't receive call\n", call->interface);
4669 return 0;
4670 }
4671
4672 if (memberp->lastqueue) {
4673 wrapuptime = get_wrapuptime(memberp->lastqueue, memberp);
4674 } else {
4675 wrapuptime = get_wrapuptime(qe->parent, memberp);
4676 }
4677 if (wrapuptime && (time(NULL) - memberp->lastcall) < wrapuptime) {
4678 ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
4679 (memberp->lastqueue ? memberp->lastqueue->name : qe->parent->name),
4680 call->interface);
4681 return 0;
4682 }
4683
4684 if (use_weight && compare_weight(qe->parent, memberp)) {
4685 ast_debug(1, "Priority queue delaying call to %s:%s\n",
4686 qe->parent->name, call->interface);
4687 return 0;
4688 }
4689
4691 ast_debug(1, "Another caller was waiting longer; delaying call to %s:%s\n",
4692 qe->parent->name, call->interface);
4693 return 0;
4694 }
4695
4696 if (!memberp->ringinuse) {
4697 struct member *mem;
4698
4700
4701 mem = ao2_find(pending_members, memberp,
4703 if (mem) {
4704 /*
4705 * If found that means this member is currently being attempted
4706 * from another calling thread, so stop trying from this thread
4707 */
4708 ast_debug(1, "%s has another call trying, can't receive call\n",
4709 call->interface);
4710 ao2_ref(mem, -1);
4712 return 0;
4713 }
4714
4715 /*
4716 * If not found add it to the container so another queue
4717 * won't attempt to call this member at the same time.
4718 */
4719 ast_debug(3, "Add %s to pending_members\n", memberp->membername);
4720 ao2_link(pending_members, memberp);
4722
4723 /*
4724 * The queue member is available. Get current status to be sure
4725 * because the device state and extension state callbacks may
4726 * not have updated the status yet.
4727 */
4729 ast_debug(1, "%s actually not available, can't receive call\n",
4730 call->interface);
4731 pending_members_remove(memberp);
4732 return 0;
4733 }
4734 }
4735
4736 return 1;
4737}
static int is_longest_waiting_caller(struct queue_ent *caller, struct member *member)
Definition: app_queue.c:4576
static int get_wrapuptime(struct call_queue *q, struct member *member)
Return wrapuptime.
Definition: app_queue.c:1991
static int compare_weight(struct call_queue *rq, struct member *member)
Definition: app_queue.c:4542
static struct ao2_container * pending_members
Definition: app_queue.c:2513
static int force_longest_waiting_caller
queues.conf [general] option
Definition: app_queue.c:1617
static void pending_members_remove(struct member *mem)
Definition: app_queue.c:2564
static int get_queue_member_status(struct member *cur)
Return the current state of a member.
Definition: app_queue.c:2850
static int use_weight
Records that one or more queues use weight.
Definition: app_queue.c:1593
static int member_status_available(int status)
Definition: app_queue.c:4643
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
Definition: astobj2.h:1087
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
Definition: astobj2.h:1063
static int call(void *data)
Definition: chan_pjsip.c:2395
int status
Definition: app_queue.c:1737
unsigned int ringinuse
Definition: app_queue.c:1751
struct call_queue * lastqueue
Definition: app_queue.c:1747
struct call_queue * parent
Definition: app_queue.c:1693

References ao2_find, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_debug, call(), compare_weight(), force_longest_waiting_caller, get_queue_member_status(), get_wrapuptime(), is_longest_waiting_caller(), member::lastcall, member::lastqueue, member_status_available(), member::membername, call_queue::name, NULL, OBJ_NOLOCK, OBJ_SEARCH_OBJECT, queue_ent::parent, member::paused, pending_members, pending_members_remove(), member::ringinuse, member::status, use_weight, and member::wrapuptime.

Referenced by ring_entry().

◆ change_priority_caller_on_queue()

static int change_priority_caller_on_queue ( const char *  queuename,
const char *  caller,
int  priority,
int  immediate 
)
static

Change priority caller into a queue.

Return values
RES_NOSUCHQUEUEqueue does not exist
RES_OKAYchange priority
RES_NOT_CALLERqueue exists but no caller
Note
Ensure the appropriate realtime queue is loaded. Note that this short-circuits if the queue is already in memory.

Definition at line 7646 of file app_queue.c.

7647{
7648 struct call_queue *q;
7649 struct queue_ent *current, *prev = NULL, *caller_qe = NULL;
7650 int res = RES_NOSUCHQUEUE;
7651
7652 /*! \note Ensure the appropriate realtime queue is loaded. Note that this
7653 * short-circuits if the queue is already in memory. */
7654 if (!(q = find_load_queue_rt_friendly(queuename))) {
7655 return res;
7656 }
7657
7658 ao2_lock(q);
7659 res = RES_NOT_CALLER;
7660 for (current = q->head; current; current = current->next) {
7661 if (strcmp(ast_channel_name(current->chan), caller) == 0) {
7662 ast_debug(1, "%s Caller new priority %d in queue %s\n",
7663 caller, priority, queuename);
7664 current->prio = priority;
7665 if (immediate) {
7666 /* This caller is being immediately moved in the queue so remove them */
7667 if (prev) {
7668 prev->next = current->next;
7669 } else {
7670 q->head = current->next;
7671 }
7672 caller_qe = current;
7673 /* The position for all callers is not recalculated in here as it will
7674 * be updated when the moved caller is inserted back into the queue
7675 */
7676 }
7677 res = RES_OKAY;
7678 break;
7679 } else if (immediate) {
7680 prev = current;
7681 }
7682 }
7683
7684 if (caller_qe) {
7685 int inserted = 0, pos = 0;
7686
7687 /* If a caller queue entry exists, we are applying their priority immediately
7688 * and have to reinsert them at the correct position.
7689 */
7690 prev = NULL;
7691 current = q->head;
7692 while (current) {
7693 if (!inserted && (caller_qe->prio > current->prio)) {
7694 insert_entry(q, prev, caller_qe, &pos);
7695 inserted = 1;
7696 }
7697
7698 /* We always update the position as it may have changed */
7699 current->pos = ++pos;
7700
7701 /* Move to the next caller in the queue */
7702 prev = current;
7703 current = current->next;
7704 }
7705
7706 if (!inserted) {
7707 insert_entry(q, prev, caller_qe, &pos);
7708 }
7709 }
7710
7711 ao2_unlock(q);
7712 return res;
7713}
#define RES_NOT_CALLER
Definition: app_queue.c:1570
static void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
Insert the 'new' entry after the 'prev' entry of queue 'q'.
Definition: app_queue.c:2089
static int priority
size_t current
Definition: main/cli.c:113
struct queue_ent * head
Definition: app_queue.c:1888
struct queue_ent * next
Definition: app_queue.c:1723

References ao2_lock, ao2_unlock, ast_channel_name(), ast_debug, current, find_load_queue_rt_friendly(), call_queue::head, insert_entry(), queue_ent::next, NULL, queue_ent::pos, priority, RES_NOSUCHQUEUE, RES_NOT_CALLER, and RES_OKAY.

Referenced by handle_queue_change_priority_caller(), and manager_change_priority_caller_on_queue().

◆ clear_queue()

static void clear_queue ( struct call_queue q)
static

Definition at line 3051 of file app_queue.c.

3052{
3053 q->holdtime = 0;
3054 q->callscompleted = 0;
3055 q->callsabandoned = 0;
3056 q->callscompletedinsl = 0;
3057 q->callsabandonedinsl = 0;
3058 q->talktime = 0;
3059
3060 if (q->members) {
3061 struct member *mem;
3062 struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
3063 while ((mem = ao2_iterator_next(&mem_iter))) {
3064 mem->calls = 0;
3065 mem->callcompletedinsl = 0;
3066 mem->lastcall = 0;
3067 mem->starttime = 0;
3068 ao2_ref(mem, -1);
3069 }
3070 ao2_iterator_destroy(&mem_iter);
3071 }
3072}
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
int talktime
Definition: app_queue.c:1861
int callsabandoned
Definition: app_queue.c:1863
int callscompleted
Definition: app_queue.c:1862
int callsabandonedinsl
Definition: app_queue.c:1864
int callscompletedinsl
Definition: app_queue.c:1866
int holdtime
Definition: app_queue.c:1860
time_t starttime
Definition: app_queue.c:1743
int callcompletedinsl
Definition: app_queue.c:1741

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, member::callcompletedinsl, member::calls, call_queue::callsabandoned, call_queue::callsabandonedinsl, call_queue::callscompleted, call_queue::callscompletedinsl, call_queue::holdtime, member::lastcall, call_queue::members, member::starttime, and call_queue::talktime.

Referenced by clear_stats(), and find_queue_by_name_rt().

◆ clear_stats()

static int clear_stats ( const char *  queuename)
static

Facilitates resetting statistics for a queue.

This function actually does not reset any statistics, but rather finds a call_queue struct which corresponds to the passed-in queue name and passes that structure to the clear_queue function. If no queuename is passed in, then all queues will have their statistics reset.

Parameters
queuenameThe name of the queue to reset the statistics for. If this is NULL or zero-length, then this means to reset the statistics for all queues
Return values
0always

Definition at line 9973 of file app_queue.c.

9974{
9975 struct call_queue *q;
9976 struct ao2_iterator queue_iter;
9977
9978 queue_iter = ao2_iterator_init(queues, 0);
9979 while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
9980 ao2_lock(q);
9981 if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename))
9982 clear_queue(q);
9983 ao2_unlock(q);
9984 queue_t_unref(q, "Done with iterator");
9985 }
9986 ao2_iterator_destroy(&queue_iter);
9987 return 0;
9988}
static void clear_queue(struct call_queue *q)
Definition: app_queue.c:3051

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_lock, ao2_t_iterator_next, ao2_unlock, ast_strlen_zero(), clear_queue(), call_queue::name, queue_t_unref, and queues.

Referenced by reload_handler().

◆ compare_weight()

static int compare_weight ( struct call_queue rq,
struct member member 
)
static

Definition at line 4542 of file app_queue.c.

4543{
4544 struct call_queue *q;
4545 struct member *mem;
4546 int found = 0;
4547 struct ao2_iterator queue_iter;
4548
4549 queue_iter = ao2_iterator_init(queues, 0);
4550 while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
4551 if (q == rq) { /* don't check myself, could deadlock */
4552 queue_t_unref(q, "Done with iterator");
4553 continue;
4554 }
4555 ao2_lock(q);
4556 if (q->count && q->members) {
4557 if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
4558 ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
4559 if (q->weight > rq->weight && q->count >= num_available_members(q)) {
4560 ast_debug(1, "Queue '%s' (weight %d, calls %d) is preferred over '%s' (weight %d, calls %d)\n", q->name, q->weight, q->count, rq->name, rq->weight, rq->count);
4561 found = 1;
4562 }
4563 ao2_ref(mem, -1);
4564 }
4565 }
4566 ao2_unlock(q);
4567 queue_t_unref(q, "Done with iterator");
4568 if (found) {
4569 break;
4570 }
4571 }
4572 ao2_iterator_destroy(&queue_iter);
4573 return found;
4574}
static int num_available_members(struct call_queue *q)
Get the number of members available to accept a call.
Definition: app_queue.c:4509
#define OBJ_POINTER
Definition: astobj2.h:1150

References ao2_find, ao2_iterator_destroy(), ao2_iterator_init(), ao2_lock, ao2_ref, ao2_t_iterator_next, ao2_unlock, ast_debug, call_queue::count, member::interface, call_queue::members, call_queue::name, num_available_members(), OBJ_POINTER, queue_t_unref, queues, and call_queue::weight.

Referenced by can_ring_entry().

◆ complete_queue()

static char * complete_queue ( const char *  line,
const char *  word,
int  pos,
int  state,
ptrdiff_t  word_list_offset 
)
static

Check if a given word is in a space-delimited list.

Parameters
lineThe line as typed not including the current word being completed
wordThe word currently being completed
posThe number of completed words in line
stateThe nth desired completion option
word_list_offsetOffset into the line where the list of queues begins. If non-zero, queues in the list will not be offered for further completion.
Returns
Returns the queue tab-completion for the given word and state

Definition at line 10309 of file app_queue.c.

10310{
10311 struct call_queue *q;
10312 char *ret = NULL;
10313 int which = 0;
10314 int wordlen = strlen(word);
10315 struct ao2_iterator queue_iter;
10316 const char *word_list = NULL;
10317
10318 /* for certain commands, already completed items should be left out of
10319 * the list */
10320 if (word_list_offset && strlen(line) >= word_list_offset) {
10321 word_list = line + word_list_offset;
10322 }
10323
10324 queue_iter = ao2_iterator_init(queues, 0);
10325 while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
10326 if (!strncasecmp(word, q->name, wordlen) && ++which > state
10327 && (!word_list_offset || !word_in_list(word_list, q->name))) {
10328 ret = ast_strdup(q->name);
10329 queue_t_unref(q, "Done with iterator");
10330 break;
10331 }
10332 queue_t_unref(q, "Done with iterator");
10333 }
10334 ao2_iterator_destroy(&queue_iter);
10335
10336 /* Pretend "rules" is at the end of the queues list in certain
10337 * circumstances since it is an alternate command that should be
10338 * tab-completable for "queue show" */
10339 if (!ret && which == state && !wordlen && !strncmp("queue show", line, 10)) {
10340 ret = ast_strdup("rules");
10341 }
10342
10343 return ret;
10344}
static int word_in_list(const char *list, const char *word)
Check if a given word is in a space-delimited list.
Definition: app_queue.c:10250
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
short word

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_t_iterator_next, ast_strdup, call_queue::name, NULL, queue_t_unref, queues, and word_in_list().

Referenced by complete_queue_add_member(), complete_queue_pause_member(), complete_queue_remove_member(), complete_queue_set_member_value(), complete_queue_show(), handle_queue_reload(), and handle_queue_reset().

◆ complete_queue_add_member()

static char * complete_queue_add_member ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 10815 of file app_queue.c.

10816{
10817 /* 0 - queue; 1 - add; 2 - member; 3 - <interface>; 4 - to; 5 - <queue>; 6 - penalty; 7 - <penalty>; 8 - as; 9 - <membername> */
10818 switch (pos) {
10819 case 3: /* Don't attempt to complete name of interface (infinite possibilities) */
10820 return NULL;
10821 case 4: /* only one possible match, "to" */
10822 return state == 0 ? ast_strdup("to") : NULL;
10823 case 5: /* <queue> */
10824 return complete_queue(line, word, pos, state, 0);
10825 case 6: /* only one possible match, "penalty" */
10826 return state == 0 ? ast_strdup("penalty") : NULL;
10827 case 7:
10828 if (0 <= state && state < 100) { /* 0-99 */
10829 char *num;
10830 if ((num = ast_malloc(3))) {
10831 sprintf(num, "%d", state);
10832 }
10833 return num;
10834 } else {
10835 return NULL;
10836 }
10837 case 8: /* only one possible match, "as" */
10838 return state == 0 ? ast_strdup("as") : NULL;
10839 case 9: /* Don't attempt to complete name of member (infinite possibilities) */
10840 return NULL;
10841 default:
10842 return NULL;
10843 }
10844}
static char * complete_queue(const char *line, const char *word, int pos, int state, ptrdiff_t word_list_offset)
Check if a given word is in a space-delimited list.
Definition: app_queue.c:10309
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191

References ast_malloc, ast_strdup, complete_queue(), and NULL.

Referenced by handle_queue_add_member().

◆ complete_queue_pause_member()

static char * complete_queue_pause_member ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 11233 of file app_queue.c.

11234{
11235 /* 0 - queue; 1 - pause; 2 - member; 3 - <interface>; 4 - queue; 5 - <queue>; 6 - reason; 7 - <reason> */
11236 switch (pos) {
11237 case 3: /* Don't attempt to complete name of interface (infinite possibilities) */
11238 return NULL;
11239 case 4: /* only one possible match, "queue" */
11240 return state == 0 ? ast_strdup("queue") : NULL;
11241 case 5: /* <queue> */
11242 return complete_queue(line, word, pos, state, 0);
11243 case 6: /* "reason" */
11244 return state == 0 ? ast_strdup("reason") : NULL;
11245 case 7: /* Can't autocomplete a reason, since it's 100% customizeable */
11246 return NULL;
11247 default:
11248 return NULL;
11249 }
11250}

References ast_strdup, complete_queue(), and NULL.

Referenced by handle_queue_pause_member().

◆ complete_queue_remove_member()

static char * complete_queue_remove_member ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 11068 of file app_queue.c.

11069{
11070 int which = 0;
11071 struct call_queue *q;
11072 struct member *m;
11073 struct ao2_iterator queue_iter;
11074 struct ao2_iterator mem_iter;
11075 int wordlen = strlen(word);
11076
11077 /* 0 - queue; 1 - remove; 2 - member; 3 - <member>; 4 - from; 5 - <queue> */
11078 if (pos > 5 || pos < 3) {
11079 return NULL;
11080 }
11081 if (pos == 4) { /* only one possible match, 'from' */
11082 return (state == 0 ? ast_strdup("from") : NULL);
11083 }
11084
11085 if (pos == 5) { /* No need to duplicate code */
11086 return complete_queue(line, word, pos, state, 0);
11087 }
11088
11089 /* here is the case for 3, <member> */
11090 queue_iter = ao2_iterator_init(queues, 0);
11091 while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
11092 ao2_lock(q);
11093 mem_iter = ao2_iterator_init(q->members, 0);
11094 while ((m = ao2_iterator_next(&mem_iter))) {
11095 if (!strncasecmp(word, m->membername, wordlen) && ++which > state) {
11096 char *tmp;
11097 tmp = ast_strdup(m->interface);
11098 ao2_ref(m, -1);
11099 ao2_iterator_destroy(&mem_iter);
11100 ao2_unlock(q);
11101 queue_t_unref(q, "Done with iterator, returning interface name");
11102 ao2_iterator_destroy(&queue_iter);
11103 return tmp;
11104 }
11105 ao2_ref(m, -1);
11106 }
11107 ao2_iterator_destroy(&mem_iter);
11108 ao2_unlock(q);
11109 queue_t_unref(q, "Done with iterator");
11110 }
11111 ao2_iterator_destroy(&queue_iter);
11112
11113 return NULL;
11114}

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_t_iterator_next, ao2_unlock, ast_strdup, complete_queue(), member::interface, member::membername, call_queue::members, NULL, queue_t_unref, queues, and tmp().

Referenced by handle_queue_remove_member().

◆ complete_queue_rule_show()

static char * complete_queue_rule_show ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 11428 of file app_queue.c.

11429{
11430 int which = 0;
11431 struct rule_list *rl_iter;
11432 int wordlen = strlen(word);
11433 char *ret = NULL;
11434 if (pos != 3) /* Wha? */ {
11435 return NULL;
11436 }
11437
11439 AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
11440 if (!strncasecmp(word, rl_iter->name, wordlen) && ++which > state) {
11441 ret = ast_strdup(rl_iter->name);
11442 break;
11443 }
11444 }
11446
11447 return ret;
11448}
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:491
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
char name[80]
Definition: app_queue.c:1894
struct rule_list::@56 list

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, rule_list::list, rule_list::name, and NULL.

Referenced by handle_queue_rule_show().

◆ complete_queue_set_member_value()

static char * complete_queue_set_member_value ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 11307 of file app_queue.c.

11308{
11309 /* 0 - queue; 1 - set; 2 - penalty/ringinuse; 3 - <value>; 4 - on; 5 - <member>; 6 - in; 7 - <queue>;*/
11310 switch (pos) {
11311 case 4:
11312 if (state == 0) {
11313 return ast_strdup("on");
11314 } else {
11315 return NULL;
11316 }
11317 case 6:
11318 if (state == 0) {
11319 return ast_strdup("in");
11320 } else {
11321 return NULL;
11322 }
11323 case 7:
11324 return complete_queue(line, word, pos, state, 0);
11325 default:
11326 return NULL;
11327 }
11328}

References ast_strdup, complete_queue(), and NULL.

Referenced by handle_queue_set_member_penalty(), and handle_queue_set_member_ringinuse().

◆ complete_queue_show()

static char * complete_queue_show ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 10346 of file app_queue.c.

10347{
10348 if (pos == 2) {
10349 return complete_queue(line, word, pos, state, 0);
10350 }
10351 return NULL;
10352}

References complete_queue(), and NULL.

Referenced by queue_show().

◆ compress_char()

static int compress_char ( const char  c)
static

Definition at line 2910 of file app_queue.c.

2911{
2912 if (c < 32) {
2913 return 0;
2914 } else if (c > 96) {
2915 return c - 64;
2916 }
2917 return c - 32;
2918}
static struct test_val c

References c.

Referenced by member_hash_fn().

◆ context_included()

static int context_included ( const char *  parent,
const char *  child 
)
static

Returns if one context includes another context.

Parameters
parentParent context to search for child
childContext to check for inclusion in parent

This function recursively checks if the context child is included in the context parent.

Return values
1if child is included in parent
0if not

Definition at line 2777 of file app_queue.c.

2778{
2779 struct ast_context *c = NULL;
2780
2781 c = ast_context_find(parent);
2782 if (!c) {
2783 /* well, if parent doesn't exist, how can the child be included in it? */
2784 return 0;
2785 }
2786 if (!strcmp(ast_get_context_name(c), parent)) {
2787 /* found the context of the hint app_queue is using. Now, see
2788 if that context includes the one that just changed state */
2789 struct ast_include *inc = NULL;
2790
2791 while ((inc = (struct ast_include*) ast_walk_context_includes(c, inc))) {
2792 const char *includename = ast_get_include_name(inc);
2793 if (!strcasecmp(child, includename)) {
2794 return 1;
2795 }
2796 /* recurse on this context, for nested includes. The
2797 PBX extension parser will prevent infinite recursion. */
2798 if (context_included(includename, child)) {
2799 return 1;
2800 }
2801 }
2802 }
2803 return 0;
2804}
static int context_included(const char *parent, const char *child)
Returns if one context includes another context.
Definition: app_queue.c:2777
const struct ast_include * ast_walk_context_includes(const struct ast_context *con, const struct ast_include *inc)
Definition: pbx.c:8650
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: extconf.c:4172
const char * ast_get_include_name(const struct ast_include *include)
Definition: pbx_include.c:50
const char * ast_get_context_name(struct ast_context *con)
Definition: ael_main.c:421
ast_context: An extension context
Definition: pbx.c:284
ast_include: include= support in extensions.conf
Definition: pbx_include.c:37

References ast_context_find(), ast_get_context_name(), ast_get_include_name(), ast_walk_context_includes(), c, context_included(), and NULL.

Referenced by context_included(), and extension_state_cb().

◆ copy_rules()

static void copy_rules ( struct queue_ent qe,
const char *  rulename 
)
static

Copy rule from global list into specified queue.

Definition at line 8469 of file app_queue.c.

8470{
8471 struct penalty_rule *pr_iter;
8472 struct rule_list *rl_iter;
8473 const char *tmp = ast_strlen_zero(rulename) ? qe->parent->defaultrule : rulename;
8475 AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
8476 if (!strcasecmp(rl_iter->name, tmp)) {
8477 break;
8478 }
8479 }
8480 if (rl_iter) {
8481 AST_LIST_TRAVERSE(&rl_iter->rules, pr_iter, list) {
8482 struct penalty_rule *new_pr = ast_calloc(1, sizeof(*new_pr));
8483 if (!new_pr) {
8484 ast_log(LOG_ERROR, "Memory allocation error when copying penalty rules! Aborting!\n");
8485 break;
8486 }
8487 new_pr->time = pr_iter->time;
8488 new_pr->max_value = pr_iter->max_value;
8489 new_pr->min_value = pr_iter->min_value;
8490 new_pr->raise_value = pr_iter->raise_value;
8491 new_pr->max_relative = pr_iter->max_relative;
8492 new_pr->min_relative = pr_iter->min_relative;
8493 new_pr->raise_relative = pr_iter->raise_relative;
8494 AST_LIST_INSERT_TAIL(&qe->qe_rules, new_pr, list);
8495 }
8496 }
8498}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:731
const ast_string_field defaultrule
Definition: app_queue.c:1829
int raise_relative
Definition: app_queue.c:1782
struct penalty_rule::@52 list
int min_relative
Definition: app_queue.c:1781
int max_relative
Definition: app_queue.c:1780
struct queue_ent::@51 qe_rules
struct rule_list::@55 rules

References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log, ast_strlen_zero(), call_queue::defaultrule, penalty_rule::list, rule_list::list, LOG_ERROR, penalty_rule::max_relative, penalty_rule::max_value, penalty_rule::min_relative, penalty_rule::min_value, rule_list::name, queue_ent::parent, queue_ent::qe_rules, penalty_rule::raise_relative, penalty_rule::raise_value, rule_list::rules, penalty_rule::time, and tmp().

Referenced by queue_exec().

◆ create_queue_member()

static struct member * create_queue_member ( const char *  interface,
const char *  membername,
int  penalty,
int  paused,
const char *  state_interface,
int  ringinuse,
int  wrapuptime 
)
static

allocate space for new queue member and set fields based on parameters passed

Definition at line 2865 of file app_queue.c.

2866{
2867 struct member *cur;
2868
2869 if ((cur = ao2_alloc(sizeof(*cur), destroy_queue_member_cb))) {
2870 cur->ringinuse = ringinuse;
2871 cur->penalty = penalty;
2872 cur->paused = paused;
2873 cur->wrapuptime = wrapuptime;
2874 if (paused) {
2875 time(&cur->lastpause); /* Update time of last pause */
2876 }
2877 time(&cur->logintime);
2878 ast_copy_string(cur->interface, interface, sizeof(cur->interface));
2881 } else {
2883 }
2885 ast_copy_string(cur->membername, membername, sizeof(cur->membername));
2886 } else {
2887 ast_copy_string(cur->membername, interface, sizeof(cur->membername));
2888 }
2889 if (!strchr(cur->interface, '/')) {
2890 ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
2891 }
2892 if (!strncmp(cur->state_interface, "hint:", 5)) {
2893 char *tmp = ast_strdupa(cur->state_interface), *context = tmp;
2894 char *exten = strsep(&context, "@") + 5;
2895
2896 ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten));
2897 ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context));
2898
2900 } else {
2901 cur->state_id = -1;
2902 }
2903 cur->status = get_queue_member_status(cur);
2904 }
2905
2906 return cur;
2907}
static int extension_state_cb(const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
Definition: app_queue.c:2806
static void destroy_queue_member_cb(void *obj)
Definition: app_queue.c:2855
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
char * strsep(char **str, const char *delims)
int ast_extension_state_add(const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
Add watcher for extension states.
Definition: pbx.c:3823
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
time_t logintime
Definition: app_queue.c:1746
char state_exten[AST_MAX_EXTENSION]
Definition: app_queue.c:1728
char state_context[AST_MAX_CONTEXT]
Definition: app_queue.c:1729
int state_id
Definition: app_queue.c:1731
time_t lastpause
Definition: app_queue.c:1745

References ao2_alloc, ast_copy_string(), ast_extension_state_add(), ast_log, ast_strdupa, ast_strlen_zero(), voicemailpwcheck::context, destroy_queue_member_cb(), extension_state_cb(), get_queue_member_status(), member::interface, member::lastpause, LOG_WARNING, member::logintime, member::membername, NULL, member::paused, member::penalty, member::ringinuse, S_OR, member::state_context, member::state_exten, member::state_id, member::state_interface, member::status, strsep(), tmp(), and member::wrapuptime.

Referenced by add_to_queue(), reload_single_member(), and rt_handle_member_record().

◆ destroy_queue()

static void destroy_queue ( void *  obj)
static

Free queue's member list then its string fields.

Definition at line 3712 of file app_queue.c.

3713{
3714 struct call_queue *q = obj;
3715 int i;
3716
3717 free_members(q, 1);
3719 for (i = 0; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
3720 if (q->sound_periodicannounce[i]) {
3722 }
3723 }
3724 ao2_ref(q->members, -1);
3725}
#define MAX_PERIODIC_ANNOUNCEMENTS
Definition: app_queue.c:1556
static void free_members(struct call_queue *q, int all)
Iterate through queue's member list and delete them.
Definition: app_queue.c:3696
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
struct ast_str * sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS]
Definition: app_queue.c:1831

References ao2_ref, ast_free, ast_string_field_free_memory, free_members(), MAX_PERIODIC_ANNOUNCEMENTS, call_queue::members, and call_queue::sound_periodicannounce.

Referenced by alloc_queue().

◆ destroy_queue_member_cb()

static void destroy_queue_member_cb ( void *  obj)
static

Definition at line 2855 of file app_queue.c.

2856{
2857 struct member *mem = obj;
2858
2859 if (mem->state_id != -1) {
2861 }
2862}
int ast_extension_state_del(int id, ast_state_cb_type change_cb)
Deletes a state change watcher by ID.
Definition: pbx.c:3856

References ast_extension_state_del(), extension_state_cb(), and member::state_id.

Referenced by create_queue_member().

◆ device_state_cb()

static void device_state_cb ( void *  unused,
struct stasis_subscription sub,
struct stasis_message msg 
)
static

set a member's status based on device state of that member's interface

Definition at line 2641 of file app_queue.c.

2642{
2643 struct ao2_iterator miter, qiter;
2644 struct ast_device_state_message *dev_state;
2645 struct member *m;
2646 struct call_queue *q;
2647 char interface[80], *slash_pos;
2648 int found = 0; /* Found this member in any queue */
2649 int found_member; /* Found this member in this queue */
2650 int avail = 0; /* Found an available member in this queue */
2651
2653 return;
2654 }
2655
2656 dev_state = stasis_message_data(msg);
2657 if (dev_state->eid) {
2658 /* ignore non-aggregate states */
2659 return;
2660 }
2661
2662 qiter = ao2_iterator_init(queues, 0);
2663 while ((q = ao2_t_iterator_next(&qiter, "Iterate over queues"))) {
2664 ao2_lock(q);
2665
2666 avail = 0;
2667 found_member = 0;
2668 miter = ao2_iterator_init(q->members, 0);
2669 for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
2670 if (!found_member) {
2671 ast_copy_string(interface, m->state_interface, sizeof(interface));
2672
2673 if ((slash_pos = strchr(interface, '/'))) {
2674 if (!strncasecmp(interface, "Local/", 6) && (slash_pos = strchr(slash_pos + 1, '/'))) {
2675 *slash_pos = '\0';
2676 }
2677 }
2678
2679 if (!strcasecmp(interface, dev_state->device)) {
2680 found_member = 1;
2681 update_status(q, m, dev_state->state);
2682 }
2683 }
2684
2685 /* check every member until we find one NOT_INUSE */
2686 if (!avail) {
2687 avail = is_member_available(q, m);
2688 }
2689 if (avail && found_member) {
2690 /* early exit as we've found an available member and the member of interest */
2691 ao2_ref(m, -1);
2692 break;
2693 }
2694 }
2695
2696 if (found_member) {
2697 found = 1;
2698 if (avail) {
2700 } else {
2702 }
2703 }
2704
2705 ao2_iterator_destroy(&miter);
2706
2707 ao2_unlock(q);
2708 queue_t_unref(q, "Done with iterator");
2709 }
2710 ao2_iterator_destroy(&qiter);
2711
2712 if (found) {
2713 ast_debug(1, "Device '%s' changed to state '%u' (%s)\n",
2714 dev_state->device,
2715 dev_state->state,
2716 ast_devstate2str(dev_state->state));
2717 } else {
2718 ast_debug(3, "Device '%s' changed to state '%u' (%s) but we don't care because they're not a member of any queue.\n",
2719 dev_state->device,
2720 dev_state->state,
2721 ast_devstate2str(dev_state->state));
2722 }
2723
2724 return;
2725}
static void update_status(struct call_queue *q, struct member *m, const int status)
set a member's status based on device state of that member's state_interface.
Definition: app_queue.c:2575
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Convert device state to text string for output.
Definition: devicestate.c:237
@ AST_DEVICE_INUSE
Definition: devicestate.h:55
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
The structure that contains device state.
Definition: devicestate.h:238
enum ast_device_state state
Definition: devicestate.h:248
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:246

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_t_iterator_next, ao2_unlock, ast_copy_string(), ast_debug, AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, ast_device_state_message_type(), ast_devstate2str(), AST_DEVSTATE_CACHABLE, ast_devstate_changed(), ast_device_state_message::device, ast_device_state_message::eid, call_queue::found, is_member_available(), call_queue::members, call_queue::name, queue_t_unref, queues, stasis_message_data(), stasis_message_type(), ast_device_state_message::state, member::state_interface, and update_status().

Referenced by load_module().

◆ do_hang()

static void do_hang ( struct callattempt o)
static

common hangup actions

Definition at line 4627 of file app_queue.c.

4628{
4629 o->stillgoing = 0;
4630 ast_hangup(o->chan);
4632 o->chan = NULL;
4633}
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2560
struct ast_channel * chan
Definition: app_queue.c:1672
unsigned int stillgoing
Definition: app_queue.c:1685

References ast_hangup(), callattempt::chan, callattempt::member, NULL, pending_members_remove(), and callattempt::stillgoing.

Referenced by ring_entry(), and wait_for_answer().

◆ do_print()

static void do_print ( struct mansession s,
int  fd,
const char *  str 
)
static

direct output to manager or cli with proper terminator

Definition at line 10020 of file app_queue.c.

10021{
10022 if (s) {
10023 astman_append(s, "%s\r\n", str);
10024 } else {
10025 ast_cli(fd, "%s\n", str);
10026 }
10027}
const char * str
Definition: app_jack.c:147
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1890

References ast_cli(), astman_append(), and str.

Referenced by __queues_show(), and print_queue().

◆ dump_queue_members()

static void dump_queue_members ( struct call_queue pm_queue)
static

Dump all members in a specific queue to the database.

<pm_family>/<queuename> = <interface>;<penalty>;<paused>;<state_interface>[|...]
static const char *const pm_family
Persistent Members astdb family.
Definition: app_queue.c:1587

Definition at line 7485 of file app_queue.c.

7486{
7487 struct member *cur_member;
7488 struct ast_str *value;
7489 struct ao2_iterator mem_iter;
7490
7491 if (!pm_queue) {
7492 return;
7493 }
7494
7495 /* 4K is a reasonable default for most applications, but we grow to
7496 * accommodate more if necessary. */
7497 if (!(value = ast_str_create(4096))) {
7498 return;
7499 }
7500
7501 mem_iter = ao2_iterator_init(pm_queue->members, 0);
7502 while ((cur_member = ao2_iterator_next(&mem_iter))) {
7503 if (!cur_member->dynamic) {
7504 ao2_ref(cur_member, -1);
7505 continue;
7506 }
7507
7508 ast_str_append(&value, 0, "%s%s;%d;%d;%s;%s;%s;%d",
7509 ast_str_strlen(value) ? "|" : "",
7510 cur_member->interface,
7511 cur_member->penalty,
7512 cur_member->paused,
7513 cur_member->membername,
7514 cur_member->state_interface,
7515 cur_member->reason_paused,
7516 cur_member->wrapuptime);
7517
7518 ao2_ref(cur_member, -1);
7519 }
7520 ao2_iterator_destroy(&mem_iter);
7521
7522 if (ast_str_strlen(value) && !cur_member) {
7523 if (ast_db_put(pm_family, pm_queue->name, ast_str_buffer(value))) {
7524 ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n");
7525 }
7526 } else {
7527 /* Delete the entry if the queue is empty or there is an error */
7528 ast_db_del(pm_family, pm_queue->name);
7529 }
7530
7531 ast_free(value);
7532}
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:341
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:478
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:730
int value
Definition: syslog.c:37

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_db_del(), ast_db_put(), ast_free, ast_log, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_strlen(), member::dynamic, member::interface, LOG_WARNING, member::membername, call_queue::members, call_queue::name, member::paused, member::penalty, pm_family, member::reason_paused, member::state_interface, value, and member::wrapuptime.

Referenced by add_to_queue(), remove_from_queue(), and set_queue_member_pause().

◆ end_bridge_callback()

static void end_bridge_callback ( void *  data)
static

Definition at line 6834 of file app_queue.c.

6835{
6836 struct queue_end_bridge *qeb = data;
6837 struct call_queue *q = qeb->q;
6838 struct ast_channel *chan = qeb->chan;
6839
6840 if (ao2_ref(qeb, -1) == 1) {
6841 set_queue_variables(q, chan);
6842 /* This unrefs the reference we made in try_calling when we allocated qeb */
6843 queue_t_unref(q, "Expire bridge_config reference");
6844 }
6845}
static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
Set variables of queue.
Definition: app_queue.c:2063
Main Channel structure associated with a channel.
struct call_queue * q
Definition: app_queue.c:6823
struct ast_channel * chan
Definition: app_queue.c:6824

References ao2_ref, queue_end_bridge::chan, queue_end_bridge::q, queue_t_unref, and set_queue_variables().

Referenced by try_calling().

◆ end_bridge_callback_data_fixup()

static void end_bridge_callback_data_fixup ( struct ast_bridge_config bconfig,
struct ast_channel originator,
struct ast_channel terminator 
)
static

Definition at line 6827 of file app_queue.c.

6828{
6829 struct queue_end_bridge *qeb = bconfig->end_bridge_callback_data;
6830 ao2_ref(qeb, +1);
6831 qeb->chan = originator;
6832}
void * end_bridge_callback_data
Definition: channel.h:1111

References ao2_ref, queue_end_bridge::chan, and ast_bridge_config::end_bridge_callback_data.

Referenced by try_calling().

◆ escape_and_substitute()

static void escape_and_substitute ( struct ast_channel chan,
const char *  input,
char *  output,
size_t  size 
)
static

Definition at line 6874 of file app_queue.c.

6876{
6877 const char *m = input;
6878 char escaped[size];
6879 char *p;
6880
6881 for (p = escaped; p < escaped + size - 1; p++, m++) {
6882 switch (*m) {
6883 case '^':
6884 if (*(m + 1) == '{') {
6885 *p = '$';
6886 }
6887 break;
6888 case ',':
6889 *p++ = '\\';
6890 /* Fall through */
6891 default:
6892 *p = *m;
6893 }
6894 if (*m == '\0')
6895 break;
6896 }
6897
6898 if (p == escaped + size) {
6899 escaped[size - 1] = '\0';
6900 }
6901
6902 pbx_substitute_variables_helper(chan, escaped, output, size - 1);
6903}
static int input(yyscan_t yyscanner)
Definition: ast_expr2f.c:1570
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: ael_main.c:211

References input(), and pbx_substitute_variables_helper().

Referenced by setup_mixmonitor().

◆ extension_state_cb()

static int extension_state_cb ( const char *  context,
const char *  exten,
struct ast_state_cb_info info,
void *  data 
)
static

Definition at line 2806 of file app_queue.c.

2807{
2808 struct ao2_iterator miter, qiter;
2809 struct member *m;
2810 struct call_queue *q;
2811 int state = info->exten_state;
2812 int found = 0, device_state = extensionstate2devicestate(state);
2813
2814 /* only interested in extension state updates involving device states */
2815 if (info->reason != AST_HINT_UPDATE_DEVICE) {
2816 return 0;
2817 }
2818
2819 qiter = ao2_iterator_init(queues, 0);
2820 while ((q = ao2_t_iterator_next(&qiter, "Iterate through queues"))) {
2821 ao2_lock(q);
2822
2823 miter = ao2_iterator_init(q->members, 0);
2824 for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
2825 if (!strcmp(m->state_exten, exten) &&
2827 /* context could be included in m->state_context. We need to check. */
2828 found = 1;
2829 update_status(q, m, device_state);
2830 }
2831 }
2832 ao2_iterator_destroy(&miter);
2833
2834 ao2_unlock(q);
2835 queue_t_unref(q, "Done with iterator");
2836 }
2837 ao2_iterator_destroy(&qiter);
2838
2839 if (found) {
2840 ast_debug(1, "Extension '%s@%s' changed to state '%d' (%s)\n", exten, context, device_state, ast_devstate2str(device_state));
2841 } else {
2842 ast_debug(3, "Extension '%s@%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n",
2843 exten, context, device_state, ast_devstate2str(device_state));
2844 }
2845
2846 return 0;
2847}
static int extensionstate2devicestate(int state)
Helper function which converts from extension state to device state values.
Definition: app_queue.c:2728
def info(msg)
@ AST_HINT_UPDATE_DEVICE
Definition: pbx.h:91

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_t_iterator_next, ao2_unlock, ast_debug, ast_devstate2str(), AST_HINT_UPDATE_DEVICE, voicemailpwcheck::context, context_included(), extensionstate2devicestate(), call_queue::found, sip_to_pjsip::info(), call_queue::members, queue_t_unref, queues, member::state_context, member::state_exten, and update_status().

Referenced by create_queue_member(), and destroy_queue_member_cb().

◆ extensionstate2devicestate()

static int extensionstate2devicestate ( int  state)
static

Helper function which converts from extension state to device state values.

Definition at line 2728 of file app_queue.c.

2729{
2730 switch (state) {
2733 break;
2736 break;
2737 case AST_EXTENSION_BUSY:
2739 break;
2742 break;
2745 break;
2748 break;
2751 break;
2754 break;
2757 default:
2759 break;
2760 }
2761
2762 return state;
2763}
enum cc_state state
Definition: ccss.c:393
@ AST_DEVICE_RINGINUSE
Definition: devicestate.h:60
@ AST_DEVICE_ONHOLD
Definition: devicestate.h:61
@ AST_DEVICE_RINGING
Definition: devicestate.h:59
@ AST_DEVICE_INVALID
Definition: devicestate.h:57
@ AST_DEVICE_BUSY
Definition: devicestate.h:56
@ AST_DEVICE_UNAVAILABLE
Definition: devicestate.h:58
@ AST_EXTENSION_REMOVED
Definition: pbx.h:62
@ AST_EXTENSION_RINGING
Definition: pbx.h:68
@ AST_EXTENSION_NOT_INUSE
Definition: pbx.h:64
@ AST_EXTENSION_INUSE
Definition: pbx.h:65
@ AST_EXTENSION_UNAVAILABLE
Definition: pbx.h:67
@ AST_EXTENSION_ONHOLD
Definition: pbx.h:69
@ AST_EXTENSION_BUSY
Definition: pbx.h:66
@ AST_EXTENSION_DEACTIVATED
Definition: pbx.h:63

References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_UNAVAILABLE, AST_EXTENSION_BUSY, AST_EXTENSION_DEACTIVATED, AST_EXTENSION_INUSE, AST_EXTENSION_NOT_INUSE, AST_EXTENSION_ONHOLD, AST_EXTENSION_REMOVED, AST_EXTENSION_RINGING, AST_EXTENSION_UNAVAILABLE, and state.

Referenced by extension_state_cb(), and get_queue_member_status().

◆ find_best()

static struct callattempt * find_best ( struct callattempt outgoing)
static

find the entry with the best metric, or NULL

Definition at line 4885 of file app_queue.c.

4886{
4887 struct callattempt *best = NULL, *cur;
4888
4889 for (cur = outgoing; cur; cur = cur->q_next) {
4890 if (cur->stillgoing && /* Not already done */
4891 !cur->chan && /* Isn't already going */
4892 (!best || cur->metric < best->metric)) { /* We haven't found one yet, or it's better */
4893 best = cur;
4894 }
4895 }
4896
4897 return best;
4898}
We define a custom "local user" structure because we use it not only for keeping track of what is in ...
Definition: app_queue.c:1669

References callattempt::metric, and NULL.

Referenced by ring_one(), store_next_lin(), and store_next_rr().

◆ find_load_queue_rt_friendly()

static struct call_queue * find_load_queue_rt_friendly ( const char *  queuename)
static

note

Note
Load from realtime before taking the "queues" container lock, to avoid blocking all queue operations while waiting for the DB.

This will be two separate database transactions, so we might see queue parameters as they were before another process changed the queue and member list as it was after the change. Thus we might see an empty member list when a queue is deleted. In practise, this is unlikely to cause a problem.

Definition at line 3895 of file app_queue.c.

3896{
3897 struct ast_variable *queue_vars;
3898 struct ast_config *member_config = NULL;
3899 struct call_queue *q = NULL, tmpq = {
3900 .name = queuename,
3901 };
3902 int prev_weight = 0;
3903
3904 /* Find the queue in the in-core list first. */
3905 q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Look for queue in memory first");
3906
3907 if (!q || q->realtime) {
3908 /*! \note Load from realtime before taking the "queues" container lock, to avoid blocking all
3909 queue operations while waiting for the DB.
3910
3911 This will be two separate database transactions, so we might
3912 see queue parameters as they were before another process
3913 changed the queue and member list as it was after the change.
3914 Thus we might see an empty member list when a queue is
3915 deleted. In practise, this is unlikely to cause a problem. */
3916
3917 queue_vars = ast_load_realtime("queues", "name", queuename, SENTINEL);
3918 if (queue_vars) {
3919 member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, SENTINEL);
3920 if (!member_config) {
3921 ast_debug(1, "No queue_members defined in config extconfig.conf\n");
3922 member_config = ast_config_new();
3923 }
3924 }
3925 if (q) {
3926 prev_weight = q->weight ? 1 : 0;
3927 queue_t_unref(q, "Need to find realtime queue");
3928 }
3929
3930 q = find_queue_by_name_rt(queuename, queue_vars, member_config);
3931 ast_config_destroy(member_config);
3932 ast_variables_destroy(queue_vars);
3933
3934 /* update the use_weight value if the queue's has gained or lost a weight */
3935 if (q) {
3936 if (!q->weight && prev_weight) {
3938 }
3939 if (q->weight && !prev_weight) {
3941 }
3942 }
3943 /* Other cases will end up with the proper value for use_weight */
3944 } else {
3946 }
3947 return q;
3948}
static struct call_queue * find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
Reload a single queue via realtime.
Definition: app_queue.c:3751
static void update_realtime_members(struct call_queue *q)
Definition: app_queue.c:4000
#define ao2_t_find(container, arg, flags, tag)
Definition: astobj2.h:1734
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3274
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Definition: main/config.c:3507
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
Definition: lock.h:757
Structure for variables, used for configurations and for channel variables.

References ao2_t_find, ast_atomic_fetchadd_int(), ast_config_destroy(), ast_config_new(), ast_debug, ast_load_realtime(), ast_load_realtime_multientry(), ast_variables_destroy(), find_queue_by_name_rt(), NULL, OBJ_POINTER, queue_t_unref, queues, call_queue::realtime, SENTINEL, update_realtime_members(), use_weight, and call_queue::weight.

Referenced by __queues_show(), add_to_queue(), change_priority_caller_on_queue(), find_member_by_queuename_and_interface(), get_member_penalty(), join_queue(), load_realtime_queues(), queue_function_exists(), queue_function_mem_read(), queue_function_qac_dep(), queue_function_queuememberlist(), queue_function_var(), qupd_exec(), reload_queue_members(), request_withdraw_caller_from_queue(), and set_member_value().

◆ find_member_by_queuename_and_interface()

static struct member * find_member_by_queuename_and_interface ( const char *  queuename,
const char *  interface 
)
static

Find a member by looking up queuename and interface.

Returns
member or NULL if member not found.

Definition at line 11927 of file app_queue.c.

11928{
11929 struct member *mem = NULL;
11930 struct call_queue *q;
11931
11932 if ((q = find_load_queue_rt_friendly(queuename))) {
11933 ao2_lock(q);
11934 mem = ao2_find(q->members, interface, OBJ_KEY);
11935 ao2_unlock(q);
11936 queue_t_unref(q, "Expiring temporary reference.");
11937 }
11938 return mem;
11939}
#define OBJ_KEY
Definition: astobj2.h:1151

References ao2_find, ao2_lock, ao2_unlock, find_load_queue_rt_friendly(), call_queue::members, NULL, OBJ_KEY, and queue_t_unref.

Referenced by handle_queue_remove_member(), manager_remove_queue_member(), and rqm_exec().

◆ find_queue_by_name_rt()

static struct call_queue * find_queue_by_name_rt ( const char *  queuename,
struct ast_variable queue_vars,
struct ast_config member_config 
)
static

Reload a single queue via realtime.

Check for statically defined queue first, check if deleted RT queue, check for new RT queue, if queue vars are not defined init them with defaults. reload RT queue vars, set RT queue members dead and reload them, return finished queue.

Return values
thequeue,
NULLif it doesn't exist.
Note
Should be called with the "queues" container locked.
Note
Hmm, can't seem to distinguish a DB failure from a not found condition... So we might delete an in-core queue in case of DB failure.

Definition at line 3751 of file app_queue.c.

3752{
3753 struct ast_variable *v;
3754 struct call_queue *q, tmpq = {
3755 .name = queuename,
3756 };
3757 struct member *m;
3758 struct ao2_iterator mem_iter;
3759 char *category = NULL;
3760 const char *tmp_name;
3761 char *tmp;
3762 char tmpbuf[64]; /* Must be longer than the longest queue param name. */
3763
3764 /* Static queues override realtime. */
3765 if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Check if static queue exists"))) {
3766 ao2_lock(q);
3767 if (!q->realtime) {
3768 if (q->dead) {
3769 ao2_unlock(q);
3770 queue_t_unref(q, "Queue is dead; can't return it");
3771 return NULL;
3772 }
3773 ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
3774 ao2_unlock(q);
3775 return q;
3776 }
3777 } else if (!member_config) {
3778 /* Not found in the list, and it's not realtime ... */
3779 return NULL;
3780 }
3781 /* Check if queue is defined in realtime. */
3782 if (!queue_vars) {
3783 /* Delete queue from in-core list if it has been deleted in realtime. */
3784 if (q) {
3785 /*! \note Hmm, can't seem to distinguish a DB failure from a not
3786 found condition... So we might delete an in-core queue
3787 in case of DB failure. */
3788 ast_debug(1, "Queue %s not found in realtime.\n", queuename);
3789
3790 q->dead = 1;
3791 /* Delete if unused (else will be deleted when last caller leaves). */
3792 queues_t_unlink(queues, q, "Unused; removing from container");
3793 ao2_unlock(q);
3794 queue_t_unref(q, "Queue is dead; can't return it");
3795 }
3796 return NULL;
3797 }
3798
3799 /* Create a new queue if an in-core entry does not exist yet. */
3800 if (!q) {
3801 struct ast_variable *tmpvar = NULL;
3802 if (!(q = alloc_queue(queuename))) {
3803 return NULL;
3804 }
3805 ao2_lock(q);
3806 clear_queue(q);
3807 q->realtime = 1;
3808 /*Before we initialize the queue, we need to set the strategy, so that linear strategy
3809 * will allocate the members properly
3810 */
3811 for (tmpvar = queue_vars; tmpvar; tmpvar = tmpvar->next) {
3812 if (!strcasecmp(tmpvar->name, "strategy")) {
3813 q->strategy = strat2int(tmpvar->value);
3814 if (q->strategy < 0) {
3815 ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
3816 tmpvar->value, q->name);
3818 }
3819 break;
3820 }
3821 }
3822 /* We traversed all variables and didn't find a strategy */
3823 if (!tmpvar) {
3825 }
3826 queues_t_link(queues, q, "Add queue to container");
3827 }
3828 init_queue(q); /* Ensure defaults for all parameters not set explicitly. */
3829
3830 memset(tmpbuf, 0, sizeof(tmpbuf));
3831 for (v = queue_vars; v; v = v->next) {
3832 /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
3833 if (strchr(v->name, '_')) {
3834 ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
3835 tmp_name = tmpbuf;
3836 tmp = tmpbuf;
3837 while ((tmp = strchr(tmp, '_'))) {
3838 *tmp++ = '-';
3839 }
3840 } else {
3841 tmp_name = v->name;
3842 }
3843
3844 /* NULL values don't get returned from realtime; blank values should
3845 * still get set. If someone doesn't want a value to be set, they
3846 * should set the realtime column to NULL, not blank. */
3847 queue_set_param(q, tmp_name, v->value, -1, 0);
3848 }
3849
3850 /* Temporarily set realtime members dead so we can detect deleted ones. */
3851 mem_iter = ao2_iterator_init(q->members, 0);
3852 while ((m = ao2_iterator_next(&mem_iter))) {
3853 if (m->realtime) {
3854 m->dead = 1;
3855 }
3856 ao2_ref(m, -1);
3857 }
3858 ao2_iterator_destroy(&mem_iter);
3859
3860 while ((category = ast_category_browse(member_config, category))) {
3861 rt_handle_member_record(q, category, member_config);
3862 }
3863
3864 /* Delete all realtime members that have been deleted in DB. */
3865 mem_iter = ao2_iterator_init(q->members, 0);
3866 while ((m = ao2_iterator_next(&mem_iter))) {
3867 if (m->dead) {
3869 ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
3870 } else {
3871 ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
3872 }
3874 }
3875 ao2_ref(m, -1);
3876 }
3877 ao2_iterator_destroy(&mem_iter);
3878
3879 ao2_unlock(q);
3880
3881 return q;
3882}
static void member_remove_from_queue(struct call_queue *queue, struct member *mem)
Definition: app_queue.c:3562
static void rt_handle_member_record(struct call_queue *q, char *category, struct ast_config *member_config)
Find rt member record to update otherwise create one.
Definition: app_queue.c:3578
#define queues_t_unlink(c, q, tag)
Definition: app_queue.c:2060
#define queues_t_link(c, q, tag)
Definition: app_queue.c:2059
static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
Configure a queue parameter.
Definition: app_queue.c:3332
static void init_queue(struct call_queue *q)
Initialize Queue default values.
Definition: app_queue.c:2949
static struct call_queue * alloc_queue(const char *queuename)
Definition: app_queue.c:3727
static int strat2int(const char *strategy)
Definition: app_queue.c:1935
struct ast_variable * next
unsigned int dead
Definition: app_queue.c:1832
unsigned int dead
Definition: app_queue.c:1748
int realtime
Definition: app_queue.c:1736

References alloc_queue(), ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_t_find, ao2_unlock, ast_category_browse(), ast_copy_string(), ast_debug, ast_log, ast_queue_log(), ast_strlen_zero(), clear_queue(), member::dead, call_queue::dead, init_queue(), member::interface, log_membername_as_agent, LOG_WARNING, member_remove_from_queue(), member::membername, call_queue::members, call_queue::name, ast_variable::name, ast_variable::next, NULL, OBJ_POINTER, queue_set_param(), QUEUE_STRATEGY_RINGALL, queue_t_unref, queues, queues_t_link, queues_t_unlink, member::realtime, call_queue::realtime, rt_handle_member_record(), strat2int(), call_queue::strategy, tmp(), and ast_variable::value.

Referenced by find_load_queue_rt_friendly().

◆ free_members()

static void free_members ( struct call_queue q,
int  all 
)
static

Iterate through queue's member list and delete them.

Definition at line 3696 of file app_queue.c.

3697{
3698 /* Free non-dynamic members */
3699 struct member *cur;
3700 struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
3701
3702 while ((cur = ao2_iterator_next(&mem_iter))) {
3703 if (all || !cur->dynamic) {
3705 }
3706 ao2_ref(cur, -1);
3707 }
3708 ao2_iterator_destroy(&mem_iter);
3709}

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, member::dynamic, member_remove_from_queue(), and call_queue::members.

Referenced by destroy_queue().

◆ get_interface_helper()

static struct member * get_interface_helper ( struct call_queue q,
const char *  interface 
)
static

Definition at line 8987 of file app_queue.c.

8988{
8989 struct member *m;
8990
8992 ast_log(LOG_ERROR, "QUEUE_MEMBER: Missing required interface argument.\n");
8993 return NULL;
8994 }
8995
8997 if (!m) {
8998 ast_log(LOG_ERROR, "Queue member interface '%s' not in queue '%s'.\n",
8999 interface, q->name);
9000 }
9001 return m;
9002}

References ast_log, ast_strlen_zero(), member::interface, interface_exists(), LOG_ERROR, call_queue::name, and NULL.

Referenced by queue_function_mem_read().

◆ get_member_penalty()

static int get_member_penalty ( char *  queuename,
char *  interface 
)
static

Gets members penalty.

Returns
Return the members penalty or RESULT_FAILURE on error.

Definition at line 8069 of file app_queue.c.

8070{
8071 int foundqueue = 0, penalty;
8072 struct call_queue *q;
8073 struct member *mem;
8074
8075 if ((q = find_load_queue_rt_friendly(queuename))) {
8076 foundqueue = 1;
8077 ao2_lock(q);
8078 if ((mem = interface_exists(q, interface))) {
8079 penalty = mem->penalty;
8080 ao2_ref(mem, -1);
8081 ao2_unlock(q);
8082 queue_t_unref(q, "Search complete");
8083 return penalty;
8084 }
8085 ao2_unlock(q);
8086 queue_t_unref(q, "Search complete");
8087 }
8088
8089 /* some useful debugging */
8090 if (foundqueue) {
8091 ast_log (LOG_ERROR, "Invalid queuename\n");
8092 } else {
8093 ast_log (LOG_ERROR, "Invalid interface\n");
8094 }
8095
8096 return RESULT_FAILURE;
8097}
#define RESULT_FAILURE
Definition: cli.h:42

References ao2_lock, ao2_ref, ao2_unlock, ast_log, find_load_queue_rt_friendly(), member::interface, interface_exists(), LOG_ERROR, member::penalty, queue_t_unref, and RESULT_FAILURE.

Referenced by queue_function_memberpenalty_read().

◆ get_member_status()

static int get_member_status ( struct call_queue q,
int  max_penalty,
int  min_penalty,
int  raise_penalty,
enum empty_conditions  conditions,
int  devstate 
)
static

Check if members are available.

This function checks to see if members are available to be called. If any member is available, the function immediately returns 0. If no members are available, then -1 is returned.

Definition at line 2422 of file app_queue.c.

2423{
2424 struct member *member;
2425 struct ao2_iterator mem_iter;
2426
2427 ao2_lock(q);
2428 mem_iter = ao2_iterator_init(q->members, 0);
2429 for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
2430 int penalty = member->penalty;
2431 if (raise_penalty != INT_MAX && penalty < raise_penalty) {
2432 ast_debug(4, "%s is having his penalty raised up from %d to %d\n", member->membername, penalty, raise_penalty);
2433 penalty = raise_penalty;
2434 }
2435 if ((max_penalty != INT_MAX && penalty > max_penalty) || (min_penalty != INT_MAX && penalty < min_penalty)) {
2436 if (conditions & QUEUE_EMPTY_PENALTY) {
2437 ast_debug(4, "%s is unavailable because his penalty is not between %d and %d\n", member->membername, min_penalty, max_penalty);
2438 continue;
2439 }
2440 }
2441
2442 switch (devstate ? ast_device_state(member->state_interface) : member->status) {
2443 case AST_DEVICE_INVALID:
2444 if (conditions & QUEUE_EMPTY_INVALID) {
2445 ast_debug(4, "%s is unavailable because his device state is 'invalid'\n", member->membername);
2446 break;
2447 }
2448 goto default_case;
2450 if (conditions & QUEUE_EMPTY_UNAVAILABLE) {
2451 ast_debug(4, "%s is unavailable because his device state is 'unavailable'\n", member->membername);
2452 break;
2453 }
2454 goto default_case;
2455 case AST_DEVICE_INUSE:
2456 if (conditions & QUEUE_EMPTY_INUSE) {
2457 ast_debug(4, "%s is unavailable because his device state is 'inuse'\n", member->membername);
2458 break;
2459 }
2460 goto default_case;
2461 case AST_DEVICE_RINGING:
2462 if (conditions & QUEUE_EMPTY_RINGING) {
2463 ast_debug(4, "%s is unavailable because his device state is 'ringing'\n", member->membername);
2464 break;
2465 }
2466 goto default_case;
2467 case AST_DEVICE_UNKNOWN:
2468 if (conditions & QUEUE_EMPTY_UNKNOWN) {
2469 ast_debug(4, "%s is unavailable because his device state is 'unknown'\n", member->membername);
2470 break;
2471 }
2472 /* Fall-through */
2473 default:
2474 default_case:
2475 if (member->paused && (conditions & QUEUE_EMPTY_PAUSED)) {
2476 ast_debug(4, "%s is unavailable because he is paused'\n", member->membername);
2477 break;
2478 } else if ((conditions & QUEUE_EMPTY_WRAPUP)
2479 && member->lastcall
2480 && get_wrapuptime(q, member)
2481 && (time(NULL) - get_wrapuptime(q, member) < member->lastcall)) {
2482 ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n",
2483 member->membername, (int) (time(NULL) - member->lastcall), get_wrapuptime(q, member));
2484 break;
2485 } else {
2486 ao2_ref(member, -1);
2487 ao2_iterator_destroy(&mem_iter);
2488 ao2_unlock(q);
2489 ast_debug(4, "%s is available.\n", member->membername);
2490 return 0;
2491 }
2492 break;
2493 }
2494 }
2495 ao2_iterator_destroy(&mem_iter);
2496 ao2_unlock(q);
2497
2498 if (!devstate && (conditions & QUEUE_EMPTY_RINGING)) {
2499 /* member state still may be RINGING due to lag in event message - check again with device state */
2500 return get_member_status(q, max_penalty, min_penalty, raise_penalty, conditions, 1);
2501 }
2502 return -1;
2503}
static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, int raise_penalty, enum empty_conditions conditions, int devstate)
Check if members are available.
Definition: app_queue.c:2422
ast_device_state
Device States.
Definition: devicestate.h:52
@ AST_DEVICE_UNKNOWN
Definition: devicestate.h:53

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_unlock, ast_debug, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_RINGING, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, get_member_status(), get_wrapuptime(), member::lastcall, member::membername, call_queue::members, NULL, member::paused, member::penalty, QUEUE_EMPTY_INUSE, QUEUE_EMPTY_INVALID, QUEUE_EMPTY_PAUSED, QUEUE_EMPTY_PENALTY, QUEUE_EMPTY_RINGING, QUEUE_EMPTY_UNAVAILABLE, QUEUE_EMPTY_UNKNOWN, QUEUE_EMPTY_WRAPUP, member::state_interface, and member::status.

Referenced by get_member_status(), join_queue(), queue_exec(), and wait_our_turn().

◆ get_queue_member_status()

static int get_queue_member_status ( struct member cur)
static

Return the current state of a member.

Definition at line 2850 of file app_queue.c.

2851{
2852 return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten));
2853}
int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
Uses hint and devicestate callback to get the state of an extension.
Definition: pbx.c:3170

References ast_extension_state(), ast_strlen_zero(), extensionstate2devicestate(), NULL, member::state_context, member::state_exten, and member::state_interface.

Referenced by can_ring_entry(), create_queue_member(), and kill_dead_members().

◆ get_wrapuptime()

static int get_wrapuptime ( struct call_queue q,
struct member member 
)
static

Return wrapuptime.

This function checks if wrapuptime in member is set and return this value. Otherwise return value the wrapuptime in the queue configuration

Returns
integer value

Definition at line 1991 of file app_queue.c.

1992{
1993 if (member->wrapuptime) {
1994 return member->wrapuptime;
1995 }
1996 return q->wrapuptime;
1997}
int wrapuptime
Definition: app_queue.c:1870

References member::wrapuptime, and call_queue::wrapuptime.

Referenced by can_ring_entry(), get_member_status(), is_member_available(), and queue_function_mem_read().

◆ handle_attended_transfer()

static void handle_attended_transfer ( void *  userdata,
struct stasis_subscription sub,
struct stasis_message msg 
)
static

Handle an attended transfer event.

This event is important in order to be able to log the end of the call to the queue log and to stasis.

Parameters
userdataData pertaining to the particular call in the queue.
subThe stasis subscription on which the message occurred.
msgThe stasis message for the attended transfer event.

Definition at line 6468 of file app_queue.c.

6470{
6471 struct queue_stasis_data *queue_data = userdata;
6472 struct ast_attended_transfer_message *atxfer_msg = stasis_message_data(msg);
6473 RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
6474 RAII_VAR(struct ast_channel_snapshot *, member_snapshot, NULL, ao2_cleanup);
6475
6476 if (atxfer_msg->result != AST_BRIDGE_TRANSFER_SUCCESS ||
6478 return;
6479 }
6480
6481 ao2_lock(queue_data);
6482
6483 if (queue_data->dying) {
6484 ao2_unlock(queue_data);
6485 return;
6486 }
6487
6488 if (ast_strlen_zero(queue_data->bridge_uniqueid)) {
6489 ao2_unlock(queue_data);
6490 return;
6491 }
6492
6493 if ((!atxfer_msg->to_transferee.bridge_snapshot || strcmp(queue_data->bridge_uniqueid,
6494 atxfer_msg->to_transferee.bridge_snapshot->uniqueid)) &&
6495 (!atxfer_msg->to_transfer_target.bridge_snapshot || strcmp(queue_data->bridge_uniqueid,
6497 ao2_unlock(queue_data);
6498 return;
6499 }
6500
6501 caller_snapshot = ast_channel_snapshot_get_latest(queue_data->caller_uniqueid);
6502 member_snapshot = ast_channel_snapshot_get_latest(queue_data->member_uniqueid);
6503
6504 ao2_unlock(queue_data);
6505
6506 ast_debug(3, "Detected attended transfer in queue %s\n", queue_data->queue->name);
6507 log_attended_transfer(queue_data, atxfer_msg);
6508
6509 send_agent_complete(queue_data->queue->name, caller_snapshot, member_snapshot, queue_data->member,
6510 queue_data->holdstart, queue_data->starttime, TRANSFER);
6511 update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl,
6512 queue_data->starttime);
6513 remove_stasis_subscriptions(queue_data);
6514}
static void send_agent_complete(const char *queuename, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer, const struct member *member, time_t holdstart, time_t callstart, enum agent_complete_reason rsn)
Send out AMI message with member call completion status information.
Definition: app_queue.c:6129
static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl, time_t starttime)
update the queue status
Definition: app_queue.c:5972
static void remove_stasis_subscriptions(struct queue_stasis_data *queue_data)
Definition: app_queue.c:6276
static void log_attended_transfer(struct queue_stasis_data *queue_data, struct ast_attended_transfer_message *atxfer_msg)
Definition: app_queue.c:6330
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
@ AST_BRIDGE_TRANSFER_SUCCESS
Definition: bridge.h:1100
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object,...
@ AST_ATTENDED_TRANSFER_DEST_THREEWAY
Message representing attended transfer.
enum ast_attended_transfer_dest_type dest_type
struct ast_bridge_channel_snapshot_pair to_transfer_target
enum ast_transfer_result result
struct ast_bridge_channel_snapshot_pair to_transferee
struct ast_bridge_snapshot * bridge_snapshot
const ast_string_field uniqueid
Definition: bridge.h:328
Structure representing a snapshot of channel state.
User data for stasis subscriptions used for queue calls.
Definition: app_queue.c:6222
const ast_string_field caller_uniqueid
Definition: app_queue.c:6230
const ast_string_field member_uniqueid
Definition: app_queue.c:6230
struct call_queue * queue
Definition: app_queue.c:6232
const ast_string_field bridge_uniqueid
Definition: app_queue.c:6230
struct member * member
Definition: app_queue.c:6234
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941

References ao2_cleanup, ao2_lock, ao2_unlock, AST_ATTENDED_TRANSFER_DEST_THREEWAY, AST_BRIDGE_TRANSFER_SUCCESS, ast_channel_snapshot_get_latest(), ast_debug, ast_strlen_zero(), ast_bridge_channel_snapshot_pair::bridge_snapshot, queue_stasis_data::bridge_uniqueid, queue_stasis_data::callcompletedinsl, queue_stasis_data::caller_uniqueid, ast_attended_transfer_message::dest_type, queue_stasis_data::dying, queue_stasis_data::holdstart, log_attended_transfer(), queue_stasis_data::member, queue_stasis_data::member_uniqueid, call_queue::name, NULL, queue_stasis_data::queue, RAII_VAR, remove_stasis_subscriptions(), ast_attended_transfer_message::result, send_agent_complete(), queue_stasis_data::starttime, stasis_message_data(), ast_attended_transfer_message::to_transfer_target, ast_attended_transfer_message::to_transferee, TRANSFER, ast_bridge_snapshot::uniqueid, and update_queue().

Referenced by setup_stasis_subs().

◆ handle_blind_transfer()

static void handle_blind_transfer ( void *  userdata,
struct stasis_subscription sub,
struct stasis_message msg 
)
static

Handle a blind transfer event.

This event is important in order to be able to log the end of the call to the queue log and to stasis.

Parameters
userdataData pertaining to the particular call in the queue.
subThe stasis subscription on which the message occurred.
msgThe stasis message for the blind transfer event

Definition at line 6409 of file app_queue.c.

6411{
6412 struct queue_stasis_data *queue_data = userdata;
6413 struct ast_blind_transfer_message *transfer_msg = stasis_message_data(msg);
6414 const char *exten;
6415 const char *context;
6416 RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
6417 RAII_VAR(struct ast_channel_snapshot *, member_snapshot, NULL, ao2_cleanup);
6418
6419 if (transfer_msg->result != AST_BRIDGE_TRANSFER_SUCCESS) {
6420 return;
6421 }
6422
6423 ao2_lock(queue_data);
6424
6425 if (queue_data->dying) {
6426 ao2_unlock(queue_data);
6427 return;
6428 }
6429
6430 if (ast_strlen_zero(queue_data->bridge_uniqueid) ||
6431 strcmp(queue_data->bridge_uniqueid, transfer_msg->bridge->uniqueid)) {
6432 ao2_unlock(queue_data);
6433 return;
6434 }
6435
6436 caller_snapshot = ast_channel_snapshot_get_latest(queue_data->caller_uniqueid);
6437 member_snapshot = ast_channel_snapshot_get_latest(queue_data->member_uniqueid);
6438
6439 ao2_unlock(queue_data);
6440
6441 exten = transfer_msg->exten;
6442 context = transfer_msg->context;
6443
6444 ast_debug(3, "Detected blind transfer in queue %s\n", queue_data->queue->name);
6445 ast_queue_log(queue_data->queue->name, queue_data->caller_uniqueid, queue_data->member->membername,
6446 "BLINDTRANSFER", "%s|%s|%ld|%ld|%d",
6447 exten, context,
6448 (long) (queue_data->starttime - queue_data->holdstart),
6449 (long) (time(NULL) - queue_data->starttime), queue_data->caller_pos);
6450
6451 send_agent_complete(queue_data->queue->name, caller_snapshot, member_snapshot, queue_data->member,
6452 queue_data->holdstart, queue_data->starttime, TRANSFER);
6453 update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl,
6454 queue_data->starttime);
6455 remove_stasis_subscriptions(queue_data);
6456}
Message published during a blind transfer.
char exten[AST_MAX_EXTENSION]
struct ast_bridge_snapshot * bridge
enum ast_transfer_result result
char context[AST_MAX_CONTEXT]

References ao2_cleanup, ao2_lock, ao2_unlock, AST_BRIDGE_TRANSFER_SUCCESS, ast_channel_snapshot_get_latest(), ast_debug, ast_queue_log(), ast_strlen_zero(), ast_blind_transfer_message::bridge, queue_stasis_data::bridge_uniqueid, queue_stasis_data::callcompletedinsl, queue_stasis_data::caller_pos, queue_stasis_data::caller_uniqueid, voicemailpwcheck::context, ast_blind_transfer_message::context, queue_stasis_data::dying, ast_blind_transfer_message::exten, queue_stasis_data::holdstart, queue_stasis_data::member, queue_stasis_data::member_uniqueid, member::membername, call_queue::name, NULL, queue_stasis_data::queue, RAII_VAR, remove_stasis_subscriptions(), ast_blind_transfer_message::result, send_agent_complete(), queue_stasis_data::starttime, stasis_message_data(), TRANSFER, ast_bridge_snapshot::uniqueid, and update_queue().

Referenced by setup_stasis_subs().

◆ handle_bridge_enter()

static void handle_bridge_enter ( void *  userdata,
struct stasis_subscription sub,
struct stasis_message msg 
)
static

Definition at line 6376 of file app_queue.c.

6378{
6379 struct queue_stasis_data *queue_data = userdata;
6380 struct ast_bridge_blob *enter_blob = stasis_message_data(msg);
6381 SCOPED_AO2LOCK(lock, queue_data);
6382
6383 if (queue_data->dying) {
6384 return;
6385 }
6386
6387 if (!ast_strlen_zero(queue_data->bridge_uniqueid)) {
6388 return;
6389 }
6390
6391 if (!strcmp(enter_blob->channel->base->uniqueid, queue_data->caller_uniqueid)) {
6392 ast_string_field_set(queue_data, bridge_uniqueid,
6393 enter_blob->bridge->uniqueid);
6394 ast_debug(3, "Detected entry of caller channel %s into bridge %s\n",
6395 enter_blob->channel->base->name, queue_data->bridge_uniqueid);
6396 }
6397}
ast_mutex_t lock
Definition: app_sla.c:331
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
Definition: lock.h:604
Blob of data associated with a bridge.
struct ast_bridge_snapshot * bridge
struct ast_channel_snapshot * channel
const ast_string_field uniqueid
const ast_string_field name
struct ast_channel_snapshot_base * base

References ast_debug, ast_string_field_set, ast_strlen_zero(), ast_channel_snapshot::base, ast_bridge_blob::bridge, queue_stasis_data::bridge_uniqueid, queue_stasis_data::caller_uniqueid, ast_bridge_blob::channel, queue_stasis_data::dying, lock, ast_channel_snapshot_base::name, SCOPED_AO2LOCK, stasis_message_data(), ast_bridge_snapshot::uniqueid, and ast_channel_snapshot_base::uniqueid.

Referenced by setup_stasis_subs().

◆ handle_hangup()

static void handle_hangup ( void *  userdata,
struct stasis_subscription sub,
struct stasis_message msg 
)
static

Definition at line 6657 of file app_queue.c.

6659{
6660 struct queue_stasis_data *queue_data = userdata;
6661 struct ast_channel_blob *channel_blob = stasis_message_data(msg);
6662 RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
6663 RAII_VAR(struct ast_channel_snapshot *, member_snapshot, NULL, ao2_cleanup);
6664 RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
6665 enum agent_complete_reason reason;
6666
6667 ao2_lock(queue_data);
6668
6669 if (queue_data->dying) {
6670 ao2_unlock(queue_data);
6671 return;
6672 }
6673
6674 if (!strcmp(channel_blob->snapshot->base->uniqueid, queue_data->caller_uniqueid)) {
6675 reason = CALLER;
6676 } else if (!strcmp(channel_blob->snapshot->base->uniqueid, queue_data->member_uniqueid)) {
6677 reason = AGENT;
6678 } else {
6679 ao2_unlock(queue_data);
6680 return;
6681 }
6682
6683 chan = ast_channel_get_by_name(channel_blob->snapshot->base->name);
6684 if (chan && (ast_channel_has_role(chan, AST_TRANSFERER_ROLE_NAME) ||
6685 !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "ATTENDEDTRANSFER")) ||
6686 !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "BLINDTRANSFER")))) {
6687 /* Channel that is hanging up is doing it as part of a transfer.
6688 * We'll get a transfer event later
6689 */
6690 ao2_unlock(queue_data);
6691 return;
6692 }
6693
6694 caller_snapshot = ast_channel_snapshot_get_latest(queue_data->caller_uniqueid);
6695 member_snapshot = ast_channel_snapshot_get_latest(queue_data->member_uniqueid);
6696
6697 ao2_unlock(queue_data);
6698
6699 ast_debug(3, "Detected hangup of queue %s channel %s\n", reason == CALLER ? "caller" : "member",
6700 channel_blob->snapshot->base->name);
6701
6702 ast_queue_log(queue_data->queue->name, queue_data->caller_uniqueid, queue_data->member->membername,
6703 reason == CALLER ? "COMPLETECALLER" : "COMPLETEAGENT", "%ld|%ld|%d",
6704 (long) (queue_data->starttime - queue_data->holdstart),
6705 (long) (time(NULL) - queue_data->starttime), queue_data->caller_pos);
6706
6707 send_agent_complete(queue_data->queue->name, caller_snapshot, member_snapshot, queue_data->member,
6708 queue_data->holdstart, queue_data->starttime, reason);
6709 update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl,
6710 queue_data->starttime);
6711 remove_stasis_subscriptions(queue_data);
6712}
agent_complete_reason
Definition: app_queue.c:6122
#define AST_TRANSFERER_ROLE_NAME
Definition: bridge_basic.h:36
int ast_channel_has_role(struct ast_channel *channel, const char *role_name)
Check if a role exists on a channel.
Definition: bridge_roles.c:394
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1473
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Blob of data associated with a channel.
struct ast_channel_snapshot * snapshot

References AGENT, ao2_cleanup, ao2_lock, ao2_unlock, ast_channel_get_by_name(), ast_channel_has_role(), ast_channel_snapshot_get_latest(), ast_debug, ast_queue_log(), ast_strlen_zero(), AST_TRANSFERER_ROLE_NAME, ast_channel_snapshot::base, queue_stasis_data::callcompletedinsl, CALLER, queue_stasis_data::caller_pos, queue_stasis_data::caller_uniqueid, queue_stasis_data::dying, queue_stasis_data::holdstart, queue_stasis_data::member, queue_stasis_data::member_uniqueid, member::membername, call_queue::name, ast_channel_snapshot_base::name, NULL, pbx_builtin_getvar_helper(), queue_stasis_data::queue, RAII_VAR, remove_stasis_subscriptions(), send_agent_complete(), ast_channel_blob::snapshot, queue_stasis_data::starttime, stasis_message_data(), ast_channel_snapshot_base::uniqueid, and update_queue().

Referenced by setup_stasis_subs().

◆ handle_local_optimization_begin()

static void handle_local_optimization_begin ( void *  userdata,
struct stasis_subscription sub,
struct stasis_message msg 
)
static

Definition at line 6542 of file app_queue.c.

6544{
6545 struct queue_stasis_data *queue_data = userdata;
6546 struct ast_multi_channel_blob *optimization_blob = stasis_message_data(msg);
6547 struct ast_channel_snapshot *local_one = ast_multi_channel_blob_get_channel(optimization_blob, "1");
6548 struct ast_channel_snapshot *local_two = ast_multi_channel_blob_get_channel(optimization_blob, "2");
6549 struct ast_channel_snapshot *source = ast_multi_channel_blob_get_channel(optimization_blob, "source");
6550 struct local_optimization *optimization;
6551 unsigned int id;
6552 SCOPED_AO2LOCK(lock, queue_data);
6553
6554 if (queue_data->dying) {
6555 return;
6556 }
6557
6558 if (!strcmp(local_one->base->uniqueid, queue_data->member_uniqueid)) {
6559 optimization = &queue_data->member_optimize;
6560 } else if (!strcmp(local_two->base->uniqueid, queue_data->caller_uniqueid)) {
6561 optimization = &queue_data->caller_optimize;
6562 } else {
6563 return;
6564 }
6565
6566 /* We only allow move-swap optimizations, so there had BETTER be a source */
6567 ast_assert(source != NULL);
6568
6569 optimization->source_chan_uniqueid = ast_strdup(source->base->uniqueid);
6570 if (!optimization->source_chan_uniqueid) {
6571 ast_log(LOG_ERROR, "Unable to track local channel optimization for channel %s. Expect further errors\n", local_one->base->name);
6572 return;
6573 }
6575
6576 optimization->id = id;
6577 optimization->in_progress = 1;
6578}
enum queue_result id
Definition: app_queue.c:1638
struct ast_channel_snapshot * ast_multi_channel_blob_get_channel(struct ast_multi_channel_blob *obj, const char *role)
Retrieve a channel snapshot associated with a specific role from a ast_multi_channel_blob.
struct ast_json * ast_multi_channel_blob_get_json(struct ast_multi_channel_blob *obj)
Retrieve the JSON blob from a ast_multi_channel_blob. Returned ast_json is still owned by obj.
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
Definition: json.c:332
A multi channel blob data structure for multi_channel_blob stasis messages.
Structure representing relevant data during a local channel optimization.
Definition: app_queue.c:6198
const char * source_chan_uniqueid
Definition: app_queue.c:6200
unsigned int id
Definition: app_queue.c:6204
struct local_optimization member_optimize
Definition: app_queue.c:6252
struct local_optimization caller_optimize
Definition: app_queue.c:6250
#define ast_assert(a)
Definition: utils.h:739

References ast_assert, ast_json_integer_get(), ast_json_object_get(), ast_log, ast_multi_channel_blob_get_channel(), ast_multi_channel_blob_get_json(), ast_strdup, ast_channel_snapshot::base, queue_stasis_data::caller_optimize, queue_stasis_data::caller_uniqueid, queue_stasis_data::dying, id, local_optimization::id, local_optimization::in_progress, lock, LOG_ERROR, queue_stasis_data::member_optimize, queue_stasis_data::member_uniqueid, ast_channel_snapshot_base::name, NULL, SCOPED_AO2LOCK, local_optimization::source_chan_uniqueid, stasis_message_data(), and ast_channel_snapshot_base::uniqueid.

Referenced by setup_stasis_subs().

◆ handle_local_optimization_end()

static void handle_local_optimization_end ( void *  userdata,
struct stasis_subscription sub,
struct stasis_message msg 
)
static

Definition at line 6593 of file app_queue.c.

6595{
6596 struct queue_stasis_data *queue_data = userdata;
6597 struct ast_multi_channel_blob *optimization_blob = stasis_message_data(msg);
6598 struct ast_channel_snapshot *local_one = ast_multi_channel_blob_get_channel(optimization_blob, "1");
6599 struct ast_channel_snapshot *local_two = ast_multi_channel_blob_get_channel(optimization_blob, "2");
6600 struct local_optimization *optimization;
6601 int is_caller;
6602 unsigned int id;
6603 SCOPED_AO2LOCK(lock, queue_data);
6604
6605 if (queue_data->dying) {
6606 return;
6607 }
6608
6609 if (!strcmp(local_one->base->uniqueid, queue_data->member_uniqueid)) {
6610 optimization = &queue_data->member_optimize;
6611 is_caller = 0;
6612 } else if (!strcmp(local_two->base->uniqueid, queue_data->caller_uniqueid)) {
6613 optimization = &queue_data->caller_optimize;
6614 is_caller = 1;
6615 } else {
6616 return;
6617 }
6618
6620
6621 if (!optimization->in_progress) {
6622 ast_log(LOG_WARNING, "Told of a local optimization end when we had no previous begin\n");
6623 return;
6624 }
6625
6626 if (id != optimization->id) {
6627 ast_log(LOG_WARNING, "Local optimization end event ID does not match begin (%u != %u)\n",
6628 id, optimization->id);
6629 return;
6630 }
6631
6632 if (is_caller) {
6633 ast_debug(3, "Local optimization: Changing queue caller uniqueid from %s to %s\n",
6634 queue_data->caller_uniqueid, optimization->source_chan_uniqueid);
6635 ast_string_field_set(queue_data, caller_uniqueid, optimization->source_chan_uniqueid);
6636 } else {
6637 ast_debug(3, "Local optimization: Changing queue member uniqueid from %s to %s\n",
6638 queue_data->member_uniqueid, optimization->source_chan_uniqueid);
6639 ast_string_field_set(queue_data, member_uniqueid, optimization->source_chan_uniqueid);
6640 }
6641
6642 optimization->in_progress = 0;
6643}

References ast_debug, ast_json_integer_get(), ast_json_object_get(), ast_log, ast_multi_channel_blob_get_channel(), ast_multi_channel_blob_get_json(), ast_string_field_set, ast_channel_snapshot::base, queue_stasis_data::caller_optimize, queue_stasis_data::caller_uniqueid, queue_stasis_data::dying, id, local_optimization::id, local_optimization::in_progress, lock, LOG_WARNING, queue_stasis_data::member_optimize, queue_stasis_data::member_uniqueid, SCOPED_AO2LOCK, local_optimization::source_chan_uniqueid, stasis_message_data(), and ast_channel_snapshot_base::uniqueid.

Referenced by setup_stasis_subs().

◆ handle_masquerade()

static void handle_masquerade ( void *  userdata,
struct stasis_subscription sub,
struct stasis_message msg 
)
static

Definition at line 6714 of file app_queue.c.

6716{
6717 struct queue_stasis_data *queue_data = userdata;
6718 struct ast_channel_blob *channel_blob = stasis_message_data(msg);
6719 const char *new_channel_id;
6720
6721 new_channel_id = ast_json_string_get(ast_json_object_get(channel_blob->blob, "newchanneluniqueid"));
6722
6723 ao2_lock(queue_data);
6724
6725 if (queue_data->dying) {
6726 ao2_unlock(queue_data);
6727 return;
6728 }
6729
6730 if (!strcmp(channel_blob->snapshot->base->uniqueid, queue_data->caller_uniqueid)) {
6731 ast_debug(1, "Replacing caller channel %s with %s due to masquerade\n", queue_data->caller_uniqueid, new_channel_id);
6732 ast_string_field_set(queue_data, caller_uniqueid, new_channel_id);
6733 } else if (!strcmp(channel_blob->snapshot->base->uniqueid, queue_data->member_uniqueid)) {
6734 ast_debug(1, "Replacing member channel %s with %s due to masquerade\n", queue_data->member_uniqueid, new_channel_id);
6735 ast_string_field_set(queue_data, member_uniqueid, new_channel_id);
6736 }
6737
6738 ao2_unlock(queue_data);
6739}
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
struct ast_json * blob

References ao2_lock, ao2_unlock, ast_debug, ast_json_object_get(), ast_json_string_get(), ast_string_field_set, ast_channel_snapshot::base, ast_channel_blob::blob, queue_stasis_data::caller_uniqueid, queue_stasis_data::dying, queue_stasis_data::member_uniqueid, ast_channel_blob::snapshot, stasis_message_data(), and ast_channel_snapshot_base::uniqueid.

Referenced by setup_stasis_subs().

◆ handle_queue_add_member()

static char * handle_queue_add_member ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 10990 of file app_queue.c.

10991{
10992 const char *queuename, *interface, *membername = NULL, *state_interface = NULL;
10993 int penalty;
10994
10995 switch ( cmd ) {
10996 case CLI_INIT:
10997 e->command = "queue add member";
10998 e->usage =
10999 "Usage: queue add member <dial string> to <queue> [penalty <penalty> [as <membername> [state_interface <interface>]]]\n"
11000 " Add a dial string (Such as a channel,e.g. SIP/6001) to a queue with optionally: a penalty, membername and a state_interface\n";
11001 return NULL;
11002 case CLI_GENERATE:
11003 return complete_queue_add_member(a->line, a->word, a->pos, a->n);
11004 }
11005
11006 if ((a->argc != 6) && (a->argc != 8) && (a->argc != 10) && (a->argc != 12)) {
11007 return CLI_SHOWUSAGE;
11008 } else if (strcmp(a->argv[4], "to")) {
11009 return CLI_SHOWUSAGE;
11010 } else if ((a->argc >= 8) && strcmp(a->argv[6], "penalty")) {
11011 return CLI_SHOWUSAGE;
11012 } else if ((a->argc >= 10) && strcmp(a->argv[8], "as")) {
11013 return CLI_SHOWUSAGE;
11014 } else if ((a->argc == 12) && strcmp(a->argv[10], "state_interface")) {
11015 return CLI_SHOWUSAGE;
11016 }
11017
11018 queuename = a->argv[5];
11019 interface = a->argv[3];
11020 if (a->argc >= 8) {
11021 if (sscanf(a->argv[7], "%30d", &penalty) == 1) {
11022 if (penalty < 0) {
11023 ast_cli(a->fd, "Penalty must be >= 0\n");
11024 penalty = 0;
11025 }
11026 } else {
11027 ast_cli(a->fd, "Penalty must be an integer >= 0\n");
11028 penalty = 0;
11029 }
11030 } else {
11031 penalty = 0;
11032 }
11033
11034 if (a->argc >= 10) {
11035 membername = a->argv[9];
11036 }
11037
11038 if (a->argc >= 12) {
11039 state_interface = a->argv[11];
11040 }
11041
11042 switch (add_to_queue(queuename, interface, membername, penalty, 0, queue_persistent_members, state_interface, NULL, 0)) {
11043 case RES_OKAY:
11044 if (ast_strlen_zero(membername) || !log_membername_as_agent) {
11045 ast_queue_log(queuename, "CLI", interface, "ADDMEMBER", "%s", "");
11046 } else {
11047 ast_queue_log(queuename, "CLI", membername, "ADDMEMBER", "%s", "");
11048 }
11049 ast_cli(a->fd, "Added interface '%s' to queue '%s'\n", interface, queuename);
11050 return CLI_SUCCESS;
11051 case RES_EXISTS:
11052 ast_cli(a->fd, "Unable to add interface '%s' to queue '%s': Already there\n", interface, queuename);
11053 return CLI_FAILURE;
11054 case RES_NOSUCHQUEUE:
11055 ast_cli(a->fd, "Unable to add interface to queue '%s': No such queue\n", queuename);
11056 return CLI_FAILURE;
11057 case RES_OUTOFMEMORY:
11058 ast_cli(a->fd, "Out of memory\n");
11059 return CLI_FAILURE;
11060 case RES_NOT_DYNAMIC:
11061 ast_cli(a->fd, "Member not dynamic\n");
11062 return CLI_FAILURE;
11063 default:
11064 return CLI_FAILURE;
11065 }
11066}
#define RES_NOT_DYNAMIC
Definition: app_queue.c:1569
static char * complete_queue_add_member(const char *line, const char *word, int pos, int state)
Definition: app_queue.c:10815
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
static struct test_val a

References a, add_to_queue(), ast_cli(), ast_queue_log(), ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_queue_add_member(), log_membername_as_agent, NULL, queue_persistent_members, RES_EXISTS, RES_NOSUCHQUEUE, RES_NOT_DYNAMIC, RES_OKAY, RES_OUTOFMEMORY, and ast_cli_entry::usage.

◆ handle_queue_change_priority_caller()

static char * handle_queue_change_priority_caller ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 11179 of file app_queue.c.

11180{
11181 const char *queuename, *caller;
11182 int priority, immediate = 0;
11183 char *res = CLI_FAILURE;
11184
11185 switch (cmd) {
11186 case CLI_INIT:
11187 e->command = "queue priority caller";
11188 e->usage =
11189 "Usage: queue priority caller <channel> on <queue> to <priority> [immediate]\n"
11190 " Change the priority of a channel on a queue, optionally applying the change in relation to existing callers.\n";
11191 return NULL;
11192 case CLI_GENERATE:
11193 return NULL;
11194 }
11195
11196 if (a->argc < 8) {
11197 return CLI_SHOWUSAGE;
11198 } else if (strcmp(a->argv[4], "on")) {
11199 return CLI_SHOWUSAGE;
11200 } else if (strcmp(a->argv[6], "to")) {
11201 return CLI_SHOWUSAGE;
11202 } else if (sscanf(a->argv[7], "%30d", &priority) != 1) {
11203 ast_log (LOG_ERROR, "<priority> parameter must be an integer.\n");
11204 return CLI_SHOWUSAGE;
11205 } else if (a->argc == 9) {
11206 if (strcmp(a->argv[8], "immediate")) {
11207 return CLI_SHOWUSAGE;
11208 }
11209 immediate = 1;
11210 }
11211
11212 caller = a->argv[3];
11213 queuename = a->argv[5];
11214
11215 switch (change_priority_caller_on_queue(queuename, caller, priority, immediate)) {
11216 case RES_OKAY:
11217 res = CLI_SUCCESS;
11218 break;
11219 case RES_NOSUCHQUEUE:
11220 ast_cli(a->fd, "Unable change priority caller %s on queue '%s': No such queue\n", caller, queuename);
11221 break;
11222 case RES_NOT_CALLER:
11223 ast_cli(a->fd, "Unable to change priority caller '%s' on queue '%s': Not there\n", caller, queuename);
11224
11225 break;
11226 }
11227
11228 return res;
11229}
static int change_priority_caller_on_queue(const char *queuename, const char *caller, int priority, int immediate)
Change priority caller into a queue.
Definition: app_queue.c:7646

References a, ast_cli(), ast_log, change_priority_caller_on_queue(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, LOG_ERROR, NULL, priority, RES_NOSUCHQUEUE, RES_NOT_CALLER, RES_OKAY, and ast_cli_entry::usage.

◆ handle_queue_pause_member()

static char * handle_queue_pause_member ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 11252 of file app_queue.c.

11253{
11254 const char *queuename, *interface, *reason;
11255 int paused;
11256
11257 switch (cmd) {
11258 case CLI_INIT:
11259 e->command = "queue {pause|unpause} member";
11260 e->usage =
11261 "Usage: queue {pause|unpause} member <member> [queue <queue> [reason <reason>]]\n"
11262 " Pause or unpause a queue member. Not specifying a particular queue\n"
11263 " will pause or unpause a member across all queues to which the member\n"
11264 " belongs.\n";
11265 return NULL;
11266 case CLI_GENERATE:
11267 return complete_queue_pause_member(a->line, a-> word, a->pos, a->n);
11268 }
11269
11270 if (a->argc < 4 || a->argc == 5 || a->argc == 7 || a->argc > 8) {
11271 return CLI_SHOWUSAGE;
11272 } else if (a->argc >= 5 && strcmp(a->argv[4], "queue")) {
11273 return CLI_SHOWUSAGE;
11274 } else if (a->argc == 8 && strcmp(a->argv[6], "reason")) {
11275 return CLI_SHOWUSAGE;
11276 }
11277
11278
11279 interface = a->argv[3];
11280 queuename = a->argc >= 6 ? a->argv[5] : NULL;
11281 reason = a->argc == 8 ? a->argv[7] : NULL;
11282 paused = !strcasecmp(a->argv[1], "pause");
11283
11284 if (set_member_paused(queuename, interface, reason, paused) == RESULT_SUCCESS) {
11285 ast_cli(a->fd, "%spaused interface '%s'", paused ? "" : "un", interface);
11286 if (!ast_strlen_zero(queuename)) {
11287 ast_cli(a->fd, " in queue '%s'", queuename);
11288 }
11289 if (!ast_strlen_zero(reason)) {
11290 ast_cli(a->fd, " for reason '%s'", reason);
11291 }
11292 ast_cli(a->fd, "\n");
11293 return CLI_SUCCESS;
11294 } else {
11295 ast_cli(a->fd, "Unable to %spause interface '%s'", paused ? "" : "un", interface);
11296 if (!ast_strlen_zero(queuename)) {
11297 ast_cli(a->fd, " in queue '%s'", queuename);
11298 }
11299 if (!ast_strlen_zero(reason)) {
11300 ast_cli(a->fd, " for re