Asterisk - The Open Source Telephony Project  GIT-master-9ed6387
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"

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)
 
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 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 = AST_BUILDOPT_SUM, .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 update_cdr
 queues.conf [general] option More...
 
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 1639 of file app_queue.c.

Referenced by queue_set_param().

◆ ANNOUNCEHOLDTIME_ONCE

#define ANNOUNCEHOLDTIME_ONCE   2

Definition at line 1640 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 1657 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 1656 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 1655 of file app_queue.c.

Referenced by queue_set_param().

◆ ANNOUNCEPOSITION_YES

#define ANNOUNCEPOSITION_YES   1

We announce position

Definition at line 1654 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 4920 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 2379 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 1641 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 1921 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 1923 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 3349 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; })

Definition at line 1922 of file app_queue.c.

Referenced by queue_exec(), queue_stasis_data_destructor(), and set_member_value().

◆ queues_t_link

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

Definition at line 1925 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 1926 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 5853 of file app_queue.c.

5853  {
5854  CALLER,
5855  AGENT,
5856  TRANSFER
5857 };

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

◆ member_properties

Enumerator
MEMBER_PENALTY 
MEMBER_RINGINUSE 

Definition at line 1633 of file app_queue.c.

1633  {
1634  MEMBER_PENALTY = 0,
1635  MEMBER_RINGINUSE = 1,
1636 };

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

◆ queue_timeout_priority

Enumerator
TIMEOUT_PRIORITY_APP 
TIMEOUT_PRIORITY_CONF 

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

References ao2_container_count(), ao2_iterator_destroy(), AO2_ITERATOR_DONTLOCK, ao2_iterator_init(), ao2_iterator_next, ao2_lock, ao2_ref, ao2_t_iterator_next, ao2_unlock, ast_category_browse(), ast_channel_name(), ast_check_realtime(), ast_config_destroy(), AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_devstate2str(), ast_load_realtime_multientry(), ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_strlen_zero, ast_term_color(), ast_term_reset(), ast_variable_retrieve(), member::calls, call_queue::callsabandoned, call_queue::callsabandonedinsl, call_queue::callscompleted, call_queue::callscompletedinsl, queue_ent::chan, CLI_SHOWUSAGE, CLI_SUCCESS, COLOR_BLACK, COLOR_BROWN, COLOR_CYAN, COLOR_GREEN, COLOR_MAGENTA, COLOR_RED, call_queue::count, do_print(), member::dynamic, find_load_queue_rt_friendly(), call_queue::head, call_queue::holdtime, int2strat(), member::interface, member::lastcall, member::lastpause, call_queue::maxlen, member::membername, call_queue::members, call_queue::name, queue_ent::next, NULL, out, member::paused, member::penalty, queue_ent::pos, queue_ent::prio, queue_t_unref, member::realtime, call_queue::realtime, member::reason_paused, member::ringinuse, SENTINEL, call_queue::servicelevel, queue_ent::start, member::starttime, member::state_interface, member::status, call_queue::strategy, call_queue::talktime, and call_queue::weight.

Referenced by queue_show().

9656 {
9657  struct call_queue *q;
9658  struct ast_str *out = ast_str_alloca(512);
9659  int found = 0;
9660  time_t now = time(NULL);
9661  struct ao2_iterator queue_iter;
9662  struct ao2_iterator mem_iter;
9663 
9664  if (argc != 2 && argc != 3) {
9665  return CLI_SHOWUSAGE;
9666  }
9667 
9668  if (argc == 3) { /* specific queue */
9669  if ((q = find_load_queue_rt_friendly(argv[2]))) {
9670  queue_t_unref(q, "Done with temporary pointer");
9671  }
9672  } else if (ast_check_realtime("queues")) {
9673  /* This block is to find any queues which are defined in realtime but
9674  * which have not yet been added to the in-core container
9675  */
9676  struct ast_config *cfg = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
9677  if (cfg) {
9678  char *category = NULL;
9679  while ((category = ast_category_browse(cfg, category))) {
9680  const char *queuename = ast_variable_retrieve(cfg, category, "name");
9681  if ((q = find_load_queue_rt_friendly(queuename))) {
9682  queue_t_unref(q, "Done with temporary pointer");
9683  }
9684  }
9685  ast_config_destroy(cfg);
9686  }
9687  }
9688 
9689  ao2_lock(queues);
9691  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
9692  float sl;
9693  float sl2;
9694 
9695  struct call_queue *realtime_queue = NULL;
9696 
9697  ao2_lock(q);
9698  /* This check is to make sure we don't print information for realtime
9699  * queues which have been deleted from realtime but which have not yet
9700  * been deleted from the in-core container. Only do this if we're not
9701  * looking for a specific queue.
9702  */
9703  if (argc < 3 && q->realtime) {
9704  realtime_queue = find_load_queue_rt_friendly(q->name);
9705  if (!realtime_queue) {
9706  ao2_unlock(q);
9707  queue_t_unref(q, "Done with iterator");
9708  continue;
9709  }
9710  queue_t_unref(realtime_queue, "Queue is already in memory");
9711  }
9712 
9713  if (argc == 3 && strcasecmp(q->name, argv[2])) {
9714  ao2_unlock(q);
9715  queue_t_unref(q, "Done with iterator");
9716  continue;
9717  }
9718  found = 1;
9719 
9720  ast_str_set(&out, 0, "%s has %d calls (max ", q->name, q->count);
9721  if (q->maxlen) {
9722  ast_str_append(&out, 0, "%d", q->maxlen);
9723  } else {
9724  ast_str_append(&out, 0, "unlimited");
9725  }
9726  sl = 0;
9727  sl2 = 0;
9728  if (q->callscompleted > 0) {
9729  sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
9730  }
9731  if (q->callscompleted + q->callsabandoned > 0) {
9732  sl2 =100 * (((float)q->callsabandonedinsl + (float)q->callscompletedinsl) / ((float)q->callsabandoned + (float)q->callscompleted));
9733  }
9734 
9735  ast_str_append(&out, 0, ") in '%s' strategy (%ds holdtime, %ds talktime), W:%d, C:%d, A:%d, SL:%2.1f%%, SL2:%2.1f%% within %ds",
9736  int2strat(q->strategy), q->holdtime, q->talktime, q->weight, q->callscompleted, q->callsabandoned, sl, sl2, q->servicelevel);
9737  do_print(s, fd, ast_str_buffer(out));
9738  if (!ao2_container_count(q->members)) {
9739  do_print(s, fd, " No Members");
9740  } else {
9741  struct member *mem;
9742 
9743  do_print(s, fd, " Members: ");
9744  mem_iter = ao2_iterator_init(q->members, 0);
9745  while ((mem = ao2_iterator_next(&mem_iter))) {
9746  ast_str_set(&out, 0, " %s", mem->membername);
9747  if (strcasecmp(mem->membername, mem->interface)) {
9748  ast_str_append(&out, 0, " (%s", mem->interface);
9749  if (!ast_strlen_zero(mem->state_interface)
9750  && strcmp(mem->state_interface, mem->interface)) {
9751  ast_str_append(&out, 0, " from %s", mem->state_interface);
9752  }
9753  ast_str_append(&out, 0, ")");
9754  }
9755  if (mem->penalty) {
9756  ast_str_append(&out, 0, " with penalty %d", mem->penalty);
9757  }
9758 
9759  ast_str_append(&out, 0, " (ringinuse %s)", mem->ringinuse ? "enabled" : "disabled");
9760 
9761  ast_str_append(&out, 0, "%s%s%s%s%s%s%s%s%s",
9762  mem->dynamic ? ast_term_color(COLOR_CYAN, COLOR_BLACK) : "", mem->dynamic ? " (dynamic)" : "", ast_term_reset(),
9763  mem->realtime ? ast_term_color(COLOR_MAGENTA, COLOR_BLACK) : "", mem->realtime ? " (realtime)" : "", ast_term_reset(),
9764  mem->starttime ? ast_term_color(COLOR_BROWN, COLOR_BLACK) : "", mem->starttime ? " (in call)" : "", ast_term_reset());
9765 
9766  if (mem->paused) {
9767  ast_str_append(&out, 0, " %s(paused%s%s was %ld secs ago)%s",
9769  ast_strlen_zero(mem->reason_paused) ? "" : ":",
9770  ast_strlen_zero(mem->reason_paused) ? "" : mem->reason_paused,
9771  (long) (now - mem->lastpause),
9772  ast_term_reset());
9773  }
9774 
9775  ast_str_append(&out, 0, " (%s%s%s)",
9780  if (mem->calls) {
9781  ast_str_append(&out, 0, " has taken %d calls (last was %ld secs ago)",
9782  mem->calls, (long) (now - mem->lastcall));
9783  } else {
9784  ast_str_append(&out, 0, " has taken no calls yet");
9785  }
9786  do_print(s, fd, ast_str_buffer(out));
9787  ao2_ref(mem, -1);
9788  }
9789  ao2_iterator_destroy(&mem_iter);
9790  }
9791  if (!q->head) {
9792  do_print(s, fd, " No Callers");
9793  } else {
9794  struct queue_ent *qe;
9795  int pos = 1;
9796 
9797  do_print(s, fd, " Callers: ");
9798  for (qe = q->head; qe; qe = qe->next) {
9799  ast_str_set(&out, 0, " %d. %s (wait: %ld:%2.2ld, prio: %d)",
9800  pos++, ast_channel_name(qe->chan), (long) (now - qe->start) / 60,
9801  (long) (now - qe->start) % 60, qe->prio);
9802  do_print(s, fd, ast_str_buffer(out));
9803  }
9804  }
9805  do_print(s, fd, ""); /* blank line between entries */
9806  ao2_unlock(q);
9807  queue_t_unref(q, "Done with iterator"); /* Unref the iterator's reference */
9808  }
9809  ao2_iterator_destroy(&queue_iter);
9810  ao2_unlock(queues);
9811  if (!found) {
9812  if (argc == 3) {
9813  ast_str_set(&out, 0, "No such queue: %s.", argv[2]);
9814  } else {
9815  ast_str_set(&out, 0, "No queues.");
9816  }
9817  do_print(s, fd, ast_str_buffer(out));
9818  }
9819  return CLI_SUCCESS;
9820 }
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:9640
const char * ast_devstate2str(enum ast_device_state devstate) attribute_pure
Convert device state to text string for output.
Definition: devicestate.c:237
int servicelevel
Definition: app_queue.c:1734
int dynamic
Definition: app_queue.c:1604
int callsabandonedinsl
Definition: app_queue.c:1733
int paused
Definition: app_queue.c:1607
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
struct ast_channel * chan
Definition: app_queue.c:1589
static struct call_queue * find_load_queue_rt_friendly(const char *queuename)
Definition: app_queue.c:3699
time_t start
Definition: app_queue.c:1586
char state_interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1599
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define COLOR_CYAN
Definition: term.h:59
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
Definition: main/config.c:3363
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.
#define COLOR_GREEN
Definition: term.h:51
int realtime
Definition: app_queue.c:1605
#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
struct ao2_container * members
Definition: app_queue.c:1755
struct queue_ent * head
Definition: app_queue.c:1756
int callscompletedinsl
Definition: app_queue.c:1735
char membername[80]
Definition: app_queue.c:1601
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1596
int holdtime
Definition: app_queue.c:1729
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 SENTINEL
Definition: compiler.h:87
static struct ao2_container * queues
Definition: app_queue.c:1769
time_t lastpause
Definition: app_queue.c:1614
int penalty
Definition: app_queue.c:1602
#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
int strategy
Definition: app_queue.c:1714
#define COLOR_RED
Definition: term.h:49
#define COLOR_BLACK
Definition: term.h:47
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
#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:1699
int talktime
Definition: app_queue.c:1730
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
char reason_paused[80]
Definition: app_queue.c:1608
#define ast_strlen_zero(a)
Definition: muted.c:73
const char * ast_term_reset(void)
Returns the terminal reset code.
Definition: term.c:306
const char * ast_term_color(int fgcolor, int bgcolor)
Return a color sequence string.
Definition: term.c:290
time_t starttime
Definition: app_queue.c:1612
int calls
Definition: app_queue.c:1603
int status
Definition: app_queue.c:1606
#define queue_t_unref(q, tag)
Definition: app_queue.c:1924
#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
int callsabandoned
Definition: app_queue.c:1732
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:1715
const char * ast_channel_name(const struct ast_channel *chan)
struct queue_ent * next
Definition: app_queue.c:1592
unsigned int ringinuse
Definition: app_queue.c:1619
#define COLOR_BROWN
Definition: term.h:53
int callscompleted
Definition: app_queue.c:1731
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:1613
static const char * int2strat(int strategy)
Definition: app_queue.c:1790
#define COLOR_MAGENTA
Definition: term.h:57

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 11470 of file app_queue.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 11470 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 7373 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().

7374 {
7375  struct call_queue *q;
7376  struct member *new_member, *old_member;
7377  int res = RES_NOSUCHQUEUE;
7378 
7379  /*! \note Ensure the appropriate realtime queue is loaded. Note that this
7380  * short-circuits if the queue is already in memory. */
7381  if (!(q = find_load_queue_rt_friendly(queuename))) {
7382  return res;
7383  }
7384 
7385  ao2_lock(q);
7386  if ((old_member = interface_exists(q, interface)) == NULL) {
7388  new_member->dynamic = 1;
7389  if (reason_paused) {
7390  ast_copy_string(new_member->reason_paused, reason_paused, sizeof(new_member->reason_paused));
7391  }
7392  member_add_to_queue(q, new_member);
7393  queue_publish_member_blob(queue_member_added_type(), queue_member_blob_create(q, new_member));
7394 
7395  if (is_member_available(q, new_member)) {
7397  }
7398 
7399  ao2_ref(new_member, -1);
7400  new_member = NULL;
7401 
7402  if (dump) {
7403  dump_queue_members(q);
7404  }
7405 
7406  res = RES_OKAY;
7407  } else {
7408  res = RES_OUTOFMEMORY;
7409  }
7410  } else {
7411  ao2_ref(old_member, -1);
7412  res = RES_EXISTS;
7413  }
7414  ao2_unlock(q);
7415  queue_t_unref(q, "Expiring temporary reference");
7416 
7417  return res;
7418 }
int dynamic
Definition: app_queue.c:1604
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:2683
int paused
Definition: app_queue.c:1607
#define RES_OKAY
Definition: app_queue.c:1441
static struct call_queue * find_load_queue_rt_friendly(const char *queuename)
Definition: app_queue.c:3699
char state_interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1599
int wrapuptime
Definition: app_queue.c:1611
unsigned int ringinuse
Definition: app_queue.c:1703
#define ao2_unlock(a)
Definition: astobj2.h:730
#define NULL
Definition: resample.c:96
char membername[80]
Definition: app_queue.c:1601
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1596
#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:3357
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:1602
static struct member * interface_exists(struct call_queue *q, const char *interface)
Definition: app_queue.c:7238
#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:2261
const ast_string_field name
Definition: app_queue.c:1699
static void dump_queue_members(struct call_queue *pm_queue)
Dump all members in a specific queue to the database.
Definition: app_queue.c:7265
char reason_paused[80]
Definition: app_queue.c:1608
#define RES_NOSUCHQUEUE
Definition: app_queue.c:1444
#define queue_t_unref(q, tag)
Definition: app_queue.c:1924
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:2237
static int is_member_available(struct call_queue *q, struct member *mem)
Definition: app_queue.c:2471

◆ alloc_queue()

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

Definition at line 3531 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().

3532 {
3533  struct call_queue *q;
3534 
3535  if ((q = ao2_t_alloc(sizeof(*q), destroy_queue, "Allocate queue"))) {
3536  if (ast_string_field_init(q, 64)) {
3537  queue_t_unref(q, "String field allocation failed");
3538  return NULL;
3539  }
3540  ast_string_field_set(q, name, queuename);
3541  }
3542  return q;
3543 }
#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:3516
static const char name[]
Definition: cdr_mysql.c:74
#define queue_t_unref(q, tag)
Definition: app_queue.c:1924
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ aqm_exec()

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

AddQueueMember application.

Definition at line 8017 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().

8018 {
8019  int res=-1;
8020  char *parse, *tmp, *temppos = NULL;
8022  AST_APP_ARG(queuename);
8023  AST_APP_ARG(interface);
8024  AST_APP_ARG(penalty);
8026  AST_APP_ARG(membername);
8027  AST_APP_ARG(state_interface);
8029  );
8030  int penalty = 0;
8031  int wrapuptime;
8032 
8033  if (ast_strlen_zero(data)) {
8034  ast_log(LOG_WARNING, "AddQueueMember requires an argument (queuename[,interface[,penalty[,options[,membername[,stateinterface][,wrapuptime]]]]])\n");
8035  return -1;
8036  }
8037 
8038  parse = ast_strdupa(data);
8039 
8040  AST_STANDARD_APP_ARGS(args, parse);
8041 
8042  if (ast_strlen_zero(args.interface)) {
8043  args.interface = ast_strdupa(ast_channel_name(chan));
8044  temppos = strrchr(args.interface, '-');
8045  if (temppos) {
8046  *temppos = '\0';
8047  }
8048  }
8049 
8050  if (!ast_strlen_zero(args.penalty)) {
8051  if ((sscanf(args.penalty, "%30d", &penalty) != 1) || penalty < 0) {
8052  ast_log(LOG_WARNING, "Penalty '%s' is invalid, must be an integer >= 0\n", args.penalty);
8053  penalty = 0;
8054  }
8055  }
8056 
8057  if (!ast_strlen_zero(args.wrapuptime)) {
8058  tmp = args.wrapuptime;
8059  ast_strip(tmp);
8060  wrapuptime = atoi(tmp);
8061  if (wrapuptime < 0) {
8062  wrapuptime = 0;
8063  }
8064  } else {
8065  wrapuptime = 0;
8066  }
8067 
8068  switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, 0, queue_persistent_members, args.state_interface, NULL, wrapuptime)) {
8069  case RES_OKAY:
8070  if (ast_strlen_zero(args.membername) || !log_membername_as_agent) {
8071  ast_queue_log(args.queuename, ast_channel_uniqueid(chan), args.interface, "ADDMEMBER", "%s", "");
8072  } else {
8073  ast_queue_log(args.queuename, ast_channel_uniqueid(chan), args.membername, "ADDMEMBER", "%s", "");
8074  }
8075  ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", args.interface, args.queuename);
8076  pbx_builtin_setvar_helper(chan, "AQMSTATUS", "ADDED");
8077  res = 0;
8078  break;
8079  case RES_EXISTS:
8080  ast_log(LOG_WARNING, "Unable to add interface '%s' to queue '%s': Already there\n", args.interface, args.queuename);
8081  pbx_builtin_setvar_helper(chan, "AQMSTATUS", "MEMBERALREADY");
8082  res = 0;
8083  break;
8084  case RES_NOSUCHQUEUE:
8085  ast_log(LOG_WARNING, "Unable to add interface to queue '%s': No such queue\n", args.queuename);
8086  pbx_builtin_setvar_helper(chan, "AQMSTATUS", "NOSUCHQUEUE");
8087  res = 0;
8088  break;
8089  case RES_OUTOFMEMORY:
8090  ast_log(LOG_ERROR, "Out of memory adding interface %s to queue %s\n", args.interface, args.queuename);
8091  break;
8092  }
8093 
8094  return res;
8095 }
#define RES_OKAY
Definition: app_queue.c:1441
int wrapuptime
Definition: app_queue.c:1740
#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:811
static int log_membername_as_agent
queues.conf [general] option
Definition: app_queue.c:1493
const char * args
#define NULL
Definition: resample.c:96
#define RES_OUTOFMEMORY
Definition: app_queue.c:1443
#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
#define ast_strlen_zero(a)
Definition: muted.c:73
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:7373
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 11470 of file app_queue.c.

◆ autopause2int()

static int autopause2int ( const char *  autopause)
static

Definition at line 1816 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().

1817 {
1818  int x;
1819  /*This 'double check' that default value is OFF */
1820  if (ast_strlen_zero(autopause)) {
1821  return QUEUE_AUTOPAUSE_OFF;
1822  }
1823 
1824  /*This 'double check' is to ensure old values works */
1825  if(ast_true(autopause)) {
1826  return QUEUE_AUTOPAUSE_ON;
1827  }
1828 
1829  for (x = 0; x < ARRAY_LEN(autopausesmodes); x++) {
1830  if (!strcasecmp(autopause, autopausesmodes[x].name)) {
1831  return autopausesmodes[x].autopause;
1832  }
1833  }
1834 
1835  /*This 'double check' that default value is OFF */
1836  return QUEUE_AUTOPAUSE_OFF;
1837 }
int autopause
Definition: app_queue.c:1421
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
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:1822
#define ast_strlen_zero(a)
Definition: muted.c:73
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 5775 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().

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

◆ callattempt_free()

static void callattempt_free ( struct callattempt doomed)
static

Definition at line 4225 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().

4226 {
4227  if (doomed->member) {
4228  ao2_ref(doomed->member, -1);
4229  }
4231  ast_free(doomed->orig_chan_name);
4232  ast_free(doomed);
4233 }
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2047
struct ast_party_connected_line connected
Definition: app_queue.c:1548
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct member * member
Definition: app_queue.c:1546
char * orig_chan_name
Definition: app_queue.c:1559
#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 4385 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().

4386 {
4387  struct member *memberp = call->member;
4388  int wrapuptime;
4389 
4390  if (memberp->paused) {
4391  ast_debug(1, "%s paused, can't receive call\n", call->interface);
4392  return 0;
4393  }
4394 
4395  if (!memberp->ringinuse && !member_status_available(memberp->status)) {
4396  ast_debug(1, "%s not available, can't receive call\n", call->interface);
4397  return 0;
4398  }
4399 
4400  if (memberp->lastqueue) {
4401  wrapuptime = get_wrapuptime(memberp->lastqueue, memberp);
4402  } else {
4403  wrapuptime = get_wrapuptime(qe->parent, memberp);
4404  }
4405  if (wrapuptime && (time(NULL) - memberp->lastcall) < wrapuptime) {
4406  ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
4407  (memberp->lastqueue ? memberp->lastqueue->name : qe->parent->name),
4408  call->interface);
4409  return 0;
4410  }
4411 
4412  if (use_weight && compare_weight(qe->parent, memberp)) {
4413  ast_debug(1, "Priority queue delaying call to %s:%s\n",
4414  qe->parent->name, call->interface);
4415  return 0;
4416  }
4417 
4418  if (!memberp->ringinuse) {
4419  struct member *mem;
4420 
4422 
4423  mem = ao2_find(pending_members, memberp,
4425  if (mem) {
4426  /*
4427  * If found that means this member is currently being attempted
4428  * from another calling thread, so stop trying from this thread
4429  */
4430  ast_debug(1, "%s has another call trying, can't receive call\n",
4431  call->interface);
4432  ao2_ref(mem, -1);
4434  return 0;
4435  }
4436 
4437  /*
4438  * If not found add it to the container so another queue
4439  * won't attempt to call this member at the same time.
4440  */
4441  ast_debug(3, "Add %s to pending_members\n", memberp->membername);
4442  ao2_link(pending_members, memberp);
4444 
4445  /*
4446  * The queue member is available. Get current status to be sure
4447  * because the device state and extension state callbacks may
4448  * not have updated the status yet.
4449  */
4451  ast_debug(1, "%s actually not available, can't receive call\n",
4452  call->interface);
4453  pending_members_remove(memberp);
4454  return 0;
4455  }
4456  }
4457 
4458  return 1;
4459 }
struct call_queue * parent
Definition: app_queue.c:1564
int paused
Definition: app_queue.c:1607
static struct ao2_container * pending_members
Definition: app_queue.c:2378
int wrapuptime
Definition: app_queue.c:1611
Assume that the ao2_container is already locked.
Definition: astobj2.h:1067
char interface[256]
Definition: app_queue.c:1544
#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:2429
char membername[80]
Definition: app_queue.c:1601
static int member_status_available(int status)
Definition: app_queue.c:4371
static int compare_weight(struct call_queue *rq, struct member *member)
Definition: app_queue.c:4320
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
struct member * member
Definition: app_queue.c:1546
struct call_queue * lastqueue
Definition: app_queue.c:1615
static int get_wrapuptime(struct call_queue *q, struct member *member)
Return wrapuptime.
Definition: app_queue.c:1859
const ast_string_field name
Definition: app_queue.c:1699
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
int status
Definition: app_queue.c:1606
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:2668
unsigned int ringinuse
Definition: app_queue.c:1619
time_t lastcall
Definition: app_queue.c:1613
#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 7426 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().

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

◆ clear_queue()

static void clear_queue ( struct call_queue q)
static

Definition at line 2860 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().

2861 {
2862  q->holdtime = 0;
2863  q->callscompleted = 0;
2864  q->callsabandoned = 0;
2865  q->callscompletedinsl = 0;
2866  q->callsabandonedinsl = 0;
2867  q->talktime = 0;
2868 
2869  if (q->members) {
2870  struct member *mem;
2871  struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
2872  while ((mem = ao2_iterator_next(&mem_iter))) {
2873  mem->calls = 0;
2874  mem->callcompletedinsl = 0;
2875  mem->lastcall = 0;
2876  mem->starttime = 0;
2877  ao2_ref(mem, -1);
2878  }
2879  ao2_iterator_destroy(&mem_iter);
2880  }
2881 }
int callsabandonedinsl
Definition: app_queue.c:1733
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct ao2_container * members
Definition: app_queue.c:1755
int callscompletedinsl
Definition: app_queue.c:1735
int holdtime
Definition: app_queue.c:1729
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int talktime
Definition: app_queue.c:1730
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
time_t starttime
Definition: app_queue.c:1612
int calls
Definition: app_queue.c:1603
int callsabandoned
Definition: app_queue.c:1732
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:1610
int callscompleted
Definition: app_queue.c:1731
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:1613

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

9594 {
9595  struct call_queue *q;
9596  struct ao2_iterator queue_iter;
9597 
9598  queue_iter = ao2_iterator_init(queues, 0);
9599  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
9600  ao2_lock(q);
9601  if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename))
9602  clear_queue(q);
9603  ao2_unlock(q);
9604  queue_t_unref(q, "Done with iterator");
9605  }
9606  ao2_iterator_destroy(&queue_iter);
9607  return 0;
9608 }
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:2860
static struct ao2_container * queues
Definition: app_queue.c:1769
#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:1699
#define ast_strlen_zero(a)
Definition: muted.c:73
#define queue_t_unref(q, tag)
Definition: app_queue.c:1924
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 4320 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().

4321 {
4322  struct call_queue *q;
4323  struct member *mem;
4324  int found = 0;
4325  struct ao2_iterator queue_iter;
4326 
4327  queue_iter = ao2_iterator_init(queues, 0);
4328  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
4329  if (q == rq) { /* don't check myself, could deadlock */
4330  queue_t_unref(q, "Done with iterator");
4331  continue;
4332  }
4333  ao2_lock(q);
4334  if (q->count && q->members) {
4335  if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
4336  ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
4337  if (q->weight > rq->weight && q->count >= num_available_members(q)) {
4338  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);
4339  found = 1;
4340  }
4341  ao2_ref(mem, -1);
4342  }
4343  }
4344  ao2_unlock(q);
4345  queue_t_unref(q, "Done with iterator");
4346  if (found) {
4347  break;
4348  }
4349  }
4350  ao2_iterator_destroy(&queue_iter);
4351  return found;
4352 }
#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:1755
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1596
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
static struct ao2_container * queues
Definition: app_queue.c:1769
#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:4287
#define ao2_t_iterator_next(iter, tag)
Definition: astobj2.h:1931
const ast_string_field name
Definition: app_queue.c:1699
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define queue_t_unref(q, tag)
Definition: app_queue.c:1924
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 9894 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().

9895 {
9896  struct call_queue *q;
9897  char *ret = NULL;
9898  int which = 0;
9899  int wordlen = strlen(word);
9900  struct ao2_iterator queue_iter;
9901  const char *word_list = NULL;
9902 
9903  /* for certain commands, already completed items should be left out of
9904  * the list */
9905  if (word_list_offset && strlen(line) >= word_list_offset) {
9906  word_list = line + word_list_offset;
9907  }
9908 
9909  queue_iter = ao2_iterator_init(queues, 0);
9910  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
9911  if (!strncasecmp(word, q->name, wordlen) && ++which > state
9912  && (!word_list_offset || !word_in_list(word_list, q->name))) {
9913  ret = ast_strdup(q->name);
9914  queue_t_unref(q, "Done with iterator");
9915  break;
9916  }
9917  queue_t_unref(q, "Done with iterator");
9918  }
9919  ao2_iterator_destroy(&queue_iter);
9920 
9921  /* Pretend "rules" is at the end of the queues list in certain
9922  * circumstances since it is an alternate command that should be
9923  * tab-completable for "queue show" */
9924  if (!ret && which == state && !wordlen && !strncmp("queue show", line, 10)) {
9925  ret = ast_strdup("rules");
9926  }
9927 
9928  return ret;
9929 }
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:1769
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:9835
#define ao2_t_iterator_next(iter, tag)
Definition: astobj2.h:1931
const ast_string_field name
Definition: app_queue.c:1699
#define queue_t_unref(q, tag)
Definition: app_queue.c:1924
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 10391 of file app_queue.c.

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

Referenced by handle_queue_add_member().

10392 {
10393  /* 0 - queue; 1 - add; 2 - member; 3 - <interface>; 4 - to; 5 - <queue>; 6 - penalty; 7 - <penalty>; 8 - as; 9 - <membername> */
10394  switch (pos) {
10395  case 3: /* Don't attempt to complete name of interface (infinite possibilities) */
10396  return NULL;
10397  case 4: /* only one possible match, "to" */
10398  return state == 0 ? ast_strdup("to") : NULL;
10399  case 5: /* <queue> */
10400  return complete_queue(line, word, pos, state, 0);
10401  case 6: /* only one possible match, "penalty" */
10402  return state == 0 ? ast_strdup("penalty") : NULL;
10403  case 7:
10404  if (0 <= state && state < 100) { /* 0-99 */
10405  char *num;
10406  if ((num = ast_malloc(3))) {
10407  sprintf(num, "%d", state);
10408  }
10409  return num;
10410  } else {
10411  return NULL;
10412  }
10413  case 8: /* only one possible match, "as" */
10414  return state == 0 ? ast_strdup("as") : NULL;
10415  case 9: /* Don't attempt to complete name of member (infinite possibilities) */
10416  return NULL;
10417  default:
10418  return NULL;
10419  }
10420 }
#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:9894
#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 10764 of file app_queue.c.

References ast_strdup, complete_queue(), and NULL.

Referenced by handle_queue_pause_member().

10765 {
10766  /* 0 - queue; 1 - pause; 2 - member; 3 - <interface>; 4 - queue; 5 - <queue>; 6 - reason; 7 - <reason> */
10767  switch (pos) {
10768  case 3: /* Don't attempt to complete name of interface (infinite possibilities) */
10769  return NULL;
10770  case 4: /* only one possible match, "queue" */
10771  return state == 0 ? ast_strdup("queue") : NULL;
10772  case 5: /* <queue> */
10773  return complete_queue(line, word, pos, state, 0);
10774  case 6: /* "reason" */
10775  return state == 0 ? ast_strdup("reason") : NULL;
10776  case 7: /* Can't autocomplete a reason, since it's 100% customizeable */
10777  return NULL;
10778  default:
10779  return NULL;
10780  }
10781 }
#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:9894
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 10604 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().

10605 {
10606  int which = 0;
10607  struct call_queue *q;
10608  struct member *m;
10609  struct ao2_iterator queue_iter;
10610  struct ao2_iterator mem_iter;
10611  int wordlen = strlen(word);
10612 
10613  /* 0 - queue; 1 - remove; 2 - member; 3 - <member>; 4 - from; 5 - <queue> */
10614  if (pos > 5 || pos < 3) {
10615  return NULL;
10616  }
10617  if (pos == 4) { /* only one possible match, 'from' */
10618  return (state == 0 ? ast_strdup("from") : NULL);
10619  }
10620 
10621  if (pos == 5) { /* No need to duplicate code */
10622  return complete_queue(line, word, pos, state, 0);
10623  }
10624 
10625  /* here is the case for 3, <member> */
10626  queue_iter = ao2_iterator_init(queues, 0);
10627  while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
10628  ao2_lock(q);
10629  mem_iter = ao2_iterator_init(q->members, 0);
10630  while ((m = ao2_iterator_next(&mem_iter))) {
10631  if (!strncasecmp(word, m->membername, wordlen) && ++which > state) {
10632  char *tmp;
10633  tmp = ast_strdup(m->interface);
10634  ao2_ref(m, -1);
10635  ao2_iterator_destroy(&mem_iter);
10636  ao2_unlock(q);
10637  queue_t_unref(q, "Done with iterator, returning interface name");
10638  ao2_iterator_destroy(&queue_iter);
10639  return tmp;
10640  }
10641  ao2_ref(m, -1);
10642  }
10643  ao2_iterator_destroy(&mem_iter);
10644  ao2_unlock(q);
10645  queue_t_unref(q, "Done with iterator");
10646  }
10647  ao2_iterator_destroy(&queue_iter);
10648 
10649  return NULL;
10650 }
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:1755
char membername[80]
Definition: app_queue.c:1601
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1596
static struct ao2_container * queues
Definition: app_queue.c:1769
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:9894
#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:1924
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 10959 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().

10960 {
10961  int which = 0;
10962  struct rule_list *rl_iter;
10963  int wordlen = strlen(word);
10964  char *ret = NULL;
10965  if (pos != 3) /* Wha? */ {
10966  return NULL;
10967  }
10968 
10970  AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
10971  if (!strncasecmp(word, rl_iter->name, wordlen) && ++which > state) {
10972  ret = ast_strdup(rl_iter->name);
10973  break;
10974  }
10975  }
10977 
10978  return ret;
10979 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
char name[80]
Definition: app_queue.c:1762
#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 10838 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().

10839 {
10840  /* 0 - queue; 1 - set; 2 - penalty/ringinuse; 3 - <value>; 4 - on; 5 - <member>; 6 - in; 7 - <queue>;*/
10841  switch (pos) {
10842  case 4:
10843  if (state == 0) {
10844  return ast_strdup("on");
10845  } else {
10846  return NULL;
10847  }
10848  case 6:
10849  if (state == 0) {
10850  return ast_strdup("in");
10851  } else {
10852  return NULL;
10853  }
10854  case 7:
10855  return complete_queue(line, word, pos, state, 0);
10856  default:
10857  return NULL;
10858  }
10859 }
#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:9894
short word

◆ complete_queue_show()

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

Definition at line 9931 of file app_queue.c.

References complete_queue(), and NULL.

Referenced by queue_show().

9932 {
9933  if (pos == 2) {
9934  return complete_queue(line, word, pos, state, 0);
9935  }
9936  return NULL;
9937 }
#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:9894
short word

◆ compress_char()

static int compress_char ( const char  c)
static

Definition at line 2727 of file app_queue.c.

Referenced by member_hash_fn().

2728 {
2729  if (c < 32) {
2730  return 0;
2731  } else if (c > 96) {
2732  return c - 64;
2733  }
2734  return c - 32;
2735 }
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 8132 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().

8133 {
8134  struct penalty_rule *pr_iter;
8135  struct rule_list *rl_iter;
8136  const char *tmp = ast_strlen_zero(rulename) ? qe->parent->defaultrule : rulename;
8138  AST_LIST_TRAVERSE(&rule_lists, rl_iter, list) {
8139  if (!strcasecmp(rl_iter->name, tmp)) {
8140  break;
8141  }
8142  }
8143  if (rl_iter) {
8144  AST_LIST_TRAVERSE(&rl_iter->rules, pr_iter, list) {
8145  struct penalty_rule *new_pr = ast_calloc(1, sizeof(*new_pr));
8146  if (!new_pr) {
8147  ast_log(LOG_ERROR, "Memory allocation error when copying penalty rules! Aborting!\n");
8148  break;
8149  }
8150  new_pr->time = pr_iter->time;
8151  new_pr->max_value = pr_iter->max_value;
8152  new_pr->min_value = pr_iter->min_value;
8153  new_pr->raise_value = pr_iter->raise_value;
8154  new_pr->max_relative = pr_iter->max_relative;
8155  new_pr->min_relative = pr_iter->min_relative;
8156  new_pr->raise_relative = pr_iter->raise_relative;
8157  AST_LIST_INSERT_TAIL(&qe->qe_rules, new_pr, list);
8158  }
8159  }
8161 }
struct call_queue * parent
Definition: app_queue.c:1564
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
int max_relative
Definition: app_queue.c:1648
char name[80]
Definition: app_queue.c:1762
int min_relative
Definition: app_queue.c:1649
#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_log
Definition: astobj2.c:42
int raise_relative
Definition: app_queue.c:1650
#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_strlen_zero(a)
Definition: muted.c:73
#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:1699
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 2683 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().

2684 {
2685  struct member *cur;
2686 
2687  if ((cur = ao2_alloc(sizeof(*cur), destroy_queue_member_cb))) {
2688  cur->ringinuse = ringinuse;
2689  cur->penalty = penalty;
2690  cur->paused = paused;
2691  cur->wrapuptime = wrapuptime;
2692  if (paused) {
2693  time(&cur->lastpause); /* Update time of last pause */
2694  }
2695  ast_copy_string(cur->interface, interface, sizeof(cur->interface));
2698  } else {
2700  }
2701  if (!ast_strlen_zero(membername)) {
2702  ast_copy_string(cur->membername, membername, sizeof(cur->membername));
2703  } else {
2704  ast_copy_string(cur->membername, interface, sizeof(cur->membername));
2705  }
2706  if (!strchr(cur->interface, '/')) {
2707  ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
2708  }
2709  if (!strncmp(cur->state_interface, "hint:", 5)) {
2710  char *tmp = ast_strdupa(cur->state_interface), *context = tmp;
2711  char *exten = strsep(&context, "@") + 5;
2712 
2713  ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten));
2714  ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context));
2715 
2717  } else {
2718  cur->state_id = -1;
2719  }
2720  cur->status = get_queue_member_status(cur);
2721  }
2722 
2723  return cur;
2724 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
int paused
Definition: app_queue.c:1607
char state_interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1599
int wrapuptime
Definition: app_queue.c:1611
#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:1601
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1596
static int extension_state_cb(const char *context, const char *exten, struct ast_state_cb_info *info, void *data)
Definition: app_queue.c:2624
#define ast_log
Definition: astobj2.c:42
time_t lastpause
Definition: app_queue.c:1614
int penalty
Definition: app_queue.c:1602
#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:2673
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define ast_strlen_zero(a)
Definition: muted.c:73
int state_id
Definition: app_queue.c:1600
int status
Definition: app_queue.c:1606
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:1598
static int get_queue_member_status(struct member *cur)
Return the current state of a member.
Definition: app_queue.c:2668
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:3816
unsigned int ringinuse
Definition: app_queue.c:1619
char state_exten[AST_MAX_EXTENSION]
Definition: app_queue.c:1597

◆ destroy_queue()

static void destroy_queue ( void *  obj)
static

Free queue's member list then its string fields.

Definition at line 3516 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().

3517 {
3518  struct call_queue *q = obj;
3519  int i;
3520 
3521  free_members(q, 1);
3523  for (i = 0; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
3524  if (q->sound_periodicannounce[i]) {
3526  }
3527  }
3528  ao2_ref(q->members, -1);
3529 }
struct ast_str * sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS]
Definition: app_queue.c:1701
#define MAX_PERIODIC_ANNOUNCEMENTS
Definition: app_queue.c:1432
struct ao2_container * members
Definition: app_queue.c:1755
static void free_members(struct call_queue *q, int all)
Iterate through queue&#39;s member list and delete them.
Definition: app_queue.c:3500
#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 2673 of file app_queue.c.

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

Referenced by create_queue_member().

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

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

2507 {
2508  struct ao2_iterator miter, qiter;
2509  struct ast_device_state_message *dev_state;
2510  struct member *m;
2511  struct call_queue *q;
2512  char interface[80], *slash_pos;
2513  int found = 0; /* Found this member in any queue */
2514  int found_member; /* Found this member in this queue */
2515  int avail = 0; /* Found an available member in this queue */
2516 
2518  return;
2519  }
2520 
2521  dev_state = stasis_message_data(msg);
2522  if (dev_state->eid) {
2523  /* ignore non-aggregate states */
2524  return;
2525  }
2526 
2527  qiter = ao2_iterator_init(queues, 0);
2528  while ((q = ao2_t_iterator_next(&qiter, "Iterate over queues"))) {
2529  ao2_lock(q);
2530 
2531  avail = 0;
2532  found_member = 0;
2533  miter = ao2_iterator_init(q->members, 0);
2534  for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
2535  if (!found_member) {
2536  ast_copy_string(interface, m->state_interface, sizeof(interface));
2537 
2538  if ((slash_pos = strchr(interface, '/'))) {
2539  if (!strncasecmp(interface, "Local/", 6) && (slash_pos = strchr(slash_pos + 1, '/'))) {
2540  *slash_pos = '\0';
2541  }
2542  }
2543 
2544  if (!strcasecmp(interface, dev_state->device)) {
2545  found_member = 1;
2546  update_status(q, m, dev_state->state);
2547  }
2548  }
2549 
2550  /* check every member until we find one NOT_INUSE */
2551  if (!avail) {
2552  avail = is_member_available(q, m);
2553  }
2554  if (avail && found_member) {
2555  /* early exit as we've found an available member and the member of interest */
2556  ao2_ref(m, -1);
2557  break;
2558  }
2559  }
2560 
2561  if (found_member) {
2562  found = 1;
2563  if (avail) {
2565  } else {
2567  }
2568  }
2569 
2570  ao2_iterator_destroy(&miter);
2571 
2572  ao2_unlock(q);
2573  queue_t_unref(q, "Done with iterator");
2574  }
2575  ao2_iterator_destroy(&qiter);
2576 
2577  if (found) {
2578  ast_debug(1, "Device '%s' changed to state '%u' (%s)\n",
2579  dev_state->device,
2580  dev_state->state,
2581  ast_devstate2str(dev_state->state));
2582  } else {
2583  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",
2584  dev_state->device,
2585  dev_state->state,
2586  ast_devstate2str(dev_state->state));
2587  }
2588 
2589  return;
2590 }
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:1599
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:1755
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:444
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:1769
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:1699
#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:2440
unsigned int found
Definition: app_queue.c:1716
#define queue_t_unref(q, tag)
Definition: app_queue.c:1924
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:2471

◆ do_hang()

static void do_hang ( struct callattempt o)
static

common hangup actions

Definition at line 4355 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().

4356 {
4357  o->stillgoing = 0;
4358  ast_hangup(o->chan);
4360  o->chan = NULL;
4361 }
#define NULL
Definition: resample.c:96
static void pending_members_remove(struct member *mem)
Definition: app_queue.c:2429
struct member * member
Definition: app_queue.c:1546
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2523
struct ast_channel * chan
Definition: app_queue.c:1543
unsigned int stillgoing
Definition: app_queue.c:1556

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

References ast_cli(), and astman_append().

Referenced by __queues_show().

9641 {
9642  if (s) {
9643  astman_append(s, "%s\r\n", str);
9644  } else {
9645  ast_cli(fd, "%s\n", str);
9646  }
9647 }
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 7265 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().

7266 {
7267  struct member *cur_member;
7268  struct ast_str *value;
7269  struct ao2_iterator mem_iter;
7270 
7271  if (!pm_queue) {
7272  return;
7273  }
7274 
7275  /* 4K is a reasonable default for most applications, but we grow to
7276  * accommodate more if necessary. */
7277  if (!(value = ast_str_create(4096))) {
7278  return;
7279  }
7280 
7281  mem_iter = ao2_iterator_init(pm_queue->members, 0);
7282  while ((cur_member = ao2_iterator_next(&mem_iter))) {
7283  if (!cur_member->dynamic) {
7284  ao2_ref(cur_member, -1);
7285  continue;
7286  }
7287 
7288  ast_str_append(&value, 0, "%s%s;%d;%d;%s;%s;%s;%d",
7289  ast_str_strlen(value) ? "|" : "",
7290  cur_member->interface,
7291  cur_member->penalty,
7292  cur_member->paused,
7293  cur_member->membername,
7294  cur_member->state_interface,
7295  cur_member->reason_paused,
7296  cur_member->wrapuptime);
7297 
7298  ao2_ref(cur_member, -1);
7299  }
7300  ao2_iterator_destroy(&mem_iter);
7301 
7302  if (ast_str_strlen(value) && !cur_member) {
7303  if (ast_db_put(pm_family, pm_queue->name, ast_str_buffer(value))) {
7304  ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n");
7305  }
7306  } else {
7307  /* Delete the entry if the queue is empty or there is an error */
7308  ast_db_del(pm_family, pm_queue->name);
7309  }
7310 
7311  ast_free(value);
7312 }
int dynamic
Definition: app_queue.c:1604
int paused
Definition: app_queue.c:1607
char state_interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1599
int wrapuptime
Definition: app_queue.c:1611
#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:1755
char membername[80]
Definition: app_queue.c:1601
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1596
#define ast_log
Definition: astobj2.c:42
int penalty
Definition: app_queue.c:1602
#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:1699
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
char reason_paused[80]
Definition: app_queue.c:1608
#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 6571 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().

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

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

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

Referenced by try_calling().

6565 {
6566  struct queue_end_bridge *qeb = bconfig->end_bridge_callback_data;
6567  ao2_ref(qeb, +1);
6568  qeb->chan = originator;
6569 }
void * end_bridge_callback_data
Definition: channel.h:1079
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct ast_channel * chan
Definition: app_queue.c:6561

◆ escape_and_substitute()

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

Definition at line 6613 of file app_queue.c.

References input(), and pbx_substitute_variables_helper().

Referenced by setup_mixmonitor().

6615 {
6616  const char *m = input;
6617  char escaped[size];
6618  char *p;
6619 
6620  for (p = escaped; p < escaped + size - 1; p++, m++) {
6621  switch (*m) {
6622  case '^':
6623  if (*(m + 1) == '{') {
6624  *p = '$';
6625  }
6626  break;
6627  case ',':
6628  *p++ = '\\';
6629  /* Fall through */
6630  default:
6631  *p = *m;
6632  }
6633  if (*m == '\0')
6634  break;
6635  }
6636 
6637  if (p == escaped + size) {
6638  escaped[size - 1] = '\0';
6639  }
6640 
6641  pbx_substitute_variables_helper(chan, escaped, output, size - 1);
6642 }
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 2624 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().

2625 {
2626  struct ao2_iterator miter, qiter;
2627  struct member *m;
2628  struct call_queue *q;
2629  int state = info->exten_state;
2630  int found = 0, device_state = extensionstate2devicestate(state);
2631 
2632  /* only interested in extension state updates involving device states */
2633  if (info->reason != AST_HINT_UPDATE_DEVICE) {
2634  return 0;
2635  }
2636 
2637  qiter = ao2_iterator_init(queues, 0);
2638  while ((q = ao2_t_iterator_next(&qiter, "Iterate through queues"))) {
2639  ao2_lock(q);
2640 
2641  miter = ao2_iterator_init(q->members, 0);
2642  for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
2643  if (!strcmp(m->state_context, context) && !strcmp(m->state_exten, exten)) {
2644  update_status(q, m, device_state);
2645  ao2_ref(m, -1);
2646  found = 1;
2647  break;
2648  }
2649  }
2650  ao2_iterator_destroy(&miter);
2651 
2652  ao2_unlock(q);
2653  queue_t_unref(q, "Done with iterator");
2654  }
2655  ao2_iterator_destroy(&qiter);
2656 
2657  if (found) {
2658  ast_debug(1, "Extension '%s@%s' changed to state '%d' (%s)\n", exten, context, device_state, ast_devstate2str(device_state));
2659  } else {
2660  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",
2661  exten, context, device_state, ast_devstate2str(device_state));
2662  }
2663 
2664  return 0;
2665 }
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:1755
enum ast_extension_states exten_state
Definition: pbx.h:104
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
static struct ao2_container * queues
Definition: app_queue.c:1769
#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:2593
#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:2440
unsigned int found
Definition: app_queue.c:1716
#define queue_t_unref(q, tag)
Definition: app_queue.c:1924
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:1598
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:1597

◆ extensionstate2devicestate()

static int extensionstate2devicestate ( int  state)
static

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

Definition at line 2593 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_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().

2594 {
2595  switch (state) {
2598  break;
2599  case AST_EXTENSION_INUSE:
2601  break;
2602  case AST_EXTENSION_BUSY:
2604  break;
2605  case AST_EXTENSION_RINGING:
2607  break;
2608  case AST_EXTENSION_ONHOLD:
2610  break;
2613  break;
2614  case AST_EXTENSION_REMOVED:
2616  default:
2618  break;
2619  }
2620 
2621  return state;
2622 }
enum sip_cc_notify_state state
Definition: chan_sip.c:956

◆ find_best()

static struct callattempt* find_best ( struct callattempt outgoing)
static

find the entry with the best metric, or NULL

Definition at line 4611 of file app_queue.c.

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

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

4612 {
4613  struct callattempt *best = NULL, *cur;
4614 
4615  for (cur = outgoing; cur; cur = cur->q_next) {
4616  if (cur->stillgoing && /* Not already done */
4617  !cur->chan && /* Isn't already going */
4618  (!best || cur->metric < best->metric)) { /* We haven't found one yet, or it's better */
4619  best = cur;
4620  }
4621  }
4622 
4623  return best;
4624 }
struct callattempt * q_next
Definition: app_queue.c:1541
#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:1540

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

3700 {
3701  struct ast_variable *queue_vars;
3702  struct ast_config *member_config = NULL;
3703  struct call_queue *q = NULL, tmpq = {
3704  .name = queuename,
3705  };
3706  int prev_weight = 0;
3707 
3708  /* Find the queue in the in-core list first. */
3709  q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Look for queue in memory first");
3710 
3711  if (!q || q->realtime) {
3712  /*! \note Load from realtime before taking the "queues" container lock, to avoid blocking all
3713  queue operations while waiting for the DB.
3714 
3715  This will be two separate database transactions, so we might
3716  see queue parameters as they were before another process
3717  changed the queue and member list as it was after the change.
3718  Thus we might see an empty member list when a queue is
3719  deleted. In practise, this is unlikely to cause a problem. */
3720 
3721  queue_vars = ast_load_realtime("queues", "name", queuename, SENTINEL);
3722  if (queue_vars) {
3723  member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, SENTINEL);
3724  if (!member_config) {
3725  ast_debug(1, "No queue_members defined in config extconfig.conf\n");
3726  member_config = ast_config_new();
3727  }
3728  }
3729  if (q) {
3730  prev_weight = q->weight ? 1 : 0;
3731  queue_t_unref(q, "Need to find realtime queue");
3732  }
3733 
3734  q = find_queue_by_name_rt(queuename, queue_vars, member_config);
3735  ast_config_destroy(member_config);
3736  ast_variables_destroy(queue_vars);
3737 
3738  /* update the use_weight value if the queue's has gained or lost a weight */
3739  if (q) {
3740  if (!q->weight && prev_weight) {
3742  }
3743  if (q->weight && !prev_weight) {
3745  }
3746  }
3747  /* Other cases will end up with the proper value for use_weight */
3748  } else {
3750  }
3751  return q;
3752 }
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:3770
#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:444
#define SENTINEL
Definition: compiler.h:87
static struct ao2_container * queues
Definition: app_queue.c:1769
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:1924
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:3555
unsigned int realtime
Definition: app_queue.c:1715
#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 11449 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().

11450 {
11451  struct member *mem = NULL;
11452  struct call_queue *q;
11453 
11454  if ((q = find_load_queue_rt_friendly(queuename))) {
11455  ao2_lock(q);
11456  mem = ao2_find(q->members, interface, OBJ_KEY);
11457  ao2_unlock(q);
11458  queue_t_unref(q, "Expiring temporary reference.");
11459  }
11460  return mem;
11461 }
static struct call_queue * find_load_queue_rt_friendly(const char *queuename)
Definition: app_queue.c:3699
#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:1755
#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:1924

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

3556 {
3557  struct ast_variable *v;
3558  struct call_queue *q, tmpq = {
3559  .name = queuename,
3560  };
3561  struct member *m;
3562  struct ao2_iterator mem_iter;
3563  char *category = NULL;
3564  const char *tmp_name;
3565  char *tmp;
3566  char tmpbuf[64]; /* Must be longer than the longest queue param name. */
3567 
3568  /* Static queues override realtime. */
3569  if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Check if static queue exists"))) {
3570  ao2_lock(q);
3571  if (!q->realtime) {
3572  if (q->dead) {
3573  ao2_unlock(q);
3574  queue_t_unref(q, "Queue is dead; can't return it");
3575  return NULL;
3576  }
3577  ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
3578  ao2_unlock(q);
3579  return q;
3580  }
3581  } else if (!member_config) {
3582  /* Not found in the list, and it's not realtime ... */
3583  return NULL;
3584  }
3585  /* Check if queue is defined in realtime. */
3586  if (!queue_vars) {
3587  /* Delete queue from in-core list if it has been deleted in realtime. */
3588  if (q) {
3589  /*! \note Hmm, can't seem to distinguish a DB failure from a not
3590  found condition... So we might delete an in-core queue
3591  in case of DB failure. */
3592  ast_debug(1, "Queue %s not found in realtime.\n", queuename);
3593 
3594  q->dead = 1;
3595  /* Delete if unused (else will be deleted when last caller leaves). */
3596  queues_t_unlink(queues, q, "Unused; removing from container");
3597  ao2_unlock(q);
3598  queue_t_unref(q, "Queue is dead; can't return it");
3599  }
3600  return NULL;
3601  }
3602 
3603  /* Create a new queue if an in-core entry does not exist yet. */
3604  if (!q) {
3605  struct ast_variable *tmpvar = NULL;
3606  if (!(q = alloc_queue(queuename))) {
3607  return NULL;
3608  }
3609  ao2_lock(q);
3610  clear_queue(q);
3611  q->realtime = 1;
3612  /*Before we initialize the queue, we need to set the strategy, so that linear strategy
3613  * will allocate the members properly
3614  */
3615  for (tmpvar = queue_vars; tmpvar; tmpvar = tmpvar->next) {
3616  if (!strcasecmp(tmpvar->name, "strategy")) {
3617  q->strategy = strat2int(tmpvar->value);
3618  if (q->strategy < 0) {
3619  ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
3620  tmpvar->value, q->name);
3622  }
3623  break;
3624  }
3625  }
3626  /* We traversed all variables and didn't find a strategy */
3627  if (!tmpvar) {
3629  }
3630  queues_t_link(queues, q, "Add queue to container");
3631  }
3632  init_queue(q); /* Ensure defaults for all parameters not set explicitly. */
3633 
3634  memset(tmpbuf, 0, sizeof(tmpbuf));
3635  for (v = queue_vars; v; v = v->next) {
3636  /* Convert to dashes `-' from underscores `_' as the latter are more SQL friendly. */
3637  if (strchr(v->name, '_')) {
3638  ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
3639  tmp_name = tmpbuf;
3640  tmp = tmpbuf;
3641  while ((tmp = strchr(tmp, '_'))) {
3642  *tmp++ = '-';
3643  }
3644  } else {
3645  tmp_name = v->name;
3646  }
3647 
3648  /* NULL values don't get returned from realtime; blank values should
3649  * still get set. If someone doesn't want a value to be set, they
3650  * should set the realtime column to NULL, not blank. */
3651  queue_set_param(q, tmp_name, v->value, -1, 0);
3652  }
3653 
3654  /* Temporarily set realtime members dead so we can detect deleted ones. */
3655  mem_iter = ao2_iterator_init(q->members, 0);
3656  while ((m = ao2_iterator_next(&mem_iter))) {
3657  if (m->realtime) {
3658  m->dead = 1;
3659  }
3660  ao2_ref(m, -1);
3661  }
3662  ao2_iterator_destroy(&mem_iter);
3663 
3664  while ((category = ast_category_browse(member_config, category))) {
3665  rt_handle_member_record(q, category, member_config);
3666  }
3667 
3668  /* Delete all realtime members that have been deleted in DB. */
3669  mem_iter = ao2_iterator_init(q->members, 0);
3670  while ((m = ao2_iterator_next(&mem_iter))) {
3671  if (m->dead) {
3673  ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
3674  } else {
3675  ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
3676  }
3678  }
3679  ao2_ref(m, -1);
3680  }
3681  ao2_iterator_destroy(&mem_iter);
3682 
3683  ao2_unlock(q);
3684 
3685  return q;
3686 }
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:3373
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:811
static int log_membername_as_agent
queues.conf [general] option
Definition: app_queue.c:1493
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
int realtime
Definition: app_queue.c:1605
#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:1616
#define NULL
Definition: resample.c:96
static void clear_queue(struct call_queue *q)
Definition: app_queue.c:2860
struct ao2_container * members
Definition: app_queue.c:1755
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:3389
char membername[80]
Definition: app_queue.c:1601
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1596
static int strat2int(const char *strategy)
Definition: app_queue.c:1803
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#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:3141
static struct ao2_container * queues
Definition: app_queue.c:1769
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ao2_lock(a)
Definition: astobj2.h:718
int strategy
Definition: app_queue.c:1714
unsigned int dead
Definition: app_queue.c:1702
const ast_string_field name
Definition: app_queue.c:1699
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ast_strlen_zero(a)
Definition: muted.c:73
static struct call_queue * alloc_queue(const char *queuename)
Definition: app_queue.c:3531
#define queues_t_link(c, q, tag)
Definition: app_queue.c:1925
#define queue_t_unref(q, tag)
Definition: app_queue.c:1924
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:1715
#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:2766
#define queues_t_unlink(c, q, tag)
Definition: app_queue.c:1926
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 3500 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().

3501 {
3502  /* Free non-dynamic members */
3503  struct member *cur;
3504  struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
3505 
3506  while ((cur = ao2_iterator_next(&mem_iter))) {
3507  if (all || !cur->dynamic) {
3508  member_remove_from_queue(q, cur);
3509  }
3510  ao2_ref(cur, -1);
3511  }
3512  ao2_iterator_destroy(&mem_iter);
3513 }
int dynamic
Definition: app_queue.c:1604
static void member_remove_from_queue(struct call_queue *queue, struct member *mem)
Definition: app_queue.c:3373
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct ao2_container * members
Definition: app_queue.c:1755
#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 8610 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().

8611 {
8612  struct member *m;
8613 
8614  if (ast_strlen_zero(interface)) {
8615  ast_log(LOG_ERROR, "QUEUE_MEMBER: Missing required interface argument.\n");
8616  return NULL;
8617  }
8618 
8619  m = interface_exists(q, interface);
8620  if (!m) {
8621  ast_log(LOG_ERROR, "Queue member interface '%s' not in queue '%s'.\n",
8622  interface, q->name);
8623  }
8624  return m;
8625 }
#define NULL
Definition: resample.c:96
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1596
#define ast_log
Definition: astobj2.c:42
static struct member * interface_exists(struct call_queue *q, const char *interface)
Definition: app_queue.c:7238
#define LOG_ERROR
Definition: logger.h:285
const ast_string_field name
Definition: app_queue.c:1699
#define ast_strlen_zero(a)
Definition: muted.c:73

◆ get_member_penalty()

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

Definition at line 7732 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().

7733 {
7734  int foundqueue = 0, penalty;
7735  struct call_queue *q;
7736  struct member *mem;
7737 
7738  if ((q = find_load_queue_rt_friendly(queuename))) {
7739  foundqueue = 1;
7740  ao2_lock(q);
7741  if ((mem = interface_exists(q, interface))) {
7742  penalty = mem->penalty;
7743  ao2_ref(mem, -1);
7744  ao2_unlock(q);
7745  queue_t_unref(q, "Search complete");
7746  return penalty;
7747  }
7748  ao2_unlock(q);
7749  queue_t_unref(q, "Search complete");
7750  }
7751 
7752  /* some useful debuging */
7753  if (foundqueue) {
7754  ast_log (LOG_ERROR, "Invalid queuename\n");
7755  } else {
7756  ast_log (LOG_ERROR, "Invalid interface\n");
7757  }
7758 
7759  return RESULT_FAILURE;
7760 }
static struct call_queue * find_load_queue_rt_friendly(const char *queuename)
Definition: app_queue.c:3699
#define ao2_unlock(a)
Definition: astobj2.h:730
char interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1596
#define ast_log
Definition: astobj2.c:42
int penalty
Definition: app_queue.c:1602
static struct member * interface_exists(struct call_queue *q, const char *interface)
Definition: app_queue.c:7238
#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:1924
#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 2287 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().

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

◆ get_queue_member_status()

static int get_queue_member_status ( struct member cur)
static

Return the current state of a member.

Definition at line 2668 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().

2669 {
2670  return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten));
2671 }
ast_device_state
Device States.
Definition: devicestate.h:52
char state_interface[AST_CHANNEL_NAME]
Definition: app_queue.c:1599
#define NULL
Definition: resample.c:96
static int extensionstate2devicestate(int state)
Helper function which converts from extension state to device state values.
Definition: app_queue.c:2593
#define ast_strlen_zero(a)
Definition: muted.c:73
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:3165
char state_exten[AST_MAX_EXTENSION]
Definition: app_queue.c:1597

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

1860 {
1861  if (member->wrapuptime) {
1862  return member->wrapuptime;
1863  }
1864  return q->wrapuptime;
1865 }
int wrapuptime
Definition: app_queue.c:1740
int wrapuptime
Definition: app_queue.c:1611

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

6204 {
6205  struct queue_stasis_data *queue_data = userdata;
6206  struct ast_attended_transfer_message *atxfer_msg = stasis_message_data(msg);
6207  RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
6208  RAII_VAR(struct ast_channel_snapshot *, member_snapshot, NULL, ao2_cleanup);
6209 
6210  if (atxfer_msg->result != AST_BRIDGE_TRANSFER_SUCCESS ||
6212  return;
6213  }
6214 
6215  ao2_lock(queue_data);
6216 
6217  if (queue_data->dying) {
6218  ao2_unlock(queue_data);
6219  return;
6220  }
6221 
6222  if (ast_strlen_zero(queue_data->bridge_uniqueid)) {
6223  ao2_unlock(queue_data);
6224  return;
6225  }
6226 
6227  if ((!atxfer_msg->to_transferee.bridge_snapshot || strcmp(queue_data->bridge_uniqueid,
6228  atxfer_msg->to_transferee.bridge_snapshot->uniqueid)) &&
6229  (!atxfer_msg->to_transfer_target.bridge_snapshot || strcmp(queue_data->bridge_uniqueid,
6230  atxfer_msg->to_transfer_target.bridge_snapshot->uniqueid))) {
6231  ao2_unlock(queue_data);
6232  return;
6233  }
6234 
6235  caller_snapshot = ast_channel_snapshot_get_latest(queue_data->caller_uniqueid);
6236  member_snapshot = ast_channel_snapshot_get_latest(queue_data->member_uniqueid);
6237 
6238  ao2_unlock(queue_data);
6239 
6240  ast_debug(3, "Detected attended transfer in queue %s\n", queue_data->queue->name);
6241  log_attended_transfer(queue_data, atxfer_msg);
6242 
6243  send_agent_complete(queue_data->queue->name, caller_snapshot, member_snapshot, queue_data->member,
6244  queue_data->holdstart, queue_data->starttime, TRANSFER);
6245  update_queue(queue_data->queue, queue_data->member, queue_data->callcompletedinsl,
6246  queue_data->starttime);
6247  remove_stasis_subscriptions(queue_data);
6248 }
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
struct ast_bridge_channel_snapshot_pair to_transfer_target
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
enum ast_transfer_result result