Asterisk - The Open Source Telephony Project  18.5.0
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/monitor.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)
}
 
enum  { OPT_ARG_CALLEE_GO_ON = 0, OPT_ARG_PREDIAL_CALLEE, OPT_ARG_PREDIAL_CALLER, 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
}
 
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)
 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 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 ouput 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)
 
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)
 
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_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 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 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 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_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_caller_abandon_type,.to_ami=queue_caller_abandon_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (queue_member_status_type,.to_ami=queue_member_status_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_removed_type,.to_ami=queue_member_removed_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_ringinuse_type,.to_ami=queue_member_ringinuse_to_ami,)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (queue_agent_called_type,.to_ami=queue_agent_called_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_complete_type,.to_ami=queue_agent_complete_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,)
 
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 *macro, 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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_CONSUMER, .optional_modules = "res_monitor", }
 
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 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 }, [ '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 char * realtime_ringinuse_field
 name of the ringinuse field in the realtime database More...
 
static int realtime_rules
 queuesrules.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
  • Optional monitoring of calls, started when call is answered

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 1636 of file app_queue.c.

Referenced by queue_set_param().

◆ ANNOUNCEHOLDTIME_ONCE

#define ANNOUNCEHOLDTIME_ONCE   2

Definition at line 1637 of file app_queue.c.

Referenced by queue_set_param(), and say_position().

◆ ANNOUNCEPOSITION_LIMIT

#define ANNOUNCEPOSITION_LIMIT   4

We not announce position more than <limit>

Definition at line 1654 of file app_queue.c.

Referenced by queue_set_param(), and say_position().

◆ ANNOUNCEPOSITION_MORE_THAN

#define ANNOUNCEPOSITION_MORE_THAN   3

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

Definition at line 1653 of file app_queue.c.

Referenced by queue_set_param(), and say_position().

◆ ANNOUNCEPOSITION_NO

#define ANNOUNCEPOSITION_NO   2

We don't announce position

Definition at line 1652 of file app_queue.c.

Referenced by queue_set_param().

◆ ANNOUNCEPOSITION_YES

#define ANNOUNCEPOSITION_YES   1

We announce position

Definition at line 1651 of file app_queue.c.

Referenced by init_queue(), queue_set_param(), and say_position().

◆ AST_MAX_WATCHERS

#define AST_MAX_WATCHERS   256

Definition at line 4923 of file app_queue.c.

Referenced by wait_for_answer().

◆ 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 1437 of file app_queue.c.

Referenced by init_queue().

◆ DEFAULT_RETRY

#define DEFAULT_RETRY   5

Definition at line 1429 of file app_queue.c.

Referenced by init_queue(), and queue_set_param().

◆ DEFAULT_TIMEOUT

#define DEFAULT_TIMEOUT   15

Definition at line 1430 of file app_queue.c.

Referenced by init_queue(), and queue_set_param().

◆ MAX_CALL_ATTEMPT_BUCKETS

#define MAX_CALL_ATTEMPT_BUCKETS   353

Definition at line 2376 of file app_queue.c.

Referenced by load_module().

◆ MAX_PERIODIC_ANNOUNCEMENTS

#define MAX_PERIODIC_ANNOUNCEMENTS   10

The maximum periodic announcements we can have

Definition at line 1432 of file app_queue.c.

Referenced by destroy_queue(), init_queue(), and queue_set_param().

◆ MAX_QUEUE_BUCKETS

#define MAX_QUEUE_BUCKETS   53

Definition at line 1439 of file app_queue.c.

Referenced by load_module().

◆ QUEUE_EVENT_VARIABLES

#define QUEUE_EVENT_VARIABLES   3

Definition at line 1638 of file app_queue.c.

◆ QUEUE_PAUSED_DEVSTATE

#define QUEUE_PAUSED_DEVSTATE   AST_DEVICE_INUSE

◆ queue_ref

#define queue_ref (   q)    ao2_bump(q)

Definition at line 1918 of file app_queue.c.

Referenced by insert_entry(), and queue_stasis_data_alloc().

◆ queue_t_ref

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

Definition at line 1920 of file app_queue.c.

Referenced by leave_queue(), and try_calling().

◆ queue_t_unref

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

◆ QUEUE_UNKNOWN_PAUSED_DEVSTATE

#define QUEUE_UNKNOWN_PAUSED_DEVSTATE   AST_DEVICE_NOT_INUSE

Definition at line 3352 of file app_queue.c.

Referenced by member_remove_from_queue().

◆ QUEUE_UNPAUSED_DEVSTATE

#define QUEUE_UNPAUSED_DEVSTATE   AST_DEVICE_NOT_INUSE

◆ queue_unref

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

◆ queues_t_link

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

Definition at line 1922 of file app_queue.c.

Referenced by find_queue_by_name_rt(), and reload_single_queue().

◆ queues_t_unlink

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

Definition at line 1923 of file app_queue.c.

Referenced by find_queue_by_name_rt(), and leave_queue().

◆ RECHECK

#define RECHECK   1

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

Definition at line 1431 of file app_queue.c.

Referenced by wait_our_turn().

◆ RES_EXISTS

#define RES_EXISTS   (-1)

◆ RES_NOSUCHQUEUE

#define RES_NOSUCHQUEUE   (-3)

◆ RES_NOT_CALLER

#define RES_NOT_CALLER   (-5)

◆ RES_NOT_DYNAMIC

#define RES_NOT_DYNAMIC   (-4)

◆ RES_OKAY

#define RES_OKAY   0

◆ RES_OUTOFMEMORY

#define RES_OUTOFMEMORY   (-2)

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 

Definition at line 1325 of file app_queue.c.

1325  {
1326  OPT_MARK_AS_ANSWERED = (1 << 0),
1327  OPT_GO_ON = (1 << 1),
1328  OPT_DATA_QUALITY = (1 << 2),
1329  OPT_CALLEE_GO_ON = (1 << 3),
1330  OPT_CALLEE_HANGUP = (1 << 4),
1331  OPT_CALLER_HANGUP = (1 << 5),
1332  OPT_IGNORE_CALL_FW = (1 << 6),
1333  OPT_IGNORE_CONNECTEDLINE = (1 << 7),
1334  OPT_CALLEE_PARK = (1 << 8),
1335  OPT_CALLER_PARK = (1 << 9),
1336  OPT_NO_RETRY = (1 << 10),
1337  OPT_RINGING = (1 << 11),
1338  OPT_RING_WHEN_RINGING = (1 << 12),
1339  OPT_CALLEE_TRANSFER = (1 << 13),
1340  OPT_CALLER_TRANSFER = (1 << 14),
1341  OPT_CALLEE_AUTOMIXMON = (1 << 15),
1342  OPT_CALLER_AUTOMIXMON = (1 << 16),
1343  OPT_CALLEE_AUTOMON = (1 << 17),
1344  OPT_CALLER_AUTOMON = (1 << 18),
1345  OPT_PREDIAL_CALLEE = (1 << 19),
1346  OPT_PREDIAL_CALLER = (1 << 20),
1347 };

◆ anonymous enum

anonymous enum
Enumerator
OPT_ARG_CALLEE_GO_ON 
OPT_ARG_PREDIAL_CALLEE 
OPT_ARG_PREDIAL_CALLER 
OPT_ARG_ARRAY_SIZE 

Definition at line 1349 of file app_queue.c.

1349  {
1353  /* note: this entry _MUST_ be the last one in the enum */
1355 };

◆ 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 1381 of file app_queue.c.

◆ anonymous enum

anonymous enum
Enumerator
QUEUE_AUTOPAUSE_OFF 
QUEUE_AUTOPAUSE_ON 
QUEUE_AUTOPAUSE_ALL 

Definition at line 1392 of file app_queue.c.

◆ agent_complete_reason

Enumerator
CALLER 
AGENT 
TRANSFER 

Definition at line 5857 of file app_queue.c.

5857  {
5858  CALLER,
5859  AGENT,
5860  TRANSFER
5861 };

◆ 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 1619 of file app_queue.c.

◆ member_properties

Enumerator
MEMBER_PENALTY 
MEMBER_RINGINUSE 

Definition at line 1630 of file app_queue.c.

1630  {
1631  MEMBER_PENALTY = 0,
1632  MEMBER_RINGINUSE = 1,
1633 };

◆ queue_reload_mask

Enumerator
QUEUE_RELOAD_PARAMETERS 
QUEUE_RELOAD_MEMBER 
QUEUE_RELOAD_RULES 
QUEUE_RESET_STATS 

Definition at line 1398 of file app_queue.c.

1398  {
1399  QUEUE_RELOAD_PARAMETERS = (1 << 0),
1400  QUEUE_RELOAD_MEMBER = (1 << 1),
1401  QUEUE_RELOAD_RULES = (1 << 2),
1402  QUEUE_RESET_STATS = (1 << 3),
1403 };

◆ queue_result

Enumerator
QUEUE_UNKNOWN 
QUEUE_TIMEOUT 
QUEUE_JOINEMPTY 
QUEUE_LEAVEEMPTY 
QUEUE_JOINUNAVAIL 
QUEUE_LEAVEUNAVAIL 
QUEUE_FULL 
QUEUE_CONTINUE 

Definition at line 1495 of file app_queue.c.

◆ queue_timeout_priority

Enumerator
TIMEOUT_PRIORITY_APP 
TIMEOUT_PRIORITY_CONF 

Definition at line 1520 of file app_queue.c.

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 9758 of file app_queue.c.

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(), LOG_WARNING, call_queue::name, NULL, out, print_queue(), queue_t_unref, queue_unref, call_queue::realtime, and SENTINEL.

Referenced by queue_show().

9759 {
9760  struct call_queue *q;
9761  struct ast_str *out = ast_str_alloca(512);
9762  struct ao2_container *sorted_queues;
9763 
9764  struct ao2_iterator queue_iter;
9765  int found = 0;
9766 
9767  if (argc != 2 && argc != 3) {
9768  return CLI_SHOWUSAGE;
9769  }
9770 
9771  if (argc == 3) { /* specific queue */
9772  if ((q = find_load_queue_rt_friendly(argv[2]))) {
9773  ao2_lock(q);
9774  print_queue(s, fd, q);
9775  ao2_unlock(q);
9776  queue_unref(q);
9777  } else {
9778  ast_str_set(&out, 0, "No such queue: %s.", argv[2]);
9779  do_print(s, fd, ast_str_buffer(out));
9780  }
9781  return CLI_SUCCESS;
9782  }
9783 
9784  if (ast_check_realtime("queues")) {
9785  /* This block is to find any queues which are defined in realtime but
9786  * which have not yet been added to the in-core container
9787  */
9788  struct ast_config *cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
9789  if (cfg) {
9790  char *category = NULL;
9791  while ((category = ast_category_browse(cfg, category))) {
9792  const char *queuename = ast_variable_retrieve(cfg, category, "name");
9793  if (ast_strlen_zero(queuename)) {
9794  ast_log(LOG_WARNING, "Ignoring realtime queue with a NULL or empty 'name.'\n");
9795  continue;
9796  }
9797  if ((q = find_load_queue_rt_friendly(queuename))) {
9798  queue_t_unref(q, "Done with temporary pointer");
9799  }
9800  }
9801  ast_config_destroy(cfg);
9802  }
9803  }
9804 
9805  /*
9806  * Snapping a copy of the container prevents having to lock both the queues container
9807  * and the queue itself at the same time. It also allows us to sort the entries.
9808  */
9809  sorted_queues = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, call_queue_sort_fn, NULL);
9810  if (!sorted_queues) {
9811  return CLI_SUCCESS;
9812  }
9813  if (ao2_container_dup(sorted_queues, queues, 0)) {
9814  ao2_ref(sorted_queues, -1);
9815  return CLI_SUCCESS;
9816  }
9817 
9818  /*
9819  * No need to lock the container since it's temporary and static.
9820  * We also unlink the entries as we use them so the container is
9821  * empty when the iterator finishes. We can then just unref the container.
9822  */
9823  queue_iter = ao2_iterator_init(sorted_queues, AO2_ITERATOR_DONTLOCK | AO2_ITERATOR_UNLINK);
9824  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
9825  struct call_queue *realtime_queue = NULL;
9826  ao2_lock(q);
9827  /* This check is to make sure we don't print information for realtime
9828  * queues which have been deleted from realtime but which have not yet
9829  * been deleted from the in-core container. Only do this if we're not
9830  * looking for a specific queue.
9831  */
9832  if (q->realtime) {
9833  realtime_queue = find_load_queue_rt_friendly(q->name);
9834  if (!realtime_queue) {
9835  ao2_unlock(q);
9836  queue_t_unref(q, "Done with iterator");
9837  continue;
9838  }
9839  queue_t_unref(realtime_queue, "Queue is already in memory");
9840  }
9841 
9842  found = 1;
9843  print_queue(s, fd, q);
9844 
9845  ao2_unlock(q);
9846  queue_t_unref(q, "Done with iterator"); /* Unref the iterator's reference */
9847  }
9848  ao2_iterator_destroy(&queue_iter);
9849  ao2_ref(sorted_queues, -1);
9850  if (!found) {
9851  ast_str_set(&out, 0, "No queues.");
9852  do_print(s, fd, ast_str_buffer(out));
9853  }
9854  return CLI_SUCCESS;
9855 }
static void do_print(struct mansession *s, int fd, const char *str)
direct ouput to manager or cli with proper terminator
Definition: app_queue.c:9644
static struct call_queue * find_load_queue_rt_friendly(const char *queuename)
Definition: app_queue.c:3702
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: main/config.c:3363
#define queue_unref(q)
Definition: app_queue.c:1919
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_str_alloca(init_len)
Definition: strings.h:800
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3328
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
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:1065
#define ast_log
Definition: astobj2.c:42
#define SENTINEL
Definition: compiler.h:87
static struct ao2_container * queues
Definition: app_queue.c:1766
#define ao2_ref(o, delta)
Definition: astobj2.h:464
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: main/config.c:3452
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
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.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define ao2_t_iterator_next(iter, tag)
Definition: astobj2.h:1931
const ast_string_field name
Definition: app_queue.c:1696
#define queue_t_unref(q, tag)
Definition: app_queue.c:1921
#define CLI_SUCCESS
Definition: cli.h:44
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
Definition: main/config.c:694
Assume that the ao2_container is already locked.
Definition: astobj2.h:1872
FILE * out
Definition: utils/frame.c:33
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
unsigned int realtime
Definition: app_queue.c:1712
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:9654
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1358
Generic container type.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 11505 of file app_queue.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 11505 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 7377 of file app_queue.c.

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(), interface_exists(), is_member_available(), member_add_to_queue(), call_queue::name, NULL, queue_member_blob_create(), queue_publish_member_blob(), queue_t_unref, member::reason_paused, RES_EXISTS, RES_NOSUCHQUEUE, RES_OKAY, RES_OUTOFMEMORY, and call_queue::ringinuse.

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

7378 {
7379  struct call_queue *q;
7380  struct member *new_member, *old_member;
7381  int res = RES_NOSUCHQUEUE;
7382 
7383  /*! \note Ensure the appropriate realtime queue is loaded. Note that this
7384  * short-circuits if the queue is already in memory. */
7385  if (!(q = find_load_queue_rt_friendly(queuename))) {
7386  return res;
7387  }
7388 
7389  ao2_lock(q);
7390  if ((old_member = interface_exists(q, interface)) == NULL) {
7392  new_member->dynamic = 1;
7393  if (reason_paused) {
7394  ast_copy_string(new_member->reason_paused, reason_paused, sizeof(new_member->reason_paused));
7395  }
7396  member_add_to_queue(q, new_member);
7397  queue_publish_member_blob(queue_member_added_type(), queue_member_blob_create(q, new_member));
7398 
7399  if (is_member_available(q, new_member)) {
7401  }
7402 
7403  ao2_ref(new_member, -1);
7404  new_member = NULL;
7405 
7406  if (dump) {
7407  dump_queue_members(q);
7408  }
7409 
7410  res = RES_OKAY;
7411  } else {
7412  res = RES_OUTOFMEMORY;
7413  }
7414  } else {
7415  ao2_ref(old_member, -1);
7416  res = RES_EXISTS;
7417  }
7418  ao2_unlock(q);
7419  queue_t_unref(q, "Expiring temporary reference");
7420 
7421  return res;
7422 }
int dynamic
Definition: app_queue.c:1601
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:2686
int paused
Definition: app_queue.c:1604
#define RES_OKAY
Definition: app_queue.c:1441
static struct call_queue * find_load_queue_rt_friendly(const char *queuename)
Definition: app_queue.c:3702
char state_interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1596
int wrapuptime
Definition: app_queue.c:1608
unsigned int ringinuse
Definition: app_queue.c:1700
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
char membername[80]
Definition: app_queue.c:1598
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1593
#define RES_OUTOFMEMORY
Definition: app_queue.c:1443
static void member_add_to_queue(struct call_queue *queue, struct member *mem)
Definition: app_queue.c:3360
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
int penalty
Definition: app_queue.c:1599
static struct member * interface_exists(struct call_queue *q, const char *interface)
Definition: app_queue.c:7242
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
static struct ast_json * queue_member_blob_create(struct call_queue *q, struct member *mem)
Definition: app_queue.c:2258
const ast_string_field name
Definition: app_queue.c:1696
static void dump_queue_members(struct call_queue *pm_queue)
Dump all members in a specific queue to the database.
Definition: app_queue.c:7269
char reason_paused[80]
Definition: app_queue.c:1605
#define RES_NOSUCHQUEUE
Definition: app_queue.c:1444
#define queue_t_unref(q, tag)
Definition: app_queue.c:1921
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define RES_EXISTS
Definition: app_queue.c:1442
static void queue_publish_member_blob(struct stasis_message_type *type, struct ast_json *blob)
Definition: app_queue.c:2234
static int is_member_available(struct call_queue *q, struct member *mem)
Definition: app_queue.c:2468

◆ alloc_queue()

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

Definition at line 3534 of file app_queue.c.

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

Referenced by find_queue_by_name_rt(), and reload_single_queue().

3535 {
3536  struct call_queue *q;
3537 
3538  if ((q = ao2_t_alloc(sizeof(*q), destroy_queue, "Allocate queue"))) {
3539  if (ast_string_field_init(q, 64)) {
3540  queue_t_unref(q, "String field allocation failed");
3541  return NULL;
3542  }
3543  ast_string_field_set(q, name, queuename);
3544  }
3545  return q;
3546 }
#define ao2_t_alloc(data_size, destructor_fn, debug_msg)
Definition: astobj2.h:409
#define NULL
Definition: resample.c:96
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
static void destroy_queue(void *obj)
Free queue&#39;s member list then its string fields.
Definition: app_queue.c:3519
static const char name[]
Definition: cdr_mysql.c:74
#define queue_t_unref(q, tag)
Definition: app_queue.c:1921
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ AO2_STRING_FIELD_SORT_FN()

AO2_STRING_FIELD_SORT_FN ( call_queue  ,
name   
)

Referenced by print_queue().

◆ aqm_exec()

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

AddQueueMember application.

Definition at line 8025 of file app_queue.c.

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_NOTICE, LOG_WARNING, member::membername, NULL, options, parse(), pbx_builtin_setvar_helper(), member::penalty, RES_EXISTS, RES_NOSUCHQUEUE, RES_OKAY, RES_OUTOFMEMORY, member::state_interface, tmp(), and member::wrapuptime.

Referenced by load_module().

8026 {
8027  int res=-1;
8028  char *parse, *tmp, *temppos = NULL;
8030  AST_APP_ARG(queuename);
8031  AST_APP_ARG(interface);
8032  AST_APP_ARG(penalty);
8034  AST_APP_ARG(membername);
8035  AST_APP_ARG(state_interface);
8037  );
8038  int penalty = 0;
8039  int wrapuptime;
8040 
8041  if (ast_strlen_zero(data)) {
8042  ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename[,interface[,penalty[,options[,membername[,stateinterface][,wrapuptime]]]]])\n");
8043  return -1;
8044  }
8045 
8046  parse = ast_strdupa(data);
8047 
8048  AST_STANDARD_APP_ARGS(args, parse);
8049 
8050  if (ast_strlen_zero(args.interface)) {
8051  args.interface = ast_strdupa(ast_channel_name(chan));
8052  temppos = strrchr(args.interface, '-');
8053  if (temppos) {
8054  *temppos = '\0';
8055  }
8056  }
8057 
8058  if (!ast_strlen_zero(args.penalty)) {
8059  if ((sscanf(args.penalty, "%30d", &penalty) != 1) || penalty < 0) {
8060  ast_log(LOG_WARNING, "Penalty '%s' is invalid, must be an integer >= 0\n", args.penalty);
8061  penalty = 0;
8062  }
8063  }
8064 
8065  if (!ast_strlen_zero(args.wrapuptime)) {
8066  tmp = args.wrapuptime;
8067  ast_strip(tmp);
8068  wrapuptime = atoi(tmp);
8069  if (wrapuptime < 0) {
8070  wrapuptime = 0;
8071  }
8072  } else {
8073  wrapuptime = 0;
8074  }
8075 
8076  switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, 0, queue_persistent_members, args.state_interface, NULL, wrapuptime)) {
8077  case RES_OKAY:
8078  if (ast_strlen_zero(args.membername) || !log_membername_as_agent) {
8079  ast_queue_log(args.queuename, ast_channel_uniqueid(chan), args.interface, "ADDMEMBER", "%s", "");
8080  } else {
8081  ast_queue_log(args.queuename, ast_channel_uniqueid(chan), args.membername, "ADDMEMBER", "%s", "");
8082  }
8083  ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", args.interface, args.queuename);
8084  pbx_builtin_setvar_helper(chan, "AQMSTATUS", "ADDED");
8085  res = 0;
8086  break;
8087  case RES_EXISTS:
8088  ast_log(LOG_WARNING, "Unable to add interface '%s' to queue '%s': Already there\n", args.interface, args.queuename);
8089  pbx_builtin_setvar_helper(chan, "AQMSTATUS", "MEMBERALREADY");
8090  res = 0;
8091  break;
8092  case RES_NOSUCHQUEUE:
8093  ast_log(LOG_WARNING, "Unable to add interface to queue '%s': No such queue\n", args.queuename);
8094  pbx_builtin_setvar_helper(chan, "AQMSTATUS", "NOSUCHQUEUE");
8095  res = 0;
8096  break;
8097  case RES_OUTOFMEMORY:
8098  ast_log(LOG_ERROR, "Out of memory adding interface %s to queue %s\n", args.interface, args.queuename);
8099  break;
8100  }
8101 
8102  return res;
8103 }
#define RES_OKAY
Definition: app_queue.c:1441
int wrapuptime
Definition: app_queue.c:1737
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
static int tmp()
Definition: bt_open.c:389
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:894
static int log_membername_as_agent
queues.conf [general] option
Definition: app_queue.c:1490
const char * args
#define NULL
Definition: resample.c:96
#define RES_OUTOFMEMORY
Definition: app_queue.c:1443
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:219
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char * ast_channel_uniqueid(const struct ast_channel *chan)
#define LOG_ERROR
Definition: logger.h:285
#define LOG_NOTICE
Definition: logger.h:263
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
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...
#define RES_NOSUCHQUEUE
Definition: app_queue.c:1444
const char * ast_channel_name(const struct ast_channel *chan)
#define RES_EXISTS
Definition: app_queue.c:1442
static struct test_options options
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
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:7377
static int queue_persistent_members
queues.conf [general] option
Definition: app_queue.c:1466
#define AST_APP_ARG(name)
Define an application argument.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 11505 of file app_queue.c.

◆ autopause2int()

static int autopause2int ( const char *  autopause)
static

Definition at line 1813 of file app_queue.c.

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

Referenced by queue_set_param().

1814 {
1815  int x;
1816  /*This 'double check' that default value is OFF */
1817  if (ast_strlen_zero(autopause)) {
1818  return QUEUE_AUTOPAUSE_OFF;
1819  }
1820 
1821  /*This 'double check' is to ensure old values works */
1822  if(ast_true(autopause)) {
1823  return QUEUE_AUTOPAUSE_ON;
1824  }
1825 
1826  for (x = 0; x < ARRAY_LEN(autopausesmodes); x++) {
1827  if (!strcasecmp(autopause, autopausesmodes[x].name)) {
1828  return autopausesmodes[x].autopause;
1829  }
1830  }
1831 
1832  /*This 'double check' that default value is OFF */
1833  return QUEUE_AUTOPAUSE_OFF;
1834 }
int autopause
Definition: app_queue.c:1421
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
#define ast_strlen_zero(foo)
Definition: strings.h:52
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
static const char name[]
Definition: cdr_mysql.c:74
static const struct autopause autopausesmodes[]

◆ 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 5779 of file app_queue.c.

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, callattempt::metric, 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, and call_queue::wrapped.

Referenced by try_calling().

5780 {
5781  /* disregarding penalty on too few members? */
5782  int membercount = ao2_container_count(q->members);
5783  unsigned char usepenalty = (membercount <= q->penaltymemberslimit) ? 0 : 1;
5784  int penalty = mem->penalty;
5785 
5786  if (usepenalty) {
5787  if (qe->raise_penalty != INT_MAX && penalty < qe->raise_penalty) {
5788  /* Low penalty is raised up to the current minimum */
5789  penalty = qe->raise_penalty;
5790  }
5791  if ((qe->max_penalty != INT_MAX && penalty > qe->max_penalty) ||
5792  (qe->min_penalty != INT_MAX && penalty < qe->min_penalty)) {
5793  return -1;
5794  }
5795  } else {
5796  ast_debug(1, "Disregarding penalty, %d members and %d in penaltymemberslimit.\n",
5797  membercount, q->penaltymemberslimit);
5798  }
5799 
5800  switch (q->strategy) {
5802  /* Everyone equal, except for penalty */
5803  tmp->metric = penalty * 1000000 * usepenalty;
5804  break;
5805  case QUEUE_STRATEGY_LINEAR:
5806  if (pos < qe->linpos) {
5807  tmp->metric = 1000 + pos;
5808  } else {
5809  if (pos > qe->linpos) {
5810  /* Indicate there is another priority */
5811  qe->linwrapped = 1;
5812  }
5813  tmp->metric = pos;
5814  }
5815  tmp->metric += penalty * 1000000 * usepenalty;
5816  break;
5819  pos = mem->queuepos;
5820  if (pos < q->rrpos) {
5821  tmp->metric = 1000 + pos;
5822  } else {
5823  if (pos > q->rrpos) {
5824  /* Indicate there is another priority */
5825  q->wrapped = 1;
5826  }
5827  tmp->metric = pos;
5828  }
5829  tmp->metric += penalty * 1000000 * usepenalty;
5830  break;
5831  case QUEUE_STRATEGY_RANDOM:
5832  tmp->metric = ast_random() % 1000;
5833  tmp->metric += penalty * 1000000 * usepenalty;
5834  break;
5836  tmp->metric = ast_random() % ((1 + penalty) * 1000);
5837  break;
5839  tmp->metric = mem->calls;
5840  tmp->metric += penalty * 1000000 * usepenalty;
5841  break;
5843  if (!mem->lastcall) {
5844  tmp->metric = 0;
5845  } else {
5846  tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
5847  }
5848  tmp->metric += penalty * 1000000 * usepenalty;
5849  break;
5850  default:
5851  ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
5852  break;
5853  }
5854  return 0;
5855 }
int queuepos
Definition: app_queue.c:1606
int raise_penalty
Definition: app_queue.c:1580
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
int min_penalty
Definition: app_queue.c:1579
int max_penalty
Definition: app_queue.c:1578
int penaltymemberslimit
Definition: app_queue.c:1738
#define LOG_WARNING
Definition: logger.h:274
int linwrapped
Definition: app_queue.c:1582
#define NULL
Definition: resample.c:96
struct ao2_container * members
Definition: app_queue.c:1752
unsigned int wrapped
Definition: app_queue.c:1706
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
int penalty
Definition: app_queue.c:1599
long int ast_random(void)
Definition: main/utils.c:2064
int strategy
Definition: app_queue.c:1711
int linpos
Definition: app_queue.c:1581
int calls
Definition: app_queue.c:1600
time_t lastcall
Definition: app_queue.c:1610

◆ callattempt_free()

static void callattempt_free ( struct callattempt doomed)
static

Definition at line 4228 of file app_queue.c.

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().

4229 {
4230  if (doomed->member) {
4231  ao2_ref(doomed->member, -1);
4232  }
4234  ast_free(doomed->orig_chan_name);
4235  ast_free(doomed);
4236 }
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2072
struct ast_party_connected_line connected
Definition: app_queue.c:1545
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct member * member
Definition: app_queue.c:1543
char * orig_chan_name
Definition: app_queue.c:1556
#define ast_free(a)
Definition: astmm.h:182

◆ can_ring_entry()

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

Definition at line 4388 of file app_queue.c.

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

Referenced by ring_entry().

4389 {
4390  struct member *memberp = call->member;
4391  int wrapuptime;
4392 
4393  if (memberp->paused) {
4394  ast_debug(1, "%s paused, can't receive call\n", call->interface);
4395  return 0;
4396  }
4397 
4398  if (!memberp->ringinuse && !member_status_available(memberp->status)) {
4399  ast_debug(1, "%s not available, can't receive call\n", call->interface);
4400  return 0;
4401  }
4402 
4403  if (memberp->lastqueue) {
4404  wrapuptime = get_wrapuptime(memberp->lastqueue, memberp);
4405  } else {
4406  wrapuptime = get_wrapuptime(qe->parent, memberp);
4407  }
4408  if (wrapuptime && (time(NULL) - memberp->lastcall) < wrapuptime) {
4409  ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
4410  (memberp->lastqueue ? memberp->lastqueue->name : qe->parent->name),
4411  call->interface);
4412  return 0;
4413  }
4414 
4415  if (use_weight && compare_weight(qe->parent, memberp)) {
4416  ast_debug(1, "Priority queue delaying call to %s:%s\n",
4417  qe->parent->name, call->interface);
4418  return 0;
4419  }
4420 
4421  if (!memberp->ringinuse) {
4422  struct member *mem;
4423 
4425 
4426  mem = ao2_find(pending_members, memberp,
4428  if (mem) {
4429  /*
4430  * If found that means this member is currently being attempted
4431  * from another calling thread, so stop trying from this thread
4432  */
4433  ast_debug(1, "%s has another call trying, can't receive call\n",
4434  call->interface);
4435  ao2_ref(mem, -1);
4437  return 0;
4438  }
4439 
4440  /*
4441  * If not found add it to the container so another queue
4442  * won't attempt to call this member at the same time.
4443  */
4444  ast_debug(3, "Add %s to pending_members\n", memberp->membername);
4445  ao2_link(pending_members, memberp);
4447 
4448  /*
4449  * The queue member is available. Get current status to be sure
4450  * because the device state and extension state callbacks may
4451  * not have updated the status yet.
4452  */
4454  ast_debug(1, "%s actually not available, can't receive call\n",
4455  call->interface);
4456  pending_members_remove(memberp);
4457  return 0;
4458  }
4459  }
4460 
4461  return 1;
4462 }
struct call_queue * parent
Definition: app_queue.c:1561
int paused
Definition: app_queue.c:1604
static struct ao2_container * pending_members
Definition: app_queue.c:2375
int wrapuptime
Definition: app_queue.c:1608
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
char interface[256]
Definition: app_queue.c:1541
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
static void pending_members_remove(struct member *mem)
Definition: app_queue.c:2426
char membername[80]
Definition: app_queue.c:1598
static int member_status_available(int status)
Definition: app_queue.c:4374
static int compare_weight(struct call_queue *rq, struct member *member)
Definition: app_queue.c:4323
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct member * member
Definition: app_queue.c:1543
struct call_queue * lastqueue
Definition: app_queue.c:1612
static int get_wrapuptime(struct call_queue *q, struct member *member)
Return wrapuptime.
Definition: app_queue.c:1856
const ast_string_field name
Definition: app_queue.c:1696
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
int status
Definition: app_queue.c:1603
The arg parameter is an object of the same type.
Definition: astobj2.h:1091
static int use_weight
Records that one or more queues use weight.
Definition: app_queue.c:1469
static int get_queue_member_status(struct member *cur)
Return the current state of a member.
Definition: app_queue.c:2671
unsigned int ringinuse
Definition: app_queue.c:1616
time_t lastcall
Definition: app_queue.c:1610
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ change_priority_caller_on_queue()

static int change_priority_caller_on_queue ( const char *  queuename,
const char *  caller,
int  priority 
)
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 7430 of file app_queue.c.

References ao2_lock, ao2_unlock, ast_channel_name(), ast_debug, queue_ent::chan, find_load_queue_rt_friendly(), call_queue::head, queue_ent::next, queue_ent::prio, priority, RES_NOSUCHQUEUE, RES_NOT_CALLER, and RES_OKAY.

Referenced by handle_queue_change_priority_caller(), and manager_change_priority_caller_on_queue().

7431 {
7432  struct call_queue *q;
7433  struct queue_ent *qe;
7434  int res = RES_NOSUCHQUEUE;
7435 
7436  /*! \note Ensure the appropriate realtime queue is loaded. Note that this
7437  * short-circuits if the queue is already in memory. */
7438  if (!(q = find_load_queue_rt_friendly(queuename))) {
7439  return res;
7440  }
7441 
7442  ao2_lock(q);
7443  res = RES_NOT_CALLER;
7444  for (qe = q->head; qe; qe = qe->next) {
7445  if (strcmp(ast_channel_name(qe->chan), caller) == 0) {
7446  ast_debug(1, "%s Caller new prioriry %d in queue %s\n",
7447  caller, priority, queuename);
7448  qe->prio = priority;
7449  res = RES_OKAY;
7450  }
7451  }
7452  ao2_unlock(q);
7453  return res;
7454 }
#define RES_OKAY
Definition: app_queue.c:1441
struct ast_channel * chan
Definition: app_queue.c:1586
static struct call_queue * find_load_queue_rt_friendly(const char *queuename)
Definition: app_queue.c:3702
#define ao2_unlock(a)
Definition: astobj2.h:730
static int priority
struct queue_ent * head
Definition: app_queue.c:1753
#define RES_NOT_CALLER
Definition: app_queue.c:1446
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ao2_lock(a)
Definition: astobj2.h:718
#define RES_NOSUCHQUEUE
Definition: app_queue.c:1444
const char * ast_channel_name(const struct ast_channel *chan)
struct queue_ent * next
Definition: app_queue.c:1589

◆ clear_queue()

static void clear_queue ( struct call_queue q)
static

Definition at line 2863 of file app_queue.c.

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().

2864 {
2865  q->holdtime = 0;
2866  q->callscompleted = 0;
2867  q->callsabandoned = 0;
2868  q->callscompletedinsl = 0;
2869  q->callsabandonedinsl = 0;
2870  q->talktime = 0;
2871 
2872  if (q->members) {
2873  struct member *mem;
2874  struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
2875  while ((mem = ao2_iterator_next(&mem_iter))) {
2876  mem->calls = 0;
2877  mem->callcompletedinsl = 0;
2878  mem->lastcall = 0;
2879  mem->starttime = 0;
2880  ao2_ref(mem, -1);
2881  }
2882  ao2_iterator_destroy(&mem_iter);
2883  }
2884 }
int callsabandonedinsl
Definition: app_queue.c:1730
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct ao2_container * members
Definition: app_queue.c:1752
int callscompletedinsl
Definition: app_queue.c:1732
int holdtime
Definition: app_queue.c:1726
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int talktime
Definition: app_queue.c:1727
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
time_t starttime
Definition: app_queue.c:1609
int calls
Definition: app_queue.c:1600
int callsabandoned
Definition: app_queue.c:1729
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
int callcompletedinsl
Definition: app_queue.c:1607
int callscompleted
Definition: app_queue.c:1728
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
time_t lastcall
Definition: app_queue.c:1610

◆ 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
void

Definition at line 9597 of file app_queue.c.

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

Referenced by reload_handler().

9598 {
9599  struct call_queue *q;
9600  struct ao2_iterator queue_iter;
9601 
9602  queue_iter = ao2_iterator_init(queues, 0);
9603  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
9604  ao2_lock(q);
9605  if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename))
9606  clear_queue(q);
9607  ao2_unlock(q);
9608  queue_t_unref(q, "Done with iterator");
9609  }
9610  ao2_iterator_destroy(&queue_iter);
9611  return 0;
9612 }
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
static void clear_queue(struct call_queue *q)
Definition: app_queue.c:2863
#define ast_strlen_zero(foo)
Definition: strings.h:52
static struct ao2_container * queues
Definition: app_queue.c:1766
#define ao2_lock(a)
Definition: astobj2.h:718
#define ao2_t_iterator_next(iter, tag)
Definition: astobj2.h:1931
const ast_string_field name
Definition: app_queue.c:1696
#define queue_t_unref(q, tag)
Definition: app_queue.c:1921
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ compare_weight()

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

Definition at line 4323 of file app_queue.c.

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, and call_queue::weight.

Referenced by can_ring_entry().

4324 {
4325  struct call_queue *q;
4326  struct member *mem;
4327  int found = 0;
4328  struct ao2_iterator queue_iter;
4329 
4330  queue_iter = ao2_iterator_init(queues, 0);
4331  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
4332  if (q == rq) { /* don't check myself, could deadlock */
4333  queue_t_unref(q, "Done with iterator");
4334  continue;
4335  }
4336  ao2_lock(q);
4337  if (q->count && q->members) {
4338  if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
4339  ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
4340  if (q->weight > rq->weight && q->count >= num_available_members(q)) {
4341  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);
4342  found = 1;
4343  }
4344  ao2_ref(mem, -1);
4345  }
4346  }
4347  ao2_unlock(q);
4348  queue_t_unref(q, "Done with iterator");
4349  if (found) {
4350  break;
4351  }
4352  }
4353  ao2_iterator_destroy(&queue_iter);
4354  return found;
4355 }
#define OBJ_POINTER
Definition: astobj2.h:1154
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
struct ao2_container * members
Definition: app_queue.c:1752
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1593
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static struct ao2_container * queues
Definition: app_queue.c:1766
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
static int num_available_members(struct call_queue *q)
Get the number of members available to accept a call.
Definition: app_queue.c:4290
#define ao2_t_iterator_next(iter, tag)
Definition: astobj2.h:1931
const ast_string_field name
Definition: app_queue.c:1696
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define queue_t_unref(q, tag)
Definition: app_queue.c:1921
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ 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 9929 of file app_queue.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_t_iterator_next, ast_strdup, call_queue::name, NULL, queue_t_unref, 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().

9930 {
9931  struct call_queue *q;
9932  char *ret = NULL;
9933  int which = 0;
9934  int wordlen = strlen(word);
9935  struct ao2_iterator queue_iter;
9936  const char *word_list = NULL;
9937 
9938  /* for certain commands, already completed items should be left out of
9939  * the list */
9940  if (word_list_offset && strlen(line) >= word_list_offset) {
9941  word_list = line + word_list_offset;
9942  }
9943 
9944  queue_iter = ao2_iterator_init(queues, 0);
9945  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
9946  if (!strncasecmp(word, q->name, wordlen) && ++which > state
9947  && (!word_list_offset || !word_in_list(word_list, q->name))) {
9948  ret = ast_strdup(q->name);
9949  queue_t_unref(q, "Done with iterator");
9950  break;
9951  }
9952  queue_t_unref(q, "Done with iterator");
9953  }
9954  ao2_iterator_destroy(&queue_iter);
9955 
9956  /* Pretend "rules" is at the end of the queues list in certain
9957  * circumstances since it is an alternate command that should be
9958  * tab-completable for "queue show" */
9959  if (!ret && which == state && !wordlen && !strncmp("queue show", line, 10)) {
9960  ret = ast_strdup("rules");
9961  }
9962 
9963  return ret;
9964 }
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
static struct ao2_container * queues
Definition: app_queue.c:1766
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:9870
#define ao2_t_iterator_next(iter, tag)
Definition: astobj2.h:1931
const ast_string_field name
Definition: app_queue.c:1696
#define queue_t_unref(q, tag)
Definition: app_queue.c:1921
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
short word

◆ complete_queue_add_member()

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

Definition at line 10426 of file app_queue.c.

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

Referenced by handle_queue_add_member().

10427 {
10428  /* 0 - queue; 1 - add; 2 - member; 3 - <interface>; 4 - to; 5 - <queue>; 6 - penalty; 7 - <penalty>; 8 - as; 9 - <membername> */
10429  switch (pos) {
10430  case 3: /* Don't attempt to complete name of interface (infinite possibilities) */
10431  return NULL;
10432  case 4: /* only one possible match, "to" */
10433  return state == 0 ? ast_strdup("to") : NULL;
10434  case 5: /* <queue> */
10435  return complete_queue(line, word, pos, state, 0);
10436  case 6: /* only one possible match, "penalty" */
10437  return state == 0 ? ast_strdup("penalty") : NULL;
10438  case 7:
10439  if (0 <= state && state < 100) { /* 0-99 */
10440  char *num;
10441  if ((num = ast_malloc(3))) {
10442  sprintf(num, "%d", state);
10443  }
10444  return num;
10445  } else {
10446  return NULL;
10447  }
10448  case 8: /* only one possible match, "as" */
10449  return state == 0 ? ast_strdup("as") : NULL;
10450  case 9: /* Don't attempt to complete name of member (infinite possibilities) */
10451  return NULL;
10452  default:
10453  return NULL;
10454  }
10455 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
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:9929
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
short word

◆ complete_queue_pause_member()

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

Definition at line 10799 of file app_queue.c.

References ast_strdup, complete_queue(), and NULL.

Referenced by handle_queue_pause_member().

10800 {
10801  /* 0 - queue; 1 - pause; 2 - member; 3 - <interface>; 4 - queue; 5 - <queue>; 6 - reason; 7 - <reason> */
10802  switch (pos) {
10803  case 3: /* Don't attempt to complete name of interface (infinite possibilities) */
10804  return NULL;
10805  case 4: /* only one possible match, "queue" */
10806  return state == 0 ? ast_strdup("queue") : NULL;
10807  case 5: /* <queue> */
10808  return complete_queue(line, word, pos, state, 0);
10809  case 6: /* "reason" */
10810  return state == 0 ? ast_strdup("reason") : NULL;
10811  case 7: /* Can't autocomplete a reason, since it's 100% customizeable */
10812  return NULL;
10813  default:
10814  return NULL;
10815  }
10816 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
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:9929
short word

◆ complete_queue_remove_member()

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

Definition at line 10639 of file app_queue.c.

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, and tmp().

Referenced by handle_queue_remove_member().

10640 {
10641  int which = 0;
10642  struct call_queue *q;
10643  struct member *m;
10644  struct ao2_iterator queue_iter;
10645  struct ao2_iterator mem_iter;
10646  int wordlen = strlen(word);
10647 
10648  /* 0 - queue; 1 - remove; 2 - member; 3 - <member>; 4 - from; 5 - <queue> */
10649  if (pos > 5 || pos < 3) {
10650  return NULL;
10651  }
10652  if (pos == 4) { /* only one possible match, 'from' */
10653  return (state == 0 ? ast_strdup("from") : NULL);
10654  }
10655 
10656  if (pos == 5) { /* No need to duplicate code */
10657  return complete_queue(line, word, pos, state, 0);
10658  }
10659 
10660  /* here is the case for 3, <member> */
10661  queue_iter = ao2_iterator_init(queues, 0);
10662  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
10663  ao2_lock(q);
10664  mem_iter = ao2_iterator_init(q->members, 0);
10665  while ((m = ao2_iterator_next(&mem_iter))) {
10666  if (!strncasecmp(word, m->membername, wordlen) && ++which > state) {
10667  char *tmp;
10668  tmp = ast_strdup(m->interface);
10669  ao2_ref(m, -1);
10670  ao2_iterator_destroy(&mem_iter);
10671  ao2_unlock(q);
10672  queue_t_unref(q, "Done with iterator, returning interface name");
10673  ao2_iterator_destroy(&queue_iter);
10674  return tmp;
10675  }
10676  ao2_ref(m, -1);
10677  }
10678  ao2_iterator_destroy(&mem_iter);
10679  ao2_unlock(q);
10680  queue_t_unref(q, "Done with iterator");
10681  }
10682  ao2_iterator_destroy(&queue_iter);
10683 
10684  return NULL;
10685 }
static int tmp()
Definition: bt_open.c:389
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
struct ao2_container * members
Definition: app_queue.c:1752
char membername[80]
Definition: app_queue.c:1598
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1593
static struct ao2_container * queues
Definition: app_queue.c:1766
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:9929
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define ao2_t_iterator_next(iter, tag)
Definition: astobj2.h:1931
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define queue_t_unref(q, tag)
Definition: app_queue.c:1921
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
short word

◆ complete_queue_rule_show()

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

Definition at line 10994 of file app_queue.c.

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().

10995 {
10996  int which = 0;
10997  struct rule_list *rl_iter;
10998  int wordlen = strlen(word);
10999  char *ret = NULL;
11000  if (pos != 3) /* Wha? */ {
11001  return NULL;
11002  }
11003 
11005  AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
11006  if (!strncasecmp(word, rl_iter->name, wordlen) && ++which > state) {
11007  ret = ast_strdup(rl_iter->name);
11008  break;
11009  }
11010  }
11012 
11013  return ret;
11014 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char name[80]
Definition: app_queue.c:1759
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct rule_list::@72 list
short word

◆ 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 10873 of file app_queue.c.

References ast_strdup, complete_queue(), and NULL.

Referenced by handle_queue_set_member_penalty(), and handle_queue_set_member_ringinuse().

10874 {
10875  /* 0 - queue; 1 - set; 2 - penalty/ringinuse; 3 - <value>; 4 - on; 5 - <member>; 6 - in; 7 - <queue>;*/
10876  switch (pos) {
10877  case 4:
10878  if (state == 0) {
10879  return ast_strdup("on");
10880  } else {
10881  return NULL;
10882  }
10883  case 6:
10884  if (state == 0) {
10885  return ast_strdup("in");
10886  } else {
10887  return NULL;
10888  }
10889  case 7:
10890  return complete_queue(line, word, pos, state, 0);
10891  default:
10892  return NULL;
10893  }
10894 }
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
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:9929
short word

◆ complete_queue_show()

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

Definition at line 9966 of file app_queue.c.

References complete_queue(), and NULL.

Referenced by queue_show().

9967 {
9968  if (pos == 2) {
9969  return complete_queue(line, word, pos, state, 0);
9970  }
9971  return NULL;
9972 }
#define NULL
Definition: resample.c:96
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:9929
short word

◆ compress_char()

static int compress_char ( const char  c)
static

Definition at line 2730 of file app_queue.c.

Referenced by member_hash_fn().

2731 {
2732  if (c < 32) {
2733  return 0;
2734  } else if (c > 96) {
2735  return c - 64;
2736  }
2737  return c - 32;
2738 }
static struct test_val c

◆ 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 8140 of file app_queue.c.

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().

8141 {
8142  struct penalty_rule *pr_iter;
8143  struct rule_list *rl_iter;
8144  const char *tmp = ast_strlen_zero(rulename) ? qe->parent->defaultrule : rulename;
8146  AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
8147  if (!strcasecmp(rl_iter->name, tmp)) {
8148  break;
8149  }
8150  }
8151  if (rl_iter) {
8152  AST_LIST_TRAVERSE(&rl_iter->rules, pr_iter, list) {
8153  struct penalty_rule *new_pr = ast_calloc(1, sizeof(*new_pr));
8154  if (!new_pr) {
8155  ast_log(LOG_ERROR, "Memory allocation error when copying penalty rules! Aborting!\n");
8156  break;
8157  }
8158  new_pr->time = pr_iter->time;
8159  new_pr->max_value = pr_iter->max_value;
8160  new_pr->min_value = pr_iter->min_value;
8161  new_pr->raise_value = pr_iter->raise_value;
8162  new_pr->max_relative = pr_iter->max_relative;
8163  new_pr->min_relative = pr_iter->min_relative;
8164  new_pr->raise_relative = pr_iter->raise_relative;
8165  AST_LIST_INSERT_TAIL(&qe->qe_rules, new_pr, list);
8166  }
8167  }
8169 }
struct call_queue * parent
Definition: app_queue.c:1561
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
int max_relative
Definition: app_queue.c:1645
char name[80]
Definition: app_queue.c:1759
int min_relative
Definition: app_queue.c:1646
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static int tmp()
Definition: bt_open.c:389
struct rule_list::@71 rules
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
int raise_relative
Definition: app_queue.c:1647
#define LOG_ERROR
Definition: logger.h:285
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
struct penalty_rule::@68 list
struct rule_list::@72 list
const ast_string_field defaultrule
Definition: app_queue.c:1696
struct queue_ent::@67 qe_rules

◆ 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 2686 of file app_queue.c.

References ao2_alloc, ast_copy_string(), ast_extension_state_add(), ast_log, ast_strdupa, ast_strlen_zero, context, destroy_queue_member_cb(), exten, extension_state_cb(), get_queue_member_status(), member::interface, member::lastpause, LOG_WARNING, 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().

2687 {
2688  struct member *cur;
2689 
2690  if ((cur = ao2_alloc(sizeof(*cur), destroy_queue_member_cb))) {
2691  cur->ringinuse = ringinuse;
2692  cur->penalty = penalty;
2693  cur->paused = paused;
2694  cur->wrapuptime = wrapuptime;
2695  if (paused) {
2696  time(&cur->lastpause); /* Update time of last pause */
2697  }
2698  ast_copy_string(cur->interface, interface, sizeof(cur->interface));
2701  } else {
2703  }
2704  if (!ast_strlen_zero(membername)) {
2705  ast_copy_string(cur->membername, membername, sizeof(cur->membername));
2706  } else {
2707  ast_copy_string(cur->membername, interface, sizeof(cur->membername));
2708  }
2709  if (!strchr(cur->interface, '/')) {
2710  ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
2711  }
2712  if (!strncmp(cur->state_interface, "hint:", 5)) {
2713  char *tmp = ast_strdupa(cur->state_interface), *context = tmp;
2714  char *exten = strsep(&context, "@") + 5;
2715 
2716  ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten));
2717  ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context));
2718 
2720  } else {
2721  cur->state_id = -1;
2722  }
2723  cur->status = get_queue_member_status(cur);
2724  }
2725 
2726  return cur;
2727 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
int paused
Definition: app_queue.c:1604
char state_interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1596
int wrapuptime
Definition: app_queue.c:1608
#define LOG_WARNING
Definition: logger.h:274
static int tmp()
Definition: bt_open.c:389
#define NULL
Definition: resample.c:96
char membername[80]
Definition: app_queue.c:1598
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1593
static int extension_state_cb(const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
Definition: app_queue.c:2627
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
time_t lastpause
Definition: app_queue.c:1611
int penalty
Definition: app_queue.c:1599
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static void destroy_queue_member_cb(void *obj)
Definition: app_queue.c:2676
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
int state_id
Definition: app_queue.c:1597
int status
Definition: app_queue.c:1603
char * strsep(char **str, const char *delims)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
char state_context[AST_MAX_CONTEXT]
Definition: app_queue.c:1595
static int get_queue_member_status(struct member *cur)
Return the current state of a member.
Definition: app_queue.c:2671
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
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:3825
unsigned int ringinuse
Definition: app_queue.c:1616
char state_exten[AST_MAX_EXTENSION]
Definition: app_queue.c:1594

◆ destroy_queue()

static void destroy_queue ( void *  obj)
static

Free queue's member list then its string fields.

Definition at line 3519 of file app_queue.c.

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().

3520 {
3521  struct call_queue *q = obj;
3522  int i;
3523 
3524  free_members(q, 1);
3526  for (i = 0; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
3527  if (q->sound_periodicannounce[i]) {
3529  }
3530  }
3531  ao2_ref(q->members, -1);
3532 }
struct ast_str * sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS]
Definition: app_queue.c:1698
#define MAX_PERIODIC_ANNOUNCEMENTS
Definition: app_queue.c:1432
struct ao2_container * members
Definition: app_queue.c:1752
static void free_members(struct call_queue *q, int all)
Iterate through queue&#39;s member list and delete them.
Definition: app_queue.c:3503
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_free(a)
Definition: astmm.h:182
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ destroy_queue_member_cb()

static void destroy_queue_member_cb ( void *  obj)
static

Definition at line 2676 of file app_queue.c.

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

Referenced by create_queue_member().

2677 {
2678  struct member *mem = obj;
2679 
2680  if (mem->state_id != -1) {
2682  }
2683 }
int ast_extension_state_del(int id, ast_state_cb_type change_cb)
Deletes a state change watcher by ID.
Definition: pbx.c:3858
static int extension_state_cb(const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
Definition: app_queue.c:2627
int state_id
Definition: app_queue.c:1597

◆ 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 2503 of file app_queue.c.

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, stasis_message_data(), stasis_message_type(), ast_device_state_message::state, member::state_interface, and update_status().

Referenced by load_module().

2504 {
2505  struct ao2_iterator miter, qiter;
2506  struct ast_device_state_message *dev_state;
2507  struct member *m;
2508  struct call_queue *q;
2509  char interface[80], *slash_pos;
2510  int found = 0; /* Found this member in any queue */
2511  int found_member; /* Found this member in this queue */
2512  int avail = 0; /* Found an available member in this queue */
2513 
2515  return;
2516  }
2517 
2518  dev_state = stasis_message_data(msg);
2519  if (dev_state->eid) {
2520  /* ignore non-aggregate states */
2521  return;
2522  }
2523 
2524  qiter = ao2_iterator_init(queues, 0);
2525  while ((q = ao2_t_iterator_next(&qiter, "Iterate over queues"))) {
2526  ao2_lock(q);
2527 
2528  avail = 0;
2529  found_member = 0;
2530  miter = ao2_iterator_init(q->members, 0);
2531  for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
2532  if (!found_member) {
2533  ast_copy_string(interface, m->state_interface, sizeof(interface));
2534 
2535  if ((slash_pos = strchr(interface, '/'))) {
2536  if (!strncasecmp(interface, "Local/", 6) && (slash_pos = strchr(slash_pos + 1, '/'))) {
2537  *slash_pos = '\0';
2538  }
2539  }
2540 
2541  if (!strcasecmp(interface, dev_state->device)) {
2542  found_member = 1;
2543  update_status(q, m, dev_state->state);
2544  }
2545  }
2546 
2547  /* check every member until we find one NOT_INUSE */
2548  if (!avail) {
2549  avail = is_member_available(q, m);
2550  }
2551  if (avail && found_member) {
2552  /* early exit as we've found an available member and the member of interest */
2553  ao2_ref(m, -1);
2554  break;
2555  }
2556  }
2557 
2558  if (found_member) {
2559  found = 1;
2560  if (avail) {
2562  } else {
2564  }
2565  }
2566 
2567  ao2_iterator_destroy(&miter);
2568 
2569  ao2_unlock(q);
2570  queue_t_unref(q, "Done with iterator");
2571  }
2572  ao2_iterator_destroy(&qiter);
2573 
2574  if (found) {
2575  ast_debug(1, "Device '%s' changed to state '%u' (%s)\n",
2576  dev_state->device,
2577  dev_state->state,
2578  ast_devstate2str(dev_state->state));
2579  } else {
2580  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",
2581  dev_state->device,
2582  dev_state->state,
2583  ast_devstate2str(dev_state->state));
2584  }
2585 
2586  return;
2587 }
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Convert device state to text string for output.
Definition: devicestate.c:237
char state_interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1596
enum ast_device_state state
Definition: devicestate.h:250
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
struct ao2_container * members
Definition: app_queue.c:1752
struct stasis_message_type * ast_device_state_message_type(void)
Get the Stasis message type for device state messages.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
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
static struct ao2_container * queues
Definition: app_queue.c:1766
const struct ast_eid * eid
The EID of the server where this message originated.
Definition: devicestate.h:248
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define ao2_t_iterator_next(iter, tag)
Definition: astobj2.h:1931
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
const ast_string_field name
Definition: app_queue.c:1696
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
static void update_status(struct call_queue *q, struct member *m, const int status)
set a member&#39;s status based on device state of that member&#39;s state_interface.
Definition: app_queue.c:2437
unsigned int found
Definition: app_queue.c:1713
#define queue_t_unref(q, tag)
Definition: app_queue.c:1921
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
The structure that contains device state.
Definition: devicestate.h:240
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
static int is_member_available(struct call_queue *q, struct member *mem)
Definition: app_queue.c:2468

◆ do_hang()

static void do_hang ( struct callattempt o)
static

common hangup actions

Definition at line 4358 of file app_queue.c.

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

Referenced by ring_entry(), and wait_for_answer().

4359 {
4360  o->stillgoing = 0;
4361  ast_hangup(o->chan);
4363  o->chan = NULL;
4364 }
#define NULL
Definition: resample.c:96
static void pending_members_remove(struct member *mem)
Definition: app_queue.c:2426
struct member * member
Definition: app_queue.c:1543
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2548
struct ast_channel * chan
Definition: app_queue.c:1540
unsigned int stillgoing
Definition: app_queue.c:1553

◆ do_print()

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

direct ouput to manager or cli with proper terminator

Definition at line 9644 of file app_queue.c.

References ast_cli(), and astman_append().

Referenced by __queues_show(), and print_queue().

9645 {
9646  if (s) {
9647  astman_append(s, "%s\r\n", str);
9648  } else {
9649  ast_cli(fd, "%s\n", str);
9650  }
9651 }
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
const char * str
Definition: app_jack.c:147
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6

◆ 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>[|...]

Definition at line 7269 of file app_queue.c.

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, member::reason_paused, member::state_interface, value, and member::wrapuptime.

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

7270 {
7271  struct member *cur_member;
7272  struct ast_str *value;
7273  struct ao2_iterator mem_iter;
7274 
7275  if (!pm_queue) {
7276  return;
7277  }
7278 
7279  /* 4K is a reasonable default for most applications, but we grow to
7280  * accommodate more if necessary. */
7281  if (!(value = ast_str_create(4096))) {
7282  return;
7283  }
7284 
7285  mem_iter = ao2_iterator_init(pm_queue->members, 0);
7286  while ((cur_member = ao2_iterator_next(&mem_iter))) {
7287  if (!cur_member->dynamic) {
7288  ao2_ref(cur_member, -1);
7289  continue;
7290  }
7291 
7292  ast_str_append(&value, 0, "%s%s;%d;%d;%s;%s;%s;%d",
7293  ast_str_strlen(value) ? "|" : "",
7294  cur_member->interface,
7295  cur_member->penalty,
7296  cur_member->paused,
7297  cur_member->membername,
7298  cur_member->state_interface,
7299  cur_member->reason_paused,
7300  cur_member->wrapuptime);
7301 
7302  ao2_ref(cur_member, -1);
7303  }
7304  ao2_iterator_destroy(&mem_iter);
7305 
7306  if (ast_str_strlen(value) && !cur_member) {
7307  if (ast_db_put(pm_family, pm_queue->name, ast_str_buffer(value))) {
7308  ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n");
7309  }
7310  } else {
7311  /* Delete the entry if the queue is empty or there is an error */
7312  ast_db_del(pm_family, pm_queue->name);
7313  }
7314 
7315  ast_free(value);
7316 }
int dynamic
Definition: app_queue.c:1601
int paused
Definition: app_queue.c:1604
char state_interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1596
int wrapuptime
Definition: app_queue.c:1608
#define LOG_WARNING
Definition: logger.h:274
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
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:1091
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
int value
Definition: syslog.c:37
struct ao2_container * members
Definition: app_queue.c:1752
char membername[80]
Definition: app_queue.c:1598
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1593
#define ast_log
Definition: astobj2.c:42
int penalty
Definition: app_queue.c:1599
#define ao2_ref(o, delta)
Definition: astobj2.h:464
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
const ast_string_field name
Definition: app_queue.c:1696
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
char reason_paused[80]
Definition: app_queue.c:1605
#define ast_free(a)
Definition: astmm.h:182
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:688
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: main/db.c:429
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: main/db.c:327
static const char *const pm_family
Persistent Members astdb family.
Definition: app_queue.c:1463
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ast_str_create(init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:620

◆ end_bridge_callback()

static void end_bridge_callback ( void *  data)
static

Definition at line 6575 of file app_queue.c.

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

Referenced by try_calling().

6576 {
6577  struct queue_end_bridge *qeb = data;
6578  struct call_queue *q = qeb->q;
6579  struct ast_channel *chan = qeb->chan;
6580 
6581  if (ao2_ref(qeb, -1) == 1) {
6582  set_queue_variables(q, chan);
6583  /* This unrefs the reference we made in try_calling when we allocated qeb */
6584  queue_t_unref(q, "Expire bridge_config reference");
6585  }
6586 }
Main Channel structure associated with a channel.
struct call_queue * q
Definition: app_queue.c:6564
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_channel * chan
Definition: app_queue.c:6565
#define queue_t_unref(q, tag)
Definition: app_queue.c:1921
static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
Set variables of queue.
Definition: app_queue.c:1926

◆ 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 6568 of file app_queue.c.

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

Referenced by try_calling().

6569 {
6570  struct queue_end_bridge *qeb = bconfig->end_bridge_callback_data;
6571  ao2_ref(qeb, +1);
6572  qeb->chan = originator;
6573 }
void * end_bridge_callback_data
Definition: channel.h:1092
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_channel * chan
Definition: app_queue.c:6565

◆ escape_and_substitute()

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

Definition at line 6617 of file app_queue.c.

References input(), and pbx_substitute_variables_helper().

Referenced by setup_mixmonitor().

6619 {
6620  const char *m = input;
6621  char escaped[size];
6622  char *p;
6623 
6624  for (p = escaped; p < escaped + size - 1; p++, m++) {
6625  switch (*m) {
6626  case '^':
6627  if (*(m + 1) == '{') {
6628  *p = '$';
6629  }
6630  break;
6631  case ',':
6632  *p++ = '\\';
6633  /* Fall through */
6634  default:
6635  *p = *m;
6636  }
6637  if (*m == '\0')
6638  break;
6639  }
6640 
6641  if (p == escaped + size) {
6642  escaped[size - 1] = '\0';
6643  }
6644 
6645  pbx_substitute_variables_helper(chan, escaped, output, size - 1);
6646 }
static int input(yyscan_t yyscanner)
Definition: ast_expr2f.c:1584
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: ael_main.c:211

◆ 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 2627 of file app_queue.c.

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, ast_state_cb_info::exten_state, extensionstate2devicestate(), call_queue::found, call_queue::members, queue_t_unref, ast_state_cb_info::reason, member::state_context, member::state_exten, and update_status().

Referenced by create_queue_member(), and destroy_queue_member_cb().

2628 {
2629  struct ao2_iterator miter, qiter;
2630  struct member *m;
2631  struct call_queue *q;
2632  int state = info->exten_state;
2633  int found = 0, device_state = extensionstate2devicestate(state);
2634 
2635  /* only interested in extension state updates involving device states */
2636  if (info->reason != AST_HINT_UPDATE_DEVICE) {
2637  return 0;
2638  }
2639 
2640  qiter = ao2_iterator_init(queues, 0);
2641  while ((q = ao2_t_iterator_next(&qiter, "Iterate through queues"))) {
2642  ao2_lock(q);
2643 
2644  miter = ao2_iterator_init(q->members, 0);
2645  for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
2646  if (!strcmp(m->state_context, context) && !strcmp(m->state_exten, exten)) {
2647  update_status(q, m, device_state);
2648  ao2_ref(m, -1);
2649  found = 1;
2650  break;
2651  }
2652  }
2653  ao2_iterator_destroy(&miter);
2654 
2655  ao2_unlock(q);
2656  queue_t_unref(q, "Done with iterator");
2657  }
2658  ao2_iterator_destroy(&qiter);
2659 
2660  if (found) {
2661  ast_debug(1, "Extension '%s@%s' changed to state '%d' (%s)\n", exten, context, device_state, ast_devstate2str(device_state));
2662  } else {
2663  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",
2664  exten, context, device_state, ast_devstate2str(device_state));
2665  }
2666 
2667  return 0;
2668 }
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Convert device state to text string for output.
Definition: devicestate.c:237
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
enum ast_state_cb_update_reason reason
Definition: pbx.h:103
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
struct ao2_container * members
Definition: app_queue.c:1752
enum ast_extension_states exten_state
Definition: pbx.h:104
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
static struct ao2_container * queues
Definition: app_queue.c:1766
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define ao2_t_iterator_next(iter, tag)
Definition: astobj2.h:1931
static int extensionstate2devicestate(int state)
Helper function which converts from extension state to device state values.
Definition: app_queue.c:2590
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
static void update_status(struct call_queue *q, struct member *m, const int status)
set a member&#39;s status based on device state of that member&#39;s state_interface.
Definition: app_queue.c:2437
unsigned int found
Definition: app_queue.c:1713
#define queue_t_unref(q, tag)
Definition: app_queue.c:1921
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
char state_context[AST_MAX_CONTEXT]
Definition: app_queue.c:1595
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
char state_exten[AST_MAX_EXTENSION]
Definition: app_queue.c:1594

◆ extensionstate2devicestate()

static int extensionstate2devicestate ( int  state)
static

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

Definition at line 2590 of file app_queue.c.

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().

2591 {
2592  switch (state) {
2595  break;
2596  case AST_EXTENSION_INUSE:
2598  break;
2599  case AST_EXTENSION_BUSY:
2601  break;
2602  case AST_EXTENSION_RINGING:
2604  break;
2607  break;
2608  case AST_EXTENSION_ONHOLD:
2610  break;
2613  break;
2616  break;
2617  case AST_EXTENSION_REMOVED:
2619  default:
2621  break;
2622  }
2623 
2624  return state;
2625 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959

◆ find_best()

static struct callattempt* find_best ( struct callattempt outgoing)
static

find the entry with the best metric, or NULL

Definition at line 4614 of file app_queue.c.

References callattempt::metric, NULL, and callattempt::q_next.

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

4615 {
4616  struct callattempt *best = NULL, *cur;
4617 
4618  for (cur = outgoing; cur; cur = cur->q_next) {
4619  if (cur->stillgoing && /* Not already done */
4620  !cur->chan && /* Isn't already going */
4621  (!best || cur->metric < best->metric)) { /* We haven't found one yet, or it's better */
4622  best = cur;
4623  }
4624  }
4625 
4626  return best;
4627 }
struct callattempt * q_next
Definition: app_queue.c:1538
#define NULL
Definition: resample.c:96
We define a custom "local user" structure because we use it not only for keeping track of what is in ...
Definition: app_queue.c:1537

◆ 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 3702 of file app_queue.c.

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, call_queue::realtime, SENTINEL, update_realtime_members(), 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(), queue_function_exists(), queue_function_mem_read(), queue_function_qac_dep(), queue_function_queuememberlist(), queue_function_var(), qupd_exec(), reload_queue_members(), and set_member_value().

3703 {
3704  struct ast_variable *queue_vars;
3705  struct ast_config *member_config = NULL;
3706  struct call_queue *q = NULL, tmpq = {
3707  .name = queuename,
3708  };
3709  int prev_weight = 0;
3710 
3711  /* Find the queue in the in-core list first. */
3712  q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Look for queue in memory first");
3713 
3714  if (!q || q->realtime) {
3715  /*! \note Load from realtime before taking the "queues" container lock, to avoid blocking all
3716  queue operations while waiting for the DB.
3717 
3718  This will be two separate database transactions, so we might
3719  see queue parameters as they were before another process
3720  changed the queue and member list as it was after the change.
3721  Thus we might see an empty member list when a queue is
3722  deleted. In practise, this is unlikely to cause a problem. */
3723 
3724  queue_vars = ast_load_realtime("queues", "name", queuename, SENTINEL);
3725  if (queue_vars) {
3726  member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, SENTINEL);
3727  if (!member_config) {
3728  ast_debug(1, "No queue_members defined in config extconfig.conf\n");
3729  member_config = ast_config_new();
3730  }
3731  }
3732  if (q) {
3733  prev_weight = q->weight ? 1 : 0;
3734  queue_t_unref(q, "Need to find realtime queue");
3735  }
3736 
3737  q = find_queue_by_name_rt(queuename, queue_vars, member_config);
3738  ast_config_destroy(member_config);
3739  ast_variables_destroy(queue_vars);
3740 
3741  /* update the use_weight value if the queue's has gained or lost a weight */
3742  if (q) {
3743  if (!q->weight && prev_weight) {
3745  }
3746  if (q->weight && !prev_weight) {
3748  }
3749  }
3750  /* Other cases will end up with the proper value for use_weight */
3751  } else {
3753  }
3754  return q;
3755 }
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
Definition: main/config.c:3339
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1263
static void update_realtime_members(struct call_queue *q)
Definition: app_queue.c:3773
#define OBJ_POINTER
Definition: astobj2.h:1154
Structure for variables, used for configurations and for channel variables.
#define NULL
Definition: resample.c:96
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:755
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define SENTINEL
Definition: compiler.h:87
static struct ao2_container * queues
Definition: app_queue.c:1766
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: extconf.c:1290
struct ast_config * ast_config_new(void)
Create a new base configuration structure.
Definition: extconf.c:3276
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
Definition: main/config.c:3452
#define queue_t_unref(q, tag)
Definition: app_queue.c:1921
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:3558
unsigned int realtime
Definition: app_queue.c:1712
#define ao2_t_find(container, arg, flags, tag)
Definition: astobj2.h:1754
static int use_weight
Records that one or more queues use weight.
Definition: app_queue.c:1469

◆ find_member_by_queuename_and_interface()

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

Definition at line 11484 of file app_queue.c.

References ao2_find, ao2_lock, ao2_unlock, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_DEVSTATE_CONSUMER, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ASTERISK_GPL_KEY, find_load_queue_rt_friendly(), load_module(), call_queue::members, NULL, OBJ_KEY, queue_t_unref, reload(), and unload_module().

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

11485 {
11486  struct member *mem = NULL;
11487  struct call_queue *q;
11488 
11489  if ((q = find_load_queue_rt_friendly(queuename))) {
11490  ao2_lock(q);
11491  mem = ao2_find(q->members, interface, OBJ_KEY);
11492  ao2_unlock(q);
11493  queue_t_unref(q, "Expiring temporary reference.");
11494  }
11495  return mem;
11496 }
static struct call_queue * find_load_queue_rt_friendly(const char *queuename)
Definition: app_queue.c:3702
#define OBJ_KEY
Definition: astobj2.h:1155
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
struct ao2_container * members
Definition: app_queue.c:1752
#define ao2_lock(a)
Definition: astobj2.h:718
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define queue_t_unref(q, tag)
Definition: app_queue.c:1921

◆ 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 3558 of file app_queue.c.

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_WARNING, member_remove_from_queue(), member::membername, call_queue::members, ast_variable::name, call_queue::name, ast_variable::next, NULL, OBJ_POINTER, queue_set_param(), QUEUE_STRATEGY_RINGALL, queue_t_unref, 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().

3559 {
3560  struct ast_variable *v;
3561  struct call_queue *q, tmpq = {
3562  .name = queuename,
3563  };
3564  struct member *m;
3565  struct ao2_iterator mem_iter;
3566  char *category = NULL;
3567  const char *tmp_name;
3568  char *tmp;
3569  char tmpbuf[64]; /* Must be longer than the longest queue param name. */
3570 
3571  /* Static queues override realtime. */
3572  if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Check if static queue exists"))) {
3573  ao2_lock(q);
3574  if (!q->realtime) {
3575  if (q->dead) {
3576  ao2_unlock(q);
3577  queue_t_unref(q, "Queue is dead; can't return it");
3578  return NULL;
3579  }
3580  ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
3581  ao2_unlock(q);
3582  return q;
3583  }
3584  } else if (!member_config) {
3585  /* Not found in the list, and it's not realtime ... */
3586  return NULL;
3587  }
3588  /* Check if queue is defined in realtime. */
3589  if (!queue_vars) {
3590  /* Delete queue from in-core list if it has been deleted in realtime. */
3591  if (q) {
3592  /*! \note Hmm, can't seem to distinguish a DB failure from a not
3593  found condition... So we might delete an in-core queue
3594  in case of DB failure. */
3595  ast_debug(1, "Queue %s not found in realtime.\n", queuename);
3596 
3597  q->dead = 1;
3598  /* Delete if unused (else will be deleted when last caller leaves). */
3599  queues_t_unlink(queues, q, "Unused; removing from container");
3600  ao2_unlock(q);
3601  queue_t_unref(q, "Queue is dead; can't return it");
3602  }
3603  return NULL;
3604  }
3605 
3606  /* Create a new queue if an in-core entry does not exist yet. */
3607  if (!q) {
3608  struct ast_variable *tmpvar = NULL;
3609  if (!(q = alloc_queue(queuename))) {
3610  return NULL;
3611  }
3612  ao2_lock(q);
3613  clear_queue(q);
3614  q->realtime = 1;
3615  /*Before we initialize the queue, we need to set the strategy, so that linear strategy
3616  * will allocate the members properly
3617  */
3618  for (tmpvar = queue_vars; tmpvar; tmpvar = tmpvar->next) {
3619  if (!strcasecmp(tmpvar->name, "strategy")) {
3620  q->strategy = strat2int(tmpvar->value);
3621  if (q->strategy < 0) {
3622  ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
3623  tmpvar->value, q->name);
3625  }
3626  break;
3627  }
3628  }
3629  /* We traversed all variables and didn't find a strategy */
3630  if (!tmpvar) {
3632  }
3633  queues_t_link(queues, q, "Add queue to container");
3634  }
3635  init_queue(q); /* Ensure defaults for all parameters not set explicitly. */
3636 
3637  memset(tmpbuf, 0, sizeof(tmpbuf));
3638  for (v = queue_vars; v; v = v->next) {
3639  /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
3640  if (strchr(v->name, '_')) {
3641  ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
3642  tmp_name = tmpbuf;
3643  tmp = tmpbuf;
3644  while ((tmp = strchr(tmp, '_'))) {
3645  *tmp++ = '-';
3646  }
3647  } else {
3648  tmp_name = v->name;
3649  }
3650 
3651  /* NULL values don't get returned from realtime; blank values should
3652  * still get set. If someone doesn't want a value to be set, they
3653  * should set the realtime column to NULL, not blank. */
3654  queue_set_param(q, tmp_name, v->value, -1, 0);
3655  }
3656 
3657  /* Temporarily set realtime members dead so we can detect deleted ones. */
3658  mem_iter = ao2_iterator_init(q->members, 0);
3659  while ((m = ao2_iterator_next(&mem_iter))) {
3660  if (m->realtime) {
3661  m->dead = 1;
3662  }
3663  ao2_ref(m, -1);
3664  }
3665  ao2_iterator_destroy(&mem_iter);
3666 
3667  while ((category = ast_category_browse(member_config, category))) {
3668  rt_handle_member_record(q, category, member_config);
3669  }
3670 
3671  /* Delete all realtime members that have been deleted in DB. */
3672  mem_iter = ao2_iterator_init(q->members, 0);
3673  while ((m = ao2_iterator_next(&mem_iter))) {
3674  if (m->dead) {
3676  ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
3677  } else {
3678  ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
3679  }
3681  }
3682  ao2_ref(m, -1);
3683  }
3684  ao2_iterator_destroy(&mem_iter);
3685 
3686  ao2_unlock(q);
3687 
3688  return q;
3689 }
struct ast_variable * next
#define OBJ_POINTER
Definition: astobj2.h:1154
#define LOG_WARNING
Definition: logger.h:274
static void member_remove_from_queue(struct call_queue *queue, struct member *mem)
Definition: app_queue.c:3376
static int tmp()
Definition: bt_open.c:389
Structure for variables, used for configurations and for channel variables.
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:894
static int log_membername_as_agent
queues.conf [general] option
Definition: app_queue.c:1490
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
int realtime
Definition: app_queue.c:1602
#define ao2_unlock(a)
Definition: astobj2.h:730
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3328
unsigned int dead
Definition: app_queue.c:1613
#define NULL
Definition: resample.c:96
static void clear_queue(struct call_queue *q)
Definition: app_queue.c:2863
struct ao2_container * members
Definition: app_queue.c:1752
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:3392
char membername[80]
Definition: app_queue.c:1598
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1593
static int strat2int(const char *strategy)
Definition: app_queue.c:1800
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
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:3144
static struct ao2_container * queues
Definition: app_queue.c:1766
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
int strategy
Definition: app_queue.c:1711
unsigned int dead
Definition: app_queue.c:1699
const ast_string_field name
Definition: app_queue.c:1696
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
static struct call_queue * alloc_queue(const char *queuename)
Definition: app_queue.c:3534
#define queues_t_link(c, q, tag)
Definition: app_queue.c:1922
#define queue_t_unref(q, tag)
Definition: app_queue.c:1921
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
unsigned int realtime
Definition: app_queue.c:1712
#define ao2_t_find(container, arg, flags, tag)
Definition: astobj2.h:1754
static void init_queue(struct call_queue *q)
Initialize Queue default values.
Definition: app_queue.c:2769
#define queues_t_unlink(c, q, tag)
Definition: app_queue.c:1923
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ 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 3503 of file app_queue.c.

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().

3504 {
3505  /* Free non-dynamic members */
3506  struct member *cur;
3507  struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
3508 
3509  while ((cur = ao2_iterator_next(&mem_iter))) {
3510  if (all || !cur->dynamic) {
3511  member_remove_from_queue(q, cur);
3512  }
3513  ao2_ref(cur, -1);
3514  }
3515  ao2_iterator_destroy(&mem_iter);
3516 }
int dynamic
Definition: app_queue.c:1601
static void member_remove_from_queue(struct call_queue *queue, struct member *mem)
Definition: app_queue.c:3376
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct ao2_container * members
Definition: app_queue.c:1752
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.

◆ get_interface_helper()

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

Definition at line 8618 of file app_queue.c.

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

Referenced by queue_function_mem_read().

8619 {
8620  struct member *m;
8621 
8622  if (ast_strlen_zero(interface)) {
8623  ast_log(LOG_ERROR, "QUEUE_MEMBER: Missing required interface argument.\n");
8624  return NULL;
8625  }
8626 
8627  m = interface_exists(q, interface);
8628  if (!m) {
8629  ast_log(LOG_ERROR, "Queue member interface '%s' not in queue '%s'.\n",
8630  interface, q->name);
8631  }
8632  return m;
8633 }
#define NULL
Definition: resample.c:96
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1593
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
static struct member * interface_exists(struct call_queue *q, const char *interface)
Definition: app_queue.c:7242
#define LOG_ERROR
Definition: logger.h:285
const ast_string_field name
Definition: app_queue.c:1696

◆ get_member_penalty()

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

Definition at line 7740 of file app_queue.c.

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

Referenced by queue_function_memberpenalty_read().

7741 {
7742  int foundqueue = 0, penalty;
7743  struct call_queue *q;
7744  struct member *mem;
7745 
7746  if ((q = find_load_queue_rt_friendly(queuename))) {
7747  foundqueue = 1;
7748  ao2_lock(q);
7749  if ((mem = interface_exists(q, interface))) {
7750  penalty = mem->penalty;
7751  ao2_ref(mem, -1);
7752  ao2_unlock(q);
7753  queue_t_unref(q, "Search complete");
7754  return penalty;
7755  }
7756  ao2_unlock(q);
7757  queue_t_unref(q, "Search complete");
7758  }
7759 
7760  /* some useful debuging */
7761  if (foundqueue) {
7762  ast_log (LOG_ERROR, "Invalid queuename\n");
7763  } else {
7764  ast_log (LOG_ERROR, "Invalid interface\n");
7765  }
7766 
7767  return RESULT_FAILURE;
7768 }
static struct call_queue * find_load_queue_rt_friendly(const char *queuename)
Definition: app_queue.c:3702
#define ao2_unlock(a)
Definition: astobj2.h:730
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1593
#define ast_log
Definition: astobj2.c:42
int penalty
Definition: app_queue.c:1599
static struct member * interface_exists(struct call_queue *q, const char *interface)
Definition: app_queue.c:7242
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
#define LOG_ERROR
Definition: logger.h:285
#define queue_t_unref(q, tag)
Definition: app_queue.c:1921
#define RESULT_FAILURE
Definition: cli.h:42

◆ 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 2284 of file app_queue.c.

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_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 join_queue(), queue_exec(), and wait_our_turn().

2285 {
2286  struct member *member;
2287  struct ao2_iterator mem_iter;
2288 
2289  ao2_lock(q);
2290  mem_iter = ao2_iterator_init(q->members, 0);
2291  for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
2292  int penalty = member->penalty;
2293  if (raise_penalty != INT_MAX && penalty < raise_penalty) {
2294  ast_debug(4, "%s is having his penalty raised up from %d to %d\n", member->membername, penalty, raise_penalty);
2295  penalty = raise_penalty;
2296  }
2297  if ((max_penalty != INT_MAX && penalty > max_penalty) || (min_penalty != INT_MAX && penalty < min_penalty)) {
2298  if (conditions & QUEUE_EMPTY_PENALTY) {
2299  ast_debug(4, "%s is unavailable because his penalty is not between %d and %d\n", member->membername, min_penalty, max_penalty);
2300  continue;
2301  }
2302  }
2303 
2304  switch (devstate ? ast_device_state(member->state_interface) : member->status) {
2305  case AST_DEVICE_INVALID:
2306  if (conditions & QUEUE_EMPTY_INVALID) {
2307  ast_debug(4, "%s is unavailable because his device state is 'invalid'\n", member->membername);
2308  break;
2309  }
2310  goto default_case;
2312  if (conditions & QUEUE_EMPTY_UNAVAILABLE) {
2313  ast_debug(4, "%s is unavailable because his device state is 'unavailable'\n", member->membername);
2314  break;
2315  }
2316  goto default_case;
2317  case AST_DEVICE_INUSE:
2318  if (conditions & QUEUE_EMPTY_INUSE) {
2319  ast_debug(4, "%s is unavailable because his device state is 'inuse'\n", member->membername);
2320  break;
2321  }
2322  goto default_case;
2323  case AST_DEVICE_RINGING:
2324  if (conditions & QUEUE_EMPTY_RINGING) {
2325  ast_debug(4, "%s is unavailable because his device state is 'ringing'\n", member->membername);
2326  break;
2327  }
2328  goto default_case;
2329  case AST_DEVICE_UNKNOWN:
2330  if (conditions & QUEUE_EMPTY_UNKNOWN) {
2331  ast_debug(4, "%s is unavailable because his device state is 'unknown'\n", member->membername);
2332  break;
2333  }
2334  /* Fall-through */
2335  default:
2336  default_case:
2337  if (member->paused && (conditions & QUEUE_EMPTY_PAUSED)) {
2338  ast_debug(4, "%s is unavailable because he is paused'\n", member->membername);
2339  break;
2340  } else if ((conditions & QUEUE_EMPTY_WRAPUP)
2341  && member->lastcall
2342  && get_wrapuptime(q, member)
2343  && (time(NULL) - get_wrapuptime(q, member) < member->lastcall)) {
2344  ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n",
2345  member->membername, (int) (time(NULL) - member->lastcall), get_wrapuptime(q, member));
2346  break;
2347  } else {
2348  ao2_ref(member, -1);
2349  ao2_iterator_destroy(&mem_iter);
2350  ao2_unlock(q);
2351  ast_debug(4, "%s is available.\n", member->membername);
2352  return 0;
2353  }
2354  break;
2355  }
2356  }
2357  ao2_iterator_destroy(&mem_iter);
2358  ao2_unlock(q);
2359 
2360  if (!devstate && (conditions & QUEUE_EMPTY_RINGING)) {
2361  /* member state still may be RINGING due to lag in event message - check again with device state */
2362  return get_member_status(q, max_penalty, min_penalty, raise_penalty, conditions, 1);
2363  }
2364  return -1;
2365 }
ast_device_state
Device States.
Definition: devicestate.h:52
int paused
Definition: app_queue.c:1604
char state_interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1596
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
struct ao2_container * members
Definition: app_queue.c:1752
char membername[80]
Definition: app_queue.c:1598
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
int penalty
Definition: app_queue.c:1599
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
static int get_wrapuptime(struct call_queue *q, struct member *member)
Return wrapuptime.
Definition: app_queue.c:1856
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
int status
Definition: app_queue.c:1603
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
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:2284
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
time_t lastcall
Definition: app_queue.c:1610

◆ get_queue_member_status()

static int get_queue_member_status ( struct member cur)
static

Return the current state of a member.

Definition at line 2671 of file app_queue.c.

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().

2672 {
2673  return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten));
2674 }
ast_device_state
Device States.
Definition: devicestate.h:52
char state_interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1596
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
static int extensionstate2devicestate(int state)
Helper function which converts from extension state to device state values.
Definition: app_queue.c:2590
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
char state_exten[AST_MAX_EXTENSION]
Definition: app_queue.c:1594

◆ 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 1856 of file app_queue.c.

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

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

1857 {
1858  if (member->wrapuptime) {
1859  return member->wrapuptime;
1860  }
1861  return q->wrapuptime;
1862 }
int wrapuptime
Definition: app_queue.c:1737
int wrapuptime
Definition: app_queue.c:1608

◆ 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.
topicThe topic for this event.
msgThe stasis message for the attended transfer event.

Definition at line 6206 of file app_queue.c.

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().

6208 {
6209  struct queue_stasis_data *queue_data = userdata;
6210  struct ast_attended_transfer_message *atxfer_msg = stasis_message_data(msg);
6211  RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
6212  RAII_VAR(struct ast_channel_snapshot *, member_snapshot, NULL, ao2_cleanup);
6213 
6214  if (atxfer_msg->result != AST_BRIDGE_TRANSFER_SUCCESS ||
6216  return;
6217  }
6218 
6219  ao2_lock(queue_data);
6220 
6221  if (queue_data->dying) {
6222  ao2_unlock(queue_data);
6223  return;
6224  }
6225 
6226  if (ast_strlen_zero(queue_data->bridge_uniqueid)) {
6227  ao2_unlock(queue_data);
6228  return;
6229  }
6230 
6231  if ((!atxfer_msg->to_transferee.bridge_snapshot || strcmp(queue_data->bridge_uniqueid,
6232  atxfer_msg->to_transferee.bridge_snapshot->uniqueid)) &&
6233  (!atxfer_msg->to_transfer_target.bridge_snapshot || strcmp(queue_data->bridge_uniqueid,
6234  atxfer_msg->to_transfer_target.bridge_snapshot->uniqueid))) {
6235  ao2_unlock(queue_data);
6236  return;
6237  }
6238 
6239  caller_snapshot = ast_channel_snapshot_get_latest(queue_data->caller_uniqueid);
6240  member_snapshot = ast_channel_snapshot_get_latest(queue_data->member_uniqueid);
6241 
6242  ao2_unlock(queue_data);
6243 
6244  ast_debug(3, "Detected attended transfer in queue %s\n", queue_data->queue->name);
6245  log_attended_transfer(queue_data, atxfer_msg);
6246 
6247  send_agent_complete(queue_data->queue->name, caller_snapshot, member_snapshot, queue_data->member,
6248  queue_data->holdstart, queue_data->starttime, TRANSFER);
6249  update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl,
6250  queue_data->starttime);
6251  remove_stasis_subscriptions(queue_data);
6252 }
Message representing attended transfer.
Structure representing a snapshot of channel state.
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
struct ast_bridge_channel_snapshot_pair to_transferee
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_bridge_channel_snapshot_pair to_transfer_target
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
enum ast_transfer_result result
struct call_queue * queue
Definition: app_queue.c:5967
#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:911
struct member * member
Definition: app_queue.c:5969
static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl, time_t starttime)
update the queue status
Definition: app_queue.c:5707
#define ao2_lock(a)
Definition: astobj2.h:718
const ast_string_field member_uniqueid
Definition: app_queue.c:5965
static void log_attended_transfer(struct queue_stasis_data *queue_data, struct ast_attended_transfer_message *atxfer_msg)
Definition: app_queue.c:6065
enum ast_attended_transfer_dest_type dest_type
const ast_string_field bridge_uniqueid
Definition: app_queue.c:5965
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
const ast_string_field name
Definition: app_queue.c:1696
const ast_string_field caller_uniqueid
Definition: app_queue.c:5965
struct ast_bridge_snapshot * bridge_snapshot
const ast_string_field uniqueid
Definition: bridge.h:336
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:5864
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...
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
User data for stasis subscriptions used for queue calls.
Definition: app_queue.c:5957
static void remove_stasis_subscriptions(struct queue_stasis_data *queue_data)
Definition: app_queue.c:6011

◆ 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.
topicThe topic for this event.
msgThe stasis message for the blind transfer event

Definition at line 6146 of file app_queue.c.

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, context, ast_blind_transfer_message::context, queue_stasis_data::dying, exten, 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().

6148 {
6149  struct queue_stasis_data *queue_data = userdata;
6150  struct ast_blind_transfer_message *transfer_msg = stasis_message_data(msg);
6151  const char *exten;
6152  const char *context;
6153  RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
6154  RAII_VAR(struct ast_channel_snapshot *, member_snapshot, NULL, ao2_cleanup);
6155 
6156  if (transfer_msg->result != AST_BRIDGE_TRANSFER_SUCCESS) {
6157  return;
6158  }
6159 
6160  ao2_lock(queue_data);
6161 
6162  if (queue_data->dying) {
6163  ao2_unlock(queue_data);
6164  return;
6165  }
6166 
6167  if (ast_strlen_zero(queue_data->bridge_uniqueid) ||
6168  strcmp(queue_data->bridge_uniqueid, transfer_msg->bridge->uniqueid)) {
6169  ao2_unlock(queue_data);
6170  return;
6171  }
6172 
6173  caller_snapshot = ast_channel_snapshot_get_latest(queue_data->caller_uniqueid);
6174  member_snapshot = ast_channel_snapshot_get_latest(queue_data->member_uniqueid);
6175 
6176  ao2_unlock(queue_data);
6177 
6178  exten = transfer_msg->exten;
6179  context = transfer_msg->context;
6180 
6181  ast_debug(3, "Detected blind transfer in queue %s\n", queue_data->queue->name);
6182  ast_queue_log(queue_data->queue->name, queue_data->caller_uniqueid, queue_data->member->membername,
6183  "BLINDTRANSFER", "%s|%s|%ld|%ld|%d",
6184  exten, context,
6185  (long) (queue_data->starttime - queue_data->holdstart),
6186  (long) (time(NULL) - queue_data->starttime), queue_data->caller_pos);
6187 
6188  send_agent_complete(queue_data->queue->name, caller_snapshot, member_snapshot, queue_data->member,
6189  queue_data->holdstart, queue_data->starttime, TRANSFER);
6190  update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl,
6191  queue_data->starttime);
6192  remove_stasis_subscriptions(queue_data);
6193 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
char exten[AST_MAX_EXTENSION]
Message published during a blind transfer.
Structure representing a snapshot of channel state.
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:894
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
char membername[80]
Definition: app_queue.c:1598
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
struct call_queue * queue
Definition: app_queue.c:5967
#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:911
struct member * member
Definition: app_queue.c:5969
static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl, time_t starttime)
update the queue status
Definition: app_queue.c:5707
#define ao2_lock(a)
Definition: astobj2.h:718
struct ast_bridge_snapshot * bridge
const ast_string_field member_uniqueid
Definition: app_queue.c:5965
const ast_string_field bridge_uniqueid
Definition: app_queue.c:5965
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
const ast_string_field name
Definition: app_queue.c:1696
const ast_string_field caller_uniqueid
Definition: app_queue.c:5965
char context[AST_MAX_CONTEXT]
const ast_string_field uniqueid
Definition: bridge.h:336
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:5864
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...
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
User data for stasis subscriptions used for queue calls.
Definition: app_queue.c:5957
static void remove_stasis_subscriptions(struct queue_stasis_data *queue_data)
Definition: app_queue.c:6011
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
enum ast_transfer_result result

◆ handle_bridge_enter()

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

Definition at line 6112 of file app_queue.c.

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_channel_snapshot_base::uniqueid, and ast_bridge_snapshot::uniqueid.

Referenced by setup_stasis_subs().

6114 {
6115  struct queue_stasis_data *queue_data = userdata;
6116  struct ast_bridge_blob *enter_blob = stasis_message_data(msg);
6117  SCOPED_AO2LOCK(lock, queue_data);
6118 
6119  if (queue_data->dying) {
6120  return;
6121  }
6122 
6123  if (!ast_strlen_zero(queue_data->bridge_uniqueid)) {
6124  return;
6125  }
6126 
6127  if (!strcmp(enter_blob->channel->base->uniqueid, queue_data->caller_uniqueid)) {
6128  ast_string_field_set(queue_data, bridge_uniqueid,
6129  enter_blob->bridge->uniqueid);
6130  ast_debug(3, "Detected entry of caller channel %s into bridge %s\n",
6131  enter_blob->channel->base->name, queue_data->